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.
Related
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?
I am running a 9 sec video on my NVIDIA Tegra jetson TK1 board using gstreamer as:
gst-launch-0.10 playbin uri=file:///home/ubuntu/widescreen.avi
I notice this drops a lot of frames and gstreamer prints these messages:
WARNING: from element /GstPlayBin:playbin0/GstBin:vbin/GstAutoVideoSink:videosink/GstXvImageSink:videosink-actual-sink-xvimage: A lot of buffers are being dropped.
Additional debug info:
gstbasesink.c(2875): gst_base_sink_is_too_late (): /GstPlayBin:playbin0/GstBin:vbin/GstAutoVideoSink:videosink/GstXvImageSink:videosink-actual-sink-xvimage:
There may be a timestamping problem, or this computer is too slow.
I ran top while executing this and indeed gstreamer is taking 95% of the CPU.
Now, when i play this video through the default media player, it plays completely fine and without any lag. I was wondering if anyone knows what may be the reason that gstreamer is unable to play it properly. I am new to gstreamer and wondering if I can do something to alleviate this.
Bins are many elements combined into one element type structure(i.e with appropriate number of sinks and sources). playbin is a standard bin with an "autovideosink" element which automatically detects video sinks.
Firstly I would suggest you to upgrade to gstreamer-1.0 in which many bugs were fixed.
Secondly the problem seems to be with your xvimagesink, hence try using ximagesink by defining explicitly, your autovideosink is selecting xvimagesink by default.
try this pipeine:-
(for hardware decoding)
gst-launch-1.0 filesrc location="location of h264 video/file.avi" ! avidemux ! h264parse ! omxh264dec ! videoconvert ! ximagesink
or for cpu decoding use avdec_h264 instead of omxh264dec
The default media player is likely using video hardware decoding if the media file is H.264, which allows it decode with less CPU resources. Try creating a gstreamer pipeline that explicitly uses the omx H.264 decoding element as discussed here (http://elinux.org/Jetson/H264_Codec).
eg. gst-launch-0.10 filesrc location=/home/ubuntu/widescreen.avi ! avidemux ! h264parse ! nv_omx_h264dec ! autovideosink
I have a gstreamer pipeline that takes video from the webcam and splits it into two threads:
1) use appsink so I can programmatically edit the captured frames
2) saves the video to a file
The pipeline looks like this:
gst-launch-1.0 v4l2src device=/dev/video0 \
! tee name=t ! queue ! videoconvert ! videoscale ! appsink name=sink caps="video/x-raw,format=RGB,width=800,framerate=15/1" t. \
! queue ! video/x-raw,width=800,framerate=15/1 ! jpegenc ! avimux ! filesink location=/tmp/output.avi
I'm using this inside a C++ app.
My problem is that in most of the time I don't need the two threads running simultaneously, but only one of them. And in rare cases - need both.
So I need some way to temporarily pause/stop either the appsink or the video saving - in order to save CPU.
The way I do it now is to destroy the pipeline and recreate it again with only one thread when needed, but that seems quite ugly.
I've been looking for a better solution, but no luck so far - is there any way to do that?
Thanks in advance!
An easier way to approach this may be to use a valve element. It has a drop property that you can set to true or false. Put it right after the queue on the tee.
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer-plugins/html/gstreamer-plugins-valve.html
EDIT: This doesn't work. Some more details are present in this post on the GStreamer mailing list:
http://gstreamer-devel.966125.n4.nabble.com/How-to-Stop-start-recording-using-Valve-element-td4661728.html
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.
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