IMFMediaSource "для mfcore.dll не загружен символ", а QueryInterface выдает "E_NOINTERFACE" - PullRequest
0 голосов
/ 27 октября 2018

Я новичок в программировании COM, но хорошо разбираюсь в C # .Net, пытаюсь запустить этот код, но по какой-то причине объект IMFMediaSource не инициализируется как Visual Studio в режиме отладки, когда я проверяю значение путем наведения курсора " Указатель pSource "показывает" Информация недоступна, символ не загружен для mfcore.dll ", однако hr возвращает" S_Ok ", но когда Next Statement выполняет" QueryInterface ", hr возвращает" E_NOINTERFACE ".

Пожалуйста, объясните подробно, что я делаю неправильно, так как мой основной мотив - создать DLL для захвата видео и использовать ее с Unity Engine C #.

#pragma comment(lib,"mfplat.lib")
#pragma message("linking with Microsoft's Media Foundation mfplat library ...")
#pragma comment(lib,"mf.lib")
#pragma comment(lib,"mfcore.lib")
#pragma message("linking with Microsoft's Media Foundation mf library ...")
#pragma comment(lib,"mfreadwrite.lib")
#pragma message("linking with Microsoft's Media Foundation mfreadwrite library ...")
#pragma comment(lib,"mfuuid.lib")
#pragma message("linking with Microsoft's Media Foundation mfuuid library ...")
#pragma comment(lib,"d3d9.lib")
#pragma message("linking with Microsoft's DirectX 3D 9 library ...")
#pragma comment(lib,"shlwapi.lib")
#pragma message("linking with Microsoft's shlwapi library ...")
#pragma comment(lib,"Advapi32.lib")
#pragma message("linking with Microsoft's Advapi32 library ...")

int main(int argc, char** argv)
{
    HRESULT hr;
    hr = ::CoInitialize(NULL);
    if (FAILED(hr))
        abort();
    hr = ::MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET);
    if (FAILED(hr))
        abort();
    IMFMediaSource*  media_source = 0;
    IMFSourceReader* source_reader = 0;
    IMFAttributes* pAttributes = 0;
    hr = MFCreateAttributes(&pAttributes, 1);
    if (FAILED(hr))
        abort();
    // Set the device type to video.
    hr = pAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID);
    if (FAILED(hr))
        abort();
    UINT32 count;
    IMFActivate **ppDevices = NULL;
    hr = MFEnumDeviceSources(pAttributes, &ppDevices, &count);
    if (FAILED(hr))
        abort();
    if (count == 0)
        abort();
    // Create the media source object.
    IMFMediaSource *pSource = NULL;
    hr = ppDevices[0]->ActivateObject(IID_IMFMediaSource, (void**)&pSource);
    if (FAILED(hr))
        abort();
    pSource->AddRef();//on hovering over the "pSource" in VS2017 shows "Information Not available, no symbol loaded for mfcore.dll"    

IMFAttributes* pSourceAttributes = NULL;
    hr = pSource->QueryInterface(IID_IMFAttributes, (void**)&pSourceAttributes);
    if (FAILED(hr))
        abort(); //hr is assigned -> "E_NOINTERFACE" and program quits

    const size_t nDeviceNameSize = 1024;
    LPWSTR pDeviceName = new WCHAR[nDeviceNameSize];
    UINT32 nActualBufferSize;
    hr = pSourceAttributes->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, pDeviceName, nDeviceNameSize, &nActualBufferSize);
    if (FAILED(hr))
        abort();
    // Set the symbolic link.
    hr = pAttributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, pDeviceName);
    if (FAILED(hr))
        abort();
    // Create device source interface
    hr = MFCreateDeviceSource(pAttributes, &media_source);
    if (FAILED(hr)) 
        abort();

}

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

IMFAttributes интерфейс доступен для объекта активации и не [обязательно] для источника мультимедиа.Если вы обновите свой код, как показано ниже, вы сможете запросить значение MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK.Причина этого заключается в том, что примитивному медиаисточнику не нужно хранить, раскрывать или даже знать о регистрационной информации - сам медиаисточник является чистой реализацией.

IMFAttributes* pSourceAttributes = NULL;
hr = //pSource
    ppDevices[0] // <<--------
    ->QueryInterface(IID_IMFAttributes, (void**)&pSourceAttributes);
if (FAILED(hr))
    abort(); //hr is assigned -> "E_NOINTERFACE" and program quits

Обратите внимание, что это документированное поведение вы можете найтиподробнее здесь: Захват аудио / видео в Media Foundation :

Вы можете запросить объекты активации для различных атрибутов, включая следующие: […] В следующем примере используется массивIMFActivate указывает и печатает отображаемое имя каждого устройства в окне отладки: […]

0 голосов
/ 27 октября 2018

Код

hr = pSource-> QueryInterface (IID_IMFAttributes, (void **) & pSourceAttributes);

возвращает E_NOINTERFACE, поскольку MediaSource не наследуетсяот IMFAttributes.Для вашей цели - получите понятное имя и символическую ссылку устройства, код должен получить IMFAttributes из IMFActivate (ppDevices[0]):

// Read friendlyName of device
ResultCode::Result MediaFoundation::readFriendlyName(IMFActivate *pDevice, std::wstring &friendlyName)
{
ResultCode::Result result = ResultCode::MEDIA_FOUNDATION_READFRIENDLYNAME_ERROR;

wchar_t *pFriendlyName = NULL;

HRESULT hr = S_OK;

hr = pDevice->GetAllocatedString(
    MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,
    &pFriendlyName,
    NULL
    );

if (FAILED(hr))
{
    DebugPrintOut::getInstance().printOut(L"MEDIA FOUNDATION: readFriendlyName cannot be executed!!!\n");

    goto finish;
}

friendlyName = std::wstring(pFriendlyName);

result = ResultCode::OK;

 finish:

if (pFriendlyName)
    CoTaskMemFree(pFriendlyName);

return result;
}

и:

// Read symbolicLink of device
ResultCode::Result MediaFoundation::readSymbolicLink(IMFActivate *pDevice, 
std::wstring &symbolicLink)
{
ResultCode::Result result = ResultCode::MEDIA_FOUNDATION_READSYMBOLICLINK_ERROR;

wchar_t *pSymbolicLink = NULL;

HRESULT hr = S_OK;

hr = pDevice->GetAllocatedString(
        MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
        &pSymbolicLink,
        NULL
        );


if (FAILED(hr))
{
    DebugPrintOut::getInstance().printOut(L"MEDIA FOUNDATION: readSymbolicLink cannot be executed!!!\n");

    goto finish;
}

symbolicLink = std::wstring(pSymbolicLink);

result = ResultCode::OK;

finish:

if (pSymbolicLink)
    CoTaskMemFree(pSymbolicLink);

return result;
}

Я рекомендую прочитать мою статью с кодом: Запись Live-видео с веб-камеры в Windows 7 и Windows 8

PS для Unity Engine. Я могу порекомендовать другой мой проект: UnityWebCamViewer

...