Windows Основа носителя: IMFSinkWriter WriteSample API, возвращающий ошибку sampleduration не установлен - PullRequest
0 голосов
/ 30 января 2020

У меня есть требование получать поток RTP (H264) и экспортировать их в файл MP4. Мы используем медиа-фундамент для экспорта кадров, полученных в RTP-потоке, в файл mp4. Таким образом, мы извлекаем кадры H264 (из пакетов RTP) и предоставляем их приемнику через API WriteSample (время выборки, длительность выборки и т. Д. c установлены). Кажется, это работает, и я получаю играбельный mp4. Но когда я не устанавливаю продолжительность выборки (используя API SetSampleDuration), writeSample выдает ошибку (MF_E_NO_SAMPLE_DURATION). Ошибка генерируется не для первых нескольких кадров, а только через определенное время (кадр через 1,48 секунды). Вопросы: 1. Зачем нужна SetSampleDuration? Я предположил, что нам не нужна длительность выборки, если мы предоставляем время выборки для каждой выборки. Sink Writer может рассчитать разницу между текущим и последним кадрами как длительность выборки 2. Почему ошибка не генерируется для первых нескольких кадров с помощью API writeSample .WriteSample выдает ошибку только через определенное время (кадр через 1,48 секунды). Это указывается c для определенных кадров. 3. Как это сделать: в идеале установить длительность выборки, если длительность между кадрами не одинакова. В моем случае средний fps равен 15, но время между 2 кадрами не одинаково. (Временная метка кадров в мс: 0, 83, 133, 200, 283 333 400, ...) 3.1. Чтобы установить длительность выборки кадра, дождитесь следующего кадра и вычтите временную метку текущего кадра из временной метки следующего кадра. Если приложение задерживается до следующего кадра. 3.2 Настройка длительности выборки на основе среднего числа кадров в секунду - это хорошо (даже если разница во времени между кадрами неодинакова). (Примечание: я пробовал 3.2, и это работает. Я не вижу визуальной проблемы. Это может быть потому, что разница во времени между кадрами не одинакова, но не сильно меняется. Но я не уверен, что это нормально. Должен ли я go для подхода 3.1)

Ответы [ 3 ]

0 голосов
/ 30 января 2020
  1. Зачем нужна SetSampleDuration? Я предположил, что нам не нужна длительность выборки, если мы предоставляем время выборки для каждой выборки. Средство записи приемника может рассчитать разницу между текущим и последним кадрами как длительность выборки

  2. Почему ошибка не генерируется для первых нескольких кадров с помощью API writeSample .WriteSample выдает ошибку только через определенное время (кадр через 1,48 секунды). Указывает ли он c на определенные кадры.

Сэмплы могут не иметь длительности, верно Но медиа-сток, который вы используете, ожидает, что длительности присутствуют, поэтому вы должны иметь их там. Или вы не можете использовать приемник, потому что он был бы несовместим.

Ваш ввод ставится в очередь и обрабатывается асинхронно. Это объясняет, почему у вас нет ошибки сразу.

... Но в потоке временные метки RTP равны 0, 7470, 11970, 18000, .... Интервал не одинаков, но в целом мы получаем 15 кадров в секунду. Как установить длительность в этом сценарии: 1. Установите значение 660000 для всей выборки или 2. Для длительности набора первой выборки - (83-0) * 10000, а для длительности набора второй выборки - (133-83) * 10000

Вопрос легкий и сложный одновременно. Формат MP4 имеет свои предположения и ожидания, когда приемник создает выходной файл, трек в нем, со своими собственными значениями шкалы времени. Несмотря на то, что он технически может следовать вашим эффективным временным параметрам и сохранять там значения 90 кГц, он сделан в предположении, что видеопоток имеет фиксированную частоту кадров. Раковина принимает ваше значение атрибута MF_MT_FRAME_RATE и извлекает из него время. Кроме того, поведение даже может стать более жестким или более смягченным с Windows обновлениями, потому что указанное c поведение не задокументировано, не обещано.

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

0 голосов
/ 31 января 2020

Если кодер, сетевой поток или захват дают вам время / продолжительность, используйте их, соблюдайте их.

Это будет лучший способ сохранить аудио / видео презентацию.

Я не могу уточнить здесь, но вы не можете сказать это:

Модуль записи приемника может рассчитать разницу между текущим и последним кадром

Это сложнее, чем это.

0 голосов
/ 30 января 2020

У вас есть несколько разных вопросов.

Для установки меток времени и продолжительности я бы рекомендовал проверить документацию . Он объясняет, как временная метка связана с временем представления и т. Д. c.

. Для установки длительности следует использовать частоту дискретизации исходного потока. Если выборка выполняется с нормальной частотой 90 кГц для H264, то при частоте 15 кадров в секунду каждая длительность составляет 66 мс. Образцы Media Foundation используют разрешение метки времени 100 нано секунд , поэтому длительность IMFSample должна составлять 660000. Ваши метки времени заголовка RTP также должны иметь интервал 6000 при 15ps (6000 x 15 = 90000).

Для отметки времени, поскольку вы сохраняете ее в файл, вы должны начинать с 0, и каждый раз, когда вы получаете приращение выборки на длительность выборки 660000.

...