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:
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.