How to remove a branch of tee in an active GStreamer pipeline? - gstreamer

everyone
The version of GStreamer I use is 1.x. I've spent a lot of time in searching a way to delete a tee branch.
In an active pipeline, a recording bin is created as below and inserted into this pipeline by branching the tee element.
"queue ! video/x-h264, width=800, height=600, framerate=10/1, stream-format=(string)byte-stream ! h264parse ! mp4mux ! filesink location=/xxxx"
It works perfectly except that I want to dynamically delete the recording bin and get a playable mp4 file. According to some discussion and tutorial, to get a correct mp4 file , we need to handle something about EOS. After trying some methods, I always got broken mp4 files.
Does anyone have sample code written in C to show me ? I'd appreciate your help.

Your best bet for cases like this may be to create two processes. The first process would run the video, and half of the tee it has would deliver h264 data to the second process through whatever means.
Here are two pipelines demonstrating the concept using UDP sockets.
gst-launch-1.0 videotestsrc ! x264enc ! tee name=t ! h264parse ! avdec_h264 ! videoconvert ! ximagesink t. ! queue ! h264parse ! rtph264pay ! udpsink host=localhost port=8888
gst-launch-1.0 udpsrc port=8888 num-buffers=300 ! application/x-rtp,media=video,encoding-name=H264 ! rtph264depay ! h264parse ! mp4mux ! filesink location=/tmp/264.mp4
The trick to getting that clean mp4 is to make sure an EOS event is delivered reliably.

Instead of dynamically adding it you just have it in the pipeline by default, and add a probe callback at the source pad of the queue in the probe callback you have to do the trick either to pass the buffer or not (GST_PAD_PROBE_DROP drops the buffer and GST_PAD_PROBE_OK passes on the buffer to next element) so when you get an event to start/stop recoding you just need to return appropriate values. And filesink you can use multifilesink instead so as to write to different files everytime you start/stop.
Note the queue which drops the buffers needs before the mux element otherwise the file would be corrupt.
Hope that helps!

Finally, I came up with a solution.
Let's say that there is an active pipeline including a recording bin.
"udpsrc port=4444 caps=\"application/x-rtp, media=(string)video,
clock-rate=(int)90000, encoding-name=(string)H264 ! rtph264depay !
tee name=tp tp. ! queue ! video/x-h264, width=800, height=600,
framerate=10/1 ! decodebin ! videoconvert ! video/x-raw, format=RGBA !
autovideosink"
recording bin:
"queue ! video/x-h264, width=800, height=600, framerate=10/1,
stream-format=(string)byte-stream ! h264parse ! mp4mux ! filesink
location=/xxxx"
After a period of time, we want to stop recording and save as a mp4 file, and video media is still streaming.
First, I use a blocking probe to block the src pad of tee. In this blocking probe callback, I use an event probe to catch EOS in the sink pad of filesink and do a busy waiting.
*if EOS is catched in the event probe callback
self->isGotEOS = YES;
*busy waiting in the blocking probe callback
while (self->isGotEOS == NO) {
usleep(100000);
}
Before entering the busy waiting while loop, an EOS event is created and sent to the sink pad of recording bin.
After the busy waiting is done:
usleep(200000);
[self destory_record_elements];
I think usleep(200000) is a trick. Without it, a non-playable mp4 file is usually the result. It would seem that 200ms is long enough handling the EOS.

I had similar problem previously, my pipeline
videotestsrc do-timestamp="TRUE" ! videoflip method=0 ! tee name=t
t. ! queue ! videoconvert ! glupload ! glshader ! autovideosink async="FALSE"
t. ! queue ! identity drop-probability=1 ! videoconvert name=conv2 ! openh264enc ! h264parse ! avimux ! multifilesink async="FALSE" post-messages=true next-file=4
Then I just change drop-probability property on identity element
drop-probability = 1 + gst_pad_send_event(conv2_sinkpad, gst_event_new_eos()); - stop recording
drop-probability = 0 - resume recording

Related

How to detect one source of funnel plugin has ended in gstreamer pipeline?

I am using gstreamer to build a pipeline with two source. One is a file source (filesrc), the other is appsrc. When the filesrc got EOS, the pipeline do not quit. appsrc still get need-data signal and will never stop itself. It seems funnel plugin will wait for all sources to end before sending EOS to pipeline. Is there a way to get notified when filesrc got end of file?
gst-launch command looks like this:
gst-launch-1.0 funnel name=f \
appsrc name=appsrc-h264-sei do-timestamp=true block=true is-live=true ! video/x-h264, stream-format=byte-stream, alignment=au ! queue ! f. \
filesrc input.h264 ! queue ! f. \
f. ! queue ! h264parse ! video/x-h264, stream-format=byte-stream, alignment=au ! mp4mux ! filesink location=file.mp4
You can install a GstPadProbe at the the funnel input pad and check for the EOS event on the callback.

Save H264 encoded stream without re-encoding

I have a gstreamer pipeline that streams using :
v4l2src ! x264enc ! rtph264pay pt=96 ! udpsink host=ip port=8554
And this pipeline that receives this stream :
/ queue ! avdec_h264 ! appsink
udpsrc ! capsfilter ! rtpjitterbuffer ! rtph264depay ! tee !
\ queue ! h264parse ! mp4mux ! filesink
Simplified receiver pipeline without the tee is :
gst-launch-1.0 udpsrc port=8080 caps="lots-of-caps" ! rtpjitterbuffer ! rtph264depay ! h264parse ! mp4mux ! filesink location=/home/rish/Desktop/recorded.264 -e
Question :
Is there a way to save the H264 encoded stream received from udpsrc without having to re-encode it? How do I correctly close the filesink?
What I've tried so far : The discussion from this thread suggests the pipeline I've tried above but file is still corrupt. (not correctly closed).
This question asks a similar question. However I do not want to decode and re-encode. Another answer in the thread suggests using matroskamux element instead of mp4mux. This works, but I'd rather prefer using mp4mux (no particular reason, but I'd like to know why matroskamux works and mp4mux doesn't).
Your pipeline is already muxing without re-encoding, there is no encoder on your pipeline. h264parse is just a parser.
you've already got an answer on how to close the stream here: Sending EoS to filesink while removing branch from tee

In GStreamer how do I simultaneously playback and record an h264 AVI file of a v4l2src?

Recorded files with gstreamer-0.10 with FPS25 and FourCIF_Format plays in fast forward mode. Any solution would be appreciated. Some times skips 3-4 seconds in recorded files.
The pipeline I'm attempting to use is:
gst-launch v4l2src device=/dev/video2 !
'video/x-raw-yuv,width=704,height=576, framerate=25/1' ! tee
name=liveTee ! queue ! mfw_isink liveTee. ! queue ! vpuenc ! avimux !
filesink location=/home/Recording.avi
I'm gonna take a rough stab at it and re-format your question a bit. This is mostly a GStreamer and Freescale question, not so much QT.
gst-launch-1.0 -e videotestsrc pattern=ball do-timestamp=true
is-live=true ! timeoverlay !
'video/x-raw,width=704,height=576,framerate=25/1' ! tee name=liveTee !
queue leaky=downstream ! videoconvert !
ximagesink async=false
liveTee. ! queue leaky=downstream ! videoconvert ! queue ! x264enc !
avimux ! filesink location=/tmp/test.avi
The thing to keep in mind is that your encoder has to keep up with the live playback. So your pipeline needs to handle the case where the encoder falls out of sync. On the queue elements behind the tee, use the leaky attribute.
Then you also want to be careful about your video source and what it's supplying. It looks like in your case you want live video, but if your source was an existing video file the pipeline would probably need some more tweaking.
NOTE: It may be even simpler than that, just adding async=false to the videosink appears to be very important.

gstreamer recording m3u8 stream

I'm trying to record stream from m3u8 file.
This pipeline works:
gst-launch-0.10 -e souphttpsrc location=(mysrc.m3u8) ! queue ! hlsdemux ! queue ! mpegtsparse ! queue ! mpegtsdemux ! queue ! audio/mpeg ! queue ! filesink location=test.ts
and (sometimes) record audio stream.
But i can't record video, whatever i do it crashes.
I tried something like this:
gst-launch-0.10 souphttpsrc location=(mysrc.m3u8) ! queue ! hlsdemux ! queue ! mpegtsparse ! queue ! mpegtsdemux ! queue ! video/x-264 ! queue ! filesink location=test.ts
But it does nothing.
You are using gstreamer 0.10 which is obsolete and unmantained, all users should upgrade to the 1.x series.
Given that warning, it is not clear whether you want to save the mpegts stream or the streams inside it.
To save the mpegts stream you can just do:
gst-launch-1.0 http://path/to/your/stream.m3u8 ! hlsdemux ! filesink
Be aware that if the HLS playlist contains multiple bitrates hlsdemux might switch bitrate and it will fail as gst-launch-1.0 isn't capable of handling this. (it is a debugging and testing tool). You can likely set a fixed "connection-speed" to make it always use the same bitrate you desire to overcome this issue.
If you want to get only the video stream and you know it is H264, try:
gst-launch-1.0 http://path/to/your/stream.m3u8 ! hlsdemux ! tsdemux ! queue ! video/x-h264 ! filesink
It might be a better idea to save it to a container format to allow easier use later, with something like:
gst-launch-1.0 http://path/to/your/stream.m3u8 ! hlsdemux ! tsdemux ! queue ! video/x-h264 ! h264parse ! qtmux ! filesink
But, as I said, please move to 1.x, HLS is much better at 1.x than it was in 0.10 and it should work.

Why does my dv1394src to ogg file pipeline stall?

I am attempting to demux a live recording from a MiniDV camera using the dv1394src element and then transcode it into a vorbis/theora ogg file. My pipeline below stalls after a few seconds. I think I have queue elements in the right space.
gst-launch -e dv1394src ! dvdemux name=demux \
oggmux name=mux ! queue ! filesink location=/tmp/test.ogg \
demux. ! queue ! audioconvert ! vorbisenc ! queue ! mux. \
demux. ! queue ! dvdec ! ffmpegcolorspace ! theoraenc ! queue ! mux.
If I remove the muxer and add filesink end points to the video and audio paths then it does not stall, but that creates two files I have to mux afterwards. I would rather do it in one pipeline.
You could try using a multiqueue after the demuxer. The multiqueue might be able to balance the amount of queued data better.