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


Запись видео в файл AVI

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

На следующем рисунке показан самый простой график для записи видео в файл AVI.

Граф захвата видео avi

Фильтр AVI Mux принимает видеопоток из контакта захвата и упаковывает его в поток AVI. Аудиопоток также может быть подключен к фильтру AVI Mux, в этом случае мультиплекс будет чередовать два потока. Фильтр "Модуль записи файлов" записывает поток AVI на диск.

Чтобы создать граф, начните с вызова метода ICaptureGraphBuilder2::SetOutputFileName следующим образом:

IBaseFilter *pMux;
hr = pBuild->SetOutputFileName(
    &MEDIASUBTYPE_Avi,  // Specifies AVI for the target file.
    L"C:\\Example.avi", // File name.
    &pMux,              // Receives a pointer to the mux.
    NULL);              // (Optional) Receives a pointer to the file sink.

Первый параметр указывает тип файла — в данном случае — AVI. Второй параметр задает имя файла. Для AVI метод SetOutputFileName создает фильтр AVI Mux и фильтр модуля записи файлов и добавляет их в граф. Он также задает имя файла в фильтре записи файлов путем вызова метода IFileSinkFilter::SetFileName и соединяет два фильтра. Метод возвращает указатель на мультиплекс AVI в третьем параметре. При необходимости он возвращает указатель на интерфейс IFileSinkFilter в четвертом параметре. Если этот интерфейс не нужен, можно задать для этого параметра значение NULL, как показано в предыдущем примере.

Затем вызовите метод ICaptureGraphBuilder2::RenderStream , чтобы подключить фильтр захвата к мультиплексии AVI, как показано ниже.

hr = pBuild->RenderStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                  // Capture filter.
    NULL,                  // Intermediate filter (optional).
    pMux);                 // Mux or file sink filter.

// Release the mux filter.
pMux->Release();

Первый параметр предоставляет категорию контактов, которая PIN_CATEGORY_CAPTURE для записи. Второй параметр задает тип носителя. Третий параметр является указателем на интерфейс IBaseFilter фильтра отслеживания . Четвертый параметр является необязательным; он позволяет направлять видеопоток через промежуточный фильтр, например кодировщик, перед его передачей в фильтр мультиплекса. В противном случае задайте для этого параметра значение NULL, как показано в предыдущем примере. Пятый параметр — это указатель на фильтр мультиплекса. Этот указатель получается путем вызова метода SetOutputFileName.

Чтобы записать звук, вызовите RenderStream с типом мультимедиа MEDIATYPE_Audio. Если вы собираете звук и видео с двух отдельных устройств, рекомендуется сделать аудиопоток master потоком. Это помогает предотвратить смещение между двумя потоками, так как фильтр AVI Mux настраивает скорость воспроизведения в видеопотоке в соответствии с аудиопотоком. Чтобы задать поток master, вызовите метод IConfigAviMux::SetMasterStream в фильтре AVI Mux:

IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
    pConfigMux->SetMasterStream(1);
    pConfigMux->Release();
}

Параметр SetMasterStream — это номер потока, который определяется порядком вызова RenderStream. Например, если сначала вызвать RenderStream для видео, а затем для звука, видео будет потоком 0, а звук — потоком 1.

Вы также можете задать способ чередовки аудио- и видеопотоков с помощью фильтра AVI Mux, вызвав метод IConfigInterleaving::p ut_Mode .

IConfigInterleaving *pInterleave = NULL;
hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
if (SUCCEEDED(hr))
{
    pInterleave->put_Mode(INTERLEAVE_CAPTURE);
    pInterleave->Release();
}

С флагом INTERLEAVE_CAPTURE мультиплекс AVI выполняет чередование со скоростью, подходящей для захвата видео. Вы также можете использовать INTERLEAVE_NONE, что означает отсутствие чередование— мультиплекс AVI будет просто записывать данные в том порядке, в котором они поступают. Флаг INTERLEAVE_FULL означает, что мультиплекс AVI выполняет полное чередование; однако этот режим менее подходит для захвата видео, так как для него требуется больше всего подслушано.

Кодирование видеопотока

Вы можете закодировать видеопоток, вставив фильтр кодировщика между фильтром захвата и фильтром AVI Mux. Используйте перечислитель системных устройств или сопоставитель фильтров , чтобы выбрать фильтр кодировщика. (Дополнительные сведения см. в разделе Перечисление устройств и фильтров.)

Укажите фильтр кодировщика в качестве четвертого параметра для RenderStream, как показано полужирным шрифтом в следующем примере:

IBaseFilter *pEncoder;
/* Create the encoder filter (not shown). */
// Add it to the filter graph.
pGraph->AddFilter(pEncoder, L"Encoder");

/* Call SetOutputFileName as shown previously. */

// Render the stream.
hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, 
    pCap, 
pEncoder, pMux);
pEncoder->Release();

Фильтр кодировщика может поддерживать IAMVideoCompression или другие интерфейсы для настройки параметров кодирования. Список возможных интерфейсов см. в разделе Интерфейсы кодирования и декодирования файлов.

Запись видео в файл