What is the sequence to be followed to play a song using gstreramer?

别来无恙 提交于 2019-12-08 04:23:59

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!