DirectShow - Невозможно создать новые темы
У меня возникают некоторые странные проблемы при интеграции графа DirectShow в существующее приложение.
Несколько вещей, чтобы покрыть сначала:
- Цель графика - получить необработанное видео от FrameGrabber, который имеет открытый интерфейс DirectShow. График дает право видео отображать через VMR9, а также предоставляет необработанные кадры некоторым алгоритмам через ISampleGrabber (Примеры DirectShow).
- График был построен и успешно запущен в отдельном проекте. Видео отображается нормально и все устраивает.
Теперь проблема возникает, когда я интегрирую это в существующий код. С момента инициализации приложения я сначала создаю и запускаю график, запускающий VMR9 в режиме без окон. Позже в процессе инициализации я создаю пару рабочих потоков через _beginthreadex. Вызовы _beginthreadex завершаются неудачно с кодом возврата 12 (Недостаточно памяти), когда и ТОЛЬКО тогда, когда график построен и запущен.
Теперь очевидный ответ: у меня недостаточно памяти или, возможно, какой-то другой ресурс. Однако в тот момент, когда потоки пытаются запустить, я использую ~420 МБ системной памяти объемом 2 ГБ. Размер стека потока был явно установлен равным 1 МБ. Так что я не без памяти, насколько я могу судить. Кроме того, в запущенном приложении есть всего 15 потоков, поэтому я не создаю абсурдную сумму.
Кто-нибудь имел / испытывал подобную проблему с DirectShow? Я вообще ищу какой-либо вклад, мы пытались отладить эту проблему уже довольно давно и не увенчались успехом.
Я опубликую любой код, который вам требуется, так как на большинстве графиков DirectShow код длинный.
редактировать
Как просили. Я не уверен, какая часть кода DirectShow приводит к сбою потоков. Однако, если я только строю, но не запускаю график, потоки работают нормально. Так что я бы догадался, что сбой происходит после вызова run. Мой код для запуска графика выглядит следующим образом:
if (CurrentState != Stopped)
return WrongState;
HRESULT hr;
printf("Attempting to run graph... ");
Timer->Start();
hr = pMediaControl->Run();
if (FAILED(hr))
{
OAFilterState State;
hr = pMediaControl->GetState(1000, &State);
if ((SUCCEEDED(hr) && State != State_Running) || FAILED(hr))
{
return FailedToStartGraph;
}
}
CurrentState = Streaming;
SetVMRSize();
Timer->Stop();
RunTime->Start();
FrameRate->Reset();
return NoError;
Функция SetVMRSize просто изменяет размер VMR до его родительского окна:
void KontronGraph::SetVMRSize()
{
if (CurrentState == Disconnected || VideoMode != ParentWindow)
return;
long lWidth, lHeight;
HRESULT hr = pWindowController->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
if (SUCCEEDED(hr))
{
RECT rcSrc, rcDest;
// Set the source rectangle.
rcSrc.left = 0;
rcSrc.right = lWidth;
rcSrc.top = 0;
rcSrc.bottom = lHeight;
// Get the window client area.
GetClientRect(MyHwnd, &rcDest);
// Set the destination rectangle.
rcDest.right = rcDest.right - rcDest.left;
rcDest.bottom = rcDest.bottom - rcDest.top;
rcDest.left = 0;
rcDest.top = 0;
// Set the video position.
hr = pWindowController->SetVideoPosition(&rcSrc, &rcDest);
}
}
Следует отметить, что pWindowController IVMRWindowlessControl9
и pMediaControl это IMediaControl
Редактировать 2
Протестировал код, используя CreateThread вместо __beginthreadex. После неудачного запуска потоков GetLastError() возвращает:
8: недостаточно памяти для обработки этой команды.
Код для создания потоков выглядит так:
HANDLE worker_thread = CreateThread(0,
Thread_Stack_Size, worker_thread_op, thread_param, 0, 0);
Некоторые параметры для CreateThread:
Thread_Stack_Size = 1024 * 1024;
typedef DWORD (WINAPI *worker_thread_op_type)(LPVOID params);
3 ответа
Для начала я бы предложил вам заменить _beginthreadex
с CreateThread
а затем использовать GetLastError
определить причину любой ошибки, которая часто более конкретна, чем коды ошибок CRT, установленные _beginthreadex
, Дайте мне знать, что вы наблюдаете, делая это, и я обновлю свой ответ.
Кроме того, можете ли вы опубликовать часть своего кода (DirectShow), которая приводит к сбою создания потока, а также строки кода, которые создают поток?
Обновление: Что бы я ни нашел относительно конкретной ошибки, вы получаете подсказки о возможной утечке памяти. Обратите внимание, что только 420 МБ (как вы упомянули) могут быть зарезервированы, но можно было бы зарезервировать больше страниц, и эти страницы все равно будут учитываться при ограничении виртуального пространства в 2 ГБ вашего приложения. Запуск графика DirectShow мог бы использовать все, что осталось от этого пространства.
Таким образом, наиболее вероятно, что DirectShow сам по себе не является причиной ошибки, а вместо этого обнаружил существующую ошибку в вашем приложении.
Вот некоторая дополнительная информация из MSDN, которая может иметь отношение к вам, особенно если вы ранее создали другие потоки в своей программе ( Размер стека потоков):
Каждый новый поток получает свое собственное пространство стека, состоящее как из зарезервированной, так и изначально выделенной памяти. Зарезервированный объем памяти представляет собой общее выделение стека в виртуальной памяти. Таким образом, зарезервированный размер ограничен диапазоном виртуальных адресов. Первоначально зафиксированные страницы не используют физическую память, пока на них не ссылаются; ... Стек освобождается при выходе из потока. Он не освобождается, если поток завершается другим потоком.
Из вашего объяснения мне не совсем ясно, является ли это проблемой или нет, но с большинством связанных с DirectX инструментов (которые я предполагаю включает в себя DirectShow) вам необходимо убедиться, что все ваши связанные вызовы происходят в одном потоке; Другими словами, если вы настроили DirectShow в данном потоке, выполняйте все ваши вызовы в нем, используя тот же поток. Прошло много времени с тех пор, как я использовал DirectShow, поэтому я не уверен на 100%, что это применимо, но это определенно решает многие проблемы с D3D, которая тесно связана с технологией.
FWIW.
На веб-страницах sysinternals есть множество видеофильмов, посвященных тому, как и кем используется память. Может быть, это может помочь вам с вашей проблемой.
http://technet.microsoft.com/en-us/sysinternals/bb963887
http://player.microsoftpdc.com/Session/1689962d-dea2-48bd-80d8-96e954fa5329
http://player.microsoftpdc.com/Session/1c97b279-d7e3-4a3e-9a76-0dac23dfddb5
Надеюсь, что это поможет вам.