LINUX.ORG.RU

ffmpeg: ускоренное видео с IP камеры и другие весёлости

 , ,


0

1

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

Ссылка на код.

По задумке, код должен делать примерно следующее (если вдруг кто-то будет пробовать запустить):

  • Кодировать входной видеофайл в видеофайл h264 (%programname% -i %вход% -o %выход.mp4%);
  • Кодировать видео с USB-вебкамеры в видеофайл h264 (%programname% -i /dev/video0 -o %выход.mp4% -w);
  • Кодировать видео с IP-камеры в видеофайл h264 (%programname% -i %неважно% -o %выход.mp4% -n).

И вроде все почти работает, кроме последнего.

Столкнулся со следующими проблемами:

  • Маленькая проблема: по дефолту ffmpeg работает с камерой по UDP. И непрерывно сыпет ошибками такого рода при обработке фреймов:
    [rtsp @ 0x2ba1080] max delay reached. need to consume packet
    [rtsp @ 0x2ba1080] RTP: missed 1324 packets                                                                                                                   
    [h264 @ 0x2ba4020] error while decoding MB 29 34, bytestream -13
    [h264 @ 0x2ba4020] concealing 4100 DC, 4100 AC, 4100 MV errors in I frame
    
    [libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS
    frame #48 encoded
    [h264 @ 0x2d30ac0] pts (21599) < dts (35999) in stream 0
    .frame #49 decoded
    [libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS
    frame #49 encoded
    [h264 @ 0x2d30ac0] pts (10799) < dts (17999) in stream 0
    .frame #50 decoded
    [libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS
    frame #50 encoded
    [h264 @ 0x2d30ac0] pts (7199) < dts (21599) in stream 0
    .[rtsp @ 0x2ba1080] max delay reached. need to consume packet
    [rtsp @ 0x2ba1080] RTP: missed 19 packets
    

    Нашел вариант переключения в режим tcp. Только вот tcp сильно тяжелее, чем udp в плане нагрузки на сеть, поэтому хотелось бы побороть ошибки при использовании udp. Что можно подкрутить для этого?

  • Большая проблема: видео с IP-камеры какое-то ускоренное, раза в 2-3 по субъективным ощущениям. Я сперва грешил на настройки кодирования, но сделал параллельно сброс разжатого видео в файл, так там оно тоже ускоренное. Напрашивается вывод про корявые настройки декодирования, но опять же, непонятно, что крутить? С USB-вебки скорость воспроизведения итогового файла нормальная, если попробовать перекодировать кусок mp4-файла, там тоже со скоростью проблем нет.

    Настройки на камере, разрешение fullHD, частота кадров 25/сек, видео отдает по ссылке вида rtsp://%url%.

  • Полученные mp4-файлы не воспроизводятся штатными средствами ОС, только через ffplay. Еще ffprobe не может определить битрейт и длительность получаемых файлов. И в них не работает перемотка.

Если у кого есть информация, как работать с ffmpeg в качестве библиотек, буду признателен за ссылки.

Описаний функций на сайте разработчика, примеров в исходниках, к сожалению, мне не хватает, чтобы разобраться, как пользоваться библиотеками ffmpeg.


Вызывайте ffmpeg через шелл и не парьте себе мозг багами в обработке мелочей типа таймштампов. ffmpeg всё сделает. В формулировке задачи нет ничего такого, что мешало бы так делать.

Только вот tcp сильно тяжелее, чем udp в плане нагрузки на сеть

Пруфы есть?

Что можно подкрутить для этого?

Можете пробросить параметр fifo_size для UDP-шного контекста через контекст RTSP. Если вы в одном и том же потоке (thread) и вычитываете, и енкодите (хотя вряд ли вы енкодите поток от IP-камер), то может помочь. Хотя правильнее разнести это в разные потоки.

примеров в исходниках, к сожалению, мне не хватает

doc/examples/transcoding.c - пример полного цикла транскодирования, должно хватать, за исключением каких-нибудь особых случаев. Есть пример и для ремультиплексирования без транскодирования.

Andrey_Utkin ★★ ()
Ответ на: комментарий от asaw

Как еще можно обозначить в тегах, что речь идет об использовании библиотек ffmpeg, а не самой приложухи? Мне с ходу только такое в голову пришло.

s3rjke ()

Язабан.

%programname%

WRG ★★★★ ()
Ответ на: комментарий от Andrey_Utkin

Пруфы есть?

Самолично тестирование не проводил. Но когда изучал всякие материалы на предмет сетевого программирования, создалось впечатление, что tcp генерит заметно больше трафика благодаря своим механизмам гарантированной доставки, чем udp. Хотя в рамках локальной сети, наверное, не стоит это учитывать.

Можете пробросить параметр fifo_size для UDP-шного контекста через контекст RTSP. Если вы в одном и том же потоке (thread) и вычитываете, и енкодите (хотя вряд ли вы енкодите поток от IP-камер), то может помочь. Хотя правильнее разнести это в разные потоки.

Спасибо, поэксперементирую (уже, видимо, завтра). На самом деле, меня напрягает больше то, что я не понимаю, что не так. Т.е. я смотрю в код и вроде как, явных косяков в логике нету. А какие-то непонятные ошибки валятся. Это вгоняет в прострацию.

doc/examples/transcoding.c - пример полного цикла транскодирования, должно хватать, за исключением каких-нибудь особых случаев. Есть пример и для ремультиплексирования без транскодирования.

Если не трудно, можете пояснить, зачем там используются некие «фильтры» (функции init_filter, init_filters)? Мне хоть и удалось этот пример скомпилировать, но у меня он падает с сегфолтом, увы.

s3rjke ()
Ответ на: комментарий от s3rjke

А какие-то непонятные ошибки валятся. Это вгоняет в прострацию.

Deal with it. Обработка мультимедиа это целая предметная область, нужно разбираться.

зачем там используются некие «фильтры» (функции init_filter, init_filters)?

Отчасти в чисто демонстрационных целях (часто именно такой цикл обработки нужен). Отчасти это избавляет от потребности в частных случаях заниматься в коде такими неабстрактными вещами, как конвертирование pixel format и т. п. Механизм фильтров сам автоматически неявно вставит фильтры для этого, если нужно.

Andrey_Utkin ★★ ()

[h264 @ 0x2d30ac0] pts (21599) < dts (35999) in stream 0

h264 decoder сигнализирует что у прилетевшего говнеца pts dts в разжопицу

[libx264 @ 0x2dc12c0] invalid DTS: PTS is less than DTS

теперь этот кадр попадает в libx264 encoder и уже энкодер жалуется.

Если pts/dts в разжопицу никакого нормального видео не получится, ни раскодировать, ни закодировать. Читайте за pts/dts в популярной литературе, ничего если начнете даже в английской википедии.

ffplay показывает камеру без ошибок?

ffmpeg работает в качестве библиотеки ровно также как утилиты ffmpeg/ffplay.

hizel ★★★★★ ()
Ответ на: комментарий от hizel

h264 decoder сигнализирует что у прилетевшего говнеца pts dts в разжопицу
Если pts/dts в разжопицу никакого нормального видео не получится, ни раскодировать, ни закодировать. Читайте за pts/dts в популярной литературе, ничего если начнете даже в английской википедии.

Я вроде бы осилил понять, что pts это что-то вроде порядкового номера пакета/фрейма, согласно которому его нужно показать на экране. Зачем нужно dts не очень понятно. Служебная информация, когда какой фрейм был декодирован?

ffplay показывает камеру без ошибок?

Ругается на deprecated pixel format, а так показывает нормально. По поводу нескольких строк ошибок в моем первом посте — эти ошибки валятся при использовании udp в качестве транспортного протокола. Сейчас я выставил tcp и больше пары ошибок за все 500 фреймов не проскакивает.

Но видео получается сильно ускоренным. time_base, что у контекста енкодера, что у исходящего потока, прописаны {1, 25}, т.е. типа 25 кадров/сек. На самой камере тоже выставленно 25 кадров/сек для потока h264. Я вижу два возможных источника проблемы, либо у меня корявые настройки декодера/енкодера, либо неправильно присваиваются pts/dts для исходящих фремов/пакетов.

Хотя если брать видео не с камеры, а просто перекодировать кусок mp4-файла, там видео получается с нормально скоростью.

ffmpeg работает в качестве библиотеки ровно также как утилиты ffmpeg/ffplay.

Это понятно, только доступного для моего уровня руководства мне найти не удалось. В интернетах довольно много кусочков кода, но большинство из них в стиле «как открыть и декодировать файл». А вот как обработать/перекодировать видео, да еще с пояснениями, что делается и почему делается именно это, пока не встречал.

s3rjke ()
Ответ на: комментарий от Andrey_Utkin

Попробую тогда разобраться с этими самыми фильтрами из примера. Возможно, они меня спасут.

Спасибо.

s3rjke ()
Ответ на: комментарий от Andrey_Utkin

Проморгал эту строчку:

Вызывайте ffmpeg через шелл и не парьте себе мозг багами в обработке мелочей типа таймштампов. ffmpeg всё сделает. В формулировке задачи нет ничего такого, что мешало бы так делать.

Конечная задача на самом деле что-то вроде «получить кусок видео в h264-формате (например с некоего видеосервера) и позволить юзеру выбрать из него нужный кадр». Вот, пробую соотв. разобраться, можно ли прикрутить к некоей другой программе немного функционала ffmpeg.

s3rjke ()
Ответ на: комментарий от hizel

Я дважды пробегался по этому материалу еще с неделю назад. :-)

И даже применил рекомендации по использованию av_resqale_q() для настроки pts/dts исходящих пакетов. Вроде это даже решило какую-то ошибку типа non-strictly monotonic pts.

Кстати, после пары исправлений, заработал пример transcoding из исходников. Который с фильтрами.

И видео, которое получается в итоге, нормально воспроизводится и перематывается. В отличие от того, что получаю я в своем, кхм, коде (воспроизведение только через ffplay). Так что буду разбираться с фильтрами и проверять, как оно справится с IP-камерой.

s3rjke ()

На лицо проблемы с сетевой частью и целостностью потока, я бы начал с этого:

1. Найти что-то, что может корректно открывать этот поток (браузер, виндовый проприетарный плеер от производителя, телевизор с волшебной китайской прошивкой). Очевидно, что если поток с камеры корректно нигде не играется, то с ним обычными средствами ничего не сделать. Или сделать, но это будет уже не «перекодирование», а «реконструирование» потока.

2. В это время, пока идет корректное отображение, поснифать трафик, разобрать по байтикам. Быть может надо будет написать какой-то простенький код для анализа пакетов

3. Попробовать выставлять PTS/DTS согласно локальным часам, выбрасывая некорректные метки, быть может что реальный FPS там плавает и на самом деле там 10-15 вместо 25, а отсюда и ускорение. Корректная расстановка таймштампов должна решить проблему.

Могу предложить свои услуги на платной основе, оплата через upwork с защитой сделки

ruzisufaka ()
Ответ на: комментарий от BruteForce

А какой он? Сишный?

Я просто немного не в курсе методологии определения принадлежности кода языку.

s3rjke ()
Ответ на: комментарий от ruzisufaka

1. Найти что-то, что может корректно открывать этот поток (браузер, виндовый проприетарный плеер от производителя, телевизор с волшебной китайской прошивкой). Очевидно, что если поток с камеры корректно нигде не играется, то с ним обычными средствами ничего не сделать. Или сделать, но это будет уже не «перекодирование», а «реконструирование» потока.

Через ffplay камера нормально проигрывается. К тому же, если сделать просто микширование (не уверен, что правильно употребляю это слово) потока камеры в файл, а потом уже заниматься перекодированием получившегося файла, то тут все нормально.

Может оно как-то связано с задержкой, которая происходит во время перекодирования фрейма. В программе-микшере и транскодере, по сути, отличается только логика обработки пакета (AVPacket). Ну и типа транскодер «долго» обрабатывает пакет и поэтому когда он читает следующий, он на самом деле не совсем следующий за обработанным, а через один или два уже. Хотя это все домыслы и гадание на кофейной гуще.

В общем-то, именно задачи транскодирования изначально и не стояло, скорее я взялся это пробовать, чтобы немного пощупать ffmpeg. Для итоговой задачи, скорее всего, хватит и простого декодирования.

Могу предложить свои услуги на платной основе, оплата через upwork с защитой сделки

Как же я тогда чему-то научусь, если за меня все будут делать? :-)

s3rjke ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.