FFmpeg размещен в вопрос обычно передается в другой двоичный файл. Этот двоичный файл сохраняет фреймы, предоставленные ffmpeg, и выполняет некоторую обработку на них.
В начале я не использовал "fifo_size = 1000000 & overrun_nonfatal = 1" варианты, и я получаю следующее сообщение об ошибке от FFmpeg
[udp @ 0x4ceb8a0] Circular buffer overrun. To avoid, increase fifo_size URL option. To survive in such case, use overrun_nonfatal option
udp://192.168.15.50:3200: Input/output error
, а затем FFmpeg обрушится. Чтобы избежать этого, я добавил «fifo_size = 1000000 & overrun_nonfatal = 1», как предлагает ffmpeg.
Однако после использования этих параметров я получил бы временный сдвиг, как описано в вопросе, а иногда он также будет иметь артефакты в кадрах.
Как уже упоминалось, проблем с процессором не возникало. поэтому изначально, мы подозревали, что УДП поток, в частности, UdP размер буфера:
https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf-udpbuffer.html
поэтому мы изменили UdP размер буфера с:
sysctl -w net.core.rmem_max=26214400
и изменил команду FFmpeg к «УДП: //231.20 .20.8: 2005? Buffer_size = 26214400 "
Однако, это не исправить проблему. ffmpeg все равно получит «Круговое переполнение буфера» и сбой. И я не смог воспроизвести этот круговой буфер переполнения, это просто случалось случайным образом.
Моя следующая мысль была размер буфера трубы, так как я нашел следующее:
http://blog.dataart.com/linux-pipes-tips-tricks/ Размер буфера, так как ядра версии 2.6.11 является 65536 байт (64K) и равна памяти страницы в старых ядрах. При попытке чтения из пустого буфера процесс чтения блокируется до появления данных. Аналогично, если вы попытаетесь записать в полный буфер, процесс записи будет заблокирован до тех пор, пока не будет доступно необходимое пространство. http://ffmpeg.gusari.org/viewtopic.php?f=12&t=624 Poster1: Что вызывает эти круговые буферные переполнения? Мое предположение заключается в том, что ffmpeg считывает входной поток в вышеупомянутый круговой буфер, а затем генерирует выходной поток, который также считывается из того же самого буфера. Переполнение произойдет, когда код, генерирующий вывод, не будет соответствовать скорости, с которой он записывается в буфер, верно? Poster2: Глядя на исходный код, кажется, что буфер переполняется либо слишком быстрым вводом, либо слишком медленным выходом (медленный cpu?). Ваше предположение верно.
Итак, теория заключалась в том, что наш бинарный файл не читает трубу достаточно быстро. В результате труба блокируется, и ffmpeg не может ее записать, и THAT приводит к переполнению буфера udp fifo (ffmpeg продолжает чтение udp INTO FIFO, но не может записать ОТ его в нашу трубу)
Мне удалось доказать эту теорию (в отдельных клеммах):
mkfifo mypipe
ffmpeg -loglevel debug -i "udp://192.168.15.50:3200?fifo_size=1000000&overrun_nonfatal=1" -r 8 -preset ultrafast -fflags nobuffer -vf scale=432:243 -f image2pipe -vcodec ppm pipe:1 > mypipe
cat <mypipe> /dev/null # run this for 10 seconds, allowing ffmpeg to start. then pause it with CTRL-Z and see ffmpeg crashing because it cannot read more udp stream
поэтому следующее было расследование, почему наш двоичный диск в какой-то момент перестает читать трубку. казалось, не было никакой причины, потому что обычно он просто считывался в память сразу же после того, как что-то придет в трубку.
Однако он также сохранил кадры на жесткий диск. и в НЕКОТОРЫХ ПУНКТАХ (иногда 12 минут, иногда 15 часов), операции с дисками замедлялись из-за операций чтения/записи (это был bcache (SSD и HDD hybrid, используя SSD в качестве кеша). Я случайно поймал этот факт, когда я удалял несколько миллионов файлов с этого диска paralelly к отладке.
так записи файлов на занятом жесткий диск будет временно заблокировать наш двоичный от чтения входной трубы.
так причина UdP кольцевого буфера накатом выпуска и в конечном итоге TimeShift был HDD и теоретическое решение - это SSD.
Это исследование заняло около 3 недель, поэтому все это в надежде, что оно, по крайней мере частично, поможет кому-то в будущем.
обновления к этому:
я также обнаружил другие узкое место, вызывающие этот же вопрос позже (замена HDD не было достаточно), который было TCP переполнения буфера сокета, вызванное POSTGRES вставок на внутреннем интерфейсе.
весь трубопровод выглядит следующим образом:
udp_videostream-> ffmpeg-> linux_pipe-> our_client_side_binary-> TCP-> our_server_side_binary-> Postgres
Postgres запросы были иногда медленно, который причинял наш сервер для прочитайте TCP-сокет медленнее, чем наш_бинал нажимал на него. в результате tcp-сокет будет заблокирован (максимум 4 Мб), и в результате клиент заблокирует его входной канал, и в результате этого ffmpeg будет сбой с этой ошибкой CBO.