Поделиться через


Управление графом захвата

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

Интерфейс IMediaControl диспетчера фильтров графов содержит методы для запуска, остановки и приостановки всего графа. Однако если на графе фильтра есть потоки записи и предварительного просмотра, вам, вероятно, потребуется управлять двумя потоками независимо. Например, может потребоваться предварительно просмотреть видео, не записывая его. Это можно сделать с помощью метода ICaptureGraphBuilder2::ControlStream .

Примечание

Этот метод не работает при записи в файл расширенного системного формата (ASF).

 

Управление потоком записи

Следующий код задает поток видеозахвата для запуска в течение четырех секунд, начиная с одной секунды после выполнения графа:

// Control the video capture stream. 
REFERENCE_TIME rtStart = 10000000, rtStop = 50000000;
const WORD wStartCookie = 1, wStopCookie = 2;  // Arbitrary values.
hr = pBuild->ControlStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                 // Capture filter.
    &rtStart, &rtStop,     // Start and stop times.
    wStartCookie, wStopCookie  // Values for the start and stop events.
);
pControl->Run();

Первый параметр указывает поток для управления в виде GUID категории контактов. Второй параметр задает тип носителя. Третий параметр — это указатель на фильтр записи. Чтобы управлять всеми потоками захвата в графе, задайте для второго и третьего параметров значение NULL.

Следующие два параметра определяют время запуска и остановки потока относительно времени начала работы графа. Вызовите IMediaControl::Run , чтобы запустить граф. Пока вы не запустите граф, метод ControlStream не будет действовать. Если граф уже запущен, параметры вступают в силу немедленно.

Последние два параметра используются для получения уведомлений о событиях при запуске и остановке потока. Для каждого потока, которым вы управляете с помощью этого метода, граф фильтра отправляет пару событий: EC_STREAM_CONTROL_STARTED при запуске потока и EC_STREAM_CONTROL_STOPPED при остановке потока. Значения wStartCookie и wStopCookie используются в качестве второго параметра события. Таким образом, lParam2 в событии start равно wStartCookie, а lParam2 в событии stop равно wStopCookie. В следующем коде показано, как получить эти события:

while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
{
    switch (evCode)
    {
    case EC_STREAM_CONTROL_STARTED: 
    // param2 == wStartCookie
    break;

    case EC_STREAM_CONTROL_STOPPED: 
    // param2 == wStopCookie
    break;
    
    } 
    pEvent->FreeEventParams(evCode, param1, param2);
}

Метод ControlStream определяет некоторые специальные значения для времени начала и остановки.

Значение Запуск Stop
MAXLONGLONG Никогда не запускайте этот поток. Не останавливайтесь, пока не остановится граф.
NULL Запуск сразу при запуске графа. Немедленно остановите.

 

Например, следующий код немедленно останавливает поток записи:

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
    0, 0,     // Start and stop times.
    wStartCookie, wStopCookie); 

Хотя вы можете остановить поток записи и перезапустить его позже, это создаст пробел в метках времени. При воспроизведении видео будет отображаться как застойное во время разрыва (в зависимости от формата файла).

Управление потоком предварительного просмотра

Чтобы управлять контактом предварительного просмотра, вызовите ControlStream , но присвойте первому параметру значение PIN_CATEGORY_PREVIEW. Это работает так же, как и для PIN_CATEGORY_CAPTURE, за исключением того, что нельзя использовать время ссылки для указания начала и остановки, так как кадры предварительного просмотра не имеют меток времени. Поэтому необходимо использовать NULL или MAXLONGLONG. Используйте значение NULL для запуска потока предварительного просмотра:

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    NULL,    // Start now.
    0,       // (Don't care.)
    wStartCookie, wStopCookie); 

Используйте MAXLONGLONG, чтобы остановить поток предварительного просмотра:

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    0,               // (Don't care.)
    MAXLONGLONG,     // Stop now.
    wStartCookie, wStopCookie); 

Не имеет значения, поступает ли поток предварительного просмотра из предварительного просмотра на фильтре захвата или из фильтра Smart Tee. Метод ControlStream работает в любом случае.

Однако для контактов видеопорта метод завершится ошибкой. В этом случае другой подход заключается в скрытии окна видео. Запросите граф для IVideoWindow и используйте метод IVideoWindow::p ut_Visible , чтобы отобразить или скрыть окно.

// Hide the video window.
IVideoWindow *pVidWin = 0;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
if (SUCCEEDED(hr))
{
    pVidWin->put_Visible(OAFALSE);
    pVidWin->Release();
}

Кроме того, при вызове метода IVideoWindow::p ut_AutoShow со значением OAFALSE перед запуском графа фильтр "Отрисовщик видео" скрывает окно, пока не указано иное. По умолчанию отрисовщик видео отображает окно при запуске графа.

Примечания об управлении потоком

Поведением по умолчанию для закрепления является доставка примеров при выполнении графа. Например, предположим, что вы вызываете ControlStream с PIN_CATEGORY_CAPTURE но не с помощью PIN_CATEGORY_PREVIEW. При запуске графа поток предварительного просмотра запустится немедленно, а поток записи — в любое время, указанное в ControlStream.

Если вы захватываете несколько потоков и отправляете их в фильтр мультиплексирования ( например, при записи звука и видео в AVI-файл), вы должны управлять обоими потоками в тандеме. В противном случае фильтр мультиплекса может блокировать ожидание одного потока, так как он пытается перемежать два потока. Задайте одинаковое время запуска и остановки для всех потоков записи перед запуском графа:

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, 
    
NULL, NULL,       // All capture streams.
    &rtStart, rtStop, 
    wStartCookie, wStopCookie); 

На внутреннем уровне метод ControlStream использует интерфейс IAMStreamControl , который предоставляется на контактах фильтра захвата, фильтр Smart Tee (если он есть) и, возможно, фильтр мультиплексирования. Этот интерфейс можно использовать напрямую, а не вызывать ControlStream, хотя в этом нет особых преимуществ.

Захват видео