简体   繁体   中英

gstreamer leaking memory when not using pulseaudio

I have written an app using Gtk and Gstreamer to play sounds. Without pulseaudio installed on my system every time a new sound is played the application uses an additional 10M of virtual memory that never gets released. If pulseaudio is installed and running the memory leak does not occur but the sound is very choppy and crashes often. Are the sections of code that handle the playing of sounds. *update_callback* is called every 10 seconds.

int current_sound;
int current_beep_type = BEEP_CONT;
int next_beep_type = -1;
gboolean sound_muted = FALSE;
static GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT;
GstElement *sound_pipeline = NULL;

int update_callback(GtkWidget *widget, gpointer data) {

    static int i = 0;
    switch((i++)%2) {
        case 0:
            play_sound("morse_code.ogg",BEEP_CONT);
            break;
        case 1:
            destroy_sound();
            break;
        default:
            break;
    }

    return TRUE;
} 



static gboolean bus_call(GstBus *bus, GstMessage *msg, void *user_data)
{
    switch (GST_MESSAGE_TYPE(msg)) {
        case GST_MESSAGE_EOS: {
            //g_print("End of stream\n");
            if(current_beep_type == BEEP_CONT) {
                gst_element_seek (sound_pipeline, 1.0,
                      GST_FORMAT_TIME,
                      seek_flags,
                      GST_SEEK_TYPE_SET, 0,
                      GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
                break;
            }
            else {
                //gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_NULL);
            }
            if(strlen(next_uri) > 0) {

                g_object_set(G_OBJECT(sound_pipeline), "uri", next_uri, NULL);

                current_beep_type = next_beep_type;
                memset(next_uri,0,sizeof(next_uri));
                if(!sound_muted) gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_PLAYING);
                else gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_PAUSED);
            }
            else {
                gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_NULL);
            }

            break;
        }
        case GST_MESSAGE_ERROR: {
            GError *err;
            gst_message_parse_error(msg, &err, NULL);
            g_error("%s", err->message);
            g_error_free(err);
            break;
        }
        default:
            break;
    }

    return TRUE;
}

void play_sound(char *sound, int beep)
{
    strcpy(next_uri,"file://");
    strcat(next_uri,SOUNDS_DIR);
    strcat(next_uri,sound);

    next_beep_type = beep;

    if(sound_pipeline == NULL) {
        mad_log(LOG_INFO,"creating sound_pipeline\n");
        GstBus *bus;
        sound_pipeline = gst_element_factory_make("playbin", "play");
        bus = gst_pipeline_get_bus(GST_PIPELINE(sound_pipeline));
        gst_bus_add_watch(bus, bus_call, loop);
        gst_object_unref(bus);
    }

    GstState state;

    gst_element_get_state(sound_pipeline,&state,NULL,500000000);

    if (state == GST_STATE_NULL) {
        //g_print("pipeline is in NULL state\n");
        g_object_set(G_OBJECT(sound_pipeline), "uri", next_uri, NULL);
        current_beep_type = next_beep_type;
        memset(next_uri,0,sizeof(next_uri));
        if(!sound_muted) gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_PLAYING);
        else gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_PAUSED);
    }

}

void destroy_sound(void) {
    if(sound_pipeline)
    {        
        current_beep_type = -1;
        gst_element_set_state(GST_ELEMENT(sound_pipeline), GST_STATE_NULL);
        g_object_unref(G_OBJECT(sound_pipeline));
        sound_pipeline = NULL;
    }
}

The current snipped is not complete, but sees to have a couple of issues. Some tips:

  • use playbin2
  • implement "mute" by using the "mute" property on playbin2
  • looped sounds would be better implemnted using the SEGMENT flag on the seek and listening to SEGMENT_DONE on the bus
  • move the common code in play_sound() and bus_call() to a separate method to make it easier to read

Ideally add a link to a complete standalone example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM