DirectShow - Невозможно создать новые темы - PullRequest
3 голосов
/ 20 января 2011

У меня возникают некоторые странные проблемы при интеграции графа DirectShow в существующее приложение.

Несколько вещей, которые нужно охватить в первую очередь:

  1. Цель графика - получить необработанное видео изFrameGrabber с открытым интерфейсом DirectShow.График дает право видео отображать через VMR9, а также предоставляет необработанные кадры некоторым алгоритмам через ISampleGrabber (Примеры DirectShow).
  2. График был построен и успешно выполнен в отдельном проекте.Видео отображается нормально, и все хорошо.

Теперь возникает проблема, когда я интегрирую это в существующий код.После инициализации приложения я сначала создаю и запускаю график, запускающий 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 и pMediaControlis IMediaControl

Edit 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 ]

2 голосов
/ 24 января 2011

Для начала я бы предложил заменить _beginthreadex на CreateThread, а затем использовать GetLastError для определения причины любой ошибки, которая часто более конкретна, чем коды ошибок CRT устанавливается _beginthreadex. Сделав это, дайте мне знать, что вы наблюдаете, и я обновлю свой ответ.

Кроме того, можете ли вы опубликовать часть своего кода (DirectShow), которая приводит к сбою создания потока, а также строки кода, создающие поток?

Обновление: Что бы я ни нашел относительно конкретной ошибки, вы получаете подсказки о возможной утечке памяти. Обратите внимание, что только 420 МБ (как вы упомянули) могут быть зафиксированы , но больше страниц могло быть зарезервировано , и эти страницы все еще учитываются при ограничении виртуального пространства в 2 ГБ вашего приложения. Запуск графика DirectShow мог бы использовать все, что осталось от этого пространства.

Так что, скорее всего, DirectShow сам по себе не является причиной ошибки, а вместо этого обнаружил существующую ошибку в вашем приложении.

Вот некоторая дополнительная информация из MSDN, которая может иметь отношение к вам, особенно если вы ранее создали другие потоки в своей программе ( Размер стека потоков ):

Каждый новый поток получает свое собственное пространство стека, состоящее как из зарезервированной, так и изначально зафиксированной памяти. Зарезервированный объем памяти представляет собой общее выделение стека в виртуальной памяти. Таким образом, зарезервированный размер ограничен диапазоном виртуальных адресов. Первоначально зафиксированные страницы не используют физическую память, пока на них не ссылаются; ... Стек освобождается при выходе из потока. Он не освобождается, если поток завершается другим потоком.

0 голосов
/ 31 января 2011

Из вашего объяснения мне не совсем ясно, является ли это проблемой или нет, но с большинством связанных с DirectX инструментов (которые я предполагаю включает в себя DirectShow) вам необходимо убедиться, что все ваши связанные вызовы происходят в одном потоке; Другими словами, если вы настроили DirectShow в данном потоке, выполняйте все свои вызовы в нем, используя тот же поток. Прошло много времени с тех пор, как я использовал DirectShow, поэтому я не уверен на 100%, что это применимо, но это определенно решает многие проблемы с D3D, который тесно связан с этой технологией.

FWIW.

0 голосов
/ 25 января 2011

На веб-страницах 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

Надеюсь, это поможет вам.

...