From d8c1044fbdeee7024bebb7906bf00aae9a8df6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 13 Oct 2010 22:51:12 +0200 Subject: [PATCH] ffmpegcolorspace: Add support for A420 --- gst/ffmpegcolorspace/avcodec.h | 1 + gst/ffmpegcolorspace/gstffmpegcodecmap.c | 23 ++ gst/ffmpegcolorspace/gstffmpegcolorspace.c | 2 +- gst/ffmpegcolorspace/imgconvert.c | 334 ++++++++++++++++++++- gst/ffmpegcolorspace/imgconvert_template.h | 255 ++++++++++++++++ 5 files changed, 613 insertions(+), 2 deletions(-) diff --git a/gst/ffmpegcolorspace/avcodec.h b/gst/ffmpegcolorspace/avcodec.h index 861804ee73..57f551ce5f 100644 --- a/gst/ffmpegcolorspace/avcodec.h +++ b/gst/ffmpegcolorspace/avcodec.h @@ -93,6 +93,7 @@ enum PixelFormat { PIX_FMT_V308, ///< Packed pixel, Y0 Cb Cr PIX_FMT_AYUV4444, ///< Packed pixel, A0 Y0 Cb Cr + PIX_FMT_YUVA420P, ///< Planar YUV 4:4:2:0 (1 Cr & Cb sample per 2x2 Y & A samples) (A420) PIX_FMT_NB }; diff --git a/gst/ffmpegcolorspace/gstffmpegcodecmap.c b/gst/ffmpegcolorspace/gstffmpegcodecmap.c index cde098fd07..bc885b12f7 100644 --- a/gst/ffmpegcolorspace/gstffmpegcodecmap.c +++ b/gst/ffmpegcolorspace/gstffmpegcodecmap.c @@ -170,6 +170,9 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context) case PIX_FMT_YUV420P: fmt = GST_MAKE_FOURCC ('I', '4', '2', '0'); break; + case PIX_FMT_YUVA420P: + fmt = GST_MAKE_FOURCC ('A', '4', '2', '0'); + break; case PIX_FMT_NV12: fmt = GST_MAKE_FOURCC ('N', 'V', '1', '2'); break; @@ -636,6 +639,9 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps, case GST_MAKE_FOURCC ('I', '4', '2', '0'): context->pix_fmt = PIX_FMT_YUV420P; break; + case GST_MAKE_FOURCC ('A', '4', '2', '0'): + context->pix_fmt = PIX_FMT_YUVA420P; + break; case GST_MAKE_FOURCC ('N', 'V', '1', '2'): context->pix_fmt = PIX_FMT_NV12; break; @@ -857,6 +863,23 @@ gst_ffmpegcsp_avpicture_fill (AVPicture * picture, return size + 2 * size2; /* PIX_FMT_YVU420P = YV12: same as PIX_FMT_YUV420P, but * with U and V plane swapped. Strides as in videotestsrc */ + case PIX_FMT_YUVA420P: + stride = GST_ROUND_UP_4 (width); + h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); + stride2 = GST_ROUND_UP_4 (w2); + h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = picture->data[2] + size2; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + picture->linesize[3] = stride; + return 2 * size + 2 * size2; case PIX_FMT_YVU410P: case PIX_FMT_YVU420P: stride = GST_ROUND_UP_4 (width); diff --git a/gst/ffmpegcolorspace/gstffmpegcolorspace.c b/gst/ffmpegcolorspace/gstffmpegcolorspace.c index 09de289100..4ba02046b4 100644 --- a/gst/ffmpegcolorspace/gstffmpegcolorspace.c +++ b/gst/ffmpegcolorspace/gstffmpegcolorspace.c @@ -47,7 +47,7 @@ GST_DEBUG_CATEGORY (ffmpegcolorspace_performance); #define FFMPEGCSP_VIDEO_CAPS \ "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ - "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV } ;" \ + "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, A420} ;" \ GST_VIDEO_CAPS_RGB";" \ GST_VIDEO_CAPS_BGR";" \ GST_VIDEO_CAPS_RGBx";" \ diff --git a/gst/ffmpegcolorspace/imgconvert.c b/gst/ffmpegcolorspace/imgconvert.c index bc3e5206fe..64ac475ec3 100644 --- a/gst/ffmpegcolorspace/imgconvert.c +++ b/gst/ffmpegcolorspace/imgconvert.c @@ -477,8 +477,18 @@ static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { /* .x_chroma_shift = */ 0, /* .y_chroma_shift = */ 0, /*.depth = */ 8 + }, + /* [PIX_FMT_YUVA420P] = */ { + /* .format = */ PIX_FMT_YUVA420P, + /* .name = */ "yuva420p", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, } - }; /* returns NULL if not found */ @@ -1595,6 +1605,76 @@ nv21_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height) } } +static void +yuva420p_to_yuv420p (AVPicture * dst, const AVPicture * src, int width, + int height) +{ + memcpy (dst->data[0], src->data[0], dst->linesize[0] * height); + memcpy (dst->data[1], src->data[1], dst->linesize[1] * ((height + 1) / 2)); + memcpy (dst->data[2], src->data[2], dst->linesize[2] * ((height + 1) / 2)); +} + +static void +yuva420p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + } + + linesrc += dst->linesize[0] * 2; + lumsrc += src->linesize[0] * 2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } + /* odd height */ + if (height % 2 != 0) { + line1 = linesrc; + lum1 = lumsrc; + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line1++ = *cb1++; + *line1++ = *lum1++; + *line1++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line1++ = *cb1++; + } + } +} + #define SCALEBITS 10 #define ONE_HALF (1 << (SCALEBITS - 1)) #define FIX(x) ((int) ((x) * (1<data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + a1_ptr = src->data[3]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + a2_ptr = a1_ptr + src->linesize[3]; + for (w = width; w >= 2; w -= 2) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d1[4 + 0] = a1_ptr[1]; + d1[4 + 1] = y1_ptr[1]; + d1[4 + 2] = cb_ptr[0]; + d1[4 + 3] = cr_ptr[0]; + + d2[0] = a2_ptr[0]; + d2[1] = y2_ptr[0]; + d2[2] = cb_ptr[0]; + d2[3] = cr_ptr[0]; + + d2[4 + 0] = a2_ptr[1]; + d2[4 + 1] = y2_ptr[1]; + d2[4 + 2] = cb_ptr[0]; + d2[4 + 3] = cr_ptr[0]; + + d1 += 2 * 4; + d2 += 2 * 4; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + a2_ptr += 2; + } + /* handle odd width */ + if (w) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d2[0] = a2_ptr[0]; + d2[1] = y2_ptr[0]; + d2[2] = cb_ptr[0]; + d2[3] = cr_ptr[0]; + + d1 += 4; + d2 += 4; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + a2_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + a1_ptr += 2 * src->linesize[3] - width; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d1[4 + 0] = a1_ptr[1]; + d1[4 + 1] = y1_ptr[1]; + d1[4 + 2] = cb_ptr[0]; + d1[4 + 3] = cr_ptr[0]; + + d1 += 2 * 4; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + } + /* handle width */ + if (w) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + d1 += 4; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + } + } +} + +static void +ayuv4444_to_yuva420p (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + int wrap, wrap3, width2; + int u1, v1, w; + uint8_t *lum, *cb, *cr, *a; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + a = dst->data[3]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + p += wrap3; + lum += wrap; + a += wrap; + + a[0] = p[0]; + lum[0] = p[1]; + u1 += p[2]; + v1 += p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + + cb[0] = u1 >> 2; + cr[0] = v1 >> 2; + + cb++; + cr++; + p += -wrap3 + 2 * 4; + lum += -wrap + 2; + a += -wrap + 2; + } + if (w) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + p += wrap3; + lum += wrap; + a += wrap; + + a[0] = p[0]; + lum[0] = p[1]; + u1 += p[2]; + v1 += p[3]; + + cb[0] = u1 >> 1; + cr[0] = v1 >> 1; + cb++; + cr++; + p += -wrap3 + 4; + lum += -wrap + 1; + a += -wrap + 1; + } + p += wrap3 + (wrap3 - width * 4); + lum += wrap + (wrap - width); + a += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + cb[0] = u1 >> 1; + cr[0] = v1 >> 1; + cb++; + cr++; + p += 2 * 4; + lum += 2; + a += 2; + } + if (w) { + a[0] = p[0]; + lum[0] = p[1]; + cb[0] = p[2]; + cr[0] = p[3]; + } + } +} + typedef struct ConvertEntry { enum PixelFormat src; @@ -2872,6 +3175,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_YVYU422, PIX_FMT_ARGB32, yvyu422_to_argb32}, {PIX_FMT_RGB24, PIX_FMT_YUV420P, rgb24_to_yuv420p}, + {PIX_FMT_RGB24, PIX_FMT_YUVA420P, rgb24_to_yuva420p}, {PIX_FMT_RGB24, PIX_FMT_NV12, rgb24_to_nv12}, {PIX_FMT_RGB24, PIX_FMT_NV21, rgb24_to_nv21}, {PIX_FMT_RGB24, PIX_FMT_RGB565, rgb24_to_rgb565}, @@ -2901,6 +3205,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_RGB32, PIX_FMT_RGB555, rgba32_to_rgb555}, {PIX_FMT_RGB32, PIX_FMT_PAL8, rgb32_to_pal8}, {PIX_FMT_RGB32, PIX_FMT_YUV420P, rgb32_to_yuv420p}, + {PIX_FMT_RGB32, PIX_FMT_YUVA420P, rgb32_to_yuva420p}, {PIX_FMT_RGB32, PIX_FMT_NV12, rgb32_to_nv12}, {PIX_FMT_RGB32, PIX_FMT_NV21, rgb32_to_nv21}, {PIX_FMT_RGB32, PIX_FMT_Y800, rgb32_to_y800}, @@ -2912,6 +3217,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_xRGB32, PIX_FMT_RGB24, xrgb32_to_rgb24}, {PIX_FMT_xRGB32, PIX_FMT_PAL8, xrgb32_to_pal8}, {PIX_FMT_xRGB32, PIX_FMT_YUV420P, xrgb32_to_yuv420p}, + {PIX_FMT_xRGB32, PIX_FMT_YUVA420P, xrgb32_to_yuva420p}, {PIX_FMT_xRGB32, PIX_FMT_NV12, xrgb32_to_nv12}, {PIX_FMT_xRGB32, PIX_FMT_NV21, xrgb32_to_nv21}, {PIX_FMT_xRGB32, PIX_FMT_Y800, xrgb32_to_y800}, @@ -2930,6 +3236,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_RGBA32, PIX_FMT_RGB555, rgba32_to_rgb555}, {PIX_FMT_RGBA32, PIX_FMT_PAL8, rgba32_to_pal8}, {PIX_FMT_RGBA32, PIX_FMT_YUV420P, rgba32_to_yuv420p}, + {PIX_FMT_RGBA32, PIX_FMT_YUVA420P, rgba32_to_yuva420p}, {PIX_FMT_RGBA32, PIX_FMT_NV12, rgba32_to_nv12}, {PIX_FMT_RGBA32, PIX_FMT_NV21, rgba32_to_nv21}, {PIX_FMT_RGBA32, PIX_FMT_Y800, rgba32_to_y800}, @@ -2941,6 +3248,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_BGR24, PIX_FMT_RGB24, bgr24_to_rgb24}, {PIX_FMT_BGR24, PIX_FMT_YUV420P, bgr24_to_yuv420p}, + {PIX_FMT_BGR24, PIX_FMT_YUVA420P, bgr24_to_yuva420p}, {PIX_FMT_BGR24, PIX_FMT_NV12, bgr24_to_nv12}, {PIX_FMT_BGR24, PIX_FMT_NV21, bgr24_to_nv21}, {PIX_FMT_BGR24, PIX_FMT_Y800, bgr24_to_y800}, @@ -2952,6 +3260,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_BGR32, PIX_FMT_RGB24, bgr32_to_rgb24}, {PIX_FMT_BGR32, PIX_FMT_RGBA32, bgr32_to_rgba32}, {PIX_FMT_BGR32, PIX_FMT_YUV420P, bgr32_to_yuv420p}, + {PIX_FMT_BGR32, PIX_FMT_YUVA420P, bgr32_to_yuva420p}, {PIX_FMT_BGR32, PIX_FMT_NV12, bgr32_to_nv12}, {PIX_FMT_BGR32, PIX_FMT_NV21, bgr32_to_nv21}, {PIX_FMT_BGR32, PIX_FMT_Y800, bgr32_to_y800}, @@ -2963,6 +3272,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_BGRx32, PIX_FMT_RGB24, bgrx32_to_rgb24}, {PIX_FMT_BGRx32, PIX_FMT_RGBA32, bgrx32_to_rgba32}, {PIX_FMT_BGRx32, PIX_FMT_YUV420P, bgrx32_to_yuv420p}, + {PIX_FMT_BGRx32, PIX_FMT_YUVA420P, bgrx32_to_yuva420p}, {PIX_FMT_BGRx32, PIX_FMT_NV12, bgrx32_to_nv12}, {PIX_FMT_BGRx32, PIX_FMT_NV21, bgrx32_to_nv21}, {PIX_FMT_BGRx32, PIX_FMT_Y800, bgrx32_to_y800}, @@ -2974,6 +3284,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_BGRA32, PIX_FMT_RGB24, bgra32_to_rgb24}, {PIX_FMT_BGRA32, PIX_FMT_RGBA32, bgra32_to_rgba32}, {PIX_FMT_BGRA32, PIX_FMT_YUV420P, bgra32_to_yuv420p}, + {PIX_FMT_BGRA32, PIX_FMT_YUVA420P, bgra32_to_yuva420p}, {PIX_FMT_BGRA32, PIX_FMT_NV12, bgra32_to_nv12}, {PIX_FMT_BGRA32, PIX_FMT_NV21, bgra32_to_nv21}, {PIX_FMT_BGRA32, PIX_FMT_Y800, bgra32_to_y800}, @@ -2986,6 +3297,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_ABGR32, PIX_FMT_RGB24, abgr32_to_rgb24}, {PIX_FMT_ABGR32, PIX_FMT_RGBA32, abgr32_to_rgba32}, {PIX_FMT_ABGR32, PIX_FMT_YUV420P, abgr32_to_yuv420p}, + {PIX_FMT_ABGR32, PIX_FMT_YUVA420P, abgr32_to_yuva420p}, {PIX_FMT_ABGR32, PIX_FMT_NV12, abgr32_to_nv12}, {PIX_FMT_ABGR32, PIX_FMT_NV21, abgr32_to_nv21}, {PIX_FMT_ABGR32, PIX_FMT_Y800, abgr32_to_y800}, @@ -2998,6 +3310,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_ARGB32, PIX_FMT_RGB24, argb32_to_rgb24}, {PIX_FMT_ARGB32, PIX_FMT_RGBA32, argb32_to_rgba32}, {PIX_FMT_ARGB32, PIX_FMT_YUV420P, argb32_to_yuv420p}, + {PIX_FMT_ARGB32, PIX_FMT_YUVA420P, argb32_to_yuva420p}, {PIX_FMT_ARGB32, PIX_FMT_NV12, argb32_to_nv12}, {PIX_FMT_ARGB32, PIX_FMT_NV21, argb32_to_nv21}, {PIX_FMT_ARGB32, PIX_FMT_Y800, argb32_to_y800}, @@ -3011,6 +3324,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_RGB555, PIX_FMT_RGB32, rgb555_to_rgba32}, {PIX_FMT_RGB555, PIX_FMT_RGBA32, rgb555_to_rgba32}, {PIX_FMT_RGB555, PIX_FMT_YUV420P, rgb555_to_yuv420p}, + {PIX_FMT_RGB555, PIX_FMT_YUVA420P, rgb555_to_yuva420p}, {PIX_FMT_RGB555, PIX_FMT_NV12, rgb555_to_nv12}, {PIX_FMT_RGB555, PIX_FMT_NV21, rgb555_to_nv21}, {PIX_FMT_RGB555, PIX_FMT_Y800, rgb555_to_y800}, @@ -3021,6 +3335,7 @@ static ConvertEntry convert_table[] = { {PIX_FMT_RGB565, PIX_FMT_RGB24, rgb565_to_rgb24}, {PIX_FMT_RGB565, PIX_FMT_YUV420P, rgb565_to_yuv420p}, + {PIX_FMT_RGB565, PIX_FMT_YUVA420P, rgb565_to_yuva420p}, {PIX_FMT_RGB565, PIX_FMT_NV12, rgb565_to_nv12}, {PIX_FMT_RGB565, PIX_FMT_NV21, rgb565_to_nv21}, {PIX_FMT_RGB565, PIX_FMT_Y800, rgb565_to_y800}, @@ -3130,6 +3445,23 @@ static ConvertEntry convert_table[] = { {PIX_FMT_AYUV4444, PIX_FMT_BGRA32, ayuv4444_to_bgra32}, {PIX_FMT_AYUV4444, PIX_FMT_ABGR32, ayuv4444_to_abgr32}, {PIX_FMT_AYUV4444, PIX_FMT_RGB24, ayuv4444_to_rgb24}, + {PIX_FMT_AYUV4444, PIX_FMT_YUVA420P, ayuv4444_to_yuva420p}, + + {PIX_FMT_YUVA420P, PIX_FMT_YUV420P, yuva420p_to_yuv420p}, + {PIX_FMT_YUVA420P, PIX_FMT_YUV422, yuva420p_to_yuv422}, + {PIX_FMT_YUVA420P, PIX_FMT_AYUV4444, yuva420p_to_ayuv4444}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB555, yuva420p_to_rgb555}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB565, yuva420p_to_rgb565}, + {PIX_FMT_YUVA420P, PIX_FMT_BGR24, yuva420p_to_bgr24}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB24, yuva420p_to_rgb24}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB32, yuva420p_to_rgb32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGR32, yuva420p_to_bgr32}, + {PIX_FMT_YUVA420P, PIX_FMT_xRGB32, yuva420p_to_xrgb32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGRx32, yuva420p_to_bgrx32}, + {PIX_FMT_YUVA420P, PIX_FMT_RGBA32, yuva420p_to_rgba32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGRA32, yuva420p_to_bgra32}, + {PIX_FMT_YUVA420P, PIX_FMT_ARGB32, yuva420p_to_argb32}, + {PIX_FMT_YUVA420P, PIX_FMT_ABGR32, yuva420p_to_abgr32}, }; static ConvertEntry * diff --git a/gst/ffmpegcolorspace/imgconvert_template.h b/gst/ffmpegcolorspace/imgconvert_template.h index 04ff788efd..fa0e8c240a 100644 --- a/gst/ffmpegcolorspace/imgconvert_template.h +++ b/gst/ffmpegcolorspace/imgconvert_template.h @@ -232,6 +232,129 @@ static void glue (yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, } } +#ifndef RGBA_OUT +#define RGBA_OUT_(d, r, g, b, a) RGB_OUT(d, r, g, b) +#define YUVA_TO_A(d, a) +#else +#define RGBA_OUT_(d, r, g, b, a) RGBA_OUT(d, r, g, b, a) +#define YUVA_TO_A(d, a) do { d = a; } while (0); +#endif + +static void glue (yuva420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *a1_ptr, *a2_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add, width2; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; +#ifdef RGBA_OUT + unsigned int a = 0; +#endif + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + a1_ptr = src->data[3]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + a2_ptr = a1_ptr + src->linesize[3]; + for (w = width; w >= 2; w -= 2) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 4 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + + YUVA_TO_A (a, a1_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGBA_OUT_ (d1 + BPP, r, g, b, a); + + YUVA_TO_A (a, a2_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGBA_OUT_ (d2, r, g, b, a); + + YUVA_TO_A (a, a2_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[1]); + RGBA_OUT_ (d2 + BPP, r, g, b, a); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + a2_ptr += 2; + } + /* handle odd width */ + if (w) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + + YUVA_TO_A (a, a2_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGBA_OUT_ (d2, r, g, b, a); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + a2_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + a1_ptr += 2 * src->linesize[3] - width; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 2 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + + YUVA_TO_A (a, a1_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGBA_OUT_ (d1 + BPP, r, g, b, a); + + d1 += 2 * BPP; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + } + /* handle width */ + if (w) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 2 pixel */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + } + } +} + static void glue (nv12_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, int width, int height) { @@ -664,6 +787,135 @@ static void glue (RGB_NAME, _to_yuv420p) (AVPicture * dst, } } +#ifndef RGBA_IN +#define RGBA_IN_(r, g, b, a, p) RGB_IN(r, g, b, p) +#else +#define RGBA_IN_(r, g, b, a, p) RGBA_IN(r, g, b, a, p) +#endif + +static void glue (RGB_NAME, _to_yuva420p) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + int wrap, wrap3, width2; + int r, g, b, r1, g1, b1, w, ra = 255; + uint8_t *lum, *cb, *cr, *a; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + a = dst->data[3]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + RGBA_IN_ (r, g, b, ra, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + + RGBA_IN_ (r, g, b, ra, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + a[1] = ra; + p += wrap3; + lum += wrap; + a += wrap; + + RGBA_IN_ (r, g, b, ra, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + + RGBA_IN_ (r, g, b, ra, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + a[1] = ra; + + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 2); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 2); + + cb++; + cr++; + p += -wrap3 + 2 * BPP; + lum += -wrap + 2; + a += -wrap + 2; + } + if (w) { + RGBA_IN_ (r, g, b, ra, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + p += wrap3; + lum += wrap; + a += wrap; + RGBA_IN_ (r, g, b, ra, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + cb++; + cr++; + p += -wrap3 + BPP; + lum += -wrap + 1; + a += -wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + a += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + RGBA_IN_ (r, g, b, ra, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + + RGBA_IN_ (r, g, b, ra, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + a[1] = ra; + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + cb++; + cr++; + p += 2 * BPP; + lum += 2; + a += 2; + } + if (w) { + RGBA_IN_ (r, g, b, ra, p); + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + cb[0] = RGB_TO_U_CCIR (r, g, b, 0); + cr[0] = RGB_TO_V_CCIR (r, g, b, 0); + } + } +} + static void glue (RGB_NAME, _to_nv12) (AVPicture * dst, const AVPicture * src, int width, int height) { @@ -1931,3 +2183,6 @@ static int glue (get_alpha_info_, RGB_NAME) (const AVPicture * src, #undef RGB_NAME #undef FMT_RGB24 #undef FMT_RGBA32 +#undef YUVA_TO_A +#undef RGBA_OUT_ +#undef RGBA_IN_