emtoion gst1 - workaround gst break between 1.10 and 1.12

so emotion was using a much older (pre 1.0) buffer map mechanism for
getting video data. a new frame map api was added to gst in 1.0 but we
didnt use it. gst broke the old buffer direct mapping for some codecs
paths between 1.10 and 1.12. since we were using a very old method/api
this broke us. this also happens to fix some vaapi issues (except
where the buffer is simply never mappable ever). so this is kind of a
fix (updating us to as more modern api) and a workaround.

@fix
This commit is contained in:
Carsten Haitzler 2017-07-19 10:44:23 +09:00
parent 68eba4817a
commit 1a16a4f10b
4 changed files with 150 additions and 42 deletions

View File

@ -6,7 +6,7 @@
Emotion_Gstreamer_Buffer *
emotion_gstreamer_buffer_alloc(EmotionVideoSink *sink,
GstBuffer *buffer,
GstBuffer *buffer,
GstVideoInfo *info,
Evas_Colorspace eformat,
int eheight,
@ -16,16 +16,19 @@ emotion_gstreamer_buffer_alloc(EmotionVideoSink *sink,
if (!sink->priv->emotion_object) return NULL;
send = malloc(sizeof (Emotion_Gstreamer_Buffer));
send = calloc(1, sizeof(Emotion_Gstreamer_Buffer));
if (!send) return NULL;
send->sink = gst_object_ref(sink);
send->frame = gst_buffer_ref(buffer);
send->info = *info;
if (gst_video_frame_map(&(send->vframe), info, buffer, GST_MAP_READ))
send->vfmapped = EINA_TRUE;
else
send->vfmapped = EINA_FALSE;
send->eformat = eformat;
send->eheight = eheight;
send->func = func;
return send;
}
@ -39,7 +42,7 @@ emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send)
Emotion_Gstreamer_Message *
emotion_gstreamer_message_alloc(Emotion_Gstreamer *ev,
GstMessage *msg)
GstMessage *msg)
{
Emotion_Gstreamer_Message *send;

View File

@ -6,7 +6,8 @@
static inline void
_evas_video_bgrx_step(unsigned char *evas_data, const unsigned char *gst_data,
unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height, unsigned int step)
unsigned int w, unsigned int h EINA_UNUSED,
unsigned int output_height, unsigned int step)
{
unsigned int x, y;
@ -25,7 +26,9 @@ _evas_video_bgrx_step(unsigned char *evas_data, const unsigned char *gst_data,
}
static void
_evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
_evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data,
unsigned int w, unsigned int h, unsigned int output_height,
Emotion_Convert_Info *info EINA_UNUSED)
{
// XXX: need to check offset and stride that gst provide and what they
// mean with a non-planar format like bgra
@ -33,7 +36,9 @@ _evas_video_bgr(unsigned char *evas_data, const unsigned char *gst_data, unsigne
}
static void
_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data,
unsigned int w, unsigned int h, unsigned int output_height,
Emotion_Convert_Info *info EINA_UNUSED)
{
// XXX: need to check offset and stride that gst provide and what they
// mean with a non-planar format like bgra
@ -41,7 +46,10 @@ _evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsign
}
static void
_evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
_evas_video_bgra(unsigned char *evas_data, const unsigned char *gst_data,
unsigned int w, unsigned int h EINA_UNUSED,
unsigned int output_height,
Emotion_Convert_Info *info EINA_UNUSED)
{
unsigned int x, y;
@ -65,51 +73,70 @@ _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 EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
_evas_video_i420(unsigned char *evas_data,
const unsigned char *gst_data EINA_UNUSED,
unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED,
unsigned int output_height,
Emotion_Convert_Info *info)
{
const unsigned char **rows, *ptr;
unsigned int i, j, jump, rh;
if (info->bpp[0] != 1) ERR("Plane 0 bpp != 1");
if (info->bpp[1] != 1) ERR("Plane 1 bpp != 1");
if (info->bpp[2] != 1) ERR("Plane 2 bpp != 1");
rh = output_height;
rows = (const unsigned char **)evas_data;
ptr = gst_data + info->plane_offset[0];
ptr = info->plane_ptr[0];
jump = info->stride[0];
for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
ptr = gst_data + info->plane_offset[1];
ptr = info->plane_ptr[1];
jump = info->stride[1];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
ptr = gst_data + info->plane_offset[2];
ptr = info->plane_ptr[2];
jump = info->stride[2];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
}
static void
_evas_video_yv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
_evas_video_yv12(unsigned char *evas_data,
const unsigned char *gst_data EINA_UNUSED,
unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED,
unsigned int output_height,
Emotion_Convert_Info *info)
{
const unsigned char **rows, *ptr;
unsigned int i, j, jump, rh;
if (info->bpp[0] != 1) ERR("Plane 0 bpp != 1");
if (info->bpp[1] != 1) ERR("Plane 1 bpp != 1");
if (info->bpp[2] != 1) ERR("Plane 2 bpp != 1");
rh = output_height;
rows = (const unsigned char **)evas_data;
ptr = gst_data + info->plane_offset[0];
ptr = info->plane_ptr[0];
jump = info->stride[0];
for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
ptr = gst_data + info->plane_offset[2];
ptr = info->plane_ptr[1];
jump = info->stride[1];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
ptr = gst_data + info->plane_offset[1];
ptr = info->plane_ptr[2];
jump = info->stride[2];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
}
static void
_evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
_evas_video_yuy2(unsigned char *evas_data, const unsigned char *gst_data,
unsigned int w, unsigned int h EINA_UNUSED,
unsigned int output_height,
Emotion_Convert_Info *info EINA_UNUSED)
{
const unsigned char **rows;
unsigned int i, stride;
@ -124,19 +151,26 @@ _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 EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info)
_evas_video_nv12(unsigned char *evas_data,
const unsigned char *gst_data EINA_UNUSED,
unsigned int w EINA_UNUSED, unsigned int h EINA_UNUSED,
unsigned int output_height, Emotion_Convert_Info *info)
{
const unsigned char **rows, *ptr;
unsigned int i, j, jump, rh;
if (info->bpp[0] != 1) ERR("Plane 0 bpp != 1");
// XXX: not sure this should be 1 but 2 bytes per pixel... no?
//if (info->bpp[1] != 1) ERR("Plane 1 bpp != 1");
rh = output_height;
rows = (const unsigned char **)evas_data;
ptr = gst_data + info->plane_offset[0];
ptr = info->plane_ptr[0];
jump = info->stride[0];
for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
ptr = gst_data + info->plane_offset[1];
ptr = info->plane_ptr[1];
jump = info->stride[1];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
}

View File

@ -39,8 +39,9 @@ typedef struct _Emotion_Gstreamer_Message Emotion_Gstreamer_Message;
struct _Emotion_Convert_Info
{
unsigned int bpp[4];
unsigned int stride[4];
unsigned int plane_offset[4];
unsigned char *plane_ptr[4];
};
struct _Emotion_Gstreamer_Metadata
@ -121,6 +122,8 @@ struct _EmotionVideoSinkPrivate {
GstBuffer *last_buffer;
GstMapInfo map_info;
GstVideoFrame last_vframe;
int frames;
int flapse;
double rtime;
@ -136,18 +139,19 @@ struct _EmotionVideoSinkPrivate {
// Protected by the buffer mutex
Eina_Bool unlocked : 1;
Eina_Bool mapped : 1;
Eina_Bool vfmapped : 1;
};
struct _Emotion_Gstreamer_Buffer
{
GstVideoFrame vframe;
EmotionVideoSink *sink;
GstBuffer *frame;
GstVideoInfo info;
Evas_Video_Convert_Cb func;
Evas_Colorspace eformat;
int eheight;
Evas_Video_Convert_Cb func;
Eina_Bool vfmapped : 1;
};
struct _Emotion_Gstreamer_Message

View File

@ -137,15 +137,28 @@ emotion_video_sink_dispose(GObject* object)
sink = EMOTION_VIDEO_SINK(object);
priv = sink->priv;
if ((priv->mapped) && (priv->last_buffer))
if (priv->vfmapped)
{
if (priv->evas_object)
{
evas_object_image_size_set(priv->evas_object, 1, 1);
evas_object_image_data_set(priv->evas_object, NULL);
}
gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
priv->mapped = EINA_FALSE;
gst_video_frame_unmap(&(priv->last_vframe));
priv->vfmapped = EINA_FALSE;
}
else
{
if ((priv->mapped) && (priv->last_buffer))
{
if (priv->evas_object)
{
evas_object_image_size_set(priv->evas_object, 1, 1);
evas_object_image_data_set(priv->evas_object, NULL);
}
gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
priv->mapped = EINA_FALSE;
}
}
if (priv->last_buffer)
{
@ -231,6 +244,16 @@ emotion_video_sink_stop(GstBaseSink* base_sink)
INF("sink stop");
eina_lock_take(&priv->m);
if (priv->vfmapped)
{
if (priv->evas_object)
{
evas_object_image_size_set(priv->evas_object, 1, 1);
evas_object_image_data_set(priv->evas_object, NULL);
}
gst_video_frame_unmap(&(priv->last_vframe));
priv->vfmapped = EINA_FALSE;
}
if (priv->last_buffer)
{
if (priv->evas_object)
@ -401,10 +424,13 @@ emotion_video_sink_main_render(void *data)
buffer = gst_buffer_ref(send->frame);
if (!gst_buffer_map(buffer, &map, GST_MAP_READ))
if (!send->vfmapped)
{
ERR("Cannot map video buffer for read.\n");
goto exit_point;
if (!gst_buffer_map(buffer, &map, GST_MAP_READ))
{
ERR("Cannot map video buffer for read.\n");
goto exit_point;
}
}
INF("sink main render [%i, %i] (source height: %i)", send->info.width, send->eheight, send->info.height);
@ -434,14 +460,39 @@ emotion_video_sink_main_render(void *data)
info.plane_offset[2] = send->info.offset[2];
info.plane_offset[3] = send->info.offset[3];
*/
info.stride[0] = send->info.stride[0];
info.stride[1] = send->info.stride[1];
info.stride[2] = send->info.stride[2];
info.stride[3] = send->info.stride[3];
info.plane_offset[0] = send->info.offset[0];
info.plane_offset[1] = send->info.offset[1];
info.plane_offset[2] = send->info.offset[2];
info.plane_offset[3] = send->info.offset[3];
if (send->vfmapped)
{
GstVideoFrame *vframe = &(send->vframe);
map.data = GST_VIDEO_FRAME_PLANE_DATA(vframe, 0);
info.bpp[0] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 0);
info.bpp[1] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 1);
info.bpp[2] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 2);
info.bpp[3] = GST_VIDEO_FRAME_COMP_PSTRIDE(vframe, 3);
info.stride[0] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 0);
info.stride[1] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 1);
info.stride[2] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 2);
info.stride[3] = GST_VIDEO_FRAME_COMP_STRIDE(vframe, 3);
info.plane_ptr[0] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 0);
info.plane_ptr[1] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 1);
info.plane_ptr[2] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 2);
info.plane_ptr[3] = GST_VIDEO_FRAME_PLANE_DATA(vframe, 3);
}
else
{
info.bpp[0] = 1;
info.bpp[1] = 1;
info.bpp[2] = 1;
info.bpp[3] = 1;
info.stride[0] = send->info.stride[0];
info.stride[1] = send->info.stride[1];
info.stride[2] = send->info.stride[2];
info.stride[3] = send->info.stride[3];
info.plane_ptr[0] = ((unsigned char *)map.data) + send->info.offset[0];
info.plane_ptr[1] = ((unsigned char *)map.data) + send->info.offset[1];
info.plane_ptr[2] = ((unsigned char *)map.data) + send->info.offset[2];
info.plane_ptr[3] = ((unsigned char *)map.data) + send->info.offset[3];
}
if (send->func)
send->func(evas_data, map.data, send->info.width, send->info.height, send->eheight, &info);
@ -459,10 +510,26 @@ emotion_video_sink_main_render(void *data)
_emotion_frame_resize(priv->emotion_object, send->info.width, send->eheight, ratio);
if ((priv->mapped) && (priv->last_buffer))
gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
priv->map_info = map;
priv->mapped = EINA_TRUE;
if (priv->vfmapped)
{
gst_video_frame_unmap(&(priv->last_vframe));
}
else
{
if ((priv->mapped) && (priv->last_buffer))
gst_buffer_unmap(priv->last_buffer, &(priv->map_info));
}
if (send->vfmapped)
{
priv->last_vframe = send->vframe;
priv->vfmapped = EINA_TRUE;
}
else
{
priv->vfmapped = EINA_FALSE;
priv->map_info = map;
priv->mapped = EINA_TRUE;
}
if (priv->last_buffer) gst_buffer_unref(priv->last_buffer);
priv->last_buffer = buffer;