From: Eunhae Choi Date: Thu, 9 Jun 2016 07:10:59 +0000 (+0900) Subject: add pcm buffer list to reduce IPC X-Git-Tag: submit/tizen/20160613.070227^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b24ec13c05c818ec1cc508cb2f6115efd6ff7afd;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git add pcm buffer list to reduce IPC If the sync is false, there are too many buffers will be sent in short time. To control the IPC, the buffer list is added. Change-Id: Ic24c77b0b6f62ecb1da8388884c92384862cabcc --- diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 7030e38..56ca6c7 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.5.80 +Version: 0.5.81 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/include/mm_player_ini.h b/src/include/mm_player_ini.h index 8cc7cfe..a9984de 100644 --- a/src/include/mm_player_ini.h +++ b/src/include/mm_player_ini.h @@ -81,6 +81,7 @@ typedef struct __mm_player_ini gchar exclude_element_keyword[PLAYER_INI_MAX_ELEMENT][PLAYER_INI_MAX_STRLEN]; gboolean async_start; gboolean disable_segtrap; + gint pcm_buffer_size; /* http streaming */ gchar httpsrc_element[PLAYER_INI_MAX_STRLEN]; @@ -152,6 +153,8 @@ typedef struct __mm_player_ini #define DEFAULT_VIDEO_PLAYBACK_SUPPORTED TRUE #define DEFAULT_LIVE_STATE_CHANGE_TIMEOUT 30 /* sec */ #define DEFAULT_LOCALPLAYBACK_STATE_CHANGE_TIMEOUT 10 /* sec */ +#define DEFAULT_PCM_BUFFER_SIZE 51200 /* bytes */ + /* http streaming */ #define DEFAULT_HTTPSRC "souphttpsrc" #define DEFAULT_HTTP_FILE_BUFFER_PATH "/home/owner/content" diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 2cf26af..2f4c501 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -436,6 +436,17 @@ typedef struct { gulong video_data_probe_id; } mm_player_gapless_t; +typedef struct { + int channel; + int bitrate; + int depth; + bool is_little_endian; + guint64 channel_mask; + void *pcm_data; + int data_size; + int buff_size; +} mm_player_audio_stream_buff_t; + typedef struct { /* STATE */ int state; // player current state @@ -530,6 +541,7 @@ typedef struct { mm_player_audio_stream_callback audio_stream_cb; void* audio_stream_cb_user_param; bool audio_stream_sink_sync; + GList* audio_stream_buff_list; /* buff list of extract pcm data */ /* audio buffer callback */ mm_player_audio_stream_callback_ex audio_stream_render_cb_ex; diff --git a/src/mm_player_ini.c b/src/mm_player_ini.c index f76f5a1..0d324e5 100644 --- a/src/mm_player_ini.c +++ b/src/mm_player_ini.c @@ -177,6 +177,7 @@ mm_player_ini_load(mm_player_ini_t* ini) ini->async_start = iniparser_getboolean(dict, "general:async start", DEFAULT_ASYNC_START); ini->video_playback_supported = iniparser_getboolean(dict, "general:video playback supported", DEFAULT_VIDEO_PLAYBACK_SUPPORTED); ini->delay_before_repeat = iniparser_getint(dict, "general:delay before repeat", DEFAULT_DELAY_BEFORE_REPEAT); + ini->pcm_buffer_size = iniparser_getint(dict, "general:pcm buffer size", DEFAULT_PCM_BUFFER_SIZE); MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_overlay, "general:videosink element x", DEFAULT_VIDEOSINK_OVERLAY); MMPLAYER_INI_GET_STRING(dict, ini->videosink_element_evas, "general:videosink element evas", DEFAULT_VIDEOSINK_EVAS); @@ -230,6 +231,7 @@ mm_player_ini_load(mm_player_ini_t* ini) ini->async_start = DEFAULT_ASYNC_START; ini->delay_before_repeat = DEFAULT_DELAY_BEFORE_REPEAT; ini->video_playback_supported = DEFAULT_VIDEO_PLAYBACK_SUPPORTED; + ini->pcm_buffer_size = DEFAULT_PCM_BUFFER_SIZE; strncpy( ini->audioresampler_element, DEFAULT_AUDIORESAMPLER, PLAYER_INI_MAX_STRLEN -1 ); strncpy( ini->audiosink_element, DEFAULT_AUDIOSINK, PLAYER_INI_MAX_STRLEN -1 ); @@ -281,6 +283,7 @@ mm_player_ini_load(mm_player_ini_t* ini) LOGD("delay before repeat(msec) : %d\n", ini->delay_before_repeat); LOGD("async_start : %d\n", ini->async_start); LOGD("video_playback_supported : %d\n", ini->video_playback_supported); + LOGD("pcm buffer size(bytes) : %d\n", ini->pcm_buffer_size); LOGD("gst param1 : %s\n", ini->gst_param[0]); LOGD("gst param2 : %s\n", ini->gst_param[1]); LOGD("gst param3 : %s\n", ini->gst_param[2]); diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index 1623668..af5bbb3 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -261,6 +261,8 @@ static gboolean __gst_seek_audio_data (GstElement * appsrc, guint64 position, gp static gboolean __gst_seek_video_data (GstElement * appsrc, guint64 position, gpointer user_data); static gboolean __gst_seek_subtitle_data (GstElement * appsrc, guint64 position, gpointer user_data); static void __mmplayer_gst_caps_notify_cb (GstPad * pad, GParamSpec * unused, gpointer data); +static void __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all); +static void __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer); /*=========================================================================================== | | @@ -1324,6 +1326,10 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @ } + if ((player->audio_stream_render_cb_ex) && (!player->audio_stream_sink_sync)) { + __mmplayer_audio_stream_clear_buffer(player, TRUE); + } + /* rewind if repeat count is greater then zero */ /* get play count */ attrs = MMPLAYER_GET_ATTRS(player); @@ -4720,6 +4726,56 @@ do \ element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\ } while(0); +static void +__mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all) +{ + GList *l = NULL; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player); + + if (player->audio_stream_buff_list) { + for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) { + mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data; + if (tmp) { + if (send_all) { + LOGD("[%lld] send remained data.", tmp->channel_mask); + __mmplayer_audio_stream_send_data(player, tmp); + } + if (tmp->pcm_data) + g_free(tmp->pcm_data); + g_free(tmp); + } + } + g_list_free(player->audio_stream_buff_list); + player->audio_stream_buff_list = NULL; + } + + MMPLAYER_FLEAVE(); +} + +static void +__mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer) +{ + MMPlayerAudioStreamDataType audio_stream = { 0, }; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex); + + audio_stream.bitrate = a_buffer->bitrate; + audio_stream.channel = a_buffer->channel; + audio_stream.depth = a_buffer->depth; + audio_stream.is_little_endian = a_buffer->is_little_endian; + audio_stream.channel_mask = a_buffer->channel_mask; + audio_stream.data_size = a_buffer->data_size; + audio_stream.data = a_buffer->pcm_data; + + LOGD ("[%lld] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); + player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param); + + MMPLAYER_FLEAVE(); +} + static void __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data) { @@ -4730,18 +4786,18 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, gint depth = 0; gint endianness = 0; guint64 channel_mask = 0; - - MMPlayerAudioStreamDataType audio_stream = { 0, }; + void *a_data = NULL; + gint a_size = 0; + mm_player_audio_stream_buff_t *a_buffer = NULL; GstMapInfo mapinfo = GST_MAP_INFO_INIT; + GList *l = NULL; MMPLAYER_FENTER(); - MMPLAYER_RETURN_IF_FAIL(player->audio_stream_render_cb_ex); - - LOGD ("__mmplayer_audio_stream_decoded_render_cb new pad: %s", GST_PAD_NAME (pad)); + MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex); gst_buffer_map(buffer, &mapinfo, GST_MAP_READ); - audio_stream.data = mapinfo.data; - audio_stream.data_size = mapinfo.size; + a_data = mapinfo.data; + a_size = mapinfo.size; GstCaps *caps = gst_pad_get_current_caps( pad ); GstStructure *structure = gst_caps_get_structure (caps, 0); @@ -4752,18 +4808,80 @@ __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, gst_structure_get_int (structure, "depth", &depth); gst_structure_get_int (structure, "endianness", &endianness); gst_structure_get (structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL); - gst_caps_unref(GST_CAPS(caps)); - audio_stream.bitrate = rate; - audio_stream.channel = channel; - audio_stream.depth = depth; - audio_stream.is_little_endian = (endianness == 1234 ? 1 : 0); - audio_stream.channel_mask = channel_mask; - LOGD ("bitrate : %d channel : %d depth: %d ls_little_endian : %d channel_mask: %d, %p", rate, channel, depth, endianness, channel_mask, player->audio_stream_cb_user_param); - player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param); - gst_buffer_unmap(buffer, &mapinfo); + /* In case of the sync is false, use buffer list. * + * The num of buffer list depends on the num of audio channels */ + if (player->audio_stream_buff_list) { + for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) { + mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data; + if (tmp) { + if (channel_mask == tmp->channel_mask) { + LOGD("[%lld] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); + + if (tmp->data_size + a_size < tmp->buff_size) { + memcpy(tmp->pcm_data+tmp->data_size, a_data, a_size); + tmp->data_size += a_size; + } else { + /* send data to client */ + __mmplayer_audio_stream_send_data(player, tmp); + + if (a_size > tmp->buff_size) { + LOGD("[%lld] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size); + tmp->pcm_data = g_realloc(tmp->pcm_data, a_size); + if (tmp->pcm_data == NULL) { + LOGE("failed to realloc data."); + goto DONE; + } + tmp->buff_size = a_size; + } + memset(tmp->pcm_data, 0x00, tmp->buff_size); + memcpy(tmp->pcm_data, a_data, a_size); + tmp->data_size = a_size; + } + goto DONE; + } + } else { + LOGE("data is empty in list."); + goto DONE; + } + } + } + /* create new audio stream data */ + a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t)); + if (a_buffer == NULL) { + LOGE("failed to alloc data."); + goto DONE; + } + a_buffer->bitrate = rate; + a_buffer->channel = channel; + a_buffer->depth = depth; + a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0); + a_buffer->channel_mask = channel_mask; + a_buffer->data_size = a_size; + + if (!player->audio_stream_sink_sync) { + /* If sync is FALSE, use buffer list to reduce the IPC. */ + a_buffer->buff_size = (a_size>player->ini.pcm_buffer_size)?(a_size):(player->ini.pcm_buffer_size); + a_buffer->pcm_data = g_malloc(a_buffer->buff_size); + if (a_buffer->pcm_data == NULL) { + LOGE("failed to alloc data."); + g_free(a_buffer); + goto DONE; + } + memcpy(a_buffer->pcm_data, a_data, a_size); + LOGD("new [%lld] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); + player->audio_stream_buff_list = g_list_append (player->audio_stream_buff_list, a_buffer); + } else { + /* If sync is TRUE, send data directly. */ + a_buffer->pcm_data = a_data; + __mmplayer_audio_stream_send_data(player, a_buffer); + g_free(a_buffer); + } + +DONE: + gst_buffer_unmap(buffer, &mapinfo); MMPLAYER_FLEAVE(); } @@ -13301,6 +13419,11 @@ __mmplayer_release_misc_post(mm_player_t* player) player->uri_info.uri_list = NULL; } + /* clean the audio stream buffer list */ + if (player->audio_stream_buff_list) { + __mmplayer_audio_stream_clear_buffer(player, FALSE); + } + player->uri_info.uri_idx = 0; MMPLAYER_FLEAVE(); }