Discussion:
Changing filesink location dynamically
ivan-perez
2017-02-01 16:30:42 UTC
Permalink
Hello

I have a pipeline which gets a video in H.264 format from a camera and
splits it into two sinks: a RTP sink and a file sink. I want the file sink
to create videos of 10 seconds every minute.

This is my pipeline at the moment:

fdsrc \
!
video/x-h264,width=320,height=240,framerate=30/1,profile=baseline,stream-format=avc,alignment=au
\
! h264parse \
! tee name=split \
split. \
! queue max-size-buffers=100 max-size-bytes=102400
max-size-time=250000000 \
! rtph264pay config-interval=1 pt=96 \
! multiudpsink sync=false \
split. \
! queue \
! mp4mux name=mp4mux \
! filesink location=video1.mp4 name=fsink

So, in one thread of my application in C, I try to stop the recording of the
first video and then create a new one after 50 seconds. This is my code:

/* pipeline started */
int i;
for (i = 2; i < 10; i++) {
sleep(10);
gst_element_send_event(mp4mux, gst_event_new_eos());
gst_element_set_state(fsink, GST_STATE_NULL);

sleep(50);
g_object_set(fsink, "location", "video{$i}.mp4", NULL);/* of course
with that `$i` properly set */
gst_element_set_state(fsink, GST_STATE_PLAYING);
}

What do I get? Right after the EOS event is sent into the pipeline, the
whole pipeline stops. I get a GST_MESSAGE_EOS in the main loop and it
therefore stops. It's like that EOS is going up in the pipeline and being
transmitted into all the elements, while what I want is that the EOS event
is only sent to the 'mp4mux' and its children (i.e. the 'filesink' element).
What's more, the video is not playable (VLC says its format is not correct).

What am I doing wrong? Thanks in advance!

Kind regards.



--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Changing-filesink-location-dynamically-tp4681677.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
Nicolas Dufresne
2017-02-01 19:35:22 UTC
Permalink
Let's say it's more complicated then that.
Post by ivan-perez
So, in one thread of my application in C, I try to stop the recording of the
    /* pipeline started */
    int i;
    for (i = 2; i < 10; i++) {
        sleep(10);
        gst_element_send_event(mp4mux, gst_event_new_eos());
        gst_element_set_state(fsink, GST_STATE_NULL);
You may get random wrong state error doing that. Since the flow will
continue. As you want to drop the flow during the following sleep, you
probably want to setup a valve, and set the "drop" property to true
during the wait.
Post by ivan-perez
        
        sleep(50);
        g_object_set(fsink, "location", "video{$i}.mp4", NULL);/* of
course
with that `$i` properly set */
        gst_element_set_state(fsink, GST_STATE_PLAYING);
I have doubt this is sufficient. The pads in the mp4mux ! fsink chain
will have the EOS flag set. You need to send a flush-start followed by
flush-stop event in order to reset those elements pads. Afterward, you
probably need to set a pad offset on the mp4mux pad(s) in order to
compensate for the time that has been running meanwhile (that I would
test first).
Post by ivan-perez
    }
What do I get? Right after the EOS event is sent into the pipeline, the
whole pipeline stops. I get a GST_MESSAGE_EOS in the main loop and it
therefore stops. It's like that EOS is going up in the pipeline and being
transmitted into all the elements, while what I want is that the EOS event
is only sent to the 'mp4mux' and its children (i.e. the 'filesink' element).
What's more, the video is not playable (VLC says its format is not correct).
What am I doing wrong? Thanks in advance!
For this last step, you have to drop the EOS event from being sent to
your pipeline. For that you'll have to create your own subclass of
GstBin and drop EOS event in handle_message() vfunc.

While at it, you'll need data probes to monitor the running-time for
when you'll start recording again. Instead of using sleeps, you could
look at the delays in running-time instead of using 10/50s sleeps.

Nicolas
Tim Müller
2017-02-05 11:08:11 UTC
Permalink
Post by ivan-perez
I have a pipeline which gets a video in H.264 format from a camera
and splits it into two sinks: a RTP sink and a file sink. I want the
file sink to create videos of 10 seconds every minute.
Couple of things you could look into:

a) we have something called splitmuxsink, which allows you to start a
new file every N seconds/minutes. It will automatically make sure that
files start with a keyframe and are playable independently. Having said
that, it depends on the sender of course, if they send key frames
frequently enough.

You could just keep creating files of ca. 10 seconds and delete 5 out
of 6 files so you only get 10 secs every minute :)

Depends what you want to do with it exactly I suppose.


b) you can check out this example:
https://people.freedesktop.org/~tpm/code/test-backlog-recording-h264.c
(you can do it without a backlog too of course)

And just start/stop things with a timer then.

Cheers
-Tim
--
Tim Müller, Centricular Ltd - http://www.centricular.com
Loading...