FFmpeg / OpenCV принудительно игнорирует длительность входного кадра с rtsp? - PullRequest
3 голосов
/ 14 июня 2019

У меня была задержка ~5 sec при воспроизведении потока RTSP с IP-камеры.После нескольких поисков (особенно этот вопрос ) я уменьшил задержку до ~1 sec, используя следующую команду:

ffplay -fflags nobuffer -flags low_delay -framedrop -strict experimental \
       -probesize 32 -sync ext rtsp://xxx.xxx.xxx.xxx

Но когда я попробовал команду mplayer -benchmark из той же командывопрос, я обнаружил, что задержка сразу уходит (т.е. почти 0 задержка).

В справочной странице mplayer он имеет вид:

-benchmark

Печатает некоторую статистику использования ЦП и пропущенных кадров в конце воспроизведения.Используйте в сочетании с -nosound и -vo null для бенчмаркинга только видеокодека.

ПРИМЕЧАНИЕ. С этой опцией MPlayer также будет игнорировать длительность кадра при воспроизведении только видео (вы можете думать об этомкак бесконечные fps).

Я чувствую, что это "игнорирование длительности кадра" является ключом к вопросу, но после нескольких поисков я не нашел никакого флага, связанного с этим в ffmpeg,Мне интересно , как заставить игнорировать длительность входного кадра в ffmpeg?

С другой стороны, причина, по которой я использую ffmpeg, заключается в том, что мне нужно выполнить обработку изображенийиспользуя opencv, в то время как я обнаружил, что при выполнении

cv.VideoCapture('rtsp://xxx.xxx.xxx.xxx')

кажется, что используется некоторая часть ffmpeg под капотом. Решение, которое напрямую решает проблему в opencv, было бы еще болееоценили.Я несколько раз пытался прочитать VideoCapture в отдельном потоке, но это не помогло.


Некоторая информация о потоке RTSP : h264, 1920x1080, 15fps, 1 ключкадр за 4 с

Некоторые другие решения, которые я пробовал :

ffmpeg -r 99999 -i ...
# didn't work

mplayer ... -dumpstream
# it core dumped

1 Ответ

0 голосов
/ 14 июня 2019

Чтение кадров с использованием VideoCapture() в отдельном потоке должно повысить производительность из-за уменьшения задержки ввода-вывода. Операция read() блокируется, поэтому основная программа останавливается, пока кадр не будет считан из потока камеры. Поместив чтение кадра в отдельный поток, мы должны иметь возможность захватывать и показывать кадры параллельно, а не полагаться на один поток для захвата кадров в последовательном порядке. Замените src ссылкой на поток RTSP.

Другая причина задержки может заключаться в том, что ваше разрешение 1920x1080. Перед тем, как показать кадр, вы можете изменить его размер, что должно повысить производительность.

from threading import Thread
import cv2, time

class VideoStreamWidget(object):
    def __init__(self, src=0):
        self.capture = cv2.VideoCapture(src)
        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
            time.sleep(.01)

    def show_frame(self):
        # Display frames in main program
        cv2.imshow('frame', self.frame)
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            cv2.destroyAllWindows()
            exit(1)

if __name__ == '__main__':
    video_stream_widget = VideoStreamWidget()
    while True:
        try:
            video_stream_widget.show_frame()
        except AttributeError:
            pass
...