From: cedric Date: Mon, 5 Sep 2011 10:57:39 +0000 (+0000) Subject: emotion: properly delay buffer destruction. X-Git-Tag: submit/2.0alpha-wayland/20121127.222018~157 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3cbd8755cd3681440fd22682667c09e2f315c759;p=profile%2Fivi%2Femotion.git emotion: properly delay buffer destruction. git-svn-id: http://svn.enlightenment.org/svn/e/trunk/emotion@63189 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/src/modules/gstreamer/emotion_gstreamer.c b/src/modules/gstreamer/emotion_gstreamer.c index 7156778..d75d1b8 100644 --- a/src/modules/gstreamer/emotion_gstreamer.c +++ b/src/modules/gstreamer/emotion_gstreamer.c @@ -385,6 +385,13 @@ em_shutdown(void *video) g_object_set(G_OBJECT(ev->sink), "evas-object", NULL, NULL); gst_element_set_state(ev->pipeline, GST_STATE_NULL); gst_object_unref(ev->pipeline); + + if (ev->last_buffer) + { + gst_buffer_unref(ev->last_buffer); + ev->last_buffer = NULL; + } + ev->pipeline = NULL; ev->sink = NULL; } diff --git a/src/modules/gstreamer/emotion_gstreamer.h b/src/modules/gstreamer/emotion_gstreamer.h index 9dd3ab9..d4a15c1 100644 --- a/src/modules/gstreamer/emotion_gstreamer.h +++ b/src/modules/gstreamer/emotion_gstreamer.h @@ -77,6 +77,9 @@ struct _Emotion_Gstreamer_Video int video_stream_nbr; int audio_stream_nbr; + /* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */ + GstBuffer *last_buffer; + /* Evas object */ Evas_Object *obj; @@ -95,12 +98,20 @@ struct _Emotion_Gstreamer_Video int in; int out; + struct + { + int width; + int height; + } fill; + Eina_Bool play : 1; Eina_Bool play_started : 1; Eina_Bool video_mute : 1; Eina_Bool audio_mute : 1; Eina_Bool pipeline_parsed : 1; Eina_Bool delete_me : 1; + Eina_Bool samsung : 1; + Eina_Bool kill_buffer : 1; }; struct _EvasVideoSink { @@ -131,9 +142,6 @@ struct _EvasVideoSinkPrivate { Eina_Lock m; Eina_Condition c; - /* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */ - GstBuffer *last_buffer; - // If this is TRUE all processing should finish ASAP // This is necessary because there could be a race between // unlock() and render(), where unlock() wins, signals the diff --git a/src/modules/gstreamer/emotion_sink.c b/src/modules/gstreamer/emotion_sink.c index 2afb2d1..6565a03 100644 --- a/src/modules/gstreamer/emotion_sink.c +++ b/src/modules/gstreamer/emotion_sink.c @@ -100,7 +100,7 @@ _evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data, unsign } static void -_evas_video_i420(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +_evas_video_i420(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) { const unsigned char **rows; unsigned int i, j; @@ -117,11 +117,11 @@ _evas_video_i420(unsigned char *evas_data, const unsigned char *gst_data, unsign rows[i] = &gst_data[h * w + j * (w / 2)]; for (j = 0; j < (rh / 2); j++, i++) - rows[i] = &gst_data[h * w + h * (w / 4) + j * (w / 2)]; + rows[i] = &gst_data[h * w + rh * (w / 4) + j * (w / 2)]; } static void -_evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +_evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) { const unsigned char **rows; unsigned int i, j; @@ -135,7 +135,7 @@ _evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsign rows[i] = &gst_data[i * w]; for (j = 0; j < (rh / 2); j++, i++) - rows[i] = &gst_data[h * w + h * (w / 4) + j * (w / 2)]; + rows[i] = &gst_data[h * w + rh * (w / 4) + j * (w / 2)]; for (j = 0; j < (rh / 2); j++, i++) rows[i] = &gst_data[h * w + j * (w / 2)]; @@ -154,7 +154,7 @@ _evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data, unsign } static void -_evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height) +_evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h __UNUSED__, unsigned int output_height) { const unsigned char **rows; unsigned int i, j; @@ -168,7 +168,7 @@ _evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsign rows[i] = &gst_data[i * w]; for (j = 0; j < (rh / 2); j++, i++) - rows[i] = &gst_data[h * w + j * w]; + rows[i] = &gst_data[rh * w + j * w]; } static void @@ -243,26 +243,28 @@ _evas_video_st12(unsigned char *evas_data, const unsigned char *gst_data, unsign } static const struct { + const char *name; guint32 fourcc; Evas_Colorspace eformat; Evas_Video_Convert_Cb func; Eina_Bool force_height; } colorspace_fourcc_convertion[] = { - { GST_MAKE_FOURCC('I', '4', '2', '0'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_i420, EINA_TRUE }, - { GST_MAKE_FOURCC('Y', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_yv12, EINA_TRUE }, - { GST_MAKE_FOURCC('Y', 'U', 'Y', '2'), EVAS_COLORSPACE_YCBCR422601_PL, _evas_video_yuy2, EINA_FALSE }, - { GST_MAKE_FOURCC('N', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR420NV12601_PL, _evas_video_nv12, EINA_TRUE }, - { GST_MAKE_FOURCC('T', 'M', '1', '2'), EVAS_COLORSPACE_YCBCR420TM12601_PL, _evas_video_mt12, EINA_TRUE } + { "I420", GST_MAKE_FOURCC('I', '4', '2', '0'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_i420, EINA_TRUE }, + { "YV12", GST_MAKE_FOURCC('Y', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR422P601_PL, _evas_video_yv12, EINA_TRUE }, + { "YUY2", GST_MAKE_FOURCC('Y', 'U', 'Y', '2'), EVAS_COLORSPACE_YCBCR422601_PL, _evas_video_yuy2, EINA_FALSE }, + { "NV12", GST_MAKE_FOURCC('N', 'V', '1', '2'), EVAS_COLORSPACE_YCBCR420NV12601_PL, _evas_video_nv12, EINA_TRUE }, + { "TM12", GST_MAKE_FOURCC('T', 'M', '1', '2'), EVAS_COLORSPACE_YCBCR420TM12601_PL, _evas_video_mt12, EINA_TRUE } }; static const struct { + const char *name; GstVideoFormat format; Evas_Colorspace eformat; Evas_Video_Convert_Cb func; } colorspace_format_convertion[] = { - { GST_VIDEO_FORMAT_BGR, EVAS_COLORSPACE_ARGB8888, _evas_video_bgr }, - { GST_VIDEO_FORMAT_BGRx, EVAS_COLORSPACE_ARGB8888, _evas_video_bgrx }, - { GST_VIDEO_FORMAT_BGRA, EVAS_COLORSPACE_ARGB8888, _evas_video_bgra } + { "BGR", GST_VIDEO_FORMAT_BGR, EVAS_COLORSPACE_ARGB8888, _evas_video_bgr }, + { "BGRx", GST_VIDEO_FORMAT_BGRx, EVAS_COLORSPACE_ARGB8888, _evas_video_bgrx }, + { "BGRA", GST_VIDEO_FORMAT_BGRA, EVAS_COLORSPACE_ARGB8888, _evas_video_bgra } }; static void @@ -285,7 +287,6 @@ evas_video_sink_init(EvasVideoSink* sink, EvasVideoSinkClass* klass __UNUSED__) INF("sink init"); sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, EVAS_TYPE_VIDEO_SINK, EvasVideoSinkPrivate); priv->o = NULL; - priv->last_buffer = NULL; priv->width = 0; priv->height = 0; priv->func = NULL; @@ -333,6 +334,8 @@ evas_video_sink_set_property(GObject * object, guint prop_id, INF("sink set ev."); eina_lock_take(&priv->m); priv->ev = g_value_get_pointer (value); + if (priv->ev) + priv->ev->samsung = EINA_TRUE; eina_lock_release(&priv->m); break; default: @@ -398,11 +401,6 @@ evas_video_sink_dispose(GObject* object) eina_lock_free(&priv->m); eina_condition_free(&priv->c); - if (priv->last_buffer) { - gst_buffer_unref(priv->last_buffer); - priv->last_buffer = NULL; - } - G_OBJECT_CLASS(parent_class)->dispose(object); } @@ -432,20 +430,29 @@ gboolean evas_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps) for (i = 0; i < sizeof (colorspace_fourcc_convertion) / sizeof (colorspace_fourcc_convertion[0]); ++i) if (fourcc == colorspace_fourcc_convertion[i].fourcc) { + fprintf(stderr, "Found '%s'\n", colorspace_fourcc_convertion[i].name); priv->eformat = colorspace_fourcc_convertion[i].eformat; priv->func = colorspace_fourcc_convertion[i].func; if (colorspace_fourcc_convertion[i].force_height) { priv->height = (priv->height >> 1) << 1; } + if (priv->ev) + priv->ev->kill_buffer = EINA_TRUE; return TRUE; } if (fourcc == GST_MAKE_FOURCC('S', 'T', '1', '2')) { + fprintf(stderr, "Found '%s'\n", "ST12"); priv->eformat = EVAS_COLORSPACE_YCBCR420TM12601_PL; priv->samsung = EINA_TRUE; priv->func = NULL; + if (priv->ev) + { + priv->ev->samsung = EINA_TRUE; + priv->ev->kill_buffer = EINA_TRUE; + } return TRUE; } } @@ -462,8 +469,11 @@ gboolean evas_video_sink_set_caps(GstBaseSink *bsink, GstCaps *caps) for (i = 0; i < sizeof (colorspace_format_convertion) / sizeof (colorspace_format_convertion[0]); ++i) if (format == colorspace_format_convertion[i].format) { + fprintf(stderr, "Found '%s'\n", colorspace_format_convertion[i].name); priv->eformat = colorspace_format_convertion[i].eformat; priv->func = colorspace_format_convertion[i].func; + if (priv->ev) + priv->ev->kill_buffer = EINA_FALSE; return TRUE; } @@ -700,10 +710,13 @@ evas_video_sink_samsung_main_render(void *data) w, h, stride * w / priv->width, elevation * h / priv->height); + send->ev->fill.width = stride * w / priv->width; + send->ev->fill.height = elevation * h / priv->height; + evas_object_image_alpha_set(priv->o, 0); evas_object_image_colorspace_set(priv->o, priv->eformat); evas_object_image_size_set(priv->o, stride, elevation); - evas_object_image_fill_set(priv->o, 0, 0, stride * w / priv->width, elevation * h / priv->height); + evas_object_image_fill_set(priv->o, 0, 0, send->ev->fill.width, send->ev->fill.height); evas_data = evas_object_image_data_get(priv->o, 1); @@ -800,8 +813,8 @@ evas_video_sink_main_render(void *data) _emotion_video_pos_update(ev->obj, ev->position, vstream->length_time); _emotion_frame_resize(ev->obj, priv->width, priv->height, ev->ratio); - if (priv->last_buffer) gst_buffer_unref(priv->last_buffer); - priv->last_buffer = gst_buffer_ref(buffer); + if (ev->last_buffer) gst_buffer_unref(ev->last_buffer); + ev->last_buffer = gst_buffer_ref(buffer); exit_point: emotion_gstreamer_buffer_free(send); @@ -957,6 +970,26 @@ _emotion_gstreamer_end(void *data, Ecore_Thread *thread) _emotion_gstreamer_video_pipeline_parse(data, EINA_TRUE); } +static void +_on_post_clear(void *data, Evas *e __UNUSED__, void *event_info __UNUSED__) +{ + Emotion_Gstreamer_Video *ev = data; + + if (!ev->kill_buffer) return ; + + if (ev->last_buffer) gst_buffer_unref(ev->last_buffer); + ev->last_buffer = NULL; +} + +static void +_on_resize_fill(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + Emotion_Gstreamer_Video *ev = data; + + if (ev->samsung) + evas_object_image_fill_set(obj, 0, 0, ev->fill.width, ev->fill.height); +} + GstElement * gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev, Evas_Object *o, @@ -974,6 +1007,9 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev, return NULL; } + evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _on_resize_fill, ev); + evas_event_callback_del_full(evas_object_evas_get(obj), EVAS_CALLBACK_RENDER_FLUSH_POST, _on_post_clear, ev); + playbin = gst_element_factory_make("playbin2", "playbin"); if (!playbin) { @@ -1002,6 +1038,8 @@ gstreamer_video_sink_new(Emotion_Gstreamer_Video *ev, g_object_set(G_OBJECT(playbin), "uri", uri, NULL); evas_object_image_pixels_get_callback_set(obj, NULL, NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _on_resize_fill, ev); + evas_event_callback_add(evas_object_evas_get(obj), EVAS_CALLBACK_RENDER_FLUSH_POST, _on_post_clear, ev); ev->pipeline = playbin; ev->sink = sink;