add pcm buffer list to reduce IPC 87/73687/2 submit/tizen/20160613.070227
authorEunhae Choi <eunhae1.choi@samsung.com>
Thu, 9 Jun 2016 07:10:59 +0000 (16:10 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Fri, 10 Jun 2016 06:35:59 +0000 (15:35 +0900)
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

packaging/libmm-player.spec
src/include/mm_player_ini.h
src/include/mm_player_priv.h
src/mm_player_ini.c
src/mm_player_priv.c

index 7030e38..56ca6c7 100644 (file)
@@ -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
index 8cc7cfe..a9984de 100644 (file)
@@ -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"
index 2cf26af..2f4c501 100644 (file)
@@ -437,6 +437,17 @@ typedef struct {
 } 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
        int prev_state;                         // player previous 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;
index f76f5a1..0d324e5 100644 (file)
@@ -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]);
index 1623668..af5bbb3 100644 (file)
@@ -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);
@@ -4721,6 +4727,56 @@ do \
 } 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)
 {
        mm_player_t* player = (mm_player_t*) 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();
 }