mirror of
https://github.com/pion/mediadevices.git
synced 2026-04-22 15:57:27 +08:00
(2/3) Fix windows camera names (#683)
* Add NV12 support * Fix camera resolution listing by supporting FORMAT_VideoInfo2 in addition to FORMAT_VideoInfo. This change allows for better compatibility with various video formats by correctly retrieving width, height, and compression details from both format types (NV12 and YUY2) * Add support for configuring video capture pin format in open method * Import wmcodecdsp and try to use their nv12 const * Remove ifndef * Use subtype.Data1 instead of biCompression * Enhance getCameraName function to retrieve friendly name from IPropertyBag, with fallback to display name. Update LDFLAGS in camera_windows.go to include oleaut32 library. * Don't mistake label for friendly name * Improve camera device name handling and memory management in Windows driver. Added checks for valid device names and initialized camera lists to prevent memory issues. Enhanced resolution listing by ensuring proper media type handling and freeing resources appropriately.
This commit is contained in:
@@ -33,6 +33,11 @@ char* getName(cameraList* list, int i)
|
||||
return list->name[i];
|
||||
}
|
||||
|
||||
char* getFriendlyName(cameraList* list, int i)
|
||||
{
|
||||
return list->friendlyName[i];
|
||||
}
|
||||
|
||||
|
||||
// printErr shows string representation of HRESULT.
|
||||
// This is for debugging.
|
||||
@@ -43,7 +48,7 @@ void printErr(HRESULT hr)
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
}
|
||||
|
||||
// getCameraName returns name of the device.
|
||||
// getCameraName returns the display name (device path) of the device.
|
||||
// returned pointer must be released by free() after use.
|
||||
char* getCameraName(IMoniker* moniker)
|
||||
{
|
||||
@@ -62,6 +67,40 @@ char* getCameraName(IMoniker* moniker)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// getDeviceFriendlyName returns the human-readable name of the device via IPropertyBag.
|
||||
// Returns nullptr if the friendly name is not available.
|
||||
// returned pointer must be released by free() after use.
|
||||
static char* getDeviceFriendlyName(IMoniker* moniker)
|
||||
{
|
||||
IPropertyBag* propBag = nullptr;
|
||||
if (FAILED(moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&propBag)))
|
||||
return nullptr;
|
||||
|
||||
VARIANT varName;
|
||||
VariantInit(&varName);
|
||||
if (FAILED(propBag->Read(L"FriendlyName", &varName, 0)))
|
||||
{
|
||||
VariantClear(&varName);
|
||||
propBag->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (varName.vt != VT_BSTR || varName.bstrVal == nullptr)
|
||||
{
|
||||
VariantClear(&varName);
|
||||
propBag->Release();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string nameStr = utf16Decode(varName.bstrVal);
|
||||
VariantClear(&varName);
|
||||
propBag->Release();
|
||||
|
||||
char* ret = (char*)malloc(nameStr.size() + 1);
|
||||
memcpy(ret, nameStr.c_str(), nameStr.size() + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// listCamera stores information of the devices to cameraList*.
|
||||
int listCamera(cameraList* list, const char** errstr)
|
||||
{
|
||||
@@ -89,6 +128,7 @@ int listCamera(cameraList* list, const char** errstr)
|
||||
{
|
||||
list->num = 0;
|
||||
list->name = nullptr;
|
||||
list->friendlyName = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -102,15 +142,18 @@ int listCamera(cameraList* list, const char** errstr)
|
||||
}
|
||||
|
||||
enumMon->Reset();
|
||||
list->name = new char*[list->num];
|
||||
list->name = new char*[list->num]();
|
||||
list->friendlyName = new char*[list->num]();
|
||||
|
||||
int i = 0;
|
||||
while (enumMon->Next(1, &moniker, nullptr) == S_OK)
|
||||
{
|
||||
list->name[i] = getCameraName(moniker);
|
||||
list->friendlyName[i] = getDeviceFriendlyName(moniker);
|
||||
moniker->Release();
|
||||
i++;
|
||||
}
|
||||
list->num = i;
|
||||
}
|
||||
|
||||
safeRelease(&enumMon);
|
||||
@@ -129,9 +172,17 @@ int freeCameraList(cameraList* list, const char** errstr)
|
||||
{
|
||||
for (int i = 0; i < list->num; ++i)
|
||||
{
|
||||
delete list->name[i];
|
||||
free(list->name[i]);
|
||||
}
|
||||
delete list->name;
|
||||
delete[] list->name;
|
||||
}
|
||||
if (list->friendlyName != nullptr)
|
||||
{
|
||||
for (int i = 0; i < list->num; ++i)
|
||||
{
|
||||
free(list->friendlyName[i]);
|
||||
}
|
||||
delete[] list->friendlyName;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -247,7 +298,10 @@ int listResolution(camera* cam, const char** errstr)
|
||||
|
||||
if (mediaType->majortype != MEDIATYPE_Video ||
|
||||
mediaType->pbFormat == nullptr)
|
||||
{
|
||||
freeMediaType(mediaType);
|
||||
continue;
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER* bmi = nullptr;
|
||||
if (mediaType->formattype == FORMAT_VideoInfo)
|
||||
@@ -260,12 +314,15 @@ int listResolution(camera* cam, const char** errstr)
|
||||
}
|
||||
else
|
||||
{
|
||||
freeMediaType(mediaType);
|
||||
continue;
|
||||
}
|
||||
|
||||
cam->props[iProp].width = bmi->biWidth;
|
||||
cam->props[iProp].height = bmi->biHeight;
|
||||
cam->props[iProp].fcc = bmi->biCompression;
|
||||
// Use subtype.Data1 for the FourCC; some drivers leave biCompression as 0.
|
||||
cam->props[iProp].fcc = mediaType->subtype.Data1;
|
||||
freeMediaType(mediaType);
|
||||
iProp++;
|
||||
}
|
||||
cam->numProps = iProp;
|
||||
@@ -367,7 +424,7 @@ int openCamera(camera* cam, const char** errstr)
|
||||
if (bmi != nullptr &&
|
||||
bmi->biWidth == cam->width &&
|
||||
bmi->biHeight == cam->height &&
|
||||
bmi->biCompression == cam->fcc)
|
||||
mt->subtype.Data1 == cam->fcc)
|
||||
{
|
||||
streamConfig->SetFormat(mt);
|
||||
freeMediaType(mt);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package camera
|
||||
|
||||
// #cgo LDFLAGS: -lstrmiids -lole32 -lquartz
|
||||
// #cgo LDFLAGS: -lstrmiids -lole32 -loleaut32 -lquartz
|
||||
// #include <dshow.h>
|
||||
// #include "camera_windows.hpp"
|
||||
import "C"
|
||||
@@ -49,11 +49,19 @@ func Initialize() {
|
||||
}
|
||||
|
||||
for i := 0; i < int(list.num); i++ {
|
||||
name := C.GoString(C.getName(&list, C.int(i)))
|
||||
driver.GetManager().Register(&camera{name: name}, driver.Info{
|
||||
Label: name,
|
||||
cName := C.getName(&list, C.int(i))
|
||||
if cName == nil {
|
||||
continue
|
||||
}
|
||||
label := C.GoString(cName)
|
||||
info := driver.Info{
|
||||
Label: label,
|
||||
DeviceType: driver.Camera,
|
||||
})
|
||||
}
|
||||
if fn := C.getFriendlyName(&list, C.int(i)); fn != nil {
|
||||
info.Name = C.GoString(fn)
|
||||
}
|
||||
driver.GetManager().Register(&camera{name: label}, info)
|
||||
}
|
||||
|
||||
C.freeCameraList(&list, &errStr)
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef struct
|
||||
{
|
||||
int num;
|
||||
char** name;
|
||||
char** friendlyName;
|
||||
} cameraList;
|
||||
|
||||
int openCamera(camera* cam, const char** errstr);
|
||||
@@ -44,6 +45,7 @@ int freeCameraList(cameraList* list, const char** errstr);
|
||||
imageProp* getProp(camera* cam, int i);
|
||||
|
||||
char* getName(cameraList* list, int i);
|
||||
char* getFriendlyName(cameraList* list, int i);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user