问题
I am building a music player based on gstreamer-0.10. I am able to play the successfully , but I have issues when I change the state of the pipeline. I have posted the code to initialize and start the pipeline below :
void start_gstreamer()
{
gst_init(0,NULL);//call to initialise gstreamer
time_val=0;//set to default value
volume = 1.0;//set volume to default value
player = gst_element_factory_make ("playbin2", "player");//get pipeline
equalizer = gst_element_factory_make ("equalizer-10bands", "equalizer");//get the 10band equalizer
convert = gst_element_factory_make ("audioconvert", "convert");
sink = gst_element_factory_make ("autoaudiosink", "audio_sink");//get the audio-sink
if (!equalizer || !convert || !sink)//check is all elements were created
{
g_printerr ("Not all elements could be created.\n");
//return -1;
}
//int i=0;
/* Create the sink bin, add the elements and link them */
bin = gst_bin_new ("audio_sink_bin");//get new bin
gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL);//add elements to bin
if(!(gst_element_link_many (equalizer, convert, sink, NULL)))//link all elements
g_print("Could not link all elements\n");
pad = gst_element_get_static_pad (equalizer, "sink");//set equalizer to sink
ghost_pad = gst_ghost_pad_new ("sink", pad);//get a ghost pad to sink
gst_pad_set_active (ghost_pad, TRUE);
gst_element_add_pad (bin, ghost_pad);//add ghost pad to the bin
gst_object_unref (pad);//unreference pad
gst_element_set_state (player, GST_STATE_READY);//set pipeline to ready state
//gst_element_set_state (player, GST_STATE_PAUSED);
/* Configure the equalizer */
g_object_set (G_OBJECT (equalizer), "band0",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band1",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band2",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band3",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band4",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band5",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band6",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band7",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band8",(gdouble) 0.0, NULL);
g_object_set (G_OBJECT (equalizer), "band9",(gdouble) 0.0, NULL);
/* Set playbin2's audio sink to be our sink bin */
g_object_set (GST_OBJECT (player), "audio-sink", bin, NULL);
}
The above code will initialize the gstreamer pipeline. I am using playbin2.
void start_playbin (char *gargv1)
{
time_t rawtime;
struct tm * timeinfo;
static gboolean i=TRUE;
gchar* uri;//to hold the path temporarily
gchar* dname;//to hold the directory name
time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf ( "START:%s\n", asctime (timeinfo) );
uri = (gchar *)g_malloc( sizeof("file://") + strlen(gargv1) + 1);//get complete path
strcpy(uri,"file://");
strcat(uri,gargv1);//add path with the file path
dname = g_uri_escape_string(uri,G_URI_RESERVED_CHARS_ALLOWED_IN_PATH,TRUE);
g_free(uri);
uri = dname;
g_object_set(player,"uri",uri,NULL);//set file path for playback in the pipeline
g_print("\n\nPlaying %s\n", gargv1);
g_free(uri);//free path
/* start playback */
gst_element_set_state (GST_ELEMENT (player), GST_STATE_READY);//set pipeline to ready state
if(i==TRUE)
{
unsigned int count=0;
while(gst_element_set_state (GST_ELEMENT (player), GST_STATE_PLAYING)!=GST_STATE_CHANGE_SUCCESS);
//g_print("here:%d\n",count++);
i=FALSE;
}
else
play_playbin();//start playback
bus = gst_pipeline_get_bus(GST_PIPELINE(player));//get bus reference
gst_bus_add_watch(bus,(GstBusFunc)cb_message,player);//add bus to be monitored by process events
g_object_unref(bus);//unreference bus
time ( &rawtime );
timeinfo = localtime ( &rawtime );
printf ( "AFTER START:%s\n", asctime (timeinfo) );
}
I had to use the if(i == TRUE) condition just because the pipeline doesn't change the state for the first time.
void stop_playbin()
{
if(gst_element_set_state (GST_ELEMENT (player), GST_STATE_NULL)!=GST_STATE_CHANGE_SUCCESS)
g_print("Playbin could not be stopped\n");
//g_assert(gst_element_set_state (GST_ELEMENT (player),GST_STATE_NULL)==GST_STATE_CHANGE_SUCCESS);
}
void pause_playbin()
{
if(gst_element_set_state (GST_ELEMENT (player), GST_STATE_PAUSED)!=GST_STATE_CHANGE_SUCCESS)
g_print("Playbin could not be paused\n");
//g_assert(gst_element_set_state (GST_ELEMENT (player), GST_STATE_PAUSED)==GST_STATE_CHANGE_SUCCESS);
}
void play_playbin()
{
if(gst_element_set_state (GST_ELEMENT (player), GST_STATE_PLAYING)!=GST_STATE_CHANGE_SUCCESS)
g_print("Playbin could not be played\n");
//g_assert(gst_element_set_state (GST_ELEMENT (player),GST_STATE_PLAYING)==GST_STATE_CHANGE_SUCCESS);
}
The above function perform play,pause and Stop function respectively. The problem is, when I send the path of the file to the function start_playbin()
I cannot change the path of the file after setting the pipeline only to ready. I have to make it
1) Ready
2)Pause or Play(cannot set state)
3)stop
and then Play(set state success) the song.
Please help me. I don't get any errors if I set the pipeline to only ready but the program hangs. What could be the problem? Is there any specific sequence to be followed to setup a pipeline and set the path of the file?
回答1:
Please look at the examples shipped with gstreamer. A few points:
- You need to set the state of the pipeline back to ready to be able to change the uri
- State-changes are asynchronous. Please read about The GstBus and make use of it. In particullar don't attach to the bus after playing. Create your playbin pipeline and attach to the bus. Then you can go to PLAYING, the bus will inform you about when the playback started and when in finished (among other things).
Also consider using 1.0 for a new application, 0.10 is in maintenance mode.
来源:https://stackoverflow.com/questions/18503876/what-is-the-sequence-to-be-followed-to-play-a-song-using-gstreramer