1

I'm writing a software to record video and audio streams from two Microsoft Azure Kinect connected to one computer. As I want to join the audio and video stream from the devices I have to figure out, which microphone array belongs to which camera. With the base container id, I could already see the parts of the Azure Kinect and bring them together (4K camera, IR camera, microphone array). But I don't see a programmatic way (c or c++).

Environment: Azure Kinect SDK 1.4.1 / Win 10

What happened until now: With the k4a SDK it is easily possible to get the video data from the cameras (RGB+IR), but the SDK does not provide means to access the microphone arrays. So I used WASAPI and the multimedia API for the audio streams.

And from Oleg's Answer I learned how to find the ContainerIDs from the Azure Kinect. There I could also see the serial number in the DeviceInstanceID.

The source code below is minimal and does neither include error checking nor output to the screen

unsigned i=0
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
TCHAR szDeviceInstanceID[MAX_DEVICE_ID_LEN];
TCHAR szDesc[1024], szHardwareIDs[4096];
WCHAR szBuffer[4096];


// loop through devices, i as number in list
   DeviceInfoData.cbSize = sizeof(DeviceInfoData);
   SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData));
   CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0);
   // put here code to display szDeviceInstanceID 
   
   SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
            &dwPropertyRegDataType, (BYTE*)szDesc, sizeof(szDesc), &dwSize));
   // put here code to display szDesc
   // ...
          fn_SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData,
                &DEVPKEY_Device_BusReportedDeviceDesc,
                &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0);
          // put here code to display szBuffer (with BusReportedDeviceDesc)
          fn_SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData,
                &DEVPKEY_Device_BaseContainerId,
                &ulPropertyType, (BYTE*)szDesc, sizeof(szDesc), &dwSize, 0);
          StringFromGUID2((REFGUID)szDesc, szBuffer, ARRAY_SIZE(szBuffer));
          // put here code to display szBuffer (BaseContainerId)
// end of loop

will output something like this:

DeviceInstanceID ----USB\VID_045E&PID_097D&MI_02\8&904C5FF&0&0002
    Device Description: WinUsb Device
    Bus Reported Device Description: Azure Kinect 4K Camera
    BaseContainerId: {A60ED20F-7C3B-4B20-AF2F-77E5987FC5E0}


DeviceInstanceID ----USB\VID_045E&PID_097C\000591600112
    Device Description: WinUsb Device
    Bus Reported Device Description: Azure Kinect Depth Camera
    BaseContainerId: {A60ED20F-7C3B-4B20-AF2F-77E5987FC5E0}


DeviceInstanceID ----USB\VID_045E&PID_097D&MI_00\8&904C5FF&0&0000
    Device Description: USB Video Device
    Bus Reported Device Description: Azure Kinect 4K Camera
    BaseContainerId: {A60ED20F-7C3B-4B20-AF2F-77E5987FC5E0}


DeviceInstanceID ----USB\VID_045E&PID_097E&MI_00\8&177D8328&0&0000
    Device Description: USB Audio 2.0
    Bus Reported Device Description: Azure Kinect Microphone Array
    BaseContainerId: {A60ED20F-7C3B-4B20-AF2F-77E5987FC5E0}

All this refers to one Azure Kinect (one BaseContainerId). And the serial number from the Azure Kinect is part of the second DeviceInstanceID (000591600112). The data from the second Azure Kinect is not include here. It is similar but with another BaseContainerId and serial number.

With the k4a SDK function k4a_device_get_serialnum() I could get the serial numbers of the kinects.

To find the Azure Kinect Microphone Arrays I checked the AudioEndpoints via

    IMMDeviceEnumerator *deviceEnumerator = NULL;
    IMMDeviceCollection *deviceCollection = NULL;
    IMMDevice *device = NULL;

    CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, 
                     IID_PPV_ARGS(&deviceEnumerator);
    deviceEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE,
                     &deviceCollection);
    // loop through devices (i)
            LPWSTR deviceName;
            deviceName = GetDeviceName(deviceCollection, i);
            device->GetId(&deviceid); 
            device->OpenPropertyStore(STGM_READ,&propstore);
            propstore->GetValue(PKEY_Device_FriendlyName ,&propvari);
            // check for Azure Kinect Microphone Array

and it will produce something like this

device name:Microphone Array (Azure Kinect Microphone Array) 
                       ({0.0.1.00000000}.{002466ae-4a3f-432c-8bae-1c3ddc8fc1f8})

device name:Microphone Array (2- Azure Kinect Microphone Array) 
                       ({0.0.1.00000000}.{0ae6a82f-5a3f-4ece-a618-80aafecb8fe8})

device name:Microphone Array (Realtek(R) Audio) 
                       ({0.0.1.00000000}.{b279e826-ffb8-465e-87d8-fe40db70cdf3})

I already checked for all types of GUID and ID in the multimedia and the device properties part but didn't see the way how to make loose ends meet. I hope it will be much simpler than what I do and would be glad to get some hint on how to pick the correct microphone array.

Jens
  • 13
  • 5
  • You can use the container ID to identify which microphone array belongs to which camera, you can use the BaseContainerID property of the device to identify the container ID, which should be unique for each camera I believe!!! You can associate each microphone array with the camera that has the same BaseContainerID property. With this information, you should be able to join the audio and video streams from the two cameras.... – SatishBoddu Mar 01 '23 at 18:29
  • Hi SatishBoddu - yes, but how do I find the ContainerID in the multimedia API? I tried with propstore->GetValue(PKEY_ContainerID ,&propvari) and propstore->GetValue(PKEY_Device_BaseContainerId, &propvari) but neither returned a value. – Jens Mar 01 '23 at 19:22
  • Do you happen to see this function? i am not able to get the Github link, if (K4A_FAILED(k4a_device_get_container_id(device, container_id_buffer, &container_id_buffer_size))) { printf("Failed to get device ContainerID\n"); k4a_device_close(device); return 1; } – SatishBoddu Mar 01 '23 at 20:54
  • let me check with my team on this ,please post here if you find any info... – SatishBoddu Mar 01 '23 at 20:54
  • Hi SatishBoddu, thank you again for the update. No, k4a_device_get_container_id() is not available in my version of the k4a SDK (v1.4.1). Having the serial number, I'm able to find the Container Id from SetupDiEnumDeviceInfo() and following CM_Get_Device_ID(). How do I use it with WASAPI / Multimedia API. Right now I'm missing the link betweeen Container Id and correct microphone array in the Multimedia API. – Jens Mar 02 '23 at 06:42
  • Did you try calling the **GetMicDeviceByContainerId()** function with the Container ID ??which was obtained from the SetupDiEnumDeviceInfo() and CM_Get_Device_ID() and you can then get a pointer to the **IMMDevice** interface for the correct microphone array, I think then you can use the WASAPI API functions to capture audio from the microphone array.[Ref](https://learn.microsoft.com/en-us/windows/apps/get-started/samples) – SatishBoddu Mar 04 '23 at 18:29
  • requires several API calls and logic to enumerate the audio endpoints, retrieve their properties, and match the Container ID with the correct microphone array.... – SatishBoddu Mar 04 '23 at 18:29
  • 1
    No I did not yet use the GetMicDeviceByContainerId, but I finally could find the correct GUID - and yes it required several API calls and some logic to enumerate the audio endpoints to get there. I learned a lot about it and still believe I'm only at the beginning. Now I will check your answer and test it. Thank you so much. – Jens Mar 06 '23 at 17:45

1 Answers1

0

Try the below sample function snippet, be sure to test it from your side... Somehow i am not able to format the code in this editor, so pasting it image format. Hoping this may help somewhat....

enter image description here

SatishBoddu
  • 752
  • 6
  • 13