emotion: properly delay buffer destruction.

SVN revision: 63189
This commit is contained in:
Cedric BAIL 2011-09-05 10:57:39 +00:00
parent 8f07a73106
commit 568df526af
3 changed files with 79 additions and 26 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;