Saving webcam jpeg stream to multiple files with gstreamer - gstreamer

I'm trying to save a MJPEG stream from a logitech C920 webcam to multiple video files (matroska).
I've got this pipeline: (1 mkv file every 60s)
gst-launch-1.0 -ev v4l2src device=/dev/video0 \
! image/jpeg,width=1280,height=720,framerate=24/1 \
! matroskamux ! multifilesink next-file=max-duration max-file-duration=60000000000 location='test1-%02d.mkv'
It outputs several files, as expected, but the files have errors, so tools like avidemux can't play them back. mkvalidator reports these:
WRN080: Unknown element [FF] at 293 size 88
WRN080: Unknown element [FF] at 494 size 64
WRN080: Unknown element [7D][01] at 566 size w98603107602
WRN801: The segment has no SeekHead section
WRN0B8: Track #1 is defined but has no frame
BTW, saving to a single file using filesink produces an mkv file without errors.
Is there a way to save multiple mkv files properly?
Any other container is also OK, but I cannot transcode (need low CPU load) and I cannot use raw (need HD with high fps).
I'm using GStreamer 1.8.2 on Ubuntu 16.04.1.
Thanks.
Update:
Following the advice below, I tried with splitmuxsink:
gst-launch-1.0 -e v4l2src device=/dev/video1 \
! image/jpeg,width=1280,height=720,framerate=24/1 \
! splitmuxsink muxer=matroskamux location='test1-%02d.mkv' \
max-size-time=10000000000
But it doesn't work: The file is never split and keeps growing in size.

The following pipeline seems to work:
gst-launch-1.0 -e v4l2src ! x264enc key-int-max=10 ! h264parse ! splitmuxsink muxer=matroskamux location='test1-%02d.mkv' max-size-time=60000000000
multifilesink doesn't know nothing about the container format, so you must use splitmuxsink to do the spliting.
Here is the quote from multifilesink doc:
It is not possible to use this element to create independently
playable mp4 files, use the splitmuxsink element for that instead.

I've got success with an upgraded GStreamer (Ubuntu 18.04)
$ gst-launch-1.0 --gst-version
GStreamer Core Library version 1.14.1
Here is a pipeline with an AVI container, where a new file is generated every ten seconds:
gst-launch-1.0 -e v4l2src device=/dev/video1 \
! image/jpeg,width=1280,height=720,framerate=24/1 \
! splitmuxsink muxer=avimux location='test1-%02d.avi' max-size-time=10000000000
It also works with matroskamux.

Related

Gstreamer preserve timestamp when encoding ts segments

I have a series of ts files(h265) which are part of a m3u8 manifest which are fed into the pipeline through fdsrc. I use the following pipeline to transcode them to H264 to be played on a Hlsjs web browser.
cat 2021-06-30T00-55-41Z_2000000.ts | gst-launch-1.0 -q mpegtsmux name=mux ! fdsink fd=1 fdsrc ! tsdemux name=demux demux. ! queue ! h265parse ! nvh265dec ! videoconvert ! videoscale ! video/x-raw,width=640,height=360 ! nvh264enc ! mux.
The individual ts segments are transcoded successfully and can be played.
However the DTS is out of aligment and when these ts segments are played as part of the hls manifest, it is not able to play as DTS is out of order.
[mpegts # 0x7fb69100a400] DTS 6496420096 < 6496446847 out of order
[hls # 0x7fb69580ea00] DTS 6496420096 < 6496446847 out of order
In FFMPEG we have copyts to preserve the timestamp.
Is there something similar in gstreamer to preserve the timestamp? Or atleast generate a timestamp with the current time so that the player doesnt complain?
I tried fdsrc do-timestamp=true but that didnt work.
I appreciate any help in this.
Best

GStreamer - RTSP to HLS / mp4

I try to save RTSP h.264 stream to HLS mp4 files:
gst-launch-1.0 rtspsrc location="rtsp://....." ! rtph264depay ! h264parse ! matroskamux ! hlssink max-files=0 playlist-length=0 location="/home/user/ch%05d.mp4" playlist-location="/home/user/list.m3u8" target-duration=15
As a result - there is only one file ch00000.mp4, which includes the whole videostream (3min instead of 15sec in "target-duration").
If I save to mpegtsmux / ts files - all is ok for the same command.
What is wrong? Thanks in advance.
HLS consists of MPEG transport stream segments. So first: matroskamux does not make sense here. You will need mpegtsmux instead. To indicate what it really is you normally would name the files with a .ts extension. It may still work for GStreamer as it is just a file name - players may reject playing it because the expect another sort of file format.
E.g.
gst-launch-1.0 rtspsrc location="rtsp://....." ! rtph264depay ! h264parse ! \
mpegtsmux ! hlssink max-files=0 playlist-length=0 location="/home/user/ch%05d.ts" \
playlist-location="/home/user/list.m3u8" target-duration=15
Do you have to use gstreamer? Otherwise I believe this ffmpeg command does what you want.
ffmpeg -i rtsp://... -c copy -hls_list_size 10 -hls_segment_type fmp4 output.m3u8

gstreamer: pass frame PTS in command line API

Currently I have a setup like this.
my-app | gst-launch-1.0 -e fdsrc ! \
videoparse format=GST_VIDEO_FORMAT_BGR width=640 height=480 ! \
videoconvert ! 'video/x-raw, format=I420' ! x265enc ! h265parse ! \
matroskamux ! filesink location=my.mkv
From my-app I am streaming raw BGR frame buffers to gst. How can I also pass presentation timestamps (PTSs) for those frames? I have somewhat full control over my-app. I can open other pipes to gst from it.
I know I have the option to use gstreamer C/C++ API or write a gstreamer plugin, but I was trying to avoid this.
I guess you can set a framerate for the videoparse element. You can also try do-timestamp=true for the fdsrc - maybe it requires a combination of both.
If you have the PTS in my-app you would probably need to wrap buffers and PTS in a real GstBuffer and use gdppay and gdpdepay as payload between the link.
For example if your my-app would dump the images in the following format:
https://github.com/GStreamer/gstreamer/blob/master/docs/random/gdp
(not sure how recent this info document is)
You could receive the data with the following pipeline:
fdsrc ! gdpdepay ! videoconvert ! ..
No need for resolution and format either as it is part of the protocol too. And you will have PTS as well if set.
If you can use GStreamer lib in my-app you could some soome pipeline like this:
appsrc ! gdppay ! fakesink dump=true
And you would push your image buffers with PTS to the appsink.
See https://github.com/GStreamer/gst-plugins-bad/tree/master/gst/gdp for some examples how gdp is used as a protocol.

Which elements are contained in decodebin?

I'm looking to decode and demux an mp4 file with gst-launch-1.0. Instead of using a bin - decodebin - I'd rather work with the seperate elements. Unfortunately, I did not find this.
My question is simple: what basic elements are contained in the decodebin?
If you can direct me to a place where I can find the composition of other bins or autopluggers that whould also be nice.
The decodebin will use all available elements in your gstreamer installation. Remember that you can launch the pipeline with decodebin and using verbose -v and guess what elements is the decodebin creating. For example, in the next pipeline that plays succesfully a mp4 file (video and audio):
gst-launch-1.0 -v filesrc location=/home/usuario/GST_/BigBuckBunny_320x180.mp4 ! queue ! qtdemux name=demuxer demuxer.video_0 ! queue ! decodebin ! videoconvert ! autovideosink demuxer.audio_0 ! queue ! decodebin ! audioconvert ! autoaudiosink
Watching the output I can conclude that the resulting pipeline is:
gst-launch-1.0 -v filesrc location=/home/usuario/GST_/BigBuckBunny_320x180.mp4 ! queue ! qtdemux name=demuxer demuxer.video_0 ! queue ! h264parse ! avdec_h264 ! videoconvert ! autovideosink demuxer.audio_0 ! queue ! aacparse ! avdec_aac ! audioconvert ! autoaudiosink
The playback components from gstreamer are available here. The playbin element will give you the full pipeline (video, audio, etc...) from the uri input.
For example, if you even don't know what kind of source you have, you can use playbin element:
gst-launch-1.0 playbin uri=file:///home/usuario/GST_/BigBuckBunny_320x180.mp4 -v
This will play automatically the file (if it is possible), and verbose output will show you the used plugins and status information.
gst-launch-1.0 can create .dot file with pipeline diagram every time pipeline changes state. To enable this functionality, set GST_DEBUG_DUMP_DOT_DIR variable to path where generated files should be saved. In this dir gst-launch-1.0 will create files like 0.00.00.069441527-gst-launch.READY_PAUSED.dot. You can then convert them to .png files using dot from ghraphviz package. To convert one file, use following command:
dot -Tpng 0.00.00.069441527-gst-launch.READY_PAUSED.dot -o0.00.00.069441527-gst-launch.READY_PAUSED.png
You also can convert them all, using following command in bash shell:
ls -1 *.dot | xargs -I{} dot -Tpng {} -o{}.png
You can find more details here:
How to generate a Gstreamer pipeline diagram (graph)

Timing is lost when converting h264 video to non segmented mp4 using gstreamer

I would like to create a non segmented .mp4 video from a matroska source. I have seen this post and created a similar pipeline. My source contains only h264 video and no sound, so my pipeline looks like this:
gst-launch-1.0 filesrc location=x.mkv ! matroskademux ! h264parse ! mp4mux ! filesink location=x.mp4
However running gst-discoverer-1.0 on the result gives a duration of 0:00:00.000000000. Also vlc is not able to play the resulting .mp4 file and it cannot be used in a HTML5 <video> element (which is the final purpose of this conversion).
If I create a segmented .mp4 by adding fragment-duration=1000 to the mp4mux element, then vlc can play the .mp4, but this is not what I want. I need a .mp4 where the total length is known. What am I doing wrong?
Additional information: The length was present in the matroska source, as displayed by gst-discoverer-1.0, and vlc can display that source. I also can replay the non segmented .mp4 with gstreamer (using gst-launch-1.0 filesrc location=x.mp4 ! qtdemux ! h264parse ! avdec_h264 ! videoconvert ! autovideosink). Inspecting the generated .dot file reveals a framerate of 10000/1 coming out of qtdemux which seems quite strange.
The solution was to add disable-passthrough=true to the h264parse element, so the pipeline now looks like this:
gst-launch-1.0 filesrc location=x.mkv ! \
matroskademux ! \
h264parse disable-passthrough=true ! \
mp4mux ! \
filesink location=x.mp4
Now the resulting .mp4 file includes the timing information and can nicely be played with vlc as well as in a <video> tag including forward/backward navigation.