Hi All ,
Could Team members please provide some pointer for below mentioned problem in Gstreamer-0.10 ( TI SDK )
1) With Gstreamer-0.10 the MUX element hangs when asked to change the state to NULL
( from PLAYING state to NULL state )
i.e
gst_element_set_state (mux, GST_STATE_NULL) , instruction hangs.
2) Same logic we tested on Gstreamer-1.0 on UBUNTU-14.04 logic where we are able to get
multiple files being created as the AVI MUX changes the state to NULL using the
same instruction ( this was done as proof of concept )
3) Attached is the stripped down sample to demonstrate the problem.
#define MACRO of VERSION can be used to compile same code effectively to
Gstreamer-0.10 ( VERSION = 0 ) & Gstreamer-1.0 ( VERSION = 1 )
Since we have the logic working on Gstreamer-1.0 , if group could please help us
to solve the above mentioned problem of " MUX getting hanged when asked to do an change of state"
we feel we could build up our solution quickly.
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <gst/gst.h> #define TIMER_DURATION 10 #define VERSION 0 GstElement *pipeline, *src, *timeoverlay, *clockoverlay, *q1, *q2, *filesink, *mux, *audiosrc, *capsfilter, *tempfilesink; GstCaps *acaps; GMainLoop *loop, *mainloop; GstPad *muxvideosinkpad, *muxaudiosinkpad, *muxsrcpad, *filesinkpad, *q1sinkpad, *q2sinkpad; static gulong probe_id; // probe ID GstBus *bus; GError *err = NULL; gchar *sinkname; char buffer[128]; volatile unsigned int attempt=0; unsigned int timer_count=0; unsigned int dynamic_filesink= 1; gboolean return_bool = FALSE, chunk = TRUE; unsigned long return_gulong =0; typedef enum { NO_NEW_FILE, // Keep current file destination NEW_FILE, // Switch file destination } NewFileStatus; static NewFileStatus newfile = NO_NEW_FILE; // Switch File Flag #if ( VERSION == 1) static GstPadProbeReturn eos_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { g_print("\t [ APP-BLOCK ]: EOS_PROBE [ START ] ===================\n"); if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS) return GST_PAD_PROBE_DROP; gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info)); #else static gboolean eos_cb (GstPad * pad, GstEvent * event, gpointer user_data) { g_print("\t [ APP-BLOCK ]: EOS_PROBE [ START ] ===================\n"); if (GST_EVENT_TYPE (event) != GST_EVENT_EOS){ return TRUE; } //Remove the probe first gst_pad_remove_event_probe (pad, probe_id); #endif gst_element_release_request_pad(mux, muxvideosinkpad); g_print("\t [ APP-BLOCK ]: About to set ELEMENTS as NULL \n"); gst_element_set_state (mux, GST_STATE_NULL); // Gst-0.10 hangs at this instruction gst_element_set_state (filesink, GST_STATE_NULL); // Remove unlinks automatically gst_bin_remove (GST_BIN (pipeline), mux); gst_bin_remove (GST_BIN (pipeline), filesink); GstElement *mux0 = gst_element_factory_make ("avimux",NULL); GstElement *fsink0 = gst_element_factory_make("filesink", NULL); mux = mux0; filesink = fsink0; if(!mux0 || !fsink0) { g_print("[ERROR]: Missing elements\n"); } gst_bin_add (GST_BIN (pipeline), mux); gst_bin_add (GST_BIN (pipeline), filesink); #if (VERSION == 1) sprintf( buffer, "test_%u.avi" , attempt); #else sprintf( buffer, "test_%d.avi" , attempt); #endif g_object_set(G_OBJECT (filesink),"location", buffer, NULL); muxsrcpad = gst_element_get_static_pad (mux,"src"); #if (VERSION == 1) muxvideosinkpad = gst_element_get_request_pad (mux, "video_%u"); #else muxvideosinkpad = gst_element_get_request_pad (mux, "video_%d"); #endif if (!gst_element_link_many (q1, mux,NULL )) { g_print ("[APP]: Failed to link DYNAMIC Pad's of elements"); return -3; } filesinkpad = gst_element_get_static_pad (filesink,"sink"); if (!gst_element_link_many (mux,filesink, NULL)) { g_print ("[APP]: Failed to link STATIC_2 Pad's of elements"); return -3; } g_print ("Moving to PLAYING\n"); gst_element_set_state (mux, GST_STATE_PLAYING); gst_element_set_state (filesink, GST_STATE_PLAYING); newfile = NO_NEW_FILE; chunk = TRUE; g_print("\t [ APP-BLOCK ]: EOS_PROBE [ STOP ] ===================\n"); #if ( VERSION == 1) return GST_PAD_PROBE_OK; #else return TRUE; #endif } #if ( VERSION == 1 ) static GstPadProbeReturn pad_probe_cb (GstPad * pad, GstPadProbeInfo * info,gpointer user_data) #else static gboolean pad_probe_cb (GstPad * pad, GstBuffer * buffer, gpointer user_data) #endif { unsigned int sleep_count =0; g_print("\t [ APP-BLOCK ]: VIDEO_PAD_BROBE [ START ] ===================\n"); #if ( VERSION == 1) gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info)); #else gst_pad_remove_buffer_probe (pad, probe_id); #endif g_object_set (G_OBJECT(src), "pattern",attempt, NULL); #if ( VERSION == 1 ) gst_pad_add_probe (filesinkpad,GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, eos_cb, user_data, NULL); #else probe_id = gst_pad_add_event_probe (filesinkpad, G_CALLBACK(eos_cb), user_data); #endif gst_pad_send_event (muxvideosinkpad, gst_event_new_eos ()); // Wait til the EOS have been processed while(newfile != NO_NEW_FILE){ g_print("In sleep %d \n",sleep_count); sleep_count=sleep_count+1; sleep(1); } g_print("\t [ APP-BLOCK ]: VIDEO_PAD_BROBE [ STOP ] ===================\n"); #if ( VERSION == 1) return GST_PAD_PROBE_OK; #else return TRUE; #endif } // End brace of video_pad_probe_cb static gboolean timeout_cb (gpointer user_data) { attempt = attempt+1; timer_count=timer_count+1; if ( chunk == TRUE ) { chunk = FALSE; g_print("\t [ APP-TIMER ]: IN-TIMER %d [ BEFORE-BLOCKING ] =========\n",timer_count); newfile = NEW_FILE; #if ( VERSION == 1 ) gst_pad_add_probe (q1sinkpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,pad_probe_cb, user_data, NULL); #else probe_id = gst_pad_add_buffer_probe (q1sinkpad, pad_probe_cb, user_data); #endif } g_print("\t [ APP-TIMER ]: IN-TIMER %d =========\n",timer_count); if ( timer_count == 12 ){ return FALSE; } return TRUE; } // End brace of "timeout_cb" static gboolean bus_cb (GstBus * bus, GstMessage * msg, gpointer user_data) { switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR:{ GError *err = NULL; gchar *dbg; gst_message_parse_error (msg, &err, &dbg); gst_object_default_error (msg->src, err, dbg); g_error_free (err); g_free (dbg); g_main_loop_quit(mainloop); break; } case GST_MESSAGE_STATE_CHANGED: { GstState old_state, new_state; gst_message_parse_state_changed (msg, &old_state, &new_state, NULL); g_print ("[ APP - MESSAGE ]: Element %s changed state from %s to %s.\n", GST_OBJECT_NAME (msg->src), gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); break; } case GST_MESSAGE_WARNING:{ GError *err = NULL; gchar *name, *debug = NULL; name = gst_object_get_path_string (msg->src); gst_message_parse_warning (msg, &err, &debug); g_print ("\n[ APP - MESSAGE ]: ERROR: from element %s: %s\n", name, err->message); if (debug != NULL) g_print ("%s \n\n",debug); g_error_free (err); g_free (debug); g_free (name); break; } case GST_MESSAGE_EOS:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_EOS\n"); break; } case GST_MESSAGE_INFO:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_INFO\n"); break; } case GST_MESSAGE_TAG:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_TAG\n"); break; } case GST_MESSAGE_BUFFERING:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_BUFFERING\n"); break; } case GST_MESSAGE_STEP_DONE:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_STEP_DONE\n"); break; } case GST_MESSAGE_CLOCK_PROVIDE:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_CLOCK_PROVIDE\n"); break; } case GST_MESSAGE_CLOCK_LOST:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_CLOCK_LOST\n"); break; } case GST_MESSAGE_NEW_CLOCK:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_NEW_CLOCK\n"); break; } case GST_MESSAGE_APPLICATION:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_APPLICATION\n"); break; } case GST_MESSAGE_ELEMENT:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_ELEMENT\n"); break; } case GST_MESSAGE_SEGMENT_START:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_SEGMENT_START\n"); break; } case GST_MESSAGE_SEGMENT_DONE:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_SEGMENT_DONE\n"); break; } case GST_MESSAGE_LATENCY:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_LATENCY\n"); break; } case GST_MESSAGE_ASYNC_START:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_ASYNC_START\n"); break; } case GST_MESSAGE_ASYNC_DONE:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_ASYNC_DONE\n"); break; } case GST_MESSAGE_REQUEST_STATE:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_REQUEST_STATE\n"); break; } case GST_MESSAGE_STEP_START:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_STEP_START\n"); break; } case GST_MESSAGE_QOS:{ g_print ("[ APP - MESSAGE ]: GST_MESSAGE_QOS\n"); break; } default: break; } return TRUE; }//End brace of SWITCH condition int main (int argc, char **argv) { gst_init (&argc, &argv); // 0 - Creating the PIPELINE pipeline = gst_pipeline_new ("pipeline"); // 1 - Creating the SRC & TIMEOVERLAY src = gst_element_factory_make ("videotestsrc", NULL); g_object_set (G_OBJECT(src), "pattern",attempt, NULL); g_object_set (G_OBJECT(src), "do-timestamp",attempt, NULL); g_object_set (G_OBJECT(src), "is-live", TRUE, NULL); clockoverlay = gst_element_factory_make ("clockoverlay", NULL ) ; g_object_set (G_OBJECT (clockoverlay), "time-format","%d-%b-%Y / %H:%M:%S",NULL); timeoverlay = gst_element_factory_make ("timeoverlay", NULL ) ; // 2 - Creating the QUEUE q1 = gst_element_factory_make ("queue", NULL); q2 = gst_element_factory_make ("queue", NULL); // 3 - Creating the MUX mux = gst_element_factory_make("avimux",NULL); // 4 - Creating the FILESINK filesink = gst_element_factory_make ("filesink", NULL); sprintf( buffer, "test_%d.avi" , attempt); g_print("\n\t [APP]: Created new file of %s \n",buffer); g_object_set(G_OBJECT(filesink),"location", buffer, NULL); // 7 - Adding all the elements in to BIN gst_bin_add_many (GST_BIN (pipeline),mux,filesink, NULL); gst_bin_add_many (GST_BIN (pipeline), src, clockoverlay ,timeoverlay, q1,NULL); // 8 - Linking all static pad if (!gst_element_link_many (src, clockoverlay,timeoverlay , q1, NULL )) { g_print ("[APP]: Failed to link src, clockoverlay,timeoverlay \n"); return -3; } if (!gst_element_link_many (mux,filesink, NULL)) { g_print ("[APP]: Failed to link mux,filesink "); return -3; } // 9 - Linking DYNAMIC PAD #if ( VERSION == 1 ) muxvideosinkpad = gst_element_get_request_pad (mux, "video_%u"); #else muxvideosinkpad = gst_element_get_request_pad (mux, "video_%d"); #endif sinkname = gst_pad_get_name (muxvideosinkpad); g_print ("\t [APP]: A new pad %s was created\n\n", sinkname); if (!gst_element_link_many (q1, mux,NULL )) { g_print ("[APP]: Failed to link DYNAMIC Pad's of q1, mux"); return -3; } g_free (sinkname); // 10 - Getting the blocking PAD muxsrcpad = gst_element_get_static_pad (mux,"src"); filesinkpad = gst_element_get_static_pad (filesink,"sink"); q1sinkpad = gst_element_get_static_pad (q1,"sink"); if (q1sinkpad == NULL){ g_print("Q1SINK pad is NULL \n"); return -4; } // 11 - Starting the PIPELINE if (gst_element_set_state (pipeline,GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { g_error ("[APP]: Failed to go into PLAYING state"); return -6; } mainloop = g_main_loop_new (NULL, FALSE); gst_bus_add_watch (GST_ELEMENT_BUS (pipeline), bus_cb, mainloop); g_timeout_add_seconds (TIMER_DURATION, timeout_cb, mainloop); g_main_loop_run (mainloop); // 10 - Stopping the PIPELINE gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0; }