Образец Grabber DirectShow вызывается, но ‘this’ в обратном вызове имеет значение NULL

Я работаю над базовой реализацией фильтра графа DirectShow для получения изображений
с моей веб-камеры в моем приложении. Я прочитал документацию и создал простой
реализация. Я создаю этот график: устройство -> samplegrabber -> nullrenderer.

Я проверяю все значения результатов, которые могу, и не получаю ошибок из SDK.

Эта проблема:

Каким-то образом мой обратный вызов вызывается правильно, но всякий раз, когда я добавляю какой-либо код внутри
функции обратного вызова (это считается как для SampleCB, так и для BufferCB) моего приложения
молча вылетает.

Я добавил точку останова в свой BufferCB, и я вижу, что «this» равно 0x0000000 / NULL.
Поскольку я проверяю все значения результатов при создании графика, я предполагаю, что мой
настройка графа верна и что эта проблема может быть связана с COM .. но это
просто дикая догадка.

Потому что Windows 7.0 SDK не предоставляет qedit.h, который содержит интерфейс
для интерфейса ISampleGrabber я сам создал этот файл и добавил соответствующий
интерфейс (я нашел содержимое где-то на посту во время поиска в Google).

Я скопировал функцию saveGraph из документации, чтобы я мог проверить график в
GraphEdit. Когда я добавляю узел рендеринга, я вижу, что автоматически преобразование цвета
узел редактируется с помощью GraphEdit. Когда я запускаю график с помощью рендерера, я вижу изображения
с веб-камеры (в графите).

Я вставил весь соответствующий код в эту суть (с трассировкой callstack + переменные)

Кто-нибудь имеет какие-либо идеи, как я могу отладить это или что это может быть за ошибка? Может ли это
быть связанным с COM?

Обновление: callstack при попытке получить доступ к члену в моем ISampleGrabberCB

ntdll.dll!_ZwRaiseException@12()  + 0x12 bytes
ntdll.dll!_ZwRaiseException@12()  + 0x12 bytes
msvcr100d.dll!__lock_fhandle(int fh)  Line 467  C
qedit.dll!CSampleGrabber::Receive()  + 0x18c bytes
qedit.dll!CTransformInputPin::Receive()  + 0x33 bytes
quartz.dll!CBaseOutputPin::Deliver()  + 0x22 bytes
quartz.dll!CVideoTransformFilter::Receive()  + 0x1aa bytes
quartz.dll!CTransformInputPin::Receive()  + 0x33 bytes
quartz.dll!CBaseInputPin::ReceiveMultiple()  + 0x33 bytes
qcap.dll!COutputQueue::ThreadProc()  + 0x103 bytes
qcap.dll!COutputQueue::InitialThreadProc()  + 0x16 bytes
kernel32.dll!@BaseThreadInitThunk@12()  + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8()  + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8()  + 0x1b bytes

Спасибо

0

Решение

Поскольку qedit.h больше нет в Windows SDK, вам нужно получить определение интерфейсов, связанных с Sample Grabber. Одним из методов является использование более старого SDK со всеми заголовками. Другой метод заключается в #import интерфейсы из библиотеки типов. И вы всегда можете переопределить их прямо в коде.

Вы можете получить правильное определение из там:

struct __declspec(uuid("0579154a-2b53-4994-b0d0-e773148eff85"))
ISampleGrabberCB : IUnknown
{
virtual HRESULT __stdcall SampleCB (double SampleTime, struct IMediaSample * pSample ) = 0;
virtual HRESULT __stdcall BufferCB (double SampleTime, unsigned char * pBuffer, long BufferLen ) = 0;
};

Потому что у вас не было __stdcall по вашему, неправильное соглашение о вызовах было использовано, и ваш this было NULL,

2

Другие решения

Маловероятно, что эта проблема связана только с COM. Вы предполагаете, что COM, кажется, как-то вызывает ваш интерфейс обратного вызова, тогда как он NULL, Но если бы это было так, вы бы увидели сбой даже без добавления какого-либо кода в вашу реализацию обратного вызова.

Как вы, наверное, знаете, все функции интерфейса в COM virtual, Вызов такой функции включает в себя сначала разыменование указателя интерфейса и чтение содержимого соответствующего vtable запись. Отсюда зовет virtual функция на NULL Указатель на интерфейс немедленно вызывает нарушение прав доступа. OTOH вызывает не виртуальную функцию на NULL Объект в порядке (по крайней мере, с точки зрения реализации, оставляя стандарт C ++ в стороне).

Я предлагаю вам внимательно посмотреть на стеки вызовов. Я считаю, что метод COM вызывается правильно. Однако в вашем конкретном примере вы не можете напрямую реализовать метод обратного вызова COM, вместо этого он может быть вызван некоторым кодом обертки (это весьма вероятно для библиотеки DirectShow). Вы должны искать проблему там.

0

По вопросам рекламы [email protected]