Known-good pipeline combined with probably-known-good appsrc unable to produce output
I am trying to get data from a numpy array to be interpreted as an image, then pushed onto the pipeline. The pipeline works well with a videotestsrc
, so I have reason to believe it should work with the appsrc
. It does not, however. But piping the appsrc
directly to a filesink
produces a rather heavy file, so it looks fairly healthy although I have trouble opening it to verify. Here's my little python script where I do my work.
import numpy as np
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GLib', '2.0')
from gi.repository import Gst, GLib # noqa: E402
def deadpan() -> Gst.Pipeline:
p = Gst.parse_launch('appsrc name=src ! filesink location=out_deadpan.mov')
src = p.get_by_name('src')
src.set_property('is-live', True)
src.connect('need-data', need_data_cb)
return p
def appsrc() -> Gst.Pipeline:
p = Gst.parse_launch('appsrc name=src ! video/x-raw,format=NV12,width=640,height=480,framerate=30/1 ! queue ! vtenc_h264 ! qtmux streamable=true fragment-duration=2 ! filesink location=out_appsrc.mov')
src = p.get_by_name('src')
src.set_property('is-live', True)
src.connect('need-data', need_data_cb)
return p
def videotestsrc() -> Gst.Pipeline:
p = Gst.parse_launch('videotestsrc ! video/x-raw,format=NV12,width=640,height=480,framerate=30/1 ! queue ! vtenc_h264 ! qtmux streamable=true fragment-duration=2 ! filesink location=out_videotestsrc.mov')
return p
def make_pipe() -> Gst.Pipeline:
return deadpan()
FRAME_NUMBER = 0
def need_data_cb(appsrc: Gst.Element, size: int):
print('need-data', size)
emit_random_ndarrays(appsrc)
def emit_random_ndarrays(appsrc: Gst.Element):
for _i in range(30):
emit_array(appsrc)
print("Emitting end-of-stream")
appsrc.emit('end-of-stream')
def emit_array(appsrc: Gst.Element):
data = np.random.rand(640, 480, 3)
duration = 1 / 30 * Gst.SECOND
buf = Gst.Buffer.new_allocate(None, data.nbytes, None)
buf.fill(0, data.tobytes())
buf.duration = duration
global FRAME_NUMBER
timestamp = FRAME_NUMBER * duration
buf.pts = buf.dts = int(timestamp)
buf.offset = timestamp
retval = appsrc.emit('push-buffer', buf)
print('pushed buffer, frame {}, duration {} ns, durations {} s'.format(FRAME_NUMBER,
duration,
duration / Gst.SECOND))
if retval != Gst.FlowReturn.OK:
print(retval)
FRAME_NUMBER += 1
def run():
Gst.init(None)
mainloop = GLib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
def main():
Gst.init(None)
pipeline = make_pipe()
pipeline.set_state(Gst.State.PLAYING)
bus = pipeline.get_bus()
bus.add_signal_watch()
def bus_msg_cb(bus, message):
# print(f"bus_msg_cb: {message.type}")
if message.type == Gst.MessageType.EOS:
print("End of stream")
pipeline.set_state(Gst.State.NULL)
bus.connect('message', bus_msg_cb)
print(f"Running pipeline: {pipeline.get_name()}")
run()
pipeline.set_state(Gst.State.NULL)
print(f"Pipeline finished, state is now: {pipeline.get_state(Gst.CLOCK_TIME_NONE)}")
if __name__ == '__main__':
main()
If I run the above script, I will get a file called out_videotestsrc.mov
which I can open with quicktime. If i change the make_pipe()
function to return appsrc()
instead, I get the following output:
❱ python3 gitlab.py (base)
Running pipeline: pipeline0
need-data 4096
pushed buffer, frame 0, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 1, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 2, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 3, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 4, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 5, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 6, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 7, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 8, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 9, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 10, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 11, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 12, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 13, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 14, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 15, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 16, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 17, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 18, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 19, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 20, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 21, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 22, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 23, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 24, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 25, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 26, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 27, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 28, duration 33333333.333333332 ns, durations 0.03333333333333333 s
pushed buffer, frame 29, duration 33333333.333333332 ns, durations 0.03333333333333333 s
Emitting end-of-stream
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.927: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.933: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.936: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.939: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.941: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.943: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.944: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.946: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.947: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.948: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.950: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.951: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.953: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.954: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.955: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.956: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.957: gst_segment_to_running_time: assertion 'segment->format == format' failed
need-data 4096
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.959: gst_segment_to_running_time: assertion 'segment->format == format' failed
pushed buffer, frame 30, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 31, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 32, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 33, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.989: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.989: gst_segment_to_running_time: assertion 'segment->format == format' failed
pushed buffer, frame 34, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.990: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.990: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:09.990: gst_segment_to_running_time: assertion 'segment->format == format' failed
pushed buffer, frame 35, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 36, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 37, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 38, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 39, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 40, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 41, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 42, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 43, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 44, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 45, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 46, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 47, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 48, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 49, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 50, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 51, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 52, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 53, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 54, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 55, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 56, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 57, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 58, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
pushed buffer, frame 59, duration 33333333.333333332 ns, durations 0.03333333333333333 s
<enum GST_FLOW_EOS of type Gst.FlowReturn>
Emitting end-of-stream
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.137: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.137: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.138: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.138: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.139: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.139: gst_segment_to_running_time: assertion 'segment->format == format' failed
(<unknown>:53216): GStreamer-CRITICAL **: 16:53:10.139: gst_segment_to_running_time: assertion 'segment->format == format' failed
End of stream
If I run the deadpan()
pipeline, it at least produces a large file.
The output files have the following sizes:
❱ ll
.rw-r--r-- 2.7k peredwardsson 21 Feb 16:52 gitlab.py
.rw-r--r--@ 907 peredwardsson 21 Feb 16:53 out_appsrc.mov
.rw-r--r--@ 221M peredwardsson 21 Feb 16:56 out_deadpan.mov
.rw-r--r--@ 22M peredwardsson 21 Feb 16:49 out_videotestsrc.mov
Quicktime can play out_videotestsrc.mov
but not out_appsrc.mov
(or out_deadpan.mov
). What can I do to make it work? It looks like the appsrc is not playing nice.