#include #include static int callback_id; gboolean bus_call(GstBus *bus, GstMessage *msg, void *data) { gchar *debug; GError *err; GMainLoop *loop = (GMainLoop*)data; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: g_print("EOS received on OBJ NAME %s\n",GST_OBJECT_NAME(msg->src)); g_main_loop_quit (loop); break; case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, &debug); g_free(debug); g_print("BUS CALL %s", err->message); g_error_free(err); g_main_loop_quit (loop); break; default: break; } return TRUE; } /** * drop_eos_probe: * @pad: pad receiving the event * @event: received event * @u_data: main pipeline * * Event probe that drop all eos events. * * Returns: FALSE to drop the event, TRUE otherwise */ gboolean drop_eos_probe (GstPad * pad, GstEvent * event, gpointer data) { gboolean ret = TRUE; static int called = 0; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: called++; if(called == 1) // stop the recording { g_print("Removing recording bin\n"); GstElement *pipeline = (GstElement*)data; GstElement *rec_bin = gst_bin_get_by_name(GST_BIN(pipeline),"recording-bin"); GstElement *tee = gst_bin_get_by_name(GST_BIN(pipeline), "viewing-tee"); GstPad *srcpad = gst_element_get_pad(tee,"src1"); GstPad *sinkpad = gst_element_get_pad(rec_bin,"sink"); gst_pad_set_blocked(srcpad, TRUE); gst_pad_unlink(srcpad, sinkpad); gst_element_remove_pad(tee, srcpad); gst_bin_remove(GST_BIN(pipeline), rec_bin); gst_pad_set_blocked(srcpad, FALSE); gst_element_set_state(GST_ELEMENT(rec_bin), GST_STATE_NULL); ret = FALSE; } else g_print("caught %d Not Dropping\n",called); break; default: break; } return ret; } /** * stop_encoding: * @data: main pipeline * * This is a glib function that gets called every 2 seconds, once called 3 times it will issue an EOS to the bin's sink pad * * Returns: FALSE to stop the event loop calling again, TRUE otherwise */ gboolean stop_encoding(gpointer *data) { static int called = 0; called++; g_print("CALLED!! %d times\n",called); if(called == 3) { GstElement *pipe = (GstElement*)data; GstElement *recording = gst_bin_get_by_name(GST_BIN(pipe),"encoding-queue"); GstPad *sinkpad = gst_element_get_static_pad(recording,"sink"); gst_pad_send_event(sinkpad,gst_event_new_eos()); } return (called == 4)?FALSE:TRUE; } int main(int argc, char* argv[]) { GMainLoop *loop; gst_init(&argc,&argv); loop = g_main_loop_new (NULL, FALSE); GstElement *pipeline, *source, *vtee, *vqueue, *tover, *xvsink, *equeue, *encoder, *muxer, *filesink; GstBin *recording; GstBus *bus; GstPad *srcpad,*sinkpad; // Create gstreamer elements pipeline = gst_pipeline_new ("eos-test-player"); source = gst_element_factory_make ("videotestsrc", "viewing-file-source"); vtee = gst_element_factory_make ("tee", "viewing-tee"); vqueue = gst_element_factory_make ("queue2", "viewing-queue"); tover = gst_element_factory_make ("timeoverlay", "viewing-overlay"); xvsink = gst_element_factory_make ("xvimagesink", "viewing-xvsink"); recording = GST_BIN(gst_bin_new("recording-bin")); equeue = gst_element_factory_make ("queue2", "encoding-queue"); encoder = gst_element_factory_make ("ffenc_mpeg4", "encoding-encoder"); muxer = gst_element_factory_make ("ffmux_mp4", "encoding-muxer"); filesink = gst_element_factory_make ("filesink", "encoding-filesink"); if(!pipeline || !source || !vtee || !vqueue || !xvsink || !tover ) { g_print("Unable to create all necessary elements\n"); return -1; } bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); g_object_set(G_OBJECT(source),"num-buffers",400, NULL); g_object_set(G_OBJECT(filesink),"location","/tmp/output.mp4", NULL); g_object_set (G_OBJECT (tover), "halign", "right", NULL); g_object_set (G_OBJECT (tover), "valign", "top", NULL); g_object_set (G_OBJECT (tover), "shaded-background", TRUE, NULL); /* create the recording bin */ gst_bin_add_many (recording, equeue,encoder,muxer,filesink,NULL); sinkpad = gst_element_get_static_pad(equeue,"sink"); gst_element_add_pad(GST_ELEMENT(recording),gst_ghost_pad_new("sink",sinkpad)); gst_object_unref(GST_OBJECT(sinkpad)); gst_element_link_many(equeue,encoder,muxer,filesink,NULL); /* we add all elements into the pipeline */ gst_bin_add_many (GST_BIN (pipeline), source, vtee, vqueue, tover, xvsink, recording, NULL); /* link elements */ gst_element_link_many(source,tover,vtee,NULL); srcpad = gst_element_get_request_pad(vtee,"src0"); sinkpad = gst_element_get_pad(vqueue,"sink"); gst_pad_link(srcpad,sinkpad); gst_element_link(vqueue,xvsink); /* link the viewing pipeline into the bin */ srcpad = gst_element_get_request_pad(vtee,"src1"); sinkpad = gst_element_get_pad(GST_ELEMENT(recording),"sink"); gst_pad_link(srcpad,sinkpad); /* EOS probe */ gst_pad_add_event_probe (gst_element_get_static_pad(muxer,"src"), G_CALLBACK (drop_eos_probe), pipeline); /* Iterate */ g_print ("Running...\n"); gst_element_set_state(pipeline,GST_STATE_PLAYING); callback_id = g_timeout_add_seconds(2,(GSourceFunc)stop_encoding,pipeline); g_main_loop_run (loop); /* Out of the main loop, clean up nicely */ g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); return 0; }