Высокая загрузка процессора при чтении потока HLS с использованием OpenCV GStreamer

#python #opencv #gstreamer

#python #opencv #gstreamer

Вопрос:

У меня есть следующий код, который создает конвейер gstreamer для обработки потока HLS.

 cap = cv2.VideoCapture(
    f"souphttpsrc is_live=true location={hls_stream_link} ! hlsdemux ! 
    queue ! decodebin ! videorate ! video/x-raw,framerate=1/1 ! 
    videoconvert ! appsink max-buffers=1 drop=true sync=false",
cv2.CAP_GSTREAMER)
  

Теперь я читаю поток следующим образом:

 while True:
    success, frame = cap.read()
    time.sleep(1.0)
  

Обратите внимание, я читаю поток со скоростью 1 кадр / с и обладаю свойствами max-buffers=1 drop=true sync=false . Делая это, я всегда извлекаю последний кадр из потока, который может предложить буфер.

Проблема в том, что загрузка процессора чрезвычайно высока, иногда достигая 120% на моей машине i7. Удаление режима ожидания ухудшило бы ситуацию.

Любые решения или идеи относительно того, почему обработка потока HLS настолько интенсивна для процессора, были бы фантастическими. Кроме того, идеи о том, как уменьшить использование, также были бы замечательными.

Ответ №1:

Вы декодируете весь поток. При программном обеспечении это может быть довольно дорогостоящим. Один из возможных шагов оптимизации, который я вижу здесь, — добавить GstPadProbe перед декодером и проанализировать бит в потоке битов и удалить все выборки, которые не являются IDR. Тогда вы будете отправлять декодеру только кадры IDR. Что уменьшило бы нагрузку на декодер, однако в конечном итоге вы получите новый кадр только после каждого интервала IDR-кадра, который обычно составляет каждые 2 секунды (но может варьироваться в зависимости от каждого).

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

1. Большое спасибо за ответ, в этом есть тонна смысла.

2. Есть идеи, как это будет выглядеть при использовании OpenCV для CLI? Я совсем новичок во всем этом мире.

3. Я понятия не имею об opencv и взаимодействии с GStreamer. С точки зрения CLI вы не можете этого сделать. Это требует некоторой кодовой логики, обычно выполняемой в коде приложения или библиотеки. Это можно сделать и на python. Вам нужно немного поработать с реальным кодом с GStreamer API.

4. Есть ли конкретная причина, по которой поток необходимо декодировать кадр за кадром, несмотря ни на что? Почему сложно или странно просто «выбирать» кадры?

5. Именно так работает большинство видеокодеков. Фреймы зависят от своих предшественников (что делает его таким эффективным). Но для того, чтобы декодировать определенный фрейм, вам нужно, чтобы все зависящие от него фреймы тоже были декодированы, иначе фрейм не имеет смысла. Исключением являются кадры IDR, которые отмечают начало группы изображений и могут быть декодированы сами по себе.