emotion - gstreamer1 - fix yuv import funcs to use gst stride + offset

so our yuv import funcs for gstreamer 1.x engine were ignoring the
plane offsets and strides provided by gstreamer. though this nicely
shows that these numbers provided are actually wrong - at least in the
testing with vaapi back-ends with gst.

so this fixes emotions' badness but there is still badness in gst
apparently. the numbers provided if used are just simply wrong for teh
image data. commented code in the src to show how to "Fix it up" by
forcing some alignment of content to get it to work.

@fix
This commit is contained in:
Carsten Haitzler 2017-04-16 12:56:11 +09:00
parent d87a65e825
commit a85494a5b2
3 changed files with 93 additions and 60 deletions

View File

@ -8,8 +8,7 @@ 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 x;
unsigned int y;
unsigned int x, y;
for (y = 0; y < output_height; ++y)
{
@ -26,23 +25,28 @@ _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)
_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
_evas_video_bgrx_step(evas_data, gst_data, w, h, output_height, 3);
}
static void
_evas_video_bgrx(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h, unsigned int output_height)
_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
_evas_video_bgrx_step(evas_data, gst_data, w, h, output_height, 4);
}
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)
_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;
unsigned int y;
unsigned int x, y;
// XXX: need to check offset and stride that gst provide and what they
// mean with a non-planar format like bgra
for (y = 0; y < output_height; ++y)
{
unsigned char alpha;
@ -61,90 +65,80 @@ _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 EINA_UNUSED, unsigned int h EINA_UNUSED, unsigned int output_height, Emotion_Convert_Info *info EINA_UNUSED)
{
const unsigned char **rows;
unsigned int i, j;
unsigned int rh;
unsigned int stride_y, stride_uv;
const unsigned char **rows, *ptr;
unsigned int i, j, jump, rh;
rh = output_height;
rows = (const unsigned char **)evas_data;
stride_y = GST_ROUND_UP_4(w);
stride_uv = GST_ROUND_UP_8(w) / 2;
ptr = gst_data + info->plane_offset[0];
jump = info->stride[0];
for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
for (i = 0; i < rh; i++)
rows[i] = &gst_data[i * stride_y];
ptr = gst_data + info->plane_offset[1];
jump = info->stride[1];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
for (j = 0; j < (rh / 2); j++, i++)
rows[i] = &gst_data[h * stride_y + j * stride_uv];
for (j = 0; j < (rh / 2); j++, i++)
rows[i] = &gst_data[h * stride_y +
(rh / 2) * stride_uv +
j * stride_uv];
ptr = gst_data + info->plane_offset[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, unsigned int h, unsigned int output_height)
_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)
{
const unsigned char **rows;
unsigned int i, j;
unsigned int rh;
unsigned int stride_y, stride_uv;
const unsigned char **rows, *ptr;
unsigned int i, j, jump, rh;
rh = output_height;
rows = (const unsigned char **)evas_data;
stride_y = GST_ROUND_UP_4(w);
stride_uv = GST_ROUND_UP_8(w) / 2;
ptr = gst_data + info->plane_offset[0];
jump = info->stride[0];
for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
for (i = 0; i < rh; i++)
rows[i] = &gst_data[i * stride_y];
ptr = gst_data + info->plane_offset[2];
jump = info->stride[1];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
for (j = 0; j < (rh / 2); j++, i++)
rows[i] = &gst_data[h * stride_y +
(rh / 2) * stride_uv +
j * stride_uv];
for (j = 0; j < (rh / 2); j++, i++)
rows[i] = &gst_data[h * stride_y + j * stride_uv];
ptr = gst_data + info->plane_offset[1];
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)
_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;
unsigned int stride;
unsigned int i, stride;
// XXX: need to check offset and stride that gst provide and what they
// mean with a non-planar format like yuy2
rows = (const unsigned char **)evas_data;
stride = GST_ROUND_UP_4(w * 2);
for (i = 0; i < output_height; i++)
rows[i] = &gst_data[i * stride];
for (i = 0; i < output_height; i++) rows[i] = &gst_data[i * stride];
}
static void
_evas_video_nv12(unsigned char *evas_data, const unsigned char *gst_data, unsigned int w, unsigned int h EINA_UNUSED, unsigned int output_height)
_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)
{
const unsigned char **rows;
unsigned int i, j;
unsigned int rh;
const unsigned char **rows, *ptr;
unsigned int i, j, jump, rh;
rh = output_height;
rows = (const unsigned char **)evas_data;
for (i = 0; i < rh; i++)
rows[i] = &gst_data[i * w];
ptr = gst_data + info->plane_offset[0];
jump = info->stride[0];
for (i = 0; i < rh; i++, ptr += jump) rows[i] = ptr;
for (j = 0; j < (rh / 2); j++, i++)
rows[i] = &gst_data[rh * w + j * w];
ptr = gst_data + info->plane_offset[1];
jump = info->stride[1];
for (j = 0; j < (rh / 2); j++, i++, ptr += jump) rows[i] = ptr;
}
const ColorSpace_Format_Convertion colorspace_format_convertion[] = {

View File

@ -20,11 +20,14 @@
#include "emotion_modules.h"
typedef struct _Emotion_Convert_Info Emotion_Convert_Info;
typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data,
const unsigned char *gst_data,
unsigned int w,
unsigned int h,
unsigned int output_height);
unsigned int output_height,
Emotion_Convert_Info *info);
typedef struct _EmotionVideoSinkPrivate EmotionVideoSinkPrivate;
typedef struct _EmotionVideoSink EmotionVideoSink;
@ -34,6 +37,12 @@ typedef struct _Emotion_Gstreamer_Metadata Emotion_Gstreamer_Metadata;
typedef struct _Emotion_Gstreamer_Buffer Emotion_Gstreamer_Buffer;
typedef struct _Emotion_Gstreamer_Message Emotion_Gstreamer_Message;
struct _Emotion_Convert_Info
{
unsigned int stride[4];
unsigned int plane_offset[4];
};
struct _Emotion_Gstreamer_Metadata
{
char *title;

View File

@ -366,6 +366,7 @@ emotion_video_sink_main_render(void *data)
GstMapInfo map;
unsigned char *evas_data;
double ratio;
Emotion_Convert_Info info;
send = data;
@ -401,7 +402,10 @@ emotion_video_sink_main_render(void *data)
buffer = gst_buffer_ref(send->frame);
if (!gst_buffer_map(buffer, &map, GST_MAP_READ))
goto exit_point;
{
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);
@ -409,12 +413,38 @@ emotion_video_sink_main_render(void *data)
evas_object_image_colorspace_set(priv->evas_object, send->eformat);
evas_object_image_size_set(priv->evas_object, send->info.width, send->eheight);
// XXX: need to handle GstVideoCropMeta to get video cropping right
evas_data = evas_object_image_data_get(priv->evas_object, 1);
// XXX: need to handle GstVideoCropMeta to get video cropping right
// XXX: can't get crop meta from buffer (always null)
// GstVideoCropMeta *meta;
// meta = gst_buffer_get_video_crop_meta(buffer);
// printf("META: %p\n", meta);
/* this just is a demo of broken vaapi back-end values for stride and
* plane offset - the below is what i needed to fix them up for a few videos
*/
/*
info.stride[0] = 64 * ((send->info.stride[0] + 63) / 64);
info.stride[1] = 64 * ((send->info.stride[1] + 63) / 64);
info.stride[2] = 64 * ((send->info.stride[2] + 63) / 64);
info.stride[3] = 64 * ((send->info.stride[3] + 63) / 64);
info.plane_offset[0] = send->info.offset[0];
info.plane_offset[1] = (((send->info.height + 15) / 16) * 16) * info.stride[1];
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->func)
send->func(evas_data, map.data, send->info.width, send->info.height, send->eheight);
send->func(evas_data, map.data, send->info.width, send->info.height, send->eheight, &info);
else
WRN("No way to decode %x colorspace !", send->eformat);