change logic for buffer management 06/64806/4 accepted/tizen/common/20160412.131157 accepted/tizen/ivi/20160415.084231 accepted/tizen/mobile/20160413.073124 accepted/tizen/tv/20160413.075432 accepted/tizen/wearable/20160413.080432 submit/tizen/20160412.064533 submit/tizen_ivi/20160415.053201
authorNAMJEONGYOON <just.nam@samsung.com>
Tue, 5 Apr 2016 11:59:06 +0000 (20:59 +0900)
committerNAMJEONGYOON <just.nam@samsung.com>
Thu, 7 Apr 2016 06:00:16 +0000 (15:00 +0900)
Change-Id: I480a0448e1f636a9a924b05b1dc6c68d32d0509f

src/include/mm_evas_renderer.h
src/mm_evas_renderer.c

index 433da22..247f26d 100644 (file)
@@ -70,6 +70,12 @@ typedef enum {
 } visible_info;
 
 typedef struct {
+       media_packet_h packet;
+       tbm_surface_h tbm_surf;
+       gint prev; /* keep previous index for destroying remained packets */
+} packet_info;
+
+typedef struct {
        gint x;
        gint y;
        gint w;
@@ -96,17 +102,15 @@ typedef struct {
        tbm_surface_h tbm_surf;
 
        /* media packet */
-       media_packet_h prev_mp;
-       media_packet_h cur_mp;
-       media_packet_h pkt[MAX_PACKET_NUM];
-       gint prev_idx;
+       packet_info pkt_info[MAX_PACKET_NUM];
        gint cur_idx;
 
        /* count undestroyed media packet */
        guint sent_buffer_cnt;
 
        /* lock */
-       GMutex mp_lock;
+       GMutex mp_lock; /* media_packet free lock */
+       GMutex idx_lock; /* to keep value of cur_idx */
 } mm_evas_info;
 
 /* create and initialize evas_info */
index 9f1e666..833b366 100644 (file)
@@ -106,6 +106,10 @@ enum {
 };
 
 /* internal */
+#ifdef _DEBUG_INDEX
+void __print_idx(mm_evas_info *evas_info);
+#endif
+void _free_previous_packets(mm_evas_info *evas_info);
 int _mm_evas_renderer_create(mm_evas_info **evas_info);
 int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
@@ -150,7 +154,7 @@ static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
                LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
                return;
        }
-       //LOGI("- test -"); //@@@@@ pre_cb will be deleted. actually it is useless
+       /* LOGI("- test -"); pre_cb will be used for flush_buffer */
 }
 
 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
@@ -171,7 +175,7 @@ static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info
 void _evas_pipe_cb(void *data, void *buffer, update_info info)
 {
        mm_evas_info *evas_info = data;
-       int ret;
+
        LOGD("[ENTER]");
 
        if (!evas_info) {
@@ -183,7 +187,8 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
 
        if (!evas_info->eo) {
                LOGW("evas_info %p", evas_info);
-               goto ERROR;
+               g_mutex_unlock(&evas_info->mp_lock);
+               return;
        }
 
        LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
@@ -202,16 +207,23 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
 
        if (info != UPDATE_TBM_SURF) {
                LOGW("invalid info type : %d", info);
-               goto ERROR;
+               g_mutex_unlock(&evas_info->mp_lock);
+               return;
        }
 
-       /* normally get tbm surf in pipe callback. if not, we can get changed tbm surf by other threads */
-       ret = media_packet_get_tbm_surface(evas_info->pkt[evas_info->cur_idx], &evas_info->tbm_surf);
-       if (ret != MEDIA_PACKET_ERROR_NONE || !evas_info->tbm_surf) {
-               LOGW("get_tbm_surface is failed");
-               goto ERROR;
+       if (evas_info->cur_idx==-1 || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
+               LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
+               g_mutex_unlock(&evas_info->mp_lock);
+               return;
        }
-       tbm_format tbm_fmt = tbm_surface_get_format(evas_info->tbm_surf);
+       g_mutex_lock(&evas_info->idx_lock);
+       /* index */
+       gint cur_idx = evas_info->cur_idx;
+       gint prev_idx = evas_info->pkt_info[cur_idx].prev;
+
+       LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
+
+       tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[evas_info->cur_idx].tbm_surf);
        switch (tbm_fmt) {
        case TBM_FORMAT_NV12:
                LOGD("tbm_surface format : TBM_FORMAT_NV12");
@@ -224,12 +236,10 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
                break;
        }
        /* it is needed to skip setting when state is pause */
-       LOGD("received (tbm_surf %p)", evas_info->tbm_surf);
-
        Evas_Native_Surface surf;
        surf.type = EVAS_NATIVE_SURFACE_TBM;
        surf.version = EVAS_NATIVE_SURFACE_VERSION;
-       surf.data.tbm.buffer = evas_info->tbm_surf;
+       surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
 //  surf.data.tbm.rot = evas_info->rotate_angle;
 //  surf.data.tbm.flip = evas_info->flip;
 
@@ -266,33 +276,62 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
        LOGD("GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)", evas_info->w, evas_info->h, evas_info->eo_size.w, evas_info->eo_size.h, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->rotate_angle, evas_info->flip);
 
        /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
-       if ((evas_info->prev_idx != -1) && evas_info->pkt[evas_info->prev_idx] && (evas_info->prev_idx != evas_info->cur_idx)) {
-               LOGD("destroy previous packet [%p] idx %d", evas_info->pkt[evas_info->prev_idx], evas_info->prev_idx);
-               if (media_packet_destroy(evas_info->pkt[evas_info->prev_idx]) != MEDIA_PACKET_ERROR_NONE)
-                       LOGE("media_packet_destroy failed %p", evas_info->pkt[evas_info->prev_idx]);
-               evas_info->pkt[evas_info->prev_idx] = NULL;
-               evas_info->sent_buffer_cnt--;
-               LOGD("sent packet %d", evas_info->sent_buffer_cnt);
-       }
-       evas_info->prev_idx = evas_info->cur_idx;
+       if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
+               _free_previous_packets(evas_info);
 
        LOGD("[LEAVE]");
+       g_mutex_unlock(&evas_info->idx_lock);
        g_mutex_unlock(&evas_info->mp_lock);
 
        return;
 
  ERROR:
-       if ((evas_info->prev_idx != -1) && evas_info->pkt[evas_info->prev_idx]) {
-               LOGD("cant render. destroy previous packet [%p] idx %d", evas_info->pkt[evas_info->prev_idx], evas_info->prev_idx);
-               if (media_packet_destroy(evas_info->pkt[evas_info->prev_idx]) != MEDIA_PACKET_ERROR_NONE)
-                       LOGE("media_packet_destroy failed %p", evas_info->pkt[evas_info->prev_idx]);
-               evas_info->pkt[evas_info->prev_idx] = NULL;
-               evas_info->sent_buffer_cnt--;
+       if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
+               LOGI("cant render");
+               _free_previous_packets(evas_info);
        }
-       evas_info->prev_idx = evas_info->cur_idx;
+       g_mutex_unlock(&evas_info->idx_lock);
        g_mutex_unlock(&evas_info->mp_lock);
 }
 
+#ifdef _DEBUG_INDEX
+void __print_idx(mm_evas_info *evas_info)
+{
+       gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
+       LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
+       while(prev_idx != -1)
+       {
+               LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
+               prev_idx = evas_info->pkt_info[prev_idx].prev;
+       }
+       LOGE("***** end");
+       return;
+}
+#endif
+
+void _free_previous_packets(mm_evas_info *evas_info)
+{
+       gint index = evas_info->cur_idx;
+       gint prev_idx = evas_info->pkt_info[index].prev;
+
+       while(prev_idx != -1)
+       {
+               LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
+               if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
+                       LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
+               evas_info->pkt_info[prev_idx].packet = NULL;
+               evas_info->pkt_info[prev_idx].tbm_surf = NULL;
+               evas_info->pkt_info[index].prev = -1;
+               evas_info->sent_buffer_cnt--;
+
+               /* move index to previous index */
+               index= prev_idx;
+               prev_idx = evas_info->pkt_info[prev_idx].prev;
+               LOGD("sent packet %d", evas_info->sent_buffer_cnt);
+       }
+       return;
+}
+
 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
 {
        media_format_h fmt;
@@ -305,7 +344,7 @@ static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
                        return true;
                } else
                        LOGW("media_format_get_video_info is failed");
-               if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) //because of media_packet_get_format
+               if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
                        LOGW("media_format_unref is failed");
        } else {
                LOGW("media_packet_get_format is failed");
@@ -317,7 +356,7 @@ int _find_empty_index(mm_evas_info *evas_info)
 {
        int i;
        for (i = 0; i < MAX_PACKET_NUM; i++) {
-               if (!evas_info->pkt[i]) {
+               if (!evas_info->pkt_info[i].packet) {
                        LOGD("selected idx %d", i);
                        return i;
                }
@@ -342,14 +381,14 @@ void _reset_pipe(mm_evas_info *evas_info)
 
        /* destroy all packets */
        for (i = 0; i < MAX_PACKET_NUM; i++) {
-               if (evas_info->pkt[i]) {
-                       LOGD("destroy packet [%p]", evas_info->pkt[i]);
-                       ret = media_packet_destroy(evas_info->pkt[i]);
+               if (evas_info->pkt_info[i].packet) {
+                       LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
+                       ret = media_packet_destroy(evas_info->pkt_info[i].packet);
                        if (ret != MEDIA_PACKET_ERROR_NONE)
-                               LOGW("media_packet_destroy failed %p", evas_info->pkt[i]);
+                               LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
                        else
                                evas_info->sent_buffer_cnt--;
-                       evas_info->pkt[i] = NULL;
+                       evas_info->pkt_info[i].packet = NULL;
                }
        }
 
@@ -394,6 +433,7 @@ int _mm_evas_renderer_create(mm_evas_info **evas_info)
                LOGD("Success create evas_info(%p)", *evas_info);
        }
        g_mutex_init(&ptr->mp_lock);
+       g_mutex_init(&ptr->idx_lock);
 
        return MM_ERROR_NONE;
 
@@ -412,6 +452,7 @@ int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
 
        ret = _mm_evas_renderer_reset(ptr);
        g_mutex_clear(&ptr->mp_lock);
+       g_mutex_clear(&ptr->idx_lock);
 
        g_free(ptr);
        ptr = NULL;
@@ -423,14 +464,22 @@ int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
 {
        MM_CHECK_NULL(evas_info);
        MM_CHECK_NULL(eo);
+       g_mutex_lock(&evas_info->idx_lock);
 
        LOGD("set evas_info");
+       int i;
+       for (i = 0; i < MAX_PACKET_NUM; i++) {
+               evas_info->pkt_info[i].packet = NULL;
+               evas_info->pkt_info[i].tbm_surf = NULL;
+               evas_info->pkt_info[i].prev = -1;
+       }
 
-       evas_info->prev_idx = evas_info->cur_idx = -1;
+       evas_info->cur_idx = -1;
        evas_info->eo = eo;
        evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
        if (!evas_info->epipe) {
                LOGE("pipe is not created");
+               g_mutex_unlock(&evas_info->idx_lock);
                return MM_ERROR_UNKNOWN;
        }
        LOGD("created pipe %p", evas_info->epipe);
@@ -439,15 +488,19 @@ int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
        evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
        LOGI("evas object %p (%d, %d, %d, %d)", evas_info->eo, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->eo_size.w, evas_info->eo_size.h);
 
+       g_mutex_unlock(&evas_info->idx_lock);
+
        return MM_ERROR_NONE;
 }
 
 int _mm_evas_renderer_reset(mm_evas_info *evas_info)
 {
        MM_CHECK_NULL(evas_info);
+       g_mutex_lock(&evas_info->idx_lock);
 
        int i;
-       int ret = MEDIA_PACKET_ERROR_NONE;
+       int ret = MM_ERROR_NONE;
+       int ret_mp = MEDIA_PACKET_ERROR_NONE;
 
        if (evas_info->eo) {
                _mm_evas_renderer_unset_callback(evas_info);
@@ -462,29 +515,33 @@ int _mm_evas_renderer_reset(mm_evas_info *evas_info)
 
        evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
        evas_info->w = evas_info->h = 0;
-       evas_info->tbm_surf = NULL;
 
        g_mutex_lock(&evas_info->mp_lock);
        for (i = 0; i < MAX_PACKET_NUM; i++) {
-               if (evas_info->pkt[i]) {
+               if (evas_info->pkt_info[i].packet) {
                        /* destroy all packets */
-                       LOGD("destroy packet [%p]", evas_info->pkt[i]);
-                       ret = media_packet_destroy(evas_info->pkt[i]);
-                       if (ret != MEDIA_PACKET_ERROR_NONE)
-                               LOGW("media_packet_destroy failed %p", evas_info->pkt[i]);
+                       LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
+                       ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
+                       if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
+                               LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
+                               ret = MM_ERROR_UNKNOWN;
+                       }
                        else
                                evas_info->sent_buffer_cnt--;
-                       evas_info->pkt[i] = NULL;
+                       evas_info->pkt_info[i].packet = NULL;
+                       evas_info->pkt_info[i].tbm_surf = NULL;
+                       evas_info->pkt_info[i].prev = -1;
                }
        }
        g_mutex_unlock(&evas_info->mp_lock);
-
        if (evas_info->sent_buffer_cnt != 0)
                LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
        evas_info->sent_buffer_cnt = 0;
-       evas_info->prev_idx = evas_info->cur_idx = -1;
+       evas_info->cur_idx = -1;
 
-       return MM_ERROR_NONE;
+       g_mutex_unlock(&evas_info->idx_lock);
+
+       return ret;
 }
 
 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
@@ -606,13 +663,16 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
        mm_evas_info *handle = (mm_evas_info *)data;
        int ret = MEDIA_PACKET_ERROR_NONE;
        bool has;
+       tbm_surface_h tbm_surf;
+       gint index;
 
        LOGD("packet [%p]", packet);
 
        if (!data || !handle) {
                LOGE("handle %p or evas_info %p is NULL", data, handle);
-               goto ERROR;
+               goto INVALID_PARAM;
        }
+       g_mutex_lock(&handle->idx_lock);
 
        ret = media_packet_has_tbm_surface_buffer(packet, &has);
        if (ret != MEDIA_PACKET_ERROR_NONE) {
@@ -623,7 +683,7 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
        /* currently we are always checking it */
        if (has && _get_video_size(packet, handle)) {
                /* Attention! if this error occurs, we need to consider managing buffer */
-               if (handle->sent_buffer_cnt > 14) {
+               if (handle->sent_buffer_cnt > 10) {
                        LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
                        goto ERROR;
 #if 0
@@ -635,16 +695,32 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
                        g_mutex_unlock(&handle->mp_lock);
 #endif
                }
-               handle->cur_idx = _find_empty_index(handle);
-               if (handle->cur_idx == -1)
+               ret = media_packet_get_tbm_surface(packet, &tbm_surf);
+               if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
+                       LOGW("get_tbm_surface is failed");
                        goto ERROR;
-               handle->pkt[handle->cur_idx] = packet;
+               }
+
+               /* find new index for current packet */
+               index = _find_empty_index(handle);
+               if (index == -1) {
+                       goto ERROR;
+               }
+
+               /* save previous index */
+               handle->pkt_info[index].prev = handle->cur_idx;
+               handle->pkt_info[index].packet = packet;
+               handle->pkt_info[index].tbm_surf = tbm_surf;
+               handle->cur_idx = index;
                handle->sent_buffer_cnt++;
                LOGD("sent packet %d", handle->sent_buffer_cnt);
+
                ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
                if (!ret) {
-                       handle->pkt[handle->cur_idx] = NULL;
-                       handle->cur_idx = handle->prev_idx;
+                       handle->pkt_info[index].packet = NULL;
+                       handle->pkt_info[index].tbm_surf = NULL;
+                       handle->pkt_info[index].prev = -1;
+                       handle->cur_idx = handle->pkt_info[index].prev;
                        handle->sent_buffer_cnt--;
                        LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
                        goto ERROR;
@@ -653,10 +729,12 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
                LOGW("no tbm_surf");
                goto ERROR;
        }
+       g_mutex_unlock(&handle->idx_lock);
 
        return;
-
- ERROR:
+ERROR:
+       g_mutex_unlock(&handle->idx_lock);
+INVALID_PARAM:
        /* destroy media_packet immediately */
        if (packet) {
                g_mutex_lock(&handle->mp_lock);
@@ -705,6 +783,8 @@ int mm_evas_renderer_update_param(MMHandleType handle)
 
 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
 {
+       MM_CHECK_NULL(handle);
+
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = NULL;
 
@@ -728,6 +808,8 @@ int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
 
 int mm_evas_renderer_destroy(MMHandleType *handle)
 {
+       MM_CHECK_NULL(handle);
+
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = (mm_evas_info *)*handle;