Как предотвратить взаимоблокировку при использовании именованных каналов?

#python #streaming #named-pipes #blocking #popen

#питон #потоковое вещание #именованные каналы #блокировка #попен

Вопрос:

У меня есть процесс захвата, который записывает необработанные видеоданные и аудиоданные в файлы. Что-то вроде этого захватит 100 кадров данных.

./capture -n 100 -f video_file -a audio_file

Давая мне аудиофайл размером 768000 байт и видеофайл размером 414720000 байт. Похоже, они складываются, как и ожидалось:

  • 414720000 == 1920×1080 (пикселей / кадр) * 2 (байт / пиксель) * 100 (кадров)
  • 768000 == 48 кб (Гц) * 2 (байт / сэмпл) * 2 канала * 100 (кадров) / 25 (кадров / с)

Затем, когда я кодирую эти данные, например

ffmpeg -i audio_file -i video_file out.flv

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

Теперь, я на самом деле хочу прямую трансляцию, а не файл, и я могу сделать это нормально только для видео с чем-то вроде этого:

./capture -f /dev/stdout | ffmpeg -i - udp://127.0.0.1:10000

Я получаю видеопоток без трансляции звука по udp, и я смог нормально принимать и воспроизводить поток. Но когда я хочу добавить звук в картинку, у меня возникают некоторые проблемы.. Я думаю, что я не могу отправить их обоих stdout , и я не могу использовать stderr , потому что процесс захвата уже обсуждает это. Поэтому я попытался сделать это с именованными каналами следующим образом:

 mkfifo audio_pipe
mkfifo video_pipe
ffmpeg -i audio_pipe -i video_pipe out.flv amp;
./capture -f video_pipe -a audio_pipe
 

Но это не работает, кажется, все заходит в тупик. Я протестировал просто запуск ./capture -f video_file -a audio_file , а затем открытие двух новых оболочек и выполнение cat video_file > /dev/null и cat audio_file > /dev/null , как только обе кошки будут запущены, это разблокирует процесс захвата, так что, похоже, у него нет проблем с записью в каналы. Я заглянул в источник кода захвата, и то, как он работает, связано с обратным вызовом «прибыл кадр» из более глубокого API, который затем переходит и записывает видеокадр и аудиоданные в таком порядке (он блокируется). Я не знаю, что делает ffmpeg, читает ли он входной видеофайл или аудиофайл последовательно, в любом порядке, или читает их одновременно в потоках. Я попытался изменить порядок на ffmpeg -i video_pipe -i audio_pipe out.flv , но, к сожалению, все по-прежнему блокируется. Использование только одного именованного канала для видеоданных работает нормально.

Как я могу решить свою проблему? Я напишу его с помощью модуля подпроцесса python, как только пойму, как лучше всего избежать проблемы блокировки.

Комментарии:

1. Я считаю, что это ограничение в ffmpeg. Он не использует неблокирующий режим для чтения из FIFOs.

Ответ №1:

В Linux буфер канала ограничен 65 КБ, возможно, вы попадаете в тупик, когда capture не будет записывать больше звука, пока не сможет записать больше видео, а ffmpeg не будет читать больше видео, пока не получит больше звука.

Комментарии:

1. Я знаю об этом, я ищу обычный способ разрешения таких взаимоблокировок. Я бы предпочел не обрабатывать связь между захватом и кодировщиком вручную, если этого можно легко избежать.

Ответ №2:

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