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;
+ dest2[8 * j + 3] = v3;
+ if (j * 2 < widthY) {
+ dest[8 * j + 4] = i_alpha;
+ dest[8 * j + 5] = y2;
+ dest[8 * j + 6] = u2;
+ dest[8 * j + 7] = v2;
+ dest2[8 * j + 4] = i_alpha;
+ dest2[8 * j + 5] = y4;
+ dest2[8 * j + 6] = u4;
+ dest2[8 * j + 7] = v4;
+ }
+ }
+ dest += dest_width * 8;
+ srcY += src_strideY;
+ dest2 += dest_width * 8;
+ srcY2 += src_strideY;
+
+ srcU += src_strideUV;
+ srcV += src_strideUV;
+ }
+ } else {
+ 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;
+
+ 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];
+
+ 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;
+ dest2[8 * j + 3] = v3;
+ if (j * 2 < widthY) {
+ dest[8 * j + 4] = i_alpha;
+ dest[8 * j + 5] = y2;
+ dest[8 * j + 6] = u2;
+ dest[8 * j + 7] = v2;
+ dest2[8 * j + 4] = i_alpha;
+ dest2[8 * j + 5] = y4;
+ dest2[8 * j + 6] = u4;
+ dest2[8 * j + 7] = v4;
+ }
+ }
+ dest += dest_width * 8;
+ srcY += src_strideY;
+ dest2 += dest_width * 8;
+ srcY2 += src_strideY;
+
+ srcU += src_strideUV;
+ srcV += src_strideUV;
+ }
+ }
+}
+
#define DEFAULT_LEFT 0
#define DEFAULT_RIGHT 0
#define DEFAULT_TOP 0
static void gst_video_box_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static gboolean video_box_recalc_transform (GstVideoBox * video_box);
+static gboolean gst_video_box_recalc_transform (GstVideoBox * video_box);
static GstCaps *gst_video_box_transform_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * from);
static gboolean gst_video_box_set_caps (GstBaseTransform * trans,
GstCaps * caps, guint * size);
static GstFlowReturn gst_video_box_transform (GstBaseTransform * trans,
GstBuffer * in, GstBuffer * out);
+static void gst_video_box_fixate_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
#define GST_TYPE_VIDEO_BOX_FILL (gst_video_box_fill_get_type())
static GType
GST_DEBUG_FUNCPTR (gst_video_box_transform_caps);
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_box_set_caps);
trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_video_box_get_unit_size);
+ trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_video_box_fixate_caps);
}
static void
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
- video_box_recalc_transform (video_box);
+ gst_video_box_recalc_transform (video_box);
GST_DEBUG_OBJECT (video_box, "Calling reconfigure");
gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (video_box));
/* get rid of format */
gst_structure_remove_field (structure, "format");
+ gst_structure_remove_field (structure, "color-matrix");
+ gst_structure_remove_field (structure, "chroma-site");
/* otherwise caps nego will fail: */
if (video_box->autocrop) {
}
static gboolean
-video_box_recalc_transform (GstVideoBox * video_box)
+gst_video_box_recalc_transform (GstVideoBox * video_box)
{
gboolean res = TRUE;
* cropping at all, we can just operate in passthrough mode */
if (video_box->in_format == video_box->out_format &&
video_box->box_left == 0 && video_box->box_right == 0 &&
- video_box->box_top == 0 && video_box->box_bottom == 0) {
+ video_box->box_top == 0 && video_box->box_bottom == 0 &&
+ video_box->in_sdtv == video_box->out_sdtv) {
GST_LOG_OBJECT (video_box, "we are using passthrough");
gst_base_transform_set_passthrough (GST_BASE_TRANSFORM_CAST (video_box),
}
static gboolean
+gst_video_box_select_processing_functions (GstVideoBox * video_box)
+{
+ switch (video_box->out_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ video_box->fill = fill_ayuv;
+ switch (video_box->in_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ video_box->copy = copy_ayuv_ayuv;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ video_box->copy = copy_i420_ayuv;
+ break;
+ default:
+ break;
+ }
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ video_box->fill = fill_i420;
+ switch (video_box->in_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ video_box->copy = copy_ayuv_i420;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ video_box->copy = copy_i420_i420;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return video_box->fill != NULL && video_box->copy != NULL;
+}
+
+static gboolean
gst_video_box_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
{
GstVideoBox *video_box = GST_VIDEO_BOX (trans);
gboolean ret;
+ const gchar *matrix;
g_mutex_lock (video_box->mutex);
gst_video_format_parse_caps (out, &video_box->out_format,
&video_box->out_width, &video_box->out_height);
+ matrix = gst_video_parse_caps_color_matrix (in);
+ video_box->in_sdtv = matrix ? g_str_equal (matrix, "sdtv") : TRUE;
+ matrix = gst_video_parse_caps_color_matrix (out);
+ video_box->out_sdtv = matrix ? g_str_equal (matrix, "sdtv") : TRUE;
+
/* something wrong getting the caps */
if (!ret)
goto no_caps;
gst_video_box_autocrop (video_box);
/* recalc the transformation strategy */
- ret = video_box_recalc_transform (video_box);
+ ret = gst_video_box_recalc_transform (video_box);
+ if (ret)
+ ret = gst_video_box_select_processing_functions (video_box);
g_mutex_unlock (video_box->mutex);
return ret;
return TRUE;
}
-static const guint8 yuv_colors_Y[VIDEO_BOX_FILL_LAST] = { 16, 150, 29 };
-static const guint8 yuv_colors_U[VIDEO_BOX_FILL_LAST] = { 128, 46, 255 };
-static const guint8 yuv_colors_V[VIDEO_BOX_FILL_LAST] = { 128, 21, 107 };
-
static void
-gst_video_box_copy_plane_i420 (GstVideoBox * video_box, const guint8 * src,
- guint8 * dest, gint br, gint bl, gint bt, gint bb, gint src_crop_width,
- gint src_crop_height, gint src_stride, gint dest_width, gint dest_stride,
- guint8 fill_color)
+gst_video_box_fixate_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
{
- gint j;
-
- /* top border */
- for (j = 0; j < bt; j++) {
- oil_splat_u8_ns (dest, &fill_color, dest_width);
- dest += dest_stride;
- }
-
- /* copy and add left and right border */
- for (j = 0; j < src_crop_height; j++) {
- oil_splat_u8_ns (dest, &fill_color, bl);
- oil_memcpy (dest + bl, src, src_crop_width);
- oil_splat_u8_ns (dest + bl + src_crop_width, &fill_color, br);
- dest += dest_stride;
- src += src_stride;
- }
+ gint width, height;
+ GstStructure *s;
+ gboolean ret;
- /* bottom border */
- for (j = 0; j < bb; j++) {
- oil_splat_u8_ns (dest, &fill_color, dest_width);
- dest += dest_stride;
- }
-}
+ ret = gst_video_format_parse_caps (caps, NULL, &width, &height);
+ if (!ret)
+ return;
-static void
-gst_video_box_apply_alpha (guint8 * dest, guint8 alpha)
-{
- if (dest[0] != 0)
- dest[0] = alpha;
+ s = gst_caps_get_structure (othercaps, 0);
+ gst_structure_fixate_field_nearest_int (s, "width", width);
+ gst_structure_fixate_field_nearest_int (s, "height", height);
}
static void
-gst_video_box_ayuv_ayuv (GstVideoBox * video_box, const guint8 * src,
+gst_video_box_process (GstVideoBox * video_box, const guint8 * src,
guint8 * dest)
{
- gint dblen = video_box->out_height * video_box->out_width;
- guint32 *destb = (guint32 *) dest;
- const guint32 *srcb = (const guint32 *) src;
- guint8 b_alpha = (guint8) (video_box->border_alpha * 255);
- guint8 i_alpha = (guint8) (video_box->alpha * 255);
+ guint b_alpha = CLAMP ((guint) video_box->border_alpha * 256, 0, 256);
+ guint i_alpha = CLAMP ((guint) video_box->alpha * 256, 0, 256);
+ GstVideoBoxFill fill_type = video_box->fill_type;
gint br, bl, bt, bb, crop_w, crop_h;
- gint i;
- guint32 *loc = destb;
- guint32 empty_pixel;
-
- GST_LOG_OBJECT (video_box, "Processing AYUV -> AYUV data");
crop_h = 0;
crop_w = 0;
- empty_pixel = GUINT32_FROM_BE ((b_alpha << 24) |
- (yuv_colors_Y[video_box->fill_type] << 16) |
- (yuv_colors_U[video_box->fill_type] << 8) |
- yuv_colors_V[video_box->fill_type]);
br = video_box->box_right;
bl = video_box->box_left;
GST_DEBUG_OBJECT (video_box, "Borders are: L:%d, R:%d, T:%d, B:%d", bl, br,
bt, bb);
- GST_DEBUG_OBJECT (video_box, "Alpha value is: %d", i_alpha);
-
- if (crop_h <= 0 || crop_w <= 0) {
- oil_splat_u32_ns (destb, &empty_pixel, dblen);
+ GST_DEBUG_OBJECT (video_box, "Alpha value is: %u (frame) %u (border)",
+ i_alpha, b_alpha);
+
+ if (crop_h < 0 || crop_w < 0) {
+ video_box->fill (fill_type, b_alpha, dest, video_box->out_sdtv,
+ video_box->out_width, video_box->out_height, 0, 0, video_box->out_width,
+ video_box->out_height);
+ } else if (bb == 0 && bt == 0 && br == 0 && bl == 0) {
+ video_box->copy (i_alpha, dest, video_box->out_sdtv, video_box->out_width,
+ video_box->out_height, 0, 0, src, video_box->in_sdtv,
+ video_box->in_width, video_box->in_height, 0, 0, crop_w, crop_h);
} else {
- const guint32 *src_loc = srcb;
+ gint src_x = 0, src_y = 0;
+ gint dest_x = 0, dest_y = 0;
/* Top border */
if (bt < 0) {
- oil_splat_u32_ns (loc, &empty_pixel, (-bt) * video_box->out_width);
- loc = loc + ((-bt) * video_box->out_width);
+ video_box->fill (fill_type, b_alpha, dest, video_box->out_sdtv,
+ video_box->out_width, video_box->out_height, 0, 0,
+ video_box->out_width, -bt);
+ dest_y += -bt;
} else {
- src_loc = src_loc + (bt * video_box->in_width);
- }
-
- if (bl >= 0)
- src_loc += bl;
-
- for (i = 0; i < crop_h; i++) {
- gint j;
-
- /* Left border */
- if (bl < 0) {
- oil_splat_u32_ns (loc, &empty_pixel, -bl);
- loc += (-bl);
- }
-
- /* Cropped area */
- oil_copy_u8 ((guint8 *) loc, (guint8 *) src_loc, crop_w * 4);
-
- for (j = 0; j < crop_w; j++)
- gst_video_box_apply_alpha ((guint8 *) & loc[j], i_alpha);
-
- src_loc += video_box->in_width;
- loc += crop_w;
-
- /* Right border */
- if (br < 0) {
- oil_splat_u32_ns (loc, &empty_pixel, -br);
- loc += (-br);
- }
+ src_y += bt;
}
- /* Bottom border */
- if (bb < 0) {
- oil_splat_u32_ns (loc, &empty_pixel, (-bb) * video_box->out_width);
- }
- }
-
- GST_LOG_OBJECT (video_box, "image created");
-}
-
-static gpointer
-gst_video_box_clear (gpointer dest, gint size)
-{
- guint8 nil = 255;
-
- oil_splat_u8_ns (dest, &nil, size);
-
- return dest;
-}
-
-static gint
-UVfloor (gint j)
-{
- return floor (((float) j) / 2);
-}
-
-static gint
-UVceil (gint j)
-{
- return ceil (((float) j) / 2);
-}
-
-static void
-gst_video_box_ayuv_i420 (GstVideoBox * video_box, const guint8 * src,
- guint8 * dest)
-{
- gint br, bl, bt, bb, crop_w, crop_h, rest;
- gint Ysize, Usize, Vsize;
- guint8 *Ydest, *Udest, *Vdest;
- guint8 *Utemp, *Vtemp;
- guint32 empty_px_values[3];
- gint i, j;
- guint Ywidth, Uwidth, Vwidth;
-
- GST_LOG_OBJECT (video_box, "AYUV to I420 conversion");
-
- crop_h = 0;
- crop_w = 0;
- rest = 0;
-
- empty_px_values[0] = yuv_colors_Y[video_box->fill_type];
- empty_px_values[1] = yuv_colors_U[video_box->fill_type];
- empty_px_values[2] = yuv_colors_V[video_box->fill_type];
-
- Ywidth =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0,
- video_box->out_width);
- Uwidth =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1,
- video_box->out_width);
- Vwidth =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2,
- video_box->out_width);
-
- Ydest =
- dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
- video_box->out_width, video_box->out_height);
- Udest =
- dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
- video_box->out_width, video_box->out_height);
- Vdest =
- dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
- video_box->out_width, video_box->out_height);
-
- Ysize =
- Ywidth * gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 0,
- video_box->out_height);
- Usize =
- Ywidth * gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 1,
- video_box->out_height);
- Vsize =
- Ywidth * gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 2,
- video_box->out_height);
-
- br = video_box->box_right;
- bl = video_box->box_left;
- bt = video_box->box_top;
- bb = video_box->box_bottom;
-
- if (br >= 0 && bl >= 0) {
- rest = Ywidth - video_box->out_width;
- crop_w = video_box->in_width - (bl + br);
- } else if (br >= 0 && bl < 0) {
- rest = Ywidth - video_box->out_width;
- crop_w = video_box->in_width - (br);
- } else if (br < 0 && bl >= 0) {
- rest = Ywidth - video_box->out_width;
- crop_w = video_box->in_width - (bl);
- } else if (br < 0 && bl < 0) {
- rest = Ywidth - video_box->out_width;
- crop_w = video_box->in_width;
- }
-
- if (bb >= 0 && bt >= 0) {
- crop_h = video_box->in_height - (bb + bt);
- } else if (bb >= 0 && bt < 0) {
- crop_h = video_box->in_height - (bb);
- } else if (bb < 0 && bt >= 0) {
- crop_h = video_box->in_height - (bt);
- } else if (bb < 0 && bt < 0) {
- crop_h = video_box->in_height;
- }
-
- Utemp = g_malloc0 (Uwidth);
- Vtemp = g_malloc0 (Vwidth);
-
- GST_LOG_OBJECT (video_box, "Borders are: L:%d, R:%d, T:%d, B:%d", bl, br, bt,
- bb);
-
- GST_LOG_OBJECT (video_box, "Starting conversion");
-
- if (crop_h <= 0 || crop_w <= 0) {
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], Ysize);
- oil_splat_u8_ns (Udest, (guint8 *) & empty_px_values[1], Usize);
- oil_splat_u8_ns (Vdest, (guint8 *) & empty_px_values[2], Vsize);
- } else {
- gboolean sumbuff = FALSE;
- const guint32 *src_loc1;
- gint a = 0;
-
- src_loc1 = (const guint32 *) src;
-
- if (bt < 0) {
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], (-bt) * Ywidth);
-
- oil_splat_u8_ns (Udest, (guint8 *) & empty_px_values[1],
- (UVfloor (-bt) * Uwidth) + 7);
- oil_splat_u8_ns (Vdest, (guint8 *) & empty_px_values[2],
- UVfloor (-bt) * Vwidth);
-
- if ((-bt) % 2 > 0) {
- oil_splat_u8_ns (Utemp, (guint8 *) & empty_px_values[1], Uwidth);
- oil_splat_u8_ns (Vtemp, (guint8 *) & empty_px_values[2], Vwidth);
- sumbuff = TRUE;
- }
-
- Ydest += ((-bt) * Ywidth);
- Udest += (UVfloor (-bt) * Uwidth);
- Vdest += (UVfloor (-bt) * Vwidth);
+ /* Left border */
+ if (bl < 0) {
+ video_box->fill (fill_type, b_alpha, dest, video_box->out_sdtv,
+ video_box->out_width, video_box->out_height, 0, dest_y, -bl, crop_h);
+ dest_x += -bl;
} else {
- src_loc1 = src_loc1 + (bt * video_box->in_width);
+ src_x += bl;
}
- if (bl >= 0)
- src_loc1 += bl;
-
- GST_LOG_OBJECT (video_box, "Cropped area");
- GST_LOG_OBJECT (video_box, "Ydest value: %p Ywidth: %u", Ydest, Ywidth);
- GST_LOG_OBJECT (video_box, "Udest value: %p Uwidth: %u", Udest, Uwidth);
- GST_LOG_OBJECT (video_box, "Vdest value: %p Vwidth: %u", Vdest, Vwidth);
- GST_LOG_OBJECT (video_box, "Rest: %d", rest);
- for (i = 0; i < crop_h; i++) {
- a = 0;
- if (sumbuff) {
- /* left border */
- if (bl < 0) {
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -bl);
-
- for (j = 0; j < -bl; j++) {
- Utemp[UVfloor (j)] = (Utemp[UVfloor (j)] + empty_px_values[1]) / 2;
- Vtemp[UVfloor (j)] = (Vtemp[UVfloor (j)] + empty_px_values[2]) / 2;
- }
- Ydest += -bl;
- a = -bl;
- }
-
- for (j = 0; j < crop_w; j++) {
- /* check ARCH */
- Ydest[j] = ((guint8 *) & src_loc1[j])[1];
- Utemp[UVfloor (a + j)] =
- (Utemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[2]) / 2;
- Vtemp[UVfloor (a + j)] =
- (Vtemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[3]) / 2;
- }
- Ydest += crop_w;
-
- /* right border */
- if (br < 0) {
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -br);
- for (j = 0; j < -br; j++) {
- Utemp[UVfloor (a + crop_w + j)] =
- (Utemp[UVfloor (a + crop_w + j)] + empty_px_values[1]) / 2;
- Vtemp[UVfloor (a + crop_w + j)] =
- (Vtemp[UVfloor (a + crop_w + j)] + empty_px_values[2]) / 2;
- }
- Ydest += -br;
- }
- oil_copy_u8 (Udest, Utemp, Uwidth);
- oil_copy_u8 (Vdest, Vtemp, Vwidth);
- Udest += Uwidth;
- Vdest += Vwidth;
- Ydest += rest;
- gst_video_box_clear (Utemp, Uwidth);
- gst_video_box_clear (Vtemp, Vwidth);
- src_loc1 += video_box->in_width;
- sumbuff = FALSE;
- } else {
- /* left border */
- a = 0;
- if (bl < 0) {
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -bl);
- oil_splat_u8_ns (Vtemp, (guint8 *) & empty_px_values[1],
- UVceil (-bl));
- oil_splat_u8_ns (Utemp, (guint8 *) & empty_px_values[2],
- UVceil (-bl));
- Ydest += -bl;
- a = -bl;
- }
-
- for (j = 0; j < crop_w; j++) {
- /* check ARCH */
- Ydest[j] = ((guint8 *) & src_loc1[j])[1];
-
- if ((a + j) % 2 > 0) {
- Utemp[UVfloor (a + j)] =
- (Utemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[2]) / 2;
- Vtemp[UVfloor (a + j)] =
- (Vtemp[UVfloor (a + j)] + ((guint8 *) & src_loc1[j])[3]) / 2;
- } else {
- Utemp[UVfloor (a + j)] = ((guint8 *) & src_loc1[j])[2];
- Vtemp[UVfloor (a + j)] = ((guint8 *) & src_loc1[j])[3];
- }
- }
- Ydest += crop_w;
-
- /* right border */
- if (br < 0) {
- j = 0;
- if ((a + crop_w) % 2 > 0) {
- Utemp[UVfloor (a + crop_w)] =
- (Utemp[UVfloor (a + crop_w)] + empty_px_values[1]) / 2;
- Vtemp[UVfloor (a + crop_w)] =
- (Vtemp[UVfloor (a + crop_w)] + empty_px_values[2]) / 2;
- a++;
- j = -1;
- }
-
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], -br);
- oil_splat_u8_ns (&Utemp[UVfloor (a + crop_w)],
- (guint8 *) & empty_px_values[1], UVceil ((-br) + j));
- oil_splat_u8_ns (&Vtemp[UVfloor (a + crop_w)],
- (guint8 *) & empty_px_values[2], UVceil ((-br) + j));
- Ydest += -br;
- }
- Ydest += rest;
- src_loc1 += video_box->in_width;
- sumbuff = TRUE;
- }
+ /* Right border */
+ if (br < 0) {
+ video_box->fill (fill_type, b_alpha, dest, video_box->out_sdtv,
+ video_box->out_width, video_box->out_height,
+ video_box->out_width + br, dest_y, -br, crop_h);
}
- /* bottom border */
+ /* Bottom border */
if (bb < 0) {
- oil_splat_u8_ns (Ydest, (guint8 *) & empty_px_values[0], (-bb) * Ywidth);
- if (sumbuff) {
- for (i = 0; i < Uwidth; i++) {
- Utemp[i] = (Utemp[i] + empty_px_values[1]) / 2;
- }
- for (i = 0; i < Vwidth; i++) {
- Vtemp[i] = (Vtemp[i] + empty_px_values[2]) / 2;
- }
-
- oil_copy_u8 (Udest, Utemp, Uwidth);
- oil_copy_u8 (Vdest, Vtemp, Vwidth);
- Udest += Uwidth;
- Vdest += Vwidth;
- sumbuff = FALSE;
- }
- oil_splat_u8_ns (Udest, (guint8 *) & empty_px_values[1],
- (UVfloor ((-bb))) * Uwidth);
- oil_splat_u8_ns (Vdest, (guint8 *) & empty_px_values[2],
- (UVfloor ((-bb))) * Vwidth);
- }
- if (sumbuff) {
- oil_copy_u8 (Udest, Utemp, Uwidth);
- oil_copy_u8 (Vdest, Vtemp, Vwidth);
- }
- }
-
- GST_LOG_OBJECT (video_box, "image created");
- g_free (Utemp);
- g_free (Vtemp);
-}
-
-static void
-gst_video_box_i420_ayuv (GstVideoBox * video_box, const guint8 * src,
- guint8 * dest)
-{
- const guint8 *srcY, *srcU, *srcV;
- gint crop_width, crop_width2, crop_height;
- gint out_width, out_height;
- gint src_stridey, src_strideu, src_stridev;
- gint br, bl, bt, bb;
- gint colorY, colorU, colorV;
- gint i, j;
- guint8 b_alpha = (guint8) (video_box->border_alpha * 255);
- guint8 i_alpha = (guint8) (video_box->alpha * 255);
- guint32 *destp;
- guint32 *destb = (guint32 *) dest;
- guint32 ayuv;
-
- br = video_box->border_right;
- bl = video_box->border_left;
- bt = video_box->border_top;
- bb = video_box->border_bottom;
-
- out_width = video_box->out_width;
- out_height = video_box->out_height;
-
- src_stridey =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0,
- video_box->in_width);
- src_strideu =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1,
- video_box->in_width);
- src_stridev =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2,
- video_box->in_width);
-
- crop_width = video_box->in_width;
- crop_width -= (video_box->crop_left + video_box->crop_right);
- crop_width2 = crop_width / 2;
- crop_height = video_box->in_height;
- crop_height -= (video_box->crop_top + video_box->crop_bottom);
-
- srcY =
- src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
- video_box->in_width, video_box->in_height);
- srcY += src_stridey * video_box->crop_top + video_box->crop_left;
- srcU =
- src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
- video_box->in_width, video_box->in_height);
- srcU += src_strideu * (video_box->crop_top / 2) + (video_box->crop_left / 2);
- srcV =
- src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
- video_box->in_width, video_box->in_height);
- srcV += src_stridev * (video_box->crop_top / 2) + (video_box->crop_left / 2);
-
- colorY = yuv_colors_Y[video_box->fill_type];
- colorU = yuv_colors_U[video_box->fill_type];
- colorV = yuv_colors_V[video_box->fill_type];
-
- ayuv =
- GUINT32_FROM_BE ((b_alpha << 24) | (colorY << 16) | (colorU << 8) |
- colorV);
-
- /* top border */
- if (bt) {
- size_t nb_pixels = bt * out_width;
-
- oil_splat_u32_ns (destb, &ayuv, nb_pixels);
- destb += nb_pixels;
- }
- for (i = 0; i < crop_height; i++) {
- destp = destb;
- /* left border */
- if (bl) {
- oil_splat_u32_ns (destp, &ayuv, bl);
- destp += bl;
- }
- dest = (guint8 *) destp;
- /* center */
- /* We can splat the alpha channel for the whole line */
- oil_splat_u8 (dest, 4, &i_alpha, crop_width);
- for (j = 0; j < crop_width2; j++) {
- dest++;
- *dest++ = *srcY++;
- *dest++ = *srcU;
- *dest++ = *srcV;
- dest++;
- *dest++ = *srcY++;
- *dest++ = *srcU++;
- *dest++ = *srcV++;
- }
- if (i % 2 == 0) {
- srcU -= crop_width2;
- srcV -= crop_width2;
- } else {
- srcU += src_strideu - crop_width2;
- srcV += src_stridev - crop_width2;
+ video_box->fill (fill_type, b_alpha, dest, video_box->out_sdtv,
+ video_box->out_width, video_box->out_height, 0, dest_y + crop_h,
+ video_box->out_width, -bb);
}
- srcY += src_stridey - (crop_width2 * 2);
- destp = (guint32 *) dest;
- /* right border */
- if (br) {
- oil_splat_u32_ns (destp, &ayuv, br);
- }
- destb += out_width;
- }
- /* bottom border */
- if (bb) {
- size_t nb_pixels = bb * out_width;
-
- oil_splat_u32_ns (destb, &ayuv, nb_pixels);
+ /* Frame */
+ video_box->copy (i_alpha, dest, video_box->out_sdtv, video_box->out_width,
+ video_box->out_height, dest_x, dest_y, src, video_box->in_sdtv,
+ video_box->in_width, video_box->in_height, src_x, src_y, crop_w,
+ crop_h);
}
-}
-
-
-static void
-gst_video_box_i420_i420 (GstVideoBox * video_box, const guint8 * src,
- guint8 * dest)
-{
- const guint8 *srcY, *srcU, *srcV;
- guint8 *destY, *destU, *destV;
- gint crop_width, crop_height;
- gint out_width, out_height;
- gint src_width, src_height;
- gint src_stride, dest_stride;
- gint br, bl, bt, bb;
-
- br = video_box->border_right;
- bl = video_box->border_left;
- bt = video_box->border_top;
- bb = video_box->border_bottom;
-
- out_width = video_box->out_width;
- out_height = video_box->out_height;
-
- src_width = video_box->in_width;
- src_height = video_box->in_height;
- crop_width = src_width - (video_box->crop_left + video_box->crop_right);
- crop_height = src_height - (video_box->crop_top + video_box->crop_bottom);
-
- /* Y plane */
- src_stride =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, src_width);
- dest_stride =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, out_width);
-
- destY =
- dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
- out_width, out_height);
-
- srcY =
- src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0,
- src_width, src_height);
- srcY += src_stride * video_box->crop_top + video_box->crop_left;
-
- gst_video_box_copy_plane_i420 (video_box, srcY, destY, br, bl, bt, bb,
- crop_width, crop_height, src_stride, out_width, dest_stride,
- yuv_colors_Y[video_box->fill_type]);
-
- br /= 2;
- bb /= 2;
- bl /= 2;
- bt /= 2;
-
- /* we need to round up to make sure we draw all the U and V lines */
- crop_width = (crop_width + 1) / 2;
- crop_height = (crop_height + 1) / 2;
-
- /* U plane */
- src_stride =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, src_width);
- dest_stride =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, out_width);
-
- destU =
- dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
- out_width, out_height);
-
- srcU =
- src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1,
- src_width, src_height);
- srcU += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
-
- gst_video_box_copy_plane_i420 (video_box, srcU, destU, br, bl, bt, bb,
- crop_width, crop_height, src_stride, out_width / 2, dest_stride,
- yuv_colors_U[video_box->fill_type]);
-
- /* V plane */
- src_stride =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, src_width);
- dest_stride =
- gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, out_width);
-
- destV =
- dest + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
- out_width, out_height);
-
- srcV =
- src + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2,
- src_width, src_height);
- srcV += src_stride * (video_box->crop_top / 2) + (video_box->crop_left / 2);
-
- gst_video_box_copy_plane_i420 (video_box, srcV, destV, br, bl, bt, bb,
- crop_width, crop_height, src_stride, out_width / 2, dest_stride,
- yuv_colors_V[video_box->fill_type]);
+ GST_LOG_OBJECT (video_box, "image created");
}
static GstFlowReturn
outdata = GST_BUFFER_DATA (out);
g_mutex_lock (video_box->mutex);
- switch (video_box->in_format) {
- case GST_VIDEO_FORMAT_AYUV:
- switch (video_box->out_format) {
- case GST_VIDEO_FORMAT_AYUV:
- gst_video_box_ayuv_ayuv (video_box, indata, outdata);
- break;
- case GST_VIDEO_FORMAT_I420:
- gst_video_box_ayuv_i420 (video_box, indata, outdata);
- break;
- default:
- goto invalid_format;
- }
- break;
- case GST_VIDEO_FORMAT_I420:
- switch (video_box->out_format) {
- case GST_VIDEO_FORMAT_AYUV:
- gst_video_box_i420_ayuv (video_box, indata, outdata);
- break;
- case GST_VIDEO_FORMAT_I420:
- gst_video_box_i420_i420 (video_box, indata, outdata);
- break;
- default:
- goto invalid_format;
- }
- break;
- default:
- goto invalid_format;
- }
+ gst_video_box_process (video_box, indata, outdata);
g_mutex_unlock (video_box->mutex);
return GST_FLOW_OK;
-
- /* ERRORS */
-invalid_format:
- {
- g_mutex_unlock (video_box->mutex);
- return GST_FLOW_ERROR;
- }
}
/* FIXME: 0.11 merge with videocrop plugin */