2

I have a Python GStreamer application that uses appsrc to record mp4 files.

The issue is that despite specifying tune=zerolatency for x264enc, there is latency, and the output video is truncated when an eos is sent to the pipeline. Depending on the machine, the latency is substantial, resulting in a much shorter than expected output file.

If I change the pipeline to save the video as an AVI file, it is not truncated. Unfortunately, the resulting file is approximately 2 GB per minute versus 12 MB per minute with H.264.

Here is the x264enc pipeline:

appsrc name=appsrc format=time is-live=true caps=video/x-raw,format=(string)BGR appsrc. ! videoconvert ! x264enc tune=zerolatency ! qtmux ! filesink location=out.mp4

When the application is finished, it sends end-of-stream messages to the appsrc and pipeline:

if self._appsrc.emit("end-of-stream") == Gst.FlowReturn.OK:
    self._sink_pipeline.send_event(Gst.Event.new_eos())

Is there a way for my application to wait while x264enc processes its buffer? A message, perhaps? I don't care how long it takes to finish. What's important is that all frames pushed to the appsrc are written to the output video file.

alexlyn
  • 21
  • 2

2 Answers2

3

You will actually have to wait for that End-Of-Stream event to pass through the pipeline before you stop it. An End-Of-Stream message will be send to the pipeline's bus when all sinks have received the End-Of-Stream.

Something like this:

# <send EOS event>

self._sink_pipeline.get_bus().timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS)

# <stop pipeline>
Florian Zwoch
  • 6,764
  • 2
  • 12
  • 21
0

Following Florian Zwoch's answer below a complete example that creates an video file and gracefully terminates the pipeline with an EOS signal.

import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject
from time import sleep

Gst.init(None)
pipe_str = ' videotestsrc name=src do-timestamp=true is-live=true !' \
           ' x264enc !' \
           ' h264parse !' \
           ' matroskamux !' \
           ' filesink name=f location=test.mp4 '

pipeline = Gst.parse_launch(pipe_str)
bus = pipeline.get_bus()

print("Entering Playing state...")
pipeline.set_state(Gst.State.PLAYING)
sleep(5)
print("Sending an EOS event to the pipeline")
pipeline.send_event(Gst.Event.new_eos())
print("Waiting for the EOS message on the bus")
bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.EOS)
print("Stopping pipeline")
pipeline.set_state(Gst.State.NULL) 

Note: Tested on Ubuntu 16.04, GStreamer 1.8.3

Daniel
  • 1,319
  • 14
  • 19