Gstreamer теряет данные при смене файловой ссылки
Я создал приложение на python, чтобы попытаться динамически изменить конвейер gstreamer, направив поток на другую файловую линию (см. Ниже). Код работает нормально и (обычно) создает серию файлов AVI. Есть пара проблем:
- Несмотря на то, что событие запуска нового файла запускается каждые 10 секунд, сами видео - только 3 секунды!
- Иногда файл будет сохранен без данных, а все последующие файлы будут пустыми.
У кого-нибудь есть понимание этих проблем?
#! /usr/bin/env python
import os
import sys
import logging
import gi
gi.require_version('Gst', "1.0")
gi.require_version('GstBase', "1.0")
gi.require_version('Gtk', "3.0")
#gi.require_version('GdkX11', '3.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import GObject, Gst, GstBase, Gtk, GstVideo, GdkX11
import numpy as np
import datetime as dt
log = logging.getLogger(__name__)
class Segmenter:
def __init__(self):
Gst.init(None)
self.terminate = False
# Create gstreamer pipeline
cmd = "v4l2src ! tee name=tee ! fakesink"
self.pipeline = Gst.parse_launch(cmd)
# Store references to gstreamer objects
self.bus = self.pipeline.get_bus()
self.recordpipe = None
def run(self):
# Initiate main loop
self.pipeline.set_state(Gst.State.PAUSED)
self.pipeline.set_state(Gst.State.PLAYING)
try:
while not self.terminate:
print(dt.datetime.now().time())
# Listen for event messages on the bus
msg = self.bus.timed_pop_filtered(10 * Gst.SECOND, (Gst.MessageType.EOS | Gst.MessageType.ERROR))
if msg:
if msg.type == Gst.MessageType.ERROR:
err, dbg = msg.parse_error()
print("ERROR:", msg.src.get_name(), ":", err)
if dbg:
print("Debug info:", dbg)
self.terminate = True
elif msg.type == Gst.MessageType.EOS:
print("End-Of-Stream reached")
self.terminate = True
else:
# No message - must have reached timeout
self.begin_new_file()
finally:
# Free up resources
self.pipeline.set_state(Gst.State.NULL)
def begin_new_file(self):
# If recording a file currently, terminate it
if self.recordpipe is not None:
# Block new data
filequeue = self.recordpipe.get_by_name("filequeue")
filequeue.get_static_pad("src").add_probe(Gst.PadProbeType.BLOCK_DOWNSTREAM, self.probe_block)
# Disconnect the recording pipe
self.pipeline.get_by_name("tee").unlink(self.recordpipe)
# Send a termination event to trigger the save
filequeue.get_static_pad("sink").send_event(Gst.Event.new_eos())
# Clear the reference to the pipe
self.recordpipe = None
# Create a new file target
filename = dt.datetime.now().strftime("%Y-%m-%d_%H.%M.%S") + ".avi"
print("Recording {}...".format(filename))
# Create a new pipeline for the new file
self.recordpipe = Gst.parse_bin_from_description("queue name=filequeue ! jpegenc ! avimux ! filesink location={} sync=False".format(filename), True)
self.pipeline.add(self.recordpipe)
# Connect to the main pipe
self.pipeline.get_by_name("tee").link(self.recordpipe)
# Start passing data
self.recordpipe.set_state(Gst.State.PLAYING)
def probe_block(self, pad, buf):
""" Callback for downstream block """
print('block.')
return True
if __name__ == '__main__':
seg = Segmenter()
seg.run()