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


Запись видео в 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 Mux в третьем параметре. При необходимости он возвращает указатель на интерфейс IFileSinkFilter в четвертом параметре. Если этот интерфейс не нужен, этот параметр можно задать для null, как показано в предыдущем примере.

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

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. Если вы записываете звук и видео с двух отдельных устройств, рекомендуется сделать аудиопоток главным. Это помогает предотвратить смещение между двумя потоками, так как фильтр AVI Mux настраивает частоту воспроизведения в видеопотоке, чтобы соответствовать звуковому потоку. Чтобы задать главный поток, вызовите метод 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::put_Mode.

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

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

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

Видеопоток можно закодировать, вставив фильтр кодировщика между фильтром записи и фильтром 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 или другие интерфейсы для настройки параметров кодирования. Список возможных интерфейсов см. в разделе Кодировка файлов и декодирование интерфейсов.

Захват видео в файл