Используйте Source Reader, чтобы получить образцы H264 из источника веб-камеры - PullRequest
1 голос
/ 23 января 2020

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

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

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

  // 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.

Ответы [ 2 ]

2 голосов
/ 23 января 2020

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

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

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

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

1 голос
/ 24 января 2020

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

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

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

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

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

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

Если вы хотите сетевой поток Пример слива, смотрите это: MFSkJpegHttpStreamer

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

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

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

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

РЕДАКТИРОВАТЬ

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

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

...