Commit 298f1c32 authored by Sebastian Dröge's avatar Sebastian Dröge

videobox: Refactor boxing to reduce code duplication

parent 2e043908
......@@ -68,6 +68,702 @@
GST_DEBUG_CATEGORY_STATIC (videobox_debug);
#define GST_CAT_DEFAULT videobox_debug
/* From videotestsrc.c */
static const guint8 yuv_sdtv_colors_Y[VIDEO_BOX_FILL_LAST] = { 16, 145, 41 };
static const guint8 yuv_sdtv_colors_U[VIDEO_BOX_FILL_LAST] = { 128, 54, 240 };
static const guint8 yuv_sdtv_colors_V[VIDEO_BOX_FILL_LAST] = { 128, 34, 110 };
static const guint8 yuv_hdtv_colors_Y[VIDEO_BOX_FILL_LAST] = { 16, 173, 32 };
static const guint8 yuv_hdtv_colors_U[VIDEO_BOX_FILL_LAST] = { 128, 42, 240 };
static const guint8 yuv_hdtv_colors_V[VIDEO_BOX_FILL_LAST] = { 128, 26, 118 };
static const guint8 rgb_colors_R[VIDEO_BOX_FILL_LAST] = { 0, 255, 0 };
static const guint8 rgb_colors_G[VIDEO_BOX_FILL_LAST] = { 0, 0, 0 };
static const guint8 rgb_colors_B[VIDEO_BOX_FILL_LAST] = { 0, 255, 255 };
/* Generated by -bad/ext/cog/generate_tables */
static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
298, 0, 459, -63514,
298, -55, -136, 19681,
298, 541, 0, -73988,
};
static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
298, 0, 409, -57068,
298, -100, -208, 34707,
298, 516, 0, -70870,
};
static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
47, 157, 16, 4096,
-26, -87, 112, 32768,
112, -102, -10, 32768,
};
static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
66, 129, 25, 4096,
-38, -74, 112, 32768,
112, -94, -18, 32768,
};
static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
256, -30, -53, 10600,
0, 261, 29, -4367,
0, 19, 262, -3289,
};
static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
256, 25, 49, -9536,
0, 253, -28, 3958,
0, -19, 252, 2918,
};
#define APPLY_MATRIX(m,o,v1,v2,v3) ((m[o*4] * v1 + m[o*4+1] * v2 + m[o*4+2] * v3 + m[o*4+3]) >> 8)
static void
fill_ayuv (GstVideoBoxFill fill_type, guint b_alpha, guint8 * dest,
gboolean sdtv, gint width, gint height, gint x, gint y, gint w, gint h)
{
guint32 empty_pixel;
if (sdtv)
empty_pixel = GUINT32_FROM_BE ((b_alpha << 24) |
(yuv_sdtv_colors_Y[fill_type] << 16) |
(yuv_sdtv_colors_U[fill_type] << 8) | yuv_sdtv_colors_V[fill_type]);
else
empty_pixel = GUINT32_FROM_BE ((b_alpha << 24) |
(yuv_hdtv_colors_Y[fill_type] << 16) |
(yuv_hdtv_colors_U[fill_type] << 8) | yuv_hdtv_colors_V[fill_type]);
if (width == w && height == h && x == 0 && y == 0) {
oil_splat_u32_ns ((guint32 *) dest, &empty_pixel, width * height);
} else {
gint i;
gint stride = 4 * width;
dest = dest + y * width * 4 + x * 4;
for (i = 0; i < h; i++) {
oil_splat_u32_ns ((guint32 *) dest, &empty_pixel, w);
dest += stride;
}
}
}
static void
copy_ayuv_ayuv (guint i_alpha, guint8 * dest, gboolean dest_sdtv,
gint dest_width, gint dest_height, gint dest_x, gint dest_y,
const guint8 * src, gboolean src_sdtv, gint src_width, gint src_height,
gint src_x, gint src_y, gint w, gint h)
{
gint i, j;
gint src_stride = 4 * src_width;
gint dest_stride = 4 * dest_width;
dest = dest + dest_y * dest_width * 4 + dest_x * 4;
src = src + src_y * src_width * 4 + src_x * 4;
w *= 4;
if (dest_sdtv != src_sdtv) {
gint matrix[12];
gint y, u, v;
memcpy (matrix,
dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
for (i = 0; i < h; i++) {
for (j = 0; j < w; j += 4) {
dest[j] = (src[j] * i_alpha) >> 8;
y = src[j + 1];
u = src[j + 2];
v = src[j + 3];
dest[j + 1] = APPLY_MATRIX (matrix, 0, y, u, v);
dest[j + 2] = APPLY_MATRIX (matrix, 1, y, u, v);
dest[j + 3] = APPLY_MATRIX (matrix, 2, y, u, v);
}
dest += dest_stride;
src += src_stride;
}
} else {
for (i = 0; i < h; i++) {
for (j = 0; j < w; j += 4) {
dest[j] = (src[j] * i_alpha) >> 8;
dest[j + 1] = src[j + 1];
dest[j + 2] = src[j + 2];
dest[j + 3] = src[j + 3];
}
dest += dest_stride;
src += src_stride;
}
}
}
static void
copy_ayuv_i420 (guint i_alpha, guint8 * dest, gboolean dest_sdtv,
gint dest_width, gint dest_height, gint dest_x, gint dest_y,
const guint8 * src, gboolean src_sdtv, gint src_width, gint src_height,
gint src_x, gint src_y, gint w, gint h)
{
gint i, j;
guint8 *destY, *destU, *destV;
gint dest_strideY, dest_strideUV;
gint widthY, widthUV;
gint hY, hUV;
dest_strideY =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, dest_width);
dest_strideUV =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, dest_width);
destY =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
dest_width, dest_height);
destU =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
dest_width, dest_height);
destV =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
dest_width, dest_height);
destY = destY + dest_y * dest_strideY + dest_x;
destU = destU + (dest_y / 2) * dest_strideUV + dest_x / 2;
destV = destV + (dest_y / 2) * dest_strideUV + dest_x / 2;
src = src + src_y * src_width * 4 + src_x * 4;
widthY = w;
widthUV = (w + 1) / 2;
hY = h;
hUV = (h + 1) / 2;
if (src_sdtv != dest_sdtv) {
gint matrix[12];
gint y1, y2, y3, y4;
gint u1, u2, u3, u4;
gint v1, v2, v3, v4;
guint8 *destY2 = destY + dest_strideY;
const guint8 *src2 = src + src_width * 4;
dest_strideY *= 2;
memcpy (matrix,
dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
for (i = 0; i < hUV; i++) {
if (i * 2 == hY) {
destY2 = destY;
}
for (j = 0; j < widthUV; j++) {
y1 = src[8 * j + 1];
u1 = src[8 * j + 2];
v1 = src[8 * j + 3];
y2 = src[8 * j + 5];
u2 = src[8 * j + 6];
v2 = src[8 * j + 7];
if (j * 2 < widthY) {
y3 = src2[8 * j + 1];
u3 = src2[8 * j + 2];
v3 = src2[8 * j + 3];
y4 = src2[8 * j + 5];
u4 = src2[8 * j + 6];
v4 = src2[8 * j + 7];
} else {
y3 = y1;
u3 = u1;
v3 = v1;
y4 = y2;
u4 = u2;
v4 = v2;
}
y1 = APPLY_MATRIX (matrix, 0, y1, u1, v1);
u1 = APPLY_MATRIX (matrix, 1, y1, u1, v1);
v1 = APPLY_MATRIX (matrix, 2, y1, u1, v1);
y3 = APPLY_MATRIX (matrix, 0, y3, u3, v3);
u3 = APPLY_MATRIX (matrix, 1, y3, u3, v3);
v3 = APPLY_MATRIX (matrix, 2, y3, u3, v3);
if (j * 2 < widthY) {
y2 = APPLY_MATRIX (matrix, 0, y2, u2, v2);
u2 = APPLY_MATRIX (matrix, 1, y2, u2, v2);
v2 = APPLY_MATRIX (matrix, 2, y2, u2, v2);
y4 = APPLY_MATRIX (matrix, 0, y4, u4, v4);
u4 = APPLY_MATRIX (matrix, 1, y4, u4, v4);
v4 = APPLY_MATRIX (matrix, 2, y4, u4, v4);
} else {
u2 = u1;
v2 = v1;
u4 = u3;
v4 = v3;
}
destY[2 * j] = y1;
destY2[2 * j] = y3;
if (j * 2 < widthY) {
destY[2 * j + 1] = y2;
destY2[2 * j + 1] = y4;
}
destU[j] = (u1 + u2 + u3 + u4) / 4;
destV[j] = (v1 + v2 + v3 + v4) / 4;
}
src += src_width * 8;
destY += dest_strideY;
src2 += src_width * 8;
destY2 += dest_strideY;
destU += dest_strideUV;
destV += dest_strideUV;
}
} else {
gint y1, y2, y3, y4;
gint u1, u2, u3, u4;
gint v1, v2, v3, v4;
guint8 *destY2 = destY + dest_strideY;
const guint8 *src2 = src + src_width * 4;
dest_strideY *= 2;
for (i = 0; i < hUV; i++) {
if (i * 2 == hY) {
destY2 = destY;
}
for (j = 0; j < widthUV; j++) {
y1 = src[8 * j + 1];
u1 = src[8 * j + 2];
v1 = src[8 * j + 3];
y2 = src[8 * j + 5];
u2 = src[8 * j + 6];
v2 = src[8 * j + 7];
if (j * 2 < widthY) {
y3 = src2[8 * j + 1];
u3 = src2[8 * j + 2];
v3 = src2[8 * j + 3];
y4 = src2[8 * j + 5];
u4 = src2[8 * j + 6];
v4 = src2[8 * j + 7];
} else {
y3 = y1;
u3 = u1;
v3 = v1;
y4 = y2;
u4 = u2;
v4 = v2;
}
destY[2 * j] = y1;
destY2[2 * j] = y3;
if (j * 2 < widthY) {
destY[2 * j + 1] = y2;
destY2[2 * j + 1] = y4;
}
destU[j] = (u1 + u2 + u3 + u4) / 4;
destV[j] = (v1 + v2 + v3 + v4) / 4;
}
src += src_width * 8;
destY += dest_strideY;
src2 += src_width * 8;
destY2 += dest_strideY;
destU += dest_strideUV;
destV += dest_strideUV;
}
}
}
static void
fill_i420 (GstVideoBoxFill fill_type, guint b_alpha, guint8 * dest,
gboolean sdtv, gint width, gint height, gint x, gint y, gint w, gint h)
{
guint8 empty_pixel[3];
guint8 *destY, *destU, *destV;
gint strideY, strideUV;
gint heightY, heightUV;
if (sdtv) {
empty_pixel[0] = yuv_sdtv_colors_Y[fill_type];
empty_pixel[1] = yuv_sdtv_colors_U[fill_type];
empty_pixel[2] = yuv_sdtv_colors_V[fill_type];
} else {
empty_pixel[0] = yuv_hdtv_colors_Y[fill_type];
empty_pixel[1] = yuv_hdtv_colors_U[fill_type];
empty_pixel[2] = yuv_hdtv_colors_V[fill_type];
}
strideY = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, width);
strideUV = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, width);
destY =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
width, height);
destU =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
width, height);
destV =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
width, height);
heightY =
gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 0, height);
heightUV =
gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 1, height);
if (width == w && height == h && x == 0 && y == 0) {
oil_splat_u8_ns (destY, &empty_pixel[0], strideY * heightY);
oil_splat_u8_ns (destU, &empty_pixel[1], strideUV * heightUV);
oil_splat_u8_ns (destV, &empty_pixel[2], strideUV * heightUV);
} else {
gint i;
gint widthY, widthUV;
gint hY, hUV;
widthY = w;
widthUV = (w + 1) / 2;
hY = h;
hUV = (h + 1) / 2;
destY = destY + y * strideY + x;
destU = destU + (y / 2) * strideUV + x / 2;
destV = destV + (y / 2) * strideUV + x / 2;
for (i = 0; i < hY; i++) {
oil_splat_u8_ns (destY, &empty_pixel[0], widthY);
destY += strideY;
}
for (i = 0; i < hUV; i++) {
oil_splat_u8_ns (destU, &empty_pixel[1], widthUV);
oil_splat_u8_ns (destV, &empty_pixel[2], widthUV);
destU += strideUV;
destV += strideUV;
}
}
}
static void
copy_i420_i420 (guint i_alpha, guint8 * dest, gboolean dest_sdtv,
gint dest_width, gint dest_height, gint dest_x, gint dest_y,
const guint8 * src, gboolean src_sdtv, gint src_width, gint src_height,
gint src_x, gint src_y, gint w, gint h)
{
gint i;
guint8 *destY, *destU, *destV;
const guint8 *srcY, *srcU, *srcV;
gint dest_strideY, dest_strideUV;
gint src_strideY, src_strideUV;
gint widthY, widthUV;
gint hY, hUV;
dest_strideY =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, dest_width);
dest_strideUV =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, dest_width);
src_strideY =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, src_width);
src_strideUV =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, src_width);
destY =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
dest_width, dest_height);
destU =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
dest_width, dest_height);
destV =
dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
dest_width, dest_height);
srcY =
src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
src_width, src_height);
srcU =
src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
src_width, src_height);
srcV =
src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
src_width, src_height);
destY = destY + dest_y * dest_strideY + dest_x;
destU = destU + (dest_y / 2) * dest_strideUV + dest_x / 2;
destV = destV + (dest_y / 2) * dest_strideUV + dest_x / 2;
srcY = srcY + src_y * src_strideY + src_x;
srcU = srcU + (src_y / 2) * src_strideUV + src_x / 2;
srcV = srcV + (src_y / 2) * src_strideUV + src_x / 2;
widthY = w;
widthUV = (w + 1) / 2;
hY = h;
hUV = (h + 1) / 2;
if (src_sdtv != dest_sdtv) {
gint matrix[12];
gint y1, y2, y3, y4;
gint u1, u2, u3, u4;
gint v1, v2, v3, v4;
gint j;
guint8 *destY2 = destY + dest_strideY;
const guint8 *srcY2 = srcY + src_strideY;
dest_strideY *= 2;
src_strideY *= 2;
memcpy (matrix,
dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
for (i = 0; i < hUV; i++) {
if (i * 2 == hY) {
destY2 = destY;
srcY2 = srcY;
}
for (j = 0; j < widthUV; j++) {
y1 = srcY[2 * j];
y2 = srcY[2 * j + 1];
y3 = srcY2[2 * j];
y4 = srcY2[2 * j + 1];
u1 = u2 = u3 = u4 = srcU[j];
v1 = v2 = v3 = v4 = srcV[j];
y1 = APPLY_MATRIX (matrix, 0, y1, u1, v1);
u1 = APPLY_MATRIX (matrix, 1, y1, u1, v1);
v1 = APPLY_MATRIX (matrix, 2, y1, u1, v1);
y2 = APPLY_MATRIX (matrix, 0, y2, u2, v2);
u2 = APPLY_MATRIX (matrix, 1, y2, u2, v2);
v2 = APPLY_MATRIX (matrix, 2, y2, u2, v2);
y3 = APPLY_MATRIX (matrix, 0, y3, u3, v3);
u3 = APPLY_MATRIX (matrix, 1, y3, u3, v3);
v3 = APPLY_MATRIX (matrix, 2, y3, u3, v3);
y4 = APPLY_MATRIX (matrix, 0, y4, u4, v4);
u4 = APPLY_MATRIX (matrix, 1, y4, u4, v4);
v4 = APPLY_MATRIX (matrix, 2, y4, u4, v4);
destY[2 * j] = y1;
destY[2 * j + 1] = y2;
destY2[2 * j] = y3;
destY2[2 * j + 1] = y4;
destU[j] = (u1 + u2 + u3 + u4) / 4;
destV[j] = (v1 + v2 + v3 + v4) / 4;
}
destY += dest_strideY;
srcY += src_strideY;
destY2 += dest_strideY;
srcY2 += src_strideY;
destU += dest_strideUV;
destV += dest_strideUV;
srcU += src_strideUV;
srcV += src_strideUV;
}
} else {
for (i = 0; i < hY; i++) {
oil_copy_u8 (destY, srcY, widthY);
destY += dest_strideY;
srcY += src_strideY;
}
for (i = 0; i < hUV; i++) {
oil_copy_u8 (destU, srcU, widthUV);
oil_copy_u8 (destV, srcV, widthUV);
destU += dest_strideUV;
destV += dest_strideUV;
srcU += src_strideUV;
srcV += src_strideUV;
}
}
}
static void
copy_i420_ayuv (guint i_alpha, guint8 * dest, gboolean dest_sdtv,
gint dest_width, gint dest_height, gint dest_x, gint dest_y,
const guint8 * src, gboolean src_sdtv, gint src_width, gint src_height,
gint src_x, gint src_y, gint w, gint h)
{
gint i;
const guint8 *srcY, *srcU, *srcV;
gint src_strideY, src_strideUV;
gint widthY, widthUV;
gint hY, hUV;
src_strideY =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, src_width);
src_strideUV =
gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, src_width);
srcY =
src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
src_width, src_height);
srcU =
src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
src_width, src_height);
srcV =
src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
src_width, src_height);
dest = dest + dest_y * dest_width * 4 + dest_x * 4;
srcY = srcY + src_y * src_strideY + src_x;
srcU = srcU + (src_y / 2) * src_strideUV + src_x / 2;
srcV = srcV + (src_y / 2) * src_strideUV + src_x / 2;
widthY = w;
widthUV = (w + 1) / 2;
hY = h;
hUV = (h + 1) / 2;
if (src_sdtv != dest_sdtv) {
gint matrix[12];
gint y1, y2, y3, y4;
gint u1, u2, u3, u4;
gint v1, v2, v3, v4;
gint j;
guint8 *dest2;
const guint8 *srcY2 = srcY + src_strideY;
dest2 = dest + dest_width * 4;
src_strideY *= 2;
memcpy (matrix,
dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
for (i = 0; i < hUV; i++) {
if (i * 2 == hY) {
srcY2 = srcY;
}
for (j = 0; j < widthUV; j++) {
y1 = srcY[2 * j];
y3 = srcY2[2 * j];
y2 = (j * 2 < widthY) ? srcY[2 * j + 1] : y1;
y4 = (j * 2 < widthY) ? srcY2[2 * j + 1] : y3;
u1 = u2 = u3 = u4 = srcU[j];
v1 = v2 = v3 = v4 = srcV[j];
y1 = APPLY_MATRIX (matrix, 0, y1, u1, v1);
u1 = APPLY_MATRIX (matrix, 1, y1, u1, v1);
v1 = APPLY_MATRIX (matrix, 2, y1, u1, v1);
y3 = APPLY_MATRIX (matrix, 0, y3, u3, v3);
u3 = APPLY_MATRIX (matrix, 1, y3, u3, v3);
v3 = APPLY_MATRIX (matrix, 2, y3, u3, v3);
if (j * 2 < widthY) {
y2 = APPLY_MATRIX (matrix, 0, y2, u2, v2);
u2 = APPLY_MATRIX (matrix, 1, y2, u2, v2);
v2 = APPLY_MATRIX (matrix, 2, y2, u2, v2);
y4 = APPLY_MATRIX (matrix, 0, y4, u4, v4);
u4 = APPLY_MATRIX (matrix, 1, y4, u4, v4);
v4 = APPLY_MATRIX (matrix, 2, y4, u4, v4);
}
dest[8 * j] = i_alpha;
dest[8 * j + 1] = y1;
dest[8 * j + 2] = u1;
dest[8 * j + 3] = v1;
dest2[8 * j] = i_alpha;
dest2[8 * j + 1] = y3;
dest2[8 * j + 2] = u3;