Post-process GStreamer playbin pipeline - gstreamer

The playbin pipeline in GStreamer is a wonderful thing in that I don't need to have any real knowledge about the individual elements needed to process the stream.
However, if I wanted to rotate the video 90 degrees (or flip it, or anything else), it appears I have to manually code up the pipeline. At the moment, I'm doing this with:
rtspsrc location=X
! rtph264depay
! h264parse
! decodebin
! videoflip method=Y
! videoconvert
! autovideosink
However, because I'm binding the video to a specific Gtk widget, I capture the message asking for the widget ID and provide that back to GStreamer so it can correctly bind.
Unfortunately, according to gst-inspect-1.0, none of those elements in the pipeline above appear to actually provide the GstVideoOverlay interface so that, when I query for one that can receive the widget identifier, I get null followed very quickly by a null pointer error. Or, if I do nothing when the null is returned, no binding occurs and GStreamer opens up a separate window to stream the video.
It turns out that playbin itself provides the required interface.
I also tried replacing autovideosink with ximagesink, and then with xvimagesink, both of which claim to support the interface but, in both cases, no element was found that supported the interface.
So my question s are basically this:
1/ Can I insert something into the above pipeline that will provide the interface?
2/ Failing that, is there a way to use playbin to analyse the stream correctly but then capture its output and pass that through more filters? The sort of thing I'm thinking of is:
playbin location=X
! videoflip method=Y
! autovideosink
In other words, can I use something like the video-sink property of playbin to stop it creating its own sink and instead pass its data through to the videoflip?
I'd prefer something that could be implemented with Gst.Parse.Launch() since I don't really want to have to mess about creating every single pipeline element manually if I can avoid it.

I'd say the way you are requesting the GstVideoOverlay is not correct or there is a bug in GStreamer, xvimagesink and ximagesink both support GstVideoOverlay interface. autovideosink doesn't but it is likely that the videosink inside it will support.
Anyway, you want to have a custom bin set to the video-sink property. You can create your bin and put the elements you want inside it, create a sink ghostpad and then set it as the video-sink of your playbin.
It is also possible to do it using parse-launch syntax:
gst-launch-1.0 playbin video-sink="videoconvert ! videoscale ! aasink" uri=file://<path/to/some/file>
Just replace the bin elements with whatever you need.

Related

play multiple sources at once, each from a different position

I would like to use gstreamer to play multiple sources (for instance two video files) simultaneously using a single pipeline but each video starting from a different position, for instance first video from the beginning and the second from the middle. Could someone guide me on how to achieve it?
Simplifying, my pipeline is an equivalent of:
gst-launch-1.0 \
uridecodebin uri=file:///Users/tmikolaj/Downloads/videoalpha_video_dancer1.webm ! videoconvert ! autovideosink \
uridecodebin uri=file:///Users/tmikolaj/Downloads/videoalpha_video_dancer1.webm ! videoconvert ! autovideosink
, but created programmatically.
Obviously, simple seeking the pipeline seeks two files at once.
I was trying to register a probe of the GST_PAD_PROBE_TYPE_EVENT_UPSTREAM type from inside the pad-added signal callback of the uridecodebin element. Inside the probe I wanted to catch the GST_EVENT_SEEK event and drop it for the first video. However, it seems that dropping the SEEK message leaves pipeline in a PAUSED state and even an explicit state change to PLAYING does nothing.
Does anybody has some hints on how to solve that problem?

Gstreamer - display and record video using Tee element hangs

My target is to stream and record video at the same time.
Gstreamer version: 1.16.1, OS: debian 11
Initially I had more complex pipeline containing compositor on one branch and different custom filters. The simplified version of my constructed pipeline is as follows:
gst-launch-1.0 videotestsrc ! "video/x-raw,width=500,height=300,framerate=50/1" ! tee name=t \
t. ! queue ! x264enc ! splitmuxsink name=mux_sink max-files=10000 next-file=5 max-size-time=600000000 location=video%02d.mp4 \
t. ! queue ! "video/x-raw,width=500,height=300,framerate=50/1" ! glimagesink
How this pipeline acts on my system is that it starts without problems but goes from NULL state to READY state and hangs there. The displayed video is also stationary and no video file is saved.
Here is svg file generated from the dot dump null->ready state: https://drive.google.com/file/d/1oGwDufDdljbuKr8b0YURvg5VxPzMtQWb/view?usp=sharing
I have already tried both branches separately without tee element - both working. I have also tried different combinations of caps filters on both queues. I tried raising gstreamer debug level to see if there was something suspicious there - nothing.
The task should be quite straight-forward, I must be missing something here.
Thanks in advance!
The latency for the default x264 settings are too high for this use case. Use tune=zerolatency option for the x264enc element or increase the queue size after the tee for the display path. This will prevent deadlocking for preroll.

Gstreamer rtsp stream to appsink to openCV

I need a bit of your help because I'm trying to receive rtsp stream by gstreamer and then put it into openCV to process video. What is worse, I will need it back from openCV but first things first. I'm quite new to this so I don't know Gstreamer well so I'm counting on you guys. Some simple examples would be best but I'll use what I have;)
Thanks in advance
You can use something like this:
uridecodebin uri=rtsp:// name=uridec ! queue ! tee name=t ! queue ! <some encoder and muxer> ! filesink t. ! queue ! videoconvert ! "video/x-raw, format=BGR" ! appsink t. ! queue ! <restream>
In this possible solution you are receiving and decoding at uridecodebin which means that for re-streaming you need to encode, as well as encoding for storing to a file. If that's not what you want you can replace uridecodebin with rtspsrc that will give you RTP streams instead of decoded raw streams. Something like:
rtspsrc ! rtpXdepay ! tee name=t ! ...
Replace X with the format you are receiving (can be done dynamically from your application). Now the output is an encoded stream that you can use in a similar way as the sample pipeline above.
Note that these suggestions are assuming your rtsp input is a single stream (video likely), if you want video and audio you need to add 2 branches out of uridecodebin or rtspsrc. I also assumed that by 'rtspStream' is some sort of external library/application that you are going to use to retransmit instead of using gstreamer itself. In any way, this should give you an idea.

What the queue element do in Gstreamer pipeline

I have this pipeline :
gst-launch -v filesrc location=video.mkv ! matroskademux name=d \
d. ! queue ! ffdec_h264 ! subtitleoverlay name=overlay ! ffmpegcolorspace ! x264enc ! mux. \
d. ! queue ! aacparse ! mux. \
filesrc location=fr.srt ! subparse ! overlay. \
matroskamux name=mux ! filesink location=vid.mkv
I'm trying to burn the subtitles to the video. I have succdeded to read the file with the subtitles but the above pipeline stuck and I have this message :
queue_dataflow gstqueue.c:1243:gst_queue_loop:<queue0> queue is empty
What's wrong with my pipeline? What the queue element do? I haven't really understood what it said in the doc.
The queue element adds a thread boundary to the pipeline and support for buffering. The input side will put buffers into a queue, which is then emptied on the output side from another thread. Via properties on the queue element you can set the size of the queue and some other things.
I don't see anything specifically wrong with your pipeline, but the message there tells you that at some point one of the queues is empty. Which might be a problem or not. It might become fuller again later.
You'll have to check the GStreamer debug logs to see if there's anything in there that hints at the actual problem. My best guess here would be that the audio queue running full because of the encoder latency of x264enc. Try making the audio queue larger, or set tune=zerolatency on x264enc.
Also I see that you're using GStreamer 0.10. It is no longer maintained since more than two years and for new applications you should really consider upgrading to the 1.x versions.
A queue is the thread boundary element through which you can force the use of threads. It does so by using a classic provider/consumer model as learned in threading classes at universities all around the world. By doing this, it acts both as a means to make data throughput between threads threadsafe, and it can also act as a buffer. Queues have several GObject properties to be configured for specific uses. For example, you can set lower and upper thresholds for the element. If there's less data than the lower threshold (default: disabled), it will block output. If there's more data than the upper threshold, it will block input or (if configured to do so) drop data.
To use a queue (and therefore force the use of two distinct threads in the pipeline), one can simply create a “queue” element and put this in as part of the pipeline. GStreamer will take care of all threading details internally.

How to get Pipeline created by playbin in textual format in Gstreamer?

I'm playing a transport stream file (*.ts) using the following pipeline:
gst-launch-0.10 playbin2 uri=file:///c:/bbb.ts
But I need to convert that into a pipeline myself. I'm not sure how to achieve this.
So far I have tried: (works fine)
gst-launch-0.10 -v filesrc location=c:/bbb.ts ! tsdemux ! audio/x-ac3 ! fakesink
But if i replace fakesink with autoaudiosink it fails with a not-linked error.
And even the fakesink doesn't work for video:
gst-launch-0.10 -v filesrc location=c:/bbb.ts ! tsdemux ! video/x-mpeg2 ! fakesink
So I have two questions:
How to find out pipeline created by playbin element.
How to play mpeg2-ts file using gstreamer pipeline.
Answer to question 1 -
There is a way to get the graphs of the pipeline created mentioned in documentation of basic tutorial-11.
A brief from the page
Getting pipeline graphs
For those cases where your pipeline starts to grow too large and you
lose track of what is connected with what, GStreamer has the
capability to output graph files. These are .dot files, readable with
free programs like GraphViz, that describe the topology of your
pipeline, along with the caps negotiated in each link.
This is also very handy when using all-in-one elements like playbin2
or uridecodebin, which instantiate several elements inside them.
I hope this resolves what you want