add bo list to reuse it when send media packet to client in case of sw codec 01/74501/2
authorEunhae Choi <eunhae1.choi@samsung.com>
Tue, 14 Jun 2016 11:00:47 +0000 (20:00 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Tue, 14 Jun 2016 12:31:48 +0000 (21:31 +0900)
Change-Id: I1055472f3308f0f65c246b6e0cca21d635d0fc08

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

index 56ca6c7adc99ea7c33bae33275d0c8513aca19ae..6aa96afc758da9a518d1d69cec31461f7e32d563 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-player
 Summary:    Multimedia Framework Player Library
-Version:    0.5.81
+Version:    0.5.82
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 693b4cf67535bc7d5224f91655879d11bd884586..10aca09294de47f61ed3ade202c50460ac716342 100644 (file)
@@ -2313,6 +2313,19 @@ int mm_player_get_num_of_video_out_buffers(MMHandleType player, int *num, int *e
  */
 int mm_player_set_media_stream_dynamic_resolution(MMHandleType player, bool drc);
 
+/**
+ * This function is to release the video stream bo to reuse. \n
+ * It's only supported when sw codec is used to decode video stream. \n
+ *
+ * @param      player  [in] Handle of player.
+ * @param      bo     [in] bo address to be released
+ *
+ * @return     This function returns zero on success, or negative value with error
+ *                     code.
+ * @since 3.0
+ */
+int mm_player_release_video_stream_bo(MMHandleType player, void* bo);
+
 /**
        @}
  */
index a9984de7a08525d0f0559aaeb83abc2f8184f932..99d6c3e76a44587c4fc3e61241168b03214326ad 100644 (file)
@@ -82,6 +82,8 @@ typedef struct __mm_player_ini
        gboolean async_start;
        gboolean disable_segtrap;
        gint pcm_buffer_size;
+       gint num_of_video_bo;
+       gint video_bo_timeout;
 
        /* http streaming */
        gchar httpsrc_element[PLAYER_INI_MAX_STRLEN];
@@ -154,6 +156,8 @@ typedef struct __mm_player_ini
 #define DEFAULT_LIVE_STATE_CHANGE_TIMEOUT              30 /* sec */
 #define DEFAULT_LOCALPLAYBACK_STATE_CHANGE_TIMEOUT     10 /* sec */
 #define DEFAULT_PCM_BUFFER_SIZE                        51200 /* bytes */
+#define DEFAULT_NUM_OF_VIDEO_BO                        10
+#define DEFAULT_TIMEOUT_OF_VIDEO_BO            10 /* sec */
 
 /* http streaming */
 #define DEFAULT_HTTPSRC                                "souphttpsrc"
index 2f4c501d698bd2280a5cffe129e0eee189cedd69..1957aabb9380e178e6492b646d9f3ba737340c90 100644 (file)
@@ -447,6 +447,16 @@ typedef struct {
        int buff_size;
 } mm_player_audio_stream_buff_t;
 
+/**
+ * @brief data of video_bo_list
+ * @details this will be used when the sw codec is running.
+ * @since_tizen 3.0
+ */
+typedef struct {
+       gboolean using;
+       void* bo;
+} mm_player_video_bo_info_t;
+
 typedef struct {
        /* STATE */
        int state;                                      // player current state
@@ -536,12 +546,16 @@ typedef struct {
        mm_player_video_stream_callback video_stream_cb;
        void* video_stream_cb_user_param;
        int use_video_stream;
+       GCond video_bo_cond;
+       GMutex video_bo_mutex;
+       GList* video_bo_list; /* mm_player_video_bo_info_t, bo list for decoded video data by sw codec */
+       int video_bo_size;
 
        /* audio stram callback */
        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 */
+       GList* audio_stream_buff_list; /* mm_player_audio_stream_buff_t, buff list of extract pcm data */
 
        /* audio buffer callback */
        mm_player_audio_stream_callback_ex audio_stream_render_cb_ex;
@@ -876,6 +890,8 @@ gint __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage *
 int _mmplayer_sound_register_with_pid(MMHandleType hplayer, int pid);
 int _mmplayer_get_client_pid(MMHandleType hplayer, int* pid);
 int __mmplayer_get_video_angle(mm_player_t* player, int *user_angle, int *org_angle);
+int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo);
+
 #ifdef __cplusplus
        }
 #endif
index a00c8aed84a96cd0271de27403e74bf62f4ed925..c48db331b68eaa6001121fd1a0ce36136b3ec717 100644 (file)
@@ -1314,3 +1314,16 @@ int mm_player_set_media_stream_dynamic_resolution(MMHandleType player, bool drc)
        return result;
 }
 
+int mm_player_release_video_stream_bo(MMHandleType player, void* bo)
+{
+       int result = MM_ERROR_NONE;
+
+       MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+       MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_COMMON_INVALID_ARGUMENT);
+//     MMPLAYER_CMD_LOCK( player );
+
+       result = _mmplayer_video_stream_release_bo(player, bo);
+
+//     MMPLAYER_CMD_UNLOCK( player );
+       return result;
+}
\ No newline at end of file
index 0d324e5a65031c1788d567206def4a8d6fa0dede..7ca5bd073447ce41191f36741b25857da32255a7 100644 (file)
@@ -178,6 +178,8 @@ mm_player_ini_load(mm_player_ini_t* ini)
                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);
+               ini->num_of_video_bo = iniparser_getint(dict, "general:video bo max", DEFAULT_NUM_OF_VIDEO_BO);
+               ini->video_bo_timeout = iniparser_getint(dict, "general:video bo timeout", DEFAULT_TIMEOUT_OF_VIDEO_BO);
 
                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);
@@ -232,6 +234,8 @@ mm_player_ini_load(mm_player_ini_t* ini)
                ini->delay_before_repeat = DEFAULT_DELAY_BEFORE_REPEAT;
                ini->video_playback_supported = DEFAULT_VIDEO_PLAYBACK_SUPPORTED;
                ini->pcm_buffer_size = DEFAULT_PCM_BUFFER_SIZE;
+               ini->num_of_video_bo = DEFAULT_NUM_OF_VIDEO_BO;
+               ini->video_bo_timeout = DEFAULT_TIMEOUT_OF_VIDEO_BO;
 
                strncpy( ini->audioresampler_element, DEFAULT_AUDIORESAMPLER, PLAYER_INI_MAX_STRLEN -1 );
                strncpy( ini->audiosink_element, DEFAULT_AUDIOSINK, PLAYER_INI_MAX_STRLEN -1 );
@@ -284,6 +288,8 @@ mm_player_ini_load(mm_player_ini_t* ini)
        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("num of video bo : %d\n", ini->num_of_video_bo);
+       LOGD("video bo timeout : %d\n", ini->video_bo_timeout);
        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 af5bbb3e7365314be360b88156f0dd2e275f5c8f..d4c464c414c03ddecaddc348c3e714a71c2d2d5e 100644 (file)
@@ -5389,6 +5389,131 @@ static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name
     return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
 }
 
+int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
+{
+       int ret = MM_ERROR_NONE;
+       GList *l = NULL;
+       MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+       MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
+
+       g_mutex_lock(&player->video_bo_mutex);
+
+       if (player->video_bo_list) {
+               for (l=g_list_first(player->video_bo_list);l;l=g_list_next(l)) {
+                       mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
+                       if (tmp && tmp->bo == bo) {
+                               tmp->using = FALSE;
+                               LOGD("release bo %p", bo);
+                               g_mutex_unlock(&player->video_bo_mutex);
+                               g_cond_signal(&player->video_bo_cond);
+                               return ret;
+                       }
+               }
+       } else {
+               /* hw codec is running or the list was reset for DRC. */
+               LOGW("there is no bo list.");
+       }
+       g_mutex_unlock(&player->video_bo_mutex);
+
+       LOGW("failed to find bo %p", bo);
+       return ret;
+}
+
+static void
+__mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
+{
+       GList *l = NULL;
+
+       MMPLAYER_FENTER();
+       MMPLAYER_RETURN_IF_FAIL(player);
+
+       g_mutex_lock(&player->video_bo_mutex);
+       if (player->video_bo_list) {
+               LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
+               for (l=g_list_first(player->video_bo_list);l;l=g_list_next(l)) {
+                       mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
+                       if (tmp) {
+                               if (tmp->bo)
+                                       tbm_bo_unref(tmp->bo);
+                               g_free(tmp);
+                       }
+               }
+               g_list_free(player->video_bo_list);
+               player->video_bo_list = NULL;
+       }
+       player->video_bo_size = 0;
+       g_mutex_unlock(&player->video_bo_mutex);
+
+       MMPLAYER_FLEAVE();
+       return;
+}
+
+static void*
+__mmplayer_video_stream_get_bo(mm_player_t* player, int size)
+{
+       GList *l = NULL;
+       MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
+       gboolean ret = TRUE;
+
+       /* check DRC, if it is, destroy the prev bo list to create again */
+       if (player->video_bo_size != size) {
+               LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
+               __mmplayer_video_stream_destroy_bo_list(player);
+               player->video_bo_size = size;
+       }
+
+       g_mutex_lock(&player->video_bo_mutex);
+
+       if (!player->video_bo_list) {
+               /* create bo list */
+               int idx = 0;
+               LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
+
+               for (idx=0 ; idx<player->ini.num_of_video_bo ; idx++) {
+                       mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
+                       bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
+                       if (!bo_info->bo) {
+                               LOGE("Fail to tbm_bo_alloc.");
+                               return NULL;
+                       }
+                       bo_info->using = FALSE;
+                       player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
+               }
+
+               /* update video num buffers */
+               player->video_num_buffers = player->ini.num_of_video_bo;
+               player->video_extra_num_buffers = (player->ini.num_of_video_bo)/2;
+
+               LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
+       }
+
+       while (TRUE) {
+               /* get bo from list*/
+               for (l=g_list_first(player->video_bo_list);l;l=g_list_next(l)){
+                       mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
+                       if (tmp && (tmp->using == FALSE)) {
+                               LOGD("found bo %p to use", tmp->bo);
+                               tmp->using = TRUE;
+                               g_mutex_unlock(&player->video_bo_mutex);
+                               return tmp->bo;
+                       }
+               }
+               if (!ret) {
+                       LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
+                       g_mutex_unlock(&player->video_bo_mutex);
+                       return NULL;
+               }
+
+               if (player->ini.video_bo_timeout <= 0) {
+                       g_cond_wait(&player->video_bo_cond, &player->video_bo_mutex);
+               } else {
+                       gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
+                       ret = g_cond_wait_until(&player->video_bo_cond, &player->video_bo_mutex, timeout);
+               }
+               continue;
+       }
+}
+
 static GstPadProbeReturn
 __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
 {
@@ -5453,14 +5578,14 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user
                video_buffer = (MMVideoBuffer *)mapinfo.data;
        }
 
-       if (video_buffer) {
+       if (video_buffer) { /* hw codec */
                /* set tbm bo */
                if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
                        /* copy pointer of tbm bo, stride, elevation */
                        memcpy(stream.bo, video_buffer->handle.bo,
                                        sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
-               }
-               else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
+               } else if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) {
+                       /* FIXME: need to check this path */
                        memcpy(stream.data, video_buffer->data,
                                        sizeof(void *) * MM_VIDEO_BUFFER_PLANE_MAX);
                }
@@ -5470,7 +5595,7 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user
                                sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
                /* set gst buffer */
                stream.internal_buffer = buffer;
-       } else {
+       } else { /* sw codec */
                tbm_bo_handle thandle;
                int stride = GST_ROUND_UP_4 (stream.width);
                int elevation = stream.height;
@@ -5478,25 +5603,24 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user
 
                gboolean gst_ret;
                gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
-               if(!gst_ret) {
+               if (!gst_ret) {
                        LOGE("fail to gst_memory_map");
                        return GST_PAD_PROBE_OK;
                }
 
                stream.stride[0] = stride;
                stream.elevation[0] = elevation;
-               if(stream.format == MM_PIXEL_FORMAT_I420) {
+               if (stream.format == MM_PIXEL_FORMAT_I420) {
                        stream.stride[1] = stream.stride[2] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (stream.width) / 2);
                        stream.elevation[1] = stream.elevation[2] = elevation / 2;
-               }
-               else {
+               } else {
                        LOGE("Not support format %d", stream.format);
                        gst_memory_unmap(dataBlock, &mapinfo);
                        return GST_PAD_PROBE_OK;
                }
 
                size = (stream.stride[0] + stream.stride[1]) * elevation;
-               stream.bo[0] = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
+               stream.bo[0] = __mmplayer_video_stream_get_bo(player, size);
                if(!stream.bo[0]) {
                        LOGE("Fail to tbm_bo_alloc!!");
                        gst_memory_unmap(dataBlock, &mapinfo);
@@ -5508,7 +5632,6 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user
                else
                        LOGE("data pointer is wrong. dest : %p, src : %p",
                                        thandle.ptr, mapinfo.data);
-
                tbm_bo_unmap(stream.bo[0]);
        }
 
@@ -5518,9 +5641,8 @@ __mmplayer_video_stream_probe (GstPad *pad, GstPadProbeInfo *info, gpointer user
 
        if (metaBlock) {
                gst_memory_unmap(metaBlock, &mapinfo);
-       }else {
+       } else {
                gst_memory_unmap(dataBlock, &mapinfo);
-               tbm_bo_unref(stream.bo[0]);
        }
 
        return GST_PAD_PROBE_OK;
@@ -9316,6 +9438,10 @@ _mmplayer_create_player(MMHandleType handle) // @
                player->pd_file_save_path = NULL;
        }
 
+       /* create video bo lock and cond */
+       g_mutex_init(&player->video_bo_mutex);
+       g_cond_init(&player->video_bo_cond);
+
        player->streaming_type = STREAMING_SERVICE_NONE;
 
        /* give default value of audio effect setting */
@@ -9557,9 +9683,9 @@ _mmplayer_destroy(MMHandleType handle) // @
                g_cond_signal( &player->repeat_thread_cond );
 
                LOGD("waitting for repeat thread exit\n");
-               g_thread_join ( player->repeat_thread );
-               g_mutex_clear(&player->repeat_thread_mutex );
-               g_cond_clear (&player->repeat_thread_cond );
+               g_thread_join(player->repeat_thread);
+               g_mutex_clear(&player->repeat_thread_mutex);
+               g_cond_clear(&player->repeat_thread_cond);
                LOGD("repeat thread released\n");
        }
 
@@ -9653,6 +9779,10 @@ _mmplayer_destroy(MMHandleType handle) // @
 
        g_mutex_clear(&player->msg_cb_lock );
 
+       /* release video bo lock and cond */
+       g_mutex_clear(&player->video_bo_mutex);
+       g_cond_clear(&player->video_bo_cond);
+
        MMPLAYER_FLEAVE();
 
        return MM_ERROR_NONE;
@@ -13419,10 +13549,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);
-       }
+       /* clear the audio stream buffer list */
+       __mmplayer_audio_stream_clear_buffer(player, FALSE);
+
+       /* clear the video stream bo list */
+       __mmplayer_video_stream_destroy_bo_list(player);
 
        player->uri_info.uri_idx = 0;
        MMPLAYER_FLEAVE();