【问题标题】:gstreamer leaking memory when not using pulseaudio不使用pulseaudio时gstreamer泄漏内存
【发布时间】:2012-05-14 03:20:04
【问题描述】:

我使用 Gtk 和 Gstreamer 编写了一个应用程序来播放声音。每次播放新声音时,如果没有在我的系统上安装 pulseaudio,应用程序会使用额外的 10M 虚拟内存,而这些虚拟内存永远不会被释放。如果安装并运行pulseaudio,则不会发生内存泄漏,但声音很断断续续,经常崩溃。是处理声音播放的代码段。 *update_callback* 每 10 秒调用一次。

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;
    }
}

【问题讨论】:

  • 你试过运行 valgrind 吗?

标签: c linux gtk gstreamer pulseaudio


【解决方案1】:

当前的剪辑不完整,但似乎有几个问题。一些提示:

  • 使用 playbin2
  • 使用 playbin2 上的“静音”属性实现“静音”
  • 在搜索时使用 SEGMENT 标志并在总线上收听 SEGMENT_DONE 会更好地实现循环声音
  • 将 play_sound() 和 bus_call() 中的通用代码移到单独的方法中,以便于阅读

最好添加指向完整独立示例的链接。

【讨论】:

    猜你喜欢
    • 2015-02-15
    • 2013-04-10
    • 2017-01-15
    • 2012-02-17
    • 1970-01-01
    • 2021-07-06
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多