source -> frameratefilter -> encoder -> h264parse -> splitmuxsink
This is my code in simple:
static gchar* cb_FormatLocation(GstElement* splitmuxsink, guint fragment_id, const int* offset){ //Set filename return filename; }gboolean timeout_callback(gpointer data){ if ( //meet signal stop video ){ g_main_loop_quit((GMainLoop*)data); return FALSE; } return TRUE; } int main(int argc, char * argv[]){ GstElement *pipeline, *source, *frameratefilter_, *h264parse, *encoder, *splitmuxsink; /* Initialize GStreamer */ /* Create the empty pipeline */ /* Create the elements */ // Set parameters for some elements g_object_set(G_OBJECT(source), "device", "/dev/video0", NULL); g_object_set(G_OBJECT(splitmuxsink), "location", filename, NULL); g_object_set(G_OBJECT(splitmuxsink), "max-size-time", nanoDuration, NULL); g_object_set(G_OBJECT(splitmuxsink), "async-handling", 1, NULL); g_signal_connect (G_OBJECT(splitmuxsink), "format-location", G_CALLBACK(cb_FormatLocation), &offset); /* Build the pipeline */ gst_bin_add_many (GST_BIN (pipeline), source, frameratefilter, encoder, h264parse, splitmuxsink, NULL); if ( gst_element_link_many(source, frameratefilter, encoder, h264parse, splitmuxsink, NULL) != TRUE ){ g_error("Failed to link save elements!"); gst_object_unref (pipeline); return -1; } /* Start playing */ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { g_printerr ("Unable to set the pipeline to the playing state.\n"); gst_object_unref (pipeline); return -1; } g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 1 , timeout_callback , loop, NULL); g_main_loop_run (loop); g_main_loop_unref(loop); bus = gst_element_get_bus (pipeline); gst_element_send_event(source, gst_event_new_eos()); gst_element_set_state (splitmuxsink, GST_STATE_PAUSED); gst_element_set_state (splitmuxsink, GST_STATE_READY); gst_element_set_state (splitmuxsink, GST_STATE_NULL); gst_element_send_event(splitmuxsink, gst_event_new_eos()); gst_element_send_event(frameratefilter, gst_event_new_eos()); gst_element_send_event(encoder, gst_event_new_eos()); gst_element_send_event(h264parse, gst_event_new_eos()); gst_element_send_event(pipeline, gst_event_new_eos()); gst_object_unref (bus); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0; }
I set video duration to 5 minutes. If I close the pipeline earlier, my video will be broken. I can't play it with error:
ERROR GStreamer encountered a general stream error. for file://video1.mp4 ERROR debug information: ../../../imx-gst1.0-plugin-4.1.6/plugins/aiurdemux/aiurdemux.c(1015): aiurdemux_pull_task (): /GstPlayBin:playbin/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstAiurDemux:aiurdemux0: streaming stopped, reason error, state 1 Reached end of play list.
And this is output after send EOS event which I get from gst-debug level 5 with GST_EVENT* keyword.
0:00:14.927594335 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b170 eos 28174 0:00:14.946297335 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b128 eos 28174 0:00:14.946422335 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b0e0 eos 28174 0:00:14.946506335 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b098 eos 28174 0:00:14.946583668 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b050 eos 28174 0:00:14.946658002 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b008 eos 28174 0:00:14.946733335 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6af60 eos 28174 0:00:14.946809002 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6af60 eos 28174 0:00:14.946920002 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b008 eos 28174 0:00:14.949387668 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b050 eos 28174
0:00:14.949892002 20227 0x55ce3e40 DEBUG GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:splitmuxsink0:video have event type eos event: 0x55b6b050, time 99:99:99.999999999, seq-num 8610, (NULL) 0:00:14.950435002 20227 0x55ce3e40 INFO
GST_EVENT gstpad.c:5622:gst_pad_send_event_unchecked:splitmuxsink0:video Received event on flushing pad. Discarding 0:00:14.951042002 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b098 eos 28174 0:00:14.951594668 20227 0x55ce3e40 DEBUG GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:capsfilter0:sink have event type eos event: 0x55b6b098, time 99:99:99.999999999, seq-num 8611, (NULL) 0:00:14.951859002 20227 0x55ce3e40 DEBUG
GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:<vpuenc_h264-0:sink> have event type eos event: 0x55b6b098, time 99:99:99.999999999, seq-num 8611, (NULL) 0:00:14.952538668 20227 0x55ce3e40 DEBUG
GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:h264parse0:sink have event type eos event: 0x55b6b098, time 99:99:99.999999999, seq-num 8611, (NULL) 0:00:14.950342002 20227 0x55ca28f0 DEBUG
GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:textoverlay:video_sink have event type eos event: 0x55b6b170, time 99:99:99.999999999, seq-num 8587, (NULL) 0:00:14.953315335 20227 0x55ca28f0 DEBUG
GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:capsfilter0:sink have event type eos event: 0x55b6b170, time 99:99:99.999999999, seq-num 8587, (NULL) 0:00:14.953753335 20227 0x55ce3e40 DEBUG
GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:splitmuxsink0:video have event type eos event: 0x55b6b098, time 99:99:99.999999999, seq-num 8611, (NULL) 0:00:14.953990335 20227 0x55ce3e40 INFO
GST_EVENT gstpad.c:5622:gst_pad_send_event_unchecked:splitmuxsink0:video Received event on flushing pad. Discarding 0:00:14.954883668 20227 0x55ce3e40 DEBUG GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b0e0 eos 28174 0:00:14.955373668 20227 0x55ce3e40 DEBUG GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:<vpuenc_h264-0:sink> have event type eos event: 0x55b6b0e0, time 99:99:99.999999999, seq-num 8612, (NULL) 0:00:14.956013335 20227 0x55ce3e40 DEBUG
GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b128 eos 28174 0:00:14.956592668 20227 0x55ce3e40 DEBUG
GST_EVENT gstpad.c:5517:gst_pad_send_event_unchecked:h264parse0:sink have event type eos event: 0x55b6b128, time 99:99:99.999999999, seq-num 8613, (NULL) 0:00:14.957167002 20227 0x55ce3e40 DEBUG
GST_EVENT gstevent.c:302:gst_event_new_custom: creating new event 0x55b6b1b8 eos 28174
As my code above, I send EOS event to each elements to stop pipeline. The pipeline also stop but video can't be played. Then, I tried to send EOS to only pipeline and wait EOS on bus message to set pipeline to NULL state. But my program is hang.
This is the way which I mentioned:
gst_element_send_event(pipeline, gst_event_new_eos()); msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,GST_MESSAGE_ERROR | GST_MESSAGE_EOS); if (msg != NULL){ gst_message_unref (msg); }
How can I close video by the right way ?