From 21bf4f04f3fdfa04aa565f144ec73a340a641cee Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 2 Jan 2012 13:30:53 +0100 Subject: [PATCH] video: fix some video formats Rename the offset field in GstVideoFormatInfo to poffset to avoid confusion with the offset of the plane in the buffer. The poffset is the offset in the plane where the first byte of the component data can be found. Properly implement the COMP_OFFSET calculations. Fix YV12 and YVU9, simply use the same offsets as the regular I420 and YUV9 variants, we use the plane info to reorder components already. Improve the unit test. --- gst-libs/gst/video/video.c | 24 ++----------- gst-libs/gst/video/video.h | 16 +++++---- tests/check/libs/video.c | 89 +++++++++++++++++++++++----------------------- 3 files changed, 56 insertions(+), 73 deletions(-) diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index f00ebd6..94bd87b 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -1259,6 +1259,7 @@ fill_planes (GstVideoInfo * info) info->size = info->stride[0] * height; break; case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */ info->stride[0] = GST_ROUND_UP_4 (width); info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2); info->stride[2] = info->stride[1]; @@ -1269,17 +1270,6 @@ fill_planes (GstVideoInfo * info) info->size = info->offset[2] + info->stride[2] * (GST_ROUND_UP_2 (height) / 2); break; - case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */ - info->stride[0] = GST_ROUND_UP_4 (width); - info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2); - info->stride[2] = info->stride[1]; - info->offset[0] = 0; - info->offset[2] = info->stride[0] * GST_ROUND_UP_2 (height); - info->offset[1] = info->offset[2] + - info->stride[1] * (GST_ROUND_UP_2 (height) / 2); - info->size = info->offset[1] + - info->stride[2] * (GST_ROUND_UP_2 (height) / 2); - break; case GST_VIDEO_FORMAT_Y41B: info->stride[0] = GST_ROUND_UP_4 (width); info->stride[1] = GST_ROUND_UP_16 (width) / 4; @@ -1331,6 +1321,7 @@ fill_planes (GstVideoInfo * info) info->size = info->offset[3] + info->stride[0]; break; case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: info->stride[0] = GST_ROUND_UP_4 (width); info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4); info->stride[2] = info->stride[1]; @@ -1341,17 +1332,6 @@ fill_planes (GstVideoInfo * info) info->size = info->offset[2] + info->stride[2] * (GST_ROUND_UP_4 (height) / 4); break; - case GST_VIDEO_FORMAT_YVU9: - info->stride[0] = GST_ROUND_UP_4 (width); - info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4); - info->stride[2] = info->stride[1]; - info->offset[0] = 0; - info->offset[2] = info->stride[0] * height; - info->offset[1] = info->offset[2] + - info->stride[1] * (GST_ROUND_UP_4 (height) / 4); - info->size = info->offset[2] + - info->stride[2] * (GST_ROUND_UP_4 (height) / 4); - break; case GST_VIDEO_FORMAT_UNKNOWN: GST_ERROR ("invalid format"); g_warning ("invalid format"); diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h index 6765120..788607f 100644 --- a/gst-libs/gst/video/video.h +++ b/gst-libs/gst/video/video.h @@ -222,7 +222,7 @@ typedef void (*GstVideoFormatPack) (GstVideoFormatInfo *info, const gp * less than the amount of components when multiple components are packed into * one plane. * @plane: the plane number where a component can be found - * @offset: the offset in the plane where the first pixel of the components + * @poffset: the offset in the plane where the first pixel of the components * can be found. If bits < 8 the amount is specified in bits. * @w_sub: subsampling factor of the width for the component. Use * GST_VIDEO_SUB_SCALE to scale a width. @@ -246,7 +246,7 @@ struct _GstVideoFormatInfo { gint pixel_stride[GST_VIDEO_MAX_COMPONENTS]; guint n_planes; guint plane[GST_VIDEO_MAX_COMPONENTS]; - guint offset[GST_VIDEO_MAX_COMPONENTS]; + guint poffset[GST_VIDEO_MAX_COMPONENTS]; guint w_sub[GST_VIDEO_MAX_COMPONENTS]; guint h_sub[GST_VIDEO_MAX_COMPONENTS]; @@ -273,7 +273,7 @@ struct _GstVideoFormatInfo { #define GST_VIDEO_FORMAT_INFO_PSTRIDE(info,c) ((info)->pixel_stride[c]) #define GST_VIDEO_FORMAT_INFO_N_PLANES(info) ((info)->n_planes) #define GST_VIDEO_FORMAT_INFO_PLANE(info,c) ((info)->plane[c]) -#define GST_VIDEO_FORMAT_INFO_OFFSET(info,c) ((info)->offset[c]) +#define GST_VIDEO_FORMAT_INFO_POFFSET(info,c) ((info)->poffset[c]) #define GST_VIDEO_FORMAT_INFO_W_SUB(info,c) ((info)->w_sub[c]) #define GST_VIDEO_FORMAT_INFO_H_SUB(info,c) ((info)->h_sub[c]) @@ -283,8 +283,10 @@ struct _GstVideoFormatInfo { #define GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info,c,h) GST_VIDEO_SUB_SCALE ((info)->h_sub[(c)],(h)) #define GST_VIDEO_FORMAT_INFO_DATA(info,planes,comp) \ - (((guint8*)(planes)[info->plane[comp]]) + info->offset[comp]) + (((guint8*)(planes)[info->plane[comp]]) + info->poffset[comp]) #define GST_VIDEO_FORMAT_INFO_STRIDE(info,strides,comp) ((strides)[info->plane[comp]]) +#define GST_VIDEO_FORMAT_INFO_OFFSET(info,offsets,comp) \ + (((offsets)[info->plane[comp]]) + info->poffset[comp]) /* format properties */ GstVideoFormat gst_video_format_from_masks (gint depth, gint bpp, gint endianness, @@ -574,12 +576,13 @@ struct _GstVideoInfo { /* dealing with components */ #define GST_VIDEO_INFO_N_COMPONENTS(i) GST_VIDEO_FORMAT_INFO_N_COMPONENTS((i)->finfo) #define GST_VIDEO_INFO_COMP_DATA(i,d,c) GST_VIDEO_FORMAT_INFO_DATA((i)->finfo,d,c) +#define GST_VIDEO_INFO_COMP_OFFSET(i,c) GST_VIDEO_FORMAT_INFO_OFFSET((i)->finfo,(i)->offset,c) #define GST_VIDEO_INFO_COMP_STRIDE(i,c) GST_VIDEO_FORMAT_INFO_STRIDE((i)->finfo,(i)->stride,c) #define GST_VIDEO_INFO_COMP_WIDTH(i,c) GST_VIDEO_FORMAT_INFO_SCALE_WIDTH((i)->finfo,c,(i)->width) #define GST_VIDEO_INFO_COMP_HEIGHT(i,c) GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT((i)->finfo,c,(i)->height) #define GST_VIDEO_INFO_COMP_PLANE(i,c) GST_VIDEO_FORMAT_INFO_PLANE((i)->finfo,c) -#define GST_VIDEO_INFO_COMP_OFFSET(i,c) GST_VIDEO_FORMAT_INFO_OFFSET((i)->finfo,c) #define GST_VIDEO_INFO_COMP_PSTRIDE(i,c) GST_VIDEO_FORMAT_INFO_PSTRIDE((i)->finfo,c) +#define GST_VIDEO_INFO_COMP_POFFSET(i,c) GST_VIDEO_FORMAT_INFO_POFFSET((i)->finfo,c) void gst_video_info_init (GstVideoInfo *info); @@ -641,11 +644,12 @@ gboolean gst_video_frame_copy (GstVideoFrame *dest, const GstVideoFr #define GST_VIDEO_FRAME_N_COMPONENTS(f) GST_VIDEO_INFO_N_COMPONENTS(&(f)->info) #define GST_VIDEO_FRAME_COMP_DATA(f,c) GST_VIDEO_INFO_COMP_DATA(&(f)->info,(f)->data,c) #define GST_VIDEO_FRAME_COMP_STRIDE(f,c) GST_VIDEO_INFO_COMP_STRIDE(&(f)->info,c) +#define GST_VIDEO_FRAME_COMP_OFFSET(f,c) GST_VIDEO_INFO_COMP_OFFSET(&(f)->info,c) #define GST_VIDEO_FRAME_COMP_WIDTH(f,c) GST_VIDEO_INFO_COMP_WIDTH(&(f)->info,c) #define GST_VIDEO_FRAME_COMP_HEIGHT(f,c) GST_VIDEO_INFO_COMP_HEIGHT(&(f)->info,c) #define GST_VIDEO_FRAME_COMP_PLANE(f,c) GST_VIDEO_INFO_COMP_PLANE(&(f)->info,c) -#define GST_VIDEO_FRAME_COMP_OFFSET(f,c) GST_VIDEO_INFO_COMP_OFFSET(&(f)->info,c) #define GST_VIDEO_FRAME_COMP_PSTRIDE(f,c) GST_VIDEO_INFO_COMP_PSTRIDE(&(f)->info,c) +#define GST_VIDEO_FRAME_COMP_POFFSET(f,c) GST_VIDEO_INFO_COMP_POFFSET(&(f)->info,c) #define GST_VIDEO_SIZE_RANGE "(int) [ 1, max ]" #define GST_VIDEO_FPS_RANGE "(fraction) [ 0, max ]" diff --git a/tests/check/libs/video.c b/tests/check/libs/video.c index 7133868..5245a24 100644 --- a/tests/check/libs/video.c +++ b/tests/check/libs/video.c @@ -69,7 +69,7 @@ static void paint_setup_YVYU (paintinfo * p, unsigned char *dest); static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest); static void paint_setup_Y41B (paintinfo * p, unsigned char *dest); static void paint_setup_Y42B (paintinfo * p, unsigned char *dest); -static void paint_setup_Y800 (paintinfo * p, unsigned char *dest); +static void paint_setup_GRAY8 (paintinfo * p, unsigned char *dest); static void paint_setup_AYUV (paintinfo * p, unsigned char *dest); #if 0 @@ -138,8 +138,8 @@ struct fourcc_list_struct fourcc_list[] = { {"Y41B", "Y41B", 12, paint_setup_Y41B}, /* Y42B */ {"Y42B", "Y42B", 16, paint_setup_Y42B}, - /* Y800 grayscale */ - {"Y800", "Y800", 8, paint_setup_Y800} + /* GRAY8 grayscale */ + {"GRAY8", "GRAY8", 8, paint_setup_GRAY8} }; /* returns the size in bytes for one video frame of the given dimensions @@ -259,7 +259,7 @@ paint_setup_Y42B (paintinfo * p, unsigned char *dest) } static void -paint_setup_Y800 (paintinfo * p, unsigned char *dest) +paint_setup_GRAY8 (paintinfo * p, unsigned char *dest) { /* untested */ p->yp = dest; @@ -334,7 +334,7 @@ video_format_is_packed (GstVideoFormat fmt) case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y41B: case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_GRAY8: case GST_VIDEO_FORMAT_YUV9: case GST_VIDEO_FORMAT_YVU9: return FALSE; @@ -444,6 +444,7 @@ GST_START_TEST (test_video_formats) GstVideoInfo vinfo; paintinfo paintinfo = { 0, }; guint off0, off1, off2, off3; + guint cs0, cs1, cs2, cs3; guint size; GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h); @@ -457,7 +458,7 @@ GST_START_TEST (test_video_formats) fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 0), paintinfo.ystride); if (!gst_video_format_is_packed (fmt) - && !GST_VIDEO_FORMAT_INFO_IS_GRAY (vf_info)) { + && !GST_VIDEO_INFO_N_PLANES (&vinfo) > 2) { /* planar */ fail_unless_equals_int (GST_VIDEO_INFO_COMP_STRIDE (&vinfo, 1), paintinfo.ustride); @@ -471,6 +472,11 @@ GST_START_TEST (test_video_formats) off1 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 1); off2 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 2); + GST_INFO ("size %d <> %d", size, paintinfo.endptr); + GST_INFO ("off0 %d <> %d", off0, paintinfo.yp); + GST_INFO ("off1 %d <> %d", off1, paintinfo.up); + GST_INFO ("off2 %d <> %d", off2, paintinfo.vp); + fail_unless_equals_int (size, (unsigned long) paintinfo.endptr); fail_unless_equals_int (off0, (unsigned long) paintinfo.yp); fail_unless_equals_int (off1, (unsigned long) paintinfo.up); @@ -480,46 +486,39 @@ GST_START_TEST (test_video_formats) off3 = GST_VIDEO_INFO_COMP_OFFSET (&vinfo, 3); fail_unless_equals_int (off3, (unsigned long) paintinfo.ap); - /* some gstvideo checks ... (FIXME: fails for Y41B and Y42B; not sure - * if the check or the _get_component_size implementation is wrong) */ - if (fmt != GST_VIDEO_FORMAT_Y41B && fmt != GST_VIDEO_FORMAT_Y42B - && fmt != GST_VIDEO_FORMAT_Y800) { - guint cs0, cs1, cs2, cs3; - - cs0 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 0) * - GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 0); - cs1 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 1) * - GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 1); - cs2 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 2) * - GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2); + cs0 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 0) * + GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 0); + cs1 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 1) * + GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 1); + cs2 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 2) * + GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2); + + /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d", + cs0, cs1, cs2, off0, off1, off2, size); */ - /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d", - cs0, cs1, cs2, off0, off1, off2, size); */ - - if (!gst_video_format_is_packed (fmt)) - fail_unless (cs0 <= off1); - - if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vinfo.finfo)) { - cs3 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 3) * - GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2); - fail_unless (cs3 < size); - /* U/V/alpha shouldn't take up more space than the Y component */ - fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0); - fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0); - fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0); - - /* all components together shouldn't take up more space than size */ - fail_unless (cs0 + cs1 + cs2 + cs3 <= size); - } else { - /* U/V shouldn't take up more space than the Y component */ - fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0); - fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0); - - /* all components together shouldn't take up more space than size */ - fail_unless (cs0 + cs1 + cs2 <= size, - "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)", - cs0, cs1, cs2, size); - } + if (!gst_video_format_is_packed (fmt)) + fail_unless (cs0 <= off1); + + if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (vinfo.finfo)) { + cs3 = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, 3) * + GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, 2); + fail_unless (cs3 < size); + /* U/V/alpha shouldn't take up more space than the Y component */ + fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0); + fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0); + fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0); + + /* all components together shouldn't take up more space than size */ + fail_unless (cs0 + cs1 + cs2 + cs3 <= size); + } else { + /* U/V shouldn't take up more space than the Y component */ + fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0); + fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0); + + /* all components together shouldn't take up more space than size */ + fail_unless (cs0 + cs1 + cs2 <= size, + "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)", + cs0, cs1, cs2, size); } } } -- 2.7.4