Используйте Source Reader для получения образцов H264 из источника веб-камеры

При использовании Source Reader я могу использовать его для получить декодированные образцы YUV, используя источник файла mp4 (пример кода ).

Как я могу сделать обратное с источником веб-камеры? Использовать Source Reader для предоставления закодированных образцов H264? Моя веб-камера поддерживает форматы пикселей RGB24 и I420, и я могу получить образцы H264, если вручную подключим преобразование H264 MFT. Но похоже, что Source Reader должен быть в состоянии позаботиться о преобразовании для меня. Я получаю сообщение об ошибке всякий раз, когда пытаюсь установить MF_MT_SUBTYPE из MFVideoFormat_H264 в программе чтения исходного кода.

Пример фрагмента показан ниже, а полный пример находится здесь.

  // Get the first available webcam.
  CHECK_HR(MFCreateAttributes(&videoConfig, 1), "Error creating video configuration.");

  // Request video capture devices.
  CHECK_HR(videoConfig->SetGUID(
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
    MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID), "Error initialising video configuration object.");

  CHECK_HR(videoConfig->SetGUID(MF_MT_SUBTYPE, WMMEDIASUBTYPE_I420),
    "Failed to set video sub type to I420.");

  CHECK_HR(MFEnumDeviceSources(videoConfig, &videoDevices, &videoDeviceCount), "Error enumerating video devices.");

  CHECK_HR(videoDevices[WEBCAM_DEVICE_INDEX]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &webcamFriendlyName, &nameLength),
    "Error retrieving video device friendly name.\n");

  wprintf(L"First available webcam: %s\n", webcamFriendlyName);

  CHECK_HR(videoDevices[WEBCAM_DEVICE_INDEX]->ActivateObject(IID_PPV_ARGS(&pVideoSource)), 
    "Error activating video device.");

  CHECK_HR(MFCreateAttributes(&pAttributes, 1),
    "Failed to create attributes.");

  // Adding this attribute creates a video source reader that will handle
  // colour conversion and avoid the need to manually convert between RGB24 and RGB32 etc.
  CHECK_HR(pAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, 1),
    "Failed to set enable video processing attribute.");

  CHECK_HR(pAttributes->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), "Failed to set major video type.");

  // Create a source reader.
  CHECK_HR(MFCreateSourceReaderFromMediaSource(
    pVideoSource,
    pAttributes,
    &pVideoReader), "Error creating video source reader.");

  MFCreateMediaType(&pSrcOutMediaType);
  CHECK_HR(pSrcOutMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), "Failed to set major video type.");
  CHECK_HR(pSrcOutMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264), "Error setting video sub type.");
  CHECK_HR(pSrcOutMediaType->SetUINT32(MF_MT_AVG_BITRATE, 240000), "Error setting average bit rate.");
  CHECK_HR(pSrcOutMediaType->SetUINT32(MF_MT_INTERLACE_MODE, 2), "Error setting interlace mode.");

  CHECK_HR(pVideoReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, pSrcOutMediaType),
    "Failed to set media type on source reader.");

  CHECK_HR(pVideoReader->GetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pFirstOutputType),
    "Error retrieving current media type from first video stream.");

  std::cout << "Source reader output media type: " << GetMediaTypeDescription(pFirstOutputType) << std::endl << std::endl;

Выход:

bind returned success
First available webcam: Logitech QuickCam Pro 9000
Failed to set media type on source reader. Error: C00D5212.
finished.

person sipsorcery    schedule 23.01.2020    source источник


Ответы (2)


Source Reader здесь не выглядит подходящим API. Это API для реализации «половины конвейера», который включает в себя необходимое декодирование, но не кодирование. Другая половина — это API Sink Writer, способный для обработки кодирования и который может кодировать H.264.

Или другой вариант, если вы не разрабатываете проект UWP, — Media Session API, который реализует сквозной конвейер.

Несмотря на то, что технически (теоретически) у вас может быть MFT кодирования как часть конвейера Source Reader, сам API Source Reader недостаточно гибок, чтобы добавлять преобразования стилей кодирования на основе запрошенных типов мультимедиа.

Таким образом, одним из решений может быть использование Source Reader для чтения с необходимым декодированием (например, вплоть до наличия видеокадров RGB32 или NV12), а затем Sink Writer для управления кодированием с соответствующим медиаприемником на его конце (или Sample Grabber в качестве медиаприемника). . Другое решение состоит в том, чтобы поместить примитивы Media Foundation в конвейер Media Session, который может управлять частями декодирования и кодирования, соединенными вместе.

person Roman R.    schedule 23.01.2020
comment
А при сеансе мультимедиа обычно для доступа к IMFSample используется Sample Grabber? Насколько я понимаю, для Sink Writer нет эквивалента Source Reader? Для доступа к необработанным образцам требуется специальный Sink Writer? - person sipsorcery; 23.01.2020
comment
Source Reader должен читать откуда-то и иметь биты видео и/или аудио, доступные для кода. Sink Writer работает наоборот: у вас есть биты данных, и вы записываете, чтобы получить данные где-то еще с кодировкой, если это необходимо. Обычно таким результатом Sink Writer является файл или потоковый протокол, и если вы хотите восстановить доступ к произведенным данным, вы можете настроить Sink Writer с Sample Grabbers. - person Roman R.; 23.01.2020
comment
Как и в случае с DirectShow, лично я никогда не использую грабберы семплов, потому что пользовательские фильтры всегда являются более гибкой альтернативой. То же самое здесь, в Media Foundation, пользовательский приемник в целом более гибкий. Тем не менее, приемник Sample Grabber работает и является более простым способом использования выходных данных. - person Roman R.; 23.01.2020
comment
Понял, спасибо. @mofo77 немного смутил меня, предложив Source Reader в качестве замены Sample Grabber в этом ответе -guid" title="образец приемника захвата не устанавливает guid типа мультимедиа"> stackoverflow.com/questions/59839187/. Но теперь я понимаю, что это имеет смысл только для сценариев декодирования. - person sipsorcery; 23.01.2020

Теперь ваш вариант использования более ясен.

Для меня ваш MFWebCamRtp — лучший оптимизированный способ: WebCam Source Reader -> Encoding -> RTP Streaming.

Но у вас возникли проблемы с синхронизацией презентации, проблемы с синхронизацией или проблемы с несинхронизированным аудио-видео. Я прав ?

Итак, вы попробовали Sample Grabber Sink, а теперь и Source Reader, как я вам советовал. Конечно, вы можете подумать, что медиа-сессия сможет сделать это лучше. Я думаю да, но потребуется дополнительная работа.

Вот что я бы сделал в вашем случае:

  • Код пользовательского приемника RTP
  • Создайте топологию с источником веб-камеры, кодировщиком h264, вашим собственным приемником RTP.
  • Добавьте свою топологию в MediaSession
  • Используйте MediaSession для воспроизведения процесса

Если вам нужен пример приемника сетевого потока, см. это: MFSkJpegHttpStreamer.

Это старо, но это хорошее начало. Эта программа также использует winsock, как и ваша.

Вы должны знать, что протокол RTP использует UDP. Очень хороший способ решить проблемы с синхронизацией... Думаю, это определенно ваша главная проблема.

Что я думаю. Вы пытаетесь компенсировать недостатки протокола RTP (UDP) управлением аудио/видео синхронизацией MediaFoundation. Я думаю, что вы просто потерпите неудачу с этим подходом.

Я думаю, что ваша главная проблема - протокол RTP.

ИЗМЕНИТЬ

Нет, у меня нет проблем с синхронизацией. Source Reader и Sample Grabber предоставляют правильные временные метки, которые я могу использовать в заголовке RTP. Точно так же никаких проблем с RTP / UDP и т. Д. Это то, о чем я знаю. Мои вопросы исходят из желания понять наиболее эффективное (наименьшее количество кода сантехники) и гибкое решение. И да, это похоже на то, что пользовательский сток-писатель - оптимальное решение.

Снова все становится яснее. Если вам нужна помощь с пользовательским приемником RTP, я буду рядом.

person mofo77    schedule 23.01.2020
comment
Нет, у меня нет проблем с синхронизацией. Source Reader и Sample Grabber предоставляют правильные временные метки, которые я могу использовать в заголовке RTP. Точно так же никаких проблем с RTP / UDP и т. Д. Это то, о чем я знаю. Мои вопросы исходят из желания понять наиболее эффективное (наименьшее количество кода сантехники) и гибкое решение. И да, это похоже на то, что пользовательский сток-писатель - оптимальное решение. - person sipsorcery; 24.01.2020