WedX - журнал о программировании и компьютерных науках

Конвейер кодирования видео — дизайн потоков

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

capture frames->encode->file-save (or stream to network)

У меня есть диллема, что было бы лучшим подходом/дизайном:

  1. один поток на канал, который вызывает API блокировки конвейера один за другим, например:

    while(1)
    {
     frame = get_next_capture_frame(); //no blocking api - every 1/60 sec
     prev_bitstream =  send_to_encode_and_get_any_already_encoded_frame(frame); //no blocking api
     send_to_save_bitstream(prev_bitstream); //no blocking api
     delay(1/60); //wait 1/60
    }
    

Или лучше использовать несколько потоков, каждый из которых выполняет свою работу: один поток для захвата, другой для кодирования и еще один для управления файлами. Эта проблема становится более сложной, поскольку задействовано более одного канала (около 6 каналов, что может привести к 6 потокам в первом подходе и 18 потокам во втором подходе).

  1. Еще одна дилемма в этой проблемной области: следует периодически запускать потоки и выполнять задание, ожидающее в очереди (скажем, пробуждение каждые 60 кадров в секунду), или следует запускать потоки в соответствии с новым событием (новый буфер для захвата, новый буфер для кодировщика и т. д.).

Ответы:


1

Типа зависит от требований. Если вы знаете, что у вас всегда будет 6 каналов со скоростью 60 кадров в секунду и что процесс захвата/кодирования/сохранения займет менее 1/60 секунды, то кодировать один поток на канал будет проще всего. Но имейте в виду, что если кодирование или сохранение иногда занимает слишком много времени, вы не получите следующий кадр по расписанию.

Вы можете использовать конвейерный подход (аналогичный вашему второму варианту), но не для каждого потока. То есть, если бы вы могли иметь один поток, который ничего не делает, кроме чтения и сохранения кадра из каждого канала 60 раз в секунду. Эти кадры попадают в очередь Captured. У вас есть отдельный поток (или, возможно, несколько потоков), читающий из очереди Captured, кодирующий данные и сохраняющий результаты в очереди вывода. Наконец, один или несколько потоков вывода читают очередь вывода и сохраняют закодированные данные.

Очереди являются общими, так что все потоки кодирования, например, читают из одной и той же захваченной очереди и записывают в одну и ту же очередь вывода. Большинство современных языков программирования имеют эффективные потокобезопасные очереди. У многих есть такие структуры, которые не требуют напряженного ожидания. То есть потоки Encoding могут ожидать незанятости в очереди Captured, если она пуста. Потоки будут уведомлены, когда что-то помещается в очередь. См., например, BlockingCollection в .NET или ConcurrentLinkedQueue в Java.

Эта модель хорошо масштабируется. Если, например, вам нужно больше потоков кодирования, чтобы не отставать от пропускной способности, вы можете просто увеличить их количество. Вы можете получить, например, два потока захвата, 8 кодировщиков и один поток вывода. Вы можете сбалансировать его в зависимости от вашей рабочей нагрузки.

Что касается планирования, я подозреваю, что вы хотели бы, чтобы ваши потоки захвата работали на периодической основе (т.е. раз в 1/60 секунды или независимо от вашей частоты кадров). Потоки кодирования и вывода должны быть настроены на ожидание в соответствующих очередях. Например, у потока вывода нет причин постоянно опрашивать очередь вывода на наличие данных. Вместо этого он может простаивать (ожидать) и получать уведомления, когда пакет помещается в очередь вывода.

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

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

04.05.2015
  • Спасибо, уважаемый, за очень подробный и полезный ответ! Я выберу первый подход из-за его простоты. 05.05.2015
  • Уважаемый @Jim, при втором анализе первого подхода кажется, что у него есть дефект. Если кодирование занимает почти 1/60, а сохранение файла также почти 1/60, то выполнение всего этого в последовательности приведет к завершению одной последовательности и 1/60 * 2, прежде чем пытаться получить следующий кадр захвата, или, может быть, я неправильно понял, что вы имели в виду. ? 05.05.2015
  • @ransh: если кодирование занимает 1/60 секунды, а сохранение занимает 1/60 секунды, то вы не можете поддерживать пропускную способность 1/60 секунды. Вам нужно будет придумать другой способ сделать что-то или ускорить сохранение. Вы можете буферизовать несколько закодированных кадров, а затем записывать их целиком, а не по одному. Это, вероятно, увеличит вашу пропускную способность. 05.05.2015
  • Я думаю, что теоретически, если время кодирования почти (но меньше) ~ 1/60, а сохранение файла почти (но меньше), чем 1/60, то первый подход все еще в порядке, пока API для кодировщика do/get поток, и файл сохранения не блокируется. Я отредактировал код в своем вопросе. Я надеюсь, что это сделает работу. 05.05.2015
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]