Получите Numpy Array Realtime от GStreamer - PullRequest
0 голосов
/ 08 ноября 2019

Я пытался получать массивы от кадра к кадру в режиме реального времени из среды GStreamer.

Я уже пытался использовать такой конвейер (из /7836263/vosproizvedenie-audio-i-video-s-pomoschy-pipeline-v-gstreamer-python с модификацией) в Python:

self.filesrc = Gst.ElementFactory.make('filesrc')
self.filesrc.set_property('location', self.source_file)
self.pipeline.add(self.filesrc)

# Demuxer
self.decoder = Gst.ElementFactory.make('decodebin')
self.decoder.connect('pad-added', self.__on_decoded_pad)
self.pipeline.add(self.decoder)

# Video elements
self.videoqueue = Gst.ElementFactory.make('queue', 'videoqueue')
self.pipeline.add(self.videoqueue)

self.autovideoconvert = Gst.ElementFactory.make('autovideoconvert')
self.pipeline.add(self.autovideoconvert)

self.autovideosink = Gst.ElementFactory.make('autovideosink')
self.pipeline.add(self.autovideosink)

# Audio elements
self.audioqueue = Gst.ElementFactory.make('queue', 'audioqueue')
self.pipeline.add(self.audioqueue)

self.audioconvert = Gst.ElementFactory.make('audioconvert')
self.pipeline.add(self.audioconvert)

self.autoaudiosink = Gst.ElementFactory.make('autoaudiosink')
self.pipeline.add(self.autoaudiosink)

self.progressreport = Gst.ElementFactory.make('progressreport')
self.progressreport.set_property('update-freq', 1)
self.pipeline.add(self.progressreport)

Все конвейеры также уже связаны. Но у меня кончается идея, как выполнять извлечение массива в реальном времени из потока. Есть ли у вас какие-либо предложения?

1 Ответ

0 голосов
/ 11 ноября 2019

Конвейер в исходном вопросе предназначен для отображения видео и воспроизведения аудио, поэтому он использует элементы autovideosink и autoaudiosink соответственно. Если вы хотите, чтобы ваши видеокадры передавались в ваше приложение, а не на экран, вам нужно использовать другой элемент приемника, а именно appsink вместо autovideosink.

self.appsink = Gst.ElementFactory.make('appsink')
self.pipeline.add(self.appsink)

Элемент appsinkимеет сигнал под названием «new-sample», который вы можете подключить к нему, который срабатывает при появлении нового кадра.

handler_id = self.app_sink.connect("new-sample", self.__on_new_sample)

Затем необходимо преобразовать формат буфера GStreamer в массив Numpy.

def __on_new_sample(self, app_sink):
    sample = app_sink.pull_sample()
    caps = sample.get_caps()

    # Extract the width and height info from the sample's caps
    height = caps.get_structure(0).get_value("height")
    width = caps.get_structure(0).get_value("width")

    # Get the actual data
    buffer = sample.get_buffer()
    # Get read access to the buffer data
    success, map_info = buffer.map(Gst.MapFlags.READ)
    if not success:
        raise RuntimeError("Could not map buffer data!")

    numpy_frame = np.ndarray(
        shape=(height, width, 3),
        dtype=np.uint8,
        buffer=map_info.data)

    # Clean up the buffer mapping
    buffer.unmap(map_info)

Обратите внимание, что этот код делает определенные предположения о данных кадра, а именно о том, что это трехцветный формат, такой как RGB, и что данные цвета будут беззнаковыми 8-разрядными.

...