Код avformat выводит немного другой вывод, чем ffmpeg с теми же параметрами - почему? - PullRequest
0 голосов
/ 14 февраля 2020

Я хотел бы получить точно такой же результат, как этот вызов командной строки ffmpeg из кода:

ffmpeg -i CAMERARTSPLINK -c:v copy -an -movflags +frag_keyframe+empty_moov -f mp4

Когда я запускаю указанную выше команду, она дает такой двоичный результат:

got 36 bytes:  0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49, 
got 512 bytes: 0, 0, 3, 76, 109, 111, 111, 118, 0, 0, 0, ..., 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 202,

Код может использовать библиотеки ffmpeg и включает в себя, но я не хочу использовать ffmpeg в качестве вызова программы (т.е. функции exe c* не предпочтительны).

Я создал небольшой демонстрационный код пример с avformat для RTSP H264 до MP4 remux. В коде многократно используется библиотека videostreamer , созданная Хоргом.

Я отправил образец кода на pastebin.com (400 lo c). Он успешно строится, но вам нужно связать его с avformat, avdevice, avcodec и avutil.

Я пытался сделать все возможное, чтобы достичь того же результата, однако при запуске этого кода первые несколько байтов после байта № 38 отличаются (может быть, не только те, что я не сравнивал ничего после байта № 548):

writeOutput: writing 36 bytes: 0, 0, 0, 36, 102, 116, 121, 112, ..., 111, 54, 109, 112, 52, 49, 
writeOutput: writing 512 bytes: 0, 0, 0, 0, 109, 111, 111, 118, 0, 0, 0, ..., 132, 0, 0, 3, 0, 4, 0, 0, 3, 0, 202, 

Вы можете видеть, что во второй строке вывод моего кода начинается с 0 0 0 0 109,

, тогда как ffmpeg дал 0 0 3 76 109.

Все остальные данные (даже здесь не вставлены байты) полностью совпадают (по крайней мере, для первых 548 байтов).

Что не так с моим кодом? Эти 2 байта кажутся очень важными для декодирования этого потока.

Ответы [ 2 ]

1 голос
/ 15 февраля 2020

102, 116, 121, 112 в ascii - ftyp Это поле типа формата mp4. 0, 0, 0, 36 это размер поля

109, 111, 111, 118 в ascii равно mdat Это поле данных. 0, 0, 0, 0 - это размер коробки.

В этом случае размер поля mdat неизвестен, потому что мы пока не знаем размер всех видео и аудио кадров. Таким образом, заполнитель ноль используется. Когда файл закончен, значение размера должно быть перезаписано с правильным размером

0 голосов
/ 20 февраля 2020

Это была глупая ошибка, связанная с ограниченными возможностями ведения журнала ffmpeg, плюс мои ограниченные знания в области видеокодеков.

Проблема заключалась в том, что ffmpeg (с входом h264) при записи атома в выходной буфер:

  • сначала устанавливает 0 для размера атома ( moven c .c # L3981 )
  • , затем заполняет оставшуюся часть буфера
  • , затем на конец, он ищет обратно размер атома в буфере и обновляет размер ( moven c .c # L4049 )

Это все хорошо, но во время заполнения остальной части буфер, он использует avio_w8 и avio_w8 будет flu sh буфер , если он достигнет его конца.

Если вы используете пользовательский ввод-вывод с avio_alloc_context И вы не определяете буфер, который является достаточно большим, И вы также не определяете операцию поиска, И записываемый атом больше, чем размер вашего буфера, он будет очищен, и ffmpeg не сможет выполнить поиск обратно. обновить размер атома.

И это, вероятно, приведет к поврежденному (и не воспроизводимому) выходному файлу или потоку видео.

Таким образом, решение состояло в том, чтобы увеличить размер буфера с 512 до 4096, в этом случае атом moov может быть подходит даже без операции поиска.

Это довольно просто, если вы знаете, что длина атома moov превышает 512 байт, и посмотрите мой пример кода.

...