/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2010> Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
+ * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
*
* Sample pipeline:
* |[
- * gst-launch videotestsrc ! videobox autocrop=true ! \
- * "video/x-raw-yuv, width=600, height=400" ! ffmpegcolorspace ! ximagesink
+ * gst-launch-1.0 videotestsrc ! videobox autocrop=true ! \
+ * "video/x-raw, width=600, height=400" ! videoconvert ! ximagesink
* ]|
*/
#endif
#include "gstvideobox.h"
+#include "gstvideoboxorc.h"
#include <math.h>
-#include <liboil/liboil.h>
#include <string.h>
-#include <gst/controller/gstcontroller.h>
-
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 };
+static const guint8 yuv_sdtv_colors_Y[VIDEO_BOX_FILL_LAST] =
+ { 16, 145, 41, 81, 210, 235 };
+static const guint8 yuv_sdtv_colors_U[VIDEO_BOX_FILL_LAST] =
+ { 128, 54, 240, 90, 16, 128 };
+static const guint8 yuv_sdtv_colors_V[VIDEO_BOX_FILL_LAST] =
+ { 128, 34, 110, 240, 146, 128 };
+
+static const guint8 yuv_hdtv_colors_Y[VIDEO_BOX_FILL_LAST] =
+ { 16, 173, 32, 63, 219, 235 };
+static const guint8 yuv_hdtv_colors_U[VIDEO_BOX_FILL_LAST] =
+ { 128, 42, 240, 102, 16, 128 };
+static const guint8 yuv_hdtv_colors_V[VIDEO_BOX_FILL_LAST] =
+ { 128, 26, 118, 240, 138, 128 };
+
+static const guint8 rgb_colors_R[VIDEO_BOX_FILL_LAST] =
+ { 0, 0, 0, 255, 255, 255 };
+static const guint8 rgb_colors_G[VIDEO_BOX_FILL_LAST] =
+ { 0, 255, 0, 0, 255, 255 };
+static const guint8 rgb_colors_B[VIDEO_BOX_FILL_LAST] =
+ { 0, 0, 255, 0, 0, 255 };
/* Generated by -bad/ext/cog/generate_tables */
static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
0, -19, 252, 2918,
};
+static const gint cog_identity_matrix_8bit[] = {
+ 256, 0, 0, 0,
+ 0, 256, 0, 0,
+ 0, 0, 256, 0,
+};
+
#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, GstVideoFormat format,
- guint8 * dest, gboolean sdtv, gint width, gint height)
+fill_ayuv (GstVideoBoxFill fill_type, guint b_alpha,
+ GstVideoFrame * frame, gboolean sdtv)
{
guint32 empty_pixel;
+ guint8 *dest;
+ gint width, height;
+ gint stride;
+
+ width = GST_VIDEO_FRAME_WIDTH (frame);
+ height = GST_VIDEO_FRAME_HEIGHT (frame);
+
+ b_alpha = CLAMP (b_alpha, 0, 255);
if (sdtv)
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]);
- oil_splat_u32_ns ((guint32 *) dest, &empty_pixel, width * height);
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
+
+ if (G_LIKELY (stride == 4 * width))
+ video_box_orc_splat_u32 ((guint32 *) dest, empty_pixel, width * height);
+ else if (height) {
+ for (; height; --height) {
+ video_box_orc_splat_u32 ((guint32 *) dest, empty_pixel, width);
+ dest += stride;
+ }
+ }
}
static void
-copy_ayuv_ayuv (guint i_alpha, GstVideoFormat dest_format, guint8 * dest,
- gboolean dest_sdtv, gint dest_width, gint dest_height, gint dest_x,
- gint dest_y, GstVideoFormat src_format, const guint8 * src,
- gboolean src_sdtv, gint src_width, gint src_height, gint src_x, gint src_y,
- gint w, gint h)
+copy_ayuv_ayuv (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, 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;
+ gint src_stride;
+ gint dest_stride;
+ guint8 *dest, *src;
+
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
- dest = dest + dest_y * dest_width * 4 + dest_x * 4;
- src = src + src_y * src_width * 4 + src_x * 4;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+
+ dest = dest + dest_y * dest_stride + dest_x * 4;
+ src = src + src_y * src_stride + src_x * 4;
w *= 4;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j += 4) {
+ /* ORC FIXME */
dest[j] = (src[j] * i_alpha) >> 8;
y = src[j + 1];
u = src[j + 2];
} else {
for (i = 0; i < h; i++) {
for (j = 0; j < w; j += 4) {
+ /* ORC FIXME */
dest[j] = (src[j] * i_alpha) >> 8;
dest[j + 1] = src[j + 1];
dest[j + 2] = src[j + 2];
}
static void
-copy_ayuv_i420 (guint i_alpha, GstVideoFormat dest_format, guint8 * dest,
- gboolean dest_sdtv, gint dest_width, gint dest_height, gint dest_x,
- gint dest_y, GstVideoFormat src_format, const guint8 * src,
- gboolean src_sdtv, gint src_width, gint src_height, gint src_x, gint src_y,
- gint w, gint h)
+copy_ayuv_i420 (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, 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);
+ guint8 *destY, *destY2, *destU, *destV;
+ gint dest_strideY, dest_strideU, dest_strideV;
+ const guint8 *src2;
+ gint src_stride;
+ gint y_idx, uv_idx;
+ gint y1, y2, y3, y4;
+ gint u1, u2, u3, u4;
+ gint v1, v2, v3, v4;
+ gint matrix[12];
+ guint8 *src;
+ gint dest_height, src_height, dest_width;
+
+ dest_height = GST_VIDEO_FRAME_HEIGHT (dest_frame);
+ dest_width = GST_VIDEO_FRAME_WIDTH (dest_frame);
+ src_height = GST_VIDEO_FRAME_HEIGHT (src_frame);
+
+ dest_strideY = GST_VIDEO_FRAME_COMP_STRIDE (dest_frame, 0);
+ dest_strideU = GST_VIDEO_FRAME_COMP_STRIDE (dest_frame, 1);
+ dest_strideV = GST_VIDEO_FRAME_COMP_STRIDE (dest_frame, 2);
+
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+
+ destY = GST_VIDEO_FRAME_COMP_DATA (dest_frame, 0);
+ destU = GST_VIDEO_FRAME_COMP_DATA (dest_frame, 1);
+ destV = GST_VIDEO_FRAME_COMP_DATA (dest_frame, 2);
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;
+ destY2 = (dest_y < dest_height) ? destY + dest_strideY : destY;
+ destU = destU + (dest_y / 2) * dest_strideU + dest_x / 2;
+ destV = destV + (dest_y / 2) * dest_strideV + dest_x / 2;
- widthY = w;
- widthUV = w / 2;
-
- hY = h;
- hUV = h / 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;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src = src + src_y * src_stride + src_x * 4;
+ src2 = (src_y < src_height) ? src + src_stride : src;
- dest_strideY *= 2;
+ h = dest_y + h;
+ w = dest_x + w;
+ if (src_sdtv != dest_sdtv)
memcpy (matrix,
dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
+ else
+ memcpy (matrix, cog_identity_matrix_8bit, 12 * sizeof (gint));
+
+ /* 1. Handle the first destination scanline specially if it
+ * doesn't start at the macro pixel boundary, i.e. blend
+ * with the background! */
+ if (dest_y % 2 == 1) {
+ /* 1.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = src[4 * 0 + 1];
+ u1 = src[4 * 0 + 2];
+ v1 = src[4 * 0 + 3];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] =
+ CLAMP ((3 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[0] =
+ CLAMP ((3 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 4, 0,
+ 255);
+
+ j = dest_x + 1;
+ y_idx = uv_idx = 1;
+ } else {
+ j = dest_x;
+ y_idx = uv_idx = 0;
+ }
- for (i = 0; i < hUV; i++) {
- if (i * 2 == hY) {
- destY2 = destY;
- }
+ /* 1.2. Copy all macro pixels from the source to the destination
+ * but blend with the background because we're only filling
+ * the lower part of the macro pixels. */
+ for (; j < w - 1; j += 2) {
+ y1 = src[4 * y_idx + 1];
+ y2 = src[4 * y_idx + 4 + 1];
+
+ u1 = src[4 * y_idx + 2];
+ u2 = src[4 * y_idx + 4 + 2];
+
+ v1 = src[4 * y_idx + 3];
+ v2 = src[4 * y_idx + 4 + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[y_idx + 1] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (2 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (2 * destV[uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+
+ y_idx += 2;
+ uv_idx++;
+ }
- 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;
- }
+ /* 1.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = src[4 * y_idx + 1];
+ u1 = src[4 * y_idx + 2];
+ v1 = src[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (destV[uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = src[4 * y_idx + 1];
+ u1 = src[4 * y_idx + 2];
+ v1 = src[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (3 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[uv_idx] =
+ CLAMP ((3 * destV[uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 4,
+ 0, 255);
+ }
- 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 += dest_strideY;
+ destY2 += dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
+ src += src_stride;
+ src2 += src_stride;
+ i = dest_y + 1;
+ } else {
+ i = dest_y;
+ }
- destY[2 * j] = y1;
- destY2[2 * j] = y3;
- if (j * 2 < widthY) {
- destY[2 * j + 1] = y2;
- destY2[2 * j + 1] = y4;
- }
+ /* 2. Copy all macro pixel scanlines, the destination scanline
+ * now starts at macro pixel boundary. */
+ for (; i < h - 1; i += 2) {
+ /* 2.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = src[4 * 0 + 1];
+ y2 = src2[4 * 0 + 1];
+ u1 = src[4 * 0 + 2];
+ u2 = src2[4 * 0 + 2];
+ v1 = src[4 * 0 + 3];
+ v2 = src2[4 * 0 + 3];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY2[0] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[0] = CLAMP (
+ (2 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[0] = CLAMP (
+ (2 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+ j = dest_x + 1;
+ y_idx = uv_idx = 1;
+ } else {
+ j = dest_x;
+ y_idx = uv_idx = 0;
+ }
- 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;
+ /* 2.2. Copy all macro pixels from the source to the destination.
+ * All pixels now start at macro pixel boundary, i.e. no
+ * blending with the background is necessary. */
+ for (; j < w - 1; j += 2) {
+ y1 = src[4 * y_idx + 1];
+ y2 = src[4 * y_idx + 4 + 1];
+ y3 = src2[4 * y_idx + 1];
+ y4 = src2[4 * y_idx + 4 + 1];
+
+ u1 = src[4 * y_idx + 2];
+ u2 = src[4 * y_idx + 4 + 2];
+ u3 = src2[4 * y_idx + 2];
+ u4 = src2[4 * y_idx + 4 + 2];
+
+ v1 = src[4 * y_idx + 3];
+ v2 = src[4 * y_idx + 4 + 3];
+ v3 = src2[4 * y_idx + 3];
+ v4 = src2[4 * y_idx + 4 + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[y_idx + 1] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destY2[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y3, u3, v3), 0, 255);
+ destY2[y_idx + 1] = CLAMP (APPLY_MATRIX (matrix, 0, y4, u4, v4), 0, 255);
+
+ destU[uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 1, y2,
+ u2, v2) + APPLY_MATRIX (matrix, 1, y3, u3,
+ v3) + APPLY_MATRIX (matrix, 1, y4, u4, v4)) / 4, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 2, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2) + APPLY_MATRIX (matrix, 2, y3, u3,
+ v3) + APPLY_MATRIX (matrix, 2, y4, u4, v4)) / 4, 0, 255);
+
+ y_idx += 2;
+ uv_idx++;
+ }
- destU += dest_strideUV;
- destV += dest_strideUV;
+ /* 2.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = src[4 * y_idx + 1];
+ y2 = src2[4 * y_idx + 1];
+
+ u1 = src[4 * y_idx + 2];
+ u2 = src2[4 * y_idx + 2];
+
+ v1 = src[4 * y_idx + 3];
+ v2 = src2[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY2[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2)) / 2, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = src[4 * y_idx + 1];
+ y2 = src2[4 * y_idx + 1];
+
+ u1 = src[4 * y_idx + 2];
+ u2 = src2[4 * y_idx + 2];
+
+ v1 = src[4 * y_idx + 3];
+ v2 = src2[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY2[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (2 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (2 * destV[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
}
- } 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;
+ destY += 2 * dest_strideY;
+ destY2 += 2 * dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
+ src += 2 * src_stride;
+ src2 += 2 * src_stride;
+ }
- for (i = 0; i < hUV; i++) {
- if (i * 2 == hY) {
- destY2 = destY;
- }
+ /* 3. Handle the last scanline if one exists. This again
+ * doesn't start at macro pixel boundary but should
+ * only fill the upper part of the macro pixels. */
+ if (i == h - 1 && i == dest_height - 1) {
+ /* 3.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = src[4 * 0 + 1];
+ u1 = src[4 * 0 + 2];
+ v1 = src[4 * 0 + 3];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] =
+ CLAMP ((destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ destV[0] =
+ CLAMP ((destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 2, 0, 255);
+
+ j = dest_x + 1;
+ y_idx = uv_idx = 1;
+ } else {
+ j = dest_x;
+ y_idx = uv_idx = 0;
+ }
- 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;
- }
+ /* 3.2. Copy all macro pixels from the source to the destination
+ * but blend with the background because we're only filling
+ * the upper part of the macro pixels. */
+ for (; j < w - 1; j += 2) {
+ y1 = src[4 * y_idx + 1];
+ y2 = src[4 * y_idx + 4 + 1];
- destY[2 * j] = y1;
- destY2[2 * j] = y3;
- if (j * 2 < widthY) {
- destY[2 * j + 1] = y2;
- destY2[2 * j + 1] = y4;
- }
+ u1 = src[4 * y_idx + 2];
+ u2 = src[4 * y_idx + 4 + 2];
- 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;
+ v1 = src[4 * y_idx + 3];
+ v2 = src[4 * y_idx + 4 + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[y_idx + 1] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+
+ destU[uv_idx] = CLAMP (
+ (2 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (2 * destV[uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+
+ y_idx += 2;
+ uv_idx++;
+ }
+
+ /* 3.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = src[4 * y_idx + 1];
+ u1 = src[4 * y_idx + 2];
+ v1 = src[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (destV[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = src[4 * y_idx + 1];
+ u1 = src[4 * y_idx + 2];
+ v1 = src[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (3 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[uv_idx] =
+ CLAMP ((3 * destV[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4,
+ 0, 255);
+ }
+ } else if (i == h - 1) {
+ /* 3.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = src[4 * 0 + 1];
+ u1 = src[4 * 0 + 2];
+ v1 = src[4 * 0 + 3];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] =
+ CLAMP ((3 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[0] =
+ CLAMP ((3 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 4, 0,
+ 255);
+
+ j = dest_x + 1;
+ y_idx = uv_idx = 1;
+ } else {
+ j = dest_x;
+ y_idx = uv_idx = 0;
+ }
+
+ /* 3.2. Copy all macro pixels from the source to the destination
+ * but blend with the background because we're only filling
+ * the upper part of the macro pixels. */
+ for (; j < w - 1; j += 2) {
+ y1 = src[4 * y_idx + 1];
+ y2 = src[4 * y_idx + 4 + 1];
+
+ u1 = src[4 * y_idx + 2];
+ u2 = src[4 * y_idx + 4 + 2];
+
+ v1 = src[4 * y_idx + 3];
+ v2 = src[4 * y_idx + 4 + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[y_idx + 1] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+
+ destU[uv_idx] = CLAMP (
+ (2 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (2 * destV[uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+
+ y_idx += 2;
+ uv_idx++;
+ }
- destU += dest_strideUV;
- destV += dest_strideUV;
+ /* 3.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = src[4 * y_idx + 1];
+ u1 = src[4 * y_idx + 2];
+ v1 = src[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ destV[uv_idx] = CLAMP (
+ (destV[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = src[4 * y_idx + 1];
+ u1 = src[4 * y_idx + 2];
+ v1 = src[4 * y_idx + 3];
+
+ destY[y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[uv_idx] = CLAMP (
+ (3 * destU[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[uv_idx] =
+ CLAMP ((3 * destV[uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4,
+ 0, 255);
}
}
}
static void
-fill_i420 (GstVideoBoxFill fill_type, guint b_alpha, GstVideoFormat format,
- guint8 * dest, gboolean sdtv, gint width, gint height)
+fill_planar_yuv (GstVideoBoxFill fill_type, guint b_alpha,
+ GstVideoFrame * frame, gboolean sdtv)
{
guint8 empty_pixel[3];
guint8 *destY, *destU, *destV;
- gint strideY, strideUV;
- gint heightY, heightUV;
+ gint strideY, strideU, strideV;
+ gint heightY, heightU, heightV;
+ gint widthY, widthU, widthV;
if (sdtv) {
empty_pixel[0] = yuv_sdtv_colors_Y[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);
-
- 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);
+ strideY = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
+ strideU = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
+ strideV = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
+
+ destY = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
+ destU = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
+ destV = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
+
+ widthY = GST_VIDEO_FRAME_COMP_WIDTH (frame, 0);
+ widthU = GST_VIDEO_FRAME_COMP_WIDTH (frame, 1);
+ widthV = GST_VIDEO_FRAME_COMP_WIDTH (frame, 2);
+
+ heightY = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0);
+ heightU = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0);
+ heightV = GST_VIDEO_FRAME_COMP_HEIGHT (frame, 0);
+
+ if (strideY == widthY) {
+ memset (destY, empty_pixel[0], strideY * heightY);
+ } else if (heightY) {
+ for (; heightY; --heightY) {
+ memset (destY, empty_pixel[0], widthY);
+ destY += strideY;
+ }
+ }
+ if (strideU == widthU) {
+ memset (destU, empty_pixel[1], strideU * heightU);
+ } else if (heightU) {
+ for (; heightU; --heightU) {
+ memset (destU, empty_pixel[0], widthY);
+ destU += strideU;
+ }
+ }
+ if (strideV == widthV) {
+ memset (destV, empty_pixel[2], strideV * heightV);
+ } else if (heightV) {
+ for (; heightV; --heightV) {
+ memset (destV, empty_pixel[0], widthV);
+ destV += strideV;
+ }
+ }
}
static void
-copy_i420_i420 (guint i_alpha, GstVideoFormat dest_format, guint8 * dest,
- gboolean dest_sdtv, gint dest_width, gint dest_height, gint dest_x,
- gint dest_y, GstVideoFormat src_format, const guint8 * src,
- gboolean src_sdtv, gint src_width, gint src_height, gint src_x, gint src_y,
- gint w, gint h)
+copy_y444_y444 (guint i_alpha, GstVideoFrame * dest,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
{
- gint i;
+ gint i, j;
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);
+ gint dest_strideY, dest_strideU, dest_strideV;
+ gint src_strideY, src_strideU, src_strideV;
+ dest_strideY = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideU = GST_VIDEO_FRAME_COMP_STRIDE (dest, 1);
+ dest_strideV = GST_VIDEO_FRAME_COMP_STRIDE (dest, 2);
- 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_strideY = GST_VIDEO_FRAME_COMP_STRIDE (src, 0);
+ src_strideU = GST_VIDEO_FRAME_COMP_STRIDE (src, 1);
+ src_strideV = GST_VIDEO_FRAME_COMP_STRIDE (src, 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;
+ destY = GST_VIDEO_FRAME_COMP_DATA (dest, 0);
+ destU = GST_VIDEO_FRAME_COMP_DATA (dest, 1);
+ destV = GST_VIDEO_FRAME_COMP_DATA (dest, 2);
+
+ srcY = GST_VIDEO_FRAME_COMP_DATA (src, 0);
+ srcU = GST_VIDEO_FRAME_COMP_DATA (src, 1);
+ srcV = GST_VIDEO_FRAME_COMP_DATA (src, 2);
- widthY = w;
- widthUV = (w + 1) / 2;
+ destY = destY + dest_y * dest_strideY + dest_x;
+ destU = destU + dest_y * dest_strideU + dest_x;
+ destV = destV + dest_y * dest_strideV + dest_x;
- hY = h;
- hUV = (h + 1) / 2;
+ srcY = srcY + src_y * src_strideY + src_x;
+ srcU = srcU + src_y * src_strideU + src_x;
+ srcV = srcV + src_y * src_strideV + src_x;
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;
+ 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 < hUV; i++) {
- if (i * 2 == hY) {
- destY2 = destY;
- srcY2 = srcY;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ y = APPLY_MATRIX (matrix, 0, srcY[j], srcU[j], srcV[j]);
+ u = APPLY_MATRIX (matrix, 1, srcY[j], srcU[j], srcV[j]);
+ v = APPLY_MATRIX (matrix, 2, srcY[j], srcU[j], srcV[j]);
+
+ destY[j] = y;
+ destU[j] = u;
+ destV[j] = v;
}
+ destY += dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
- 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];
+ srcY += src_strideY;
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
+ } else {
+ for (i = 0; i < h; i++) {
+ memcpy (destY, srcY, w);
+ memcpy (destU, srcU, w);
+ memcpy (destV, srcV, w);
- y1 = APPLY_MATRIX (matrix, 0, y1, u1, v1);
- u1 = APPLY_MATRIX (matrix, 1, y1, u1, v1);
- v1 = APPLY_MATRIX (matrix, 2, y1, u1, v1);
+ destY += dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
- y2 = APPLY_MATRIX (matrix, 0, y2, u2, v2);
- u2 = APPLY_MATRIX (matrix, 1, y2, u2, v2);
- v2 = APPLY_MATRIX (matrix, 2, y2, u2, v2);
+ srcY += src_strideY;
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
+ }
+}
- y3 = APPLY_MATRIX (matrix, 0, y3, u3, v3);
- u3 = APPLY_MATRIX (matrix, 1, y3, u3, v3);
- v3 = APPLY_MATRIX (matrix, 2, y3, u3, v3);
+static void
+copy_y42b_y42b (guint i_alpha, GstVideoFrame * dest,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ gint i, j;
+ guint8 *destY, *destU, *destV;
+ const guint8 *srcY, *srcU, *srcV;
+ gint dest_strideY, dest_strideU, dest_strideV;
+ gint src_strideY, src_strideU, src_strideV;
+ gint src_y_idx, src_uv_idx;
+ gint dest_y_idx, dest_uv_idx;
+ gint matrix[12];
+ gint y1, y2;
+ gint u1, u2;
+ gint v1, v2;
+ gint dest_width;
+
+ dest_width = GST_VIDEO_FRAME_WIDTH (dest);
+
+ dest_strideY = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideU = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideV = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+
+ src_strideY = GST_VIDEO_FRAME_COMP_STRIDE (src, 0);
+ src_strideU = GST_VIDEO_FRAME_COMP_STRIDE (src, 1);
+ src_strideV = GST_VIDEO_FRAME_COMP_STRIDE (src, 2);
+
+ destY = GST_VIDEO_FRAME_COMP_DATA (dest, 0);
+ destU = GST_VIDEO_FRAME_COMP_DATA (dest, 1);
+ destV = GST_VIDEO_FRAME_COMP_DATA (dest, 2);
+
+ srcY = GST_VIDEO_FRAME_COMP_DATA (src, 0);
+ srcU = GST_VIDEO_FRAME_COMP_DATA (src, 1);
+ srcV = GST_VIDEO_FRAME_COMP_DATA (src, 2);
- 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 = destY + dest_y * dest_strideY + dest_x;
+ destU = destU + dest_y * dest_strideU + dest_x / 2;
+ destV = destV + dest_y * dest_strideV + dest_x / 2;
- destY[2 * j] = y1;
- destY[2 * j + 1] = y2;
- destY2[2 * j] = y3;
- destY2[2 * j + 1] = y4;
+ srcY = srcY + src_y * src_strideY + src_x;
+ srcU = srcU + src_y * src_strideU + src_x / 2;
+ srcV = srcV + src_y * src_strideV + src_x / 2;
- 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;
+ h = dest_y + h;
+ w = dest_x + w;
- destU += dest_strideUV;
- destV += dest_strideUV;
- srcU += src_strideUV;
- srcV += src_strideUV;
+ if (src_sdtv != dest_sdtv)
+ memcpy (matrix,
+ dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
+ cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
+ else
+ memcpy (matrix, cog_identity_matrix_8bit, 12 * sizeof (gint));
+
+ /* 1. Copy all macro pixel scanlines, the destination scanline
+ * now starts at macro pixel boundary. */
+ for (i = dest_y; i < h; i++) {
+ /* 1.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = srcY[0];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] = CLAMP (
+ (destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ destV[0] = CLAMP (
+ (destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 2, 0, 255);
+ j = dest_x + 1;
+ src_y_idx = dest_y_idx = dest_uv_idx = 1;
+ src_uv_idx = (src_x % 2) + 1;
+ } else {
+ j = dest_x;
+ src_y_idx = dest_y_idx = dest_uv_idx = 0;
+ src_uv_idx = (src_x % 2);
}
- } else {
- for (i = 0; i < hY; i++) {
- oil_copy_u8 (destY, srcY, widthY);
- destY += dest_strideY;
- srcY += src_strideY;
+
+ /* 1.2. Copy all macro pixels from the source to the destination.
+ * All pixels now start at macro pixel boundary, i.e. no
+ * blending with the background is necessary. */
+ for (; j < w - 1; j += 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+ u2 = srcU[src_uv_idx / 2];
+ v2 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+
+ destU[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 1, y2,
+ u2, v2)) / 2, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 2, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2)) / 2, 0, 255);
+
+ dest_y_idx += 2;
+ src_y_idx += 2;
+ dest_uv_idx++;
}
- 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;
+ /* 1.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ destV[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ } else if (j == w - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 2, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 2, 0, 255);
}
+
+ destY += dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
+ srcY += src_strideY;
+
+ srcU += src_strideU;
+ srcV += src_strideV;
}
}
static void
-copy_i420_ayuv (guint i_alpha, GstVideoFormat dest_format, guint8 * dest,
- gboolean dest_sdtv, gint dest_width, gint dest_height, gint dest_x,
- gint dest_y, GstVideoFormat src_format, const guint8 * src,
- gboolean src_sdtv, gint src_width, gint src_height, gint src_x, gint src_y,
- gint w, gint h)
+copy_y41b_y41b (guint i_alpha, GstVideoFrame * dest,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
{
- gint i;
+ gint i, j;
+ guint8 *destY, *destU, *destV;
const guint8 *srcY, *srcU, *srcV;
- gint src_strideY, src_strideUV;
- gint widthY, widthUV;
- gint hY, hUV;
+ gint dest_strideY, dest_strideU, dest_strideV;
+ gint src_strideY, src_strideU, src_strideV;
+ gint src_y_idx, src_uv_idx;
+ gint dest_y_idx, dest_uv_idx;
+ gint matrix[12];
+ gint y1, y2, y3, y4;
+ gint u1, u2, u3, u4;
+ gint v1, v2, v3, v4;
+ gint dest_width;
+
+ dest_width = GST_VIDEO_FRAME_WIDTH (dest);
+
+ dest_strideY = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideU = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideV = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+
+ src_strideY = GST_VIDEO_FRAME_COMP_STRIDE (src, 0);
+ src_strideU = GST_VIDEO_FRAME_COMP_STRIDE (src, 1);
+ src_strideV = GST_VIDEO_FRAME_COMP_STRIDE (src, 2);
+
+ destY = GST_VIDEO_FRAME_COMP_DATA (dest, 0);
+ destU = GST_VIDEO_FRAME_COMP_DATA (dest, 1);
+ destV = GST_VIDEO_FRAME_COMP_DATA (dest, 2);
+
+ srcY = GST_VIDEO_FRAME_COMP_DATA (src, 0);
+ srcU = GST_VIDEO_FRAME_COMP_DATA (src, 1);
+ srcV = GST_VIDEO_FRAME_COMP_DATA (src, 2);
- 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 = destY + dest_y * dest_strideY + dest_x;
+ destU = destU + dest_y * dest_strideU + dest_x / 4;
+ destV = destV + dest_y * dest_strideV + dest_x / 4;
- 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);
+ srcY = srcY + src_y * src_strideY + src_x;
+ srcU = srcU + src_y * src_strideU + src_x / 4;
+ srcV = srcV + src_y * src_strideV + src_x / 4;
+ h = dest_y + h;
+ w = dest_x + w;
- dest = dest + dest_y * dest_width * 4 + dest_x * 4;
+ if (src_sdtv != dest_sdtv)
+ memcpy (matrix,
+ dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
+ cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
+ else
+ memcpy (matrix, cog_identity_matrix_8bit, 12 * sizeof (gint));
+
+ /* 1. Copy all macro pixel scanlines, the destination scanline
+ * now starts at macro pixel boundary. */
+ for (i = dest_y; i < h; i++) {
+ /* 1.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 4 == 1) {
+ y1 = srcY[0];
+ y2 = srcY[1];
+ y3 = srcY[2];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[1] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u1, v1), 0, 255);
+ destY[2] = CLAMP (APPLY_MATRIX (matrix, 0, y3, u1, v1), 0, 255);
+
+ destU[0] = CLAMP (
+ (destU[0] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y3, u1, v1)) / 4, 0, 255);
+ destV[0] =
+ CLAMP ((destV[0] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y3, u1, v1)) / 4, 0, 255);
+
+ j = dest_x + 3;
+ src_y_idx = dest_y_idx = 3;
+ dest_uv_idx = 1;
+ src_uv_idx = (src_x % 4) + 3;
+ } else if (dest_x % 4 == 2) {
+ y1 = srcY[0];
+ y2 = srcY[1];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[1] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u1, v1), 0, 255);
+
+ destU[0] = CLAMP (
+ (2 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u1, v1)) / 4, 0, 255);
+ destV[0] =
+ CLAMP ((2 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u1, v1)) / 4, 0, 255);
+
+ j = dest_x + 2;
+ src_y_idx = dest_y_idx = 2;
+ dest_uv_idx = 1;
+ src_uv_idx = (src_x % 4) + 2;
+ } else if (dest_x % 4 == 3) {
+ y1 = srcY[0];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+
+ destU[0] = CLAMP (
+ (3 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0, 255);
+ destV[0] = CLAMP (
+ (3 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 4, 0, 255);
+
+ j = dest_x + 1;
+ src_y_idx = dest_y_idx = 1;
+ dest_uv_idx = 1;
+ src_uv_idx = (src_x % 4) + 1;
+ } else {
+ j = dest_x;
+ src_y_idx = dest_y_idx = dest_uv_idx = 0;
+ src_uv_idx = (src_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;
+ /* 1.2. Copy all macro pixels from the source to the destination.
+ * All pixels now start at macro pixel boundary, i.e. no
+ * blending with the background is necessary. */
+ for (; j < w - 3; j += 4) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+ y3 = srcY[src_y_idx + 2];
+ y4 = srcY[src_y_idx + 3];
+
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+ src_uv_idx++;
+ u2 = srcU[src_uv_idx / 4];
+ v2 = srcV[src_uv_idx / 4];
+ src_uv_idx++;
+ u3 = srcU[src_uv_idx / 4];
+ v3 = srcV[src_uv_idx / 4];
+ src_uv_idx++;
+ u4 = srcU[src_uv_idx / 4];
+ v4 = srcV[src_uv_idx / 4];
+ src_uv_idx++;
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destY[dest_y_idx + 2] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y3, u3, v3), 0, 255);
+ destY[dest_y_idx + 3] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y4, u4, v4), 0, 255);
+
+ destU[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 1, y2,
+ u2, v2) + APPLY_MATRIX (matrix, 1, y3, u3,
+ v3) + APPLY_MATRIX (matrix, 1, y4, u4, v4)) / 4, 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((APPLY_MATRIX (matrix, 2, y1, u1, v1) + APPLY_MATRIX (matrix,
+ 2, y2, u2, v2) + APPLY_MATRIX (matrix, 2, y3, u3,
+ v3) + APPLY_MATRIX (matrix, 2, y4, u4, v4)) / 4, 0, 255);
+
+ dest_y_idx += 4;
+ src_y_idx += 4;
+ dest_uv_idx++;
+ }
- widthY = w;
- widthUV = (w + 1) / 2;
+ /* 1.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ destV[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ } else if (j == w - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (destU[dest_uv_idx] + 3 * APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 4, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (destV[dest_uv_idx] + 3 * APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 4, 0, 255);
+ } else if (j == w - 2 && j == dest_width - 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ destV[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ } else if (j == w - 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u1, v1), 0, 255);
+ destU[dest_uv_idx] =
+ CLAMP ((destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 2, 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 2, 0, 255);
+ } else if (j == w - 3 && j == dest_width - 3) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+ y3 = srcY[src_y_idx + 2];
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u1, v1), 0, 255);
+ destY[dest_y_idx + 2] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y3, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ destV[dest_uv_idx] = CLAMP (APPLY_MATRIX (matrix, 1, y1, u1, v1), 0, 255);
+ } else if (j == w - 3) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+ y3 = srcY[src_y_idx + 2];
+ u1 = srcU[src_uv_idx / 4];
+ v1 = srcV[src_uv_idx / 4];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u1, v1), 0, 255);
+ destY[dest_y_idx + 2] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y3, u1, v1), 0, 255);
+ destU[dest_uv_idx] =
+ CLAMP ((3 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 4, 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((3 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 4, 0, 255);
+ }
- hY = h;
- hUV = (h + 1) / 2;
+ destY += dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
+ srcY += src_strideY;
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
+}
- 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;
+static void
+copy_i420_i420 (guint i_alpha, GstVideoFrame * dest,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ gint i, j;
+ guint8 *destY, *destU, *destV;
+ const guint8 *srcY, *srcU, *srcV;
+ guint8 *destY2;
+ const guint8 *srcY2, *srcU2, *srcV2;
+ gint dest_strideY, dest_strideU, dest_strideV;
+ gint src_strideY, src_strideU, src_strideV;
+ gint src_y_idx, src_uv_idx;
+ gint dest_y_idx, dest_uv_idx;
+ gint matrix[12];
+ gint y1, y2, y3, y4;
+ gint u1, u2, u3, u4;
+ gint v1, v2, v3, v4;
+ gint dest_width, dest_height;
+
+ dest_width = GST_VIDEO_FRAME_WIDTH (dest);
+ dest_height = GST_VIDEO_FRAME_HEIGHT (dest);
+
+ dest_strideY = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideU = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+ dest_strideV = GST_VIDEO_FRAME_COMP_STRIDE (dest, 0);
+
+ src_strideY = GST_VIDEO_FRAME_COMP_STRIDE (src, 0);
+ src_strideU = GST_VIDEO_FRAME_COMP_STRIDE (src, 1);
+ src_strideV = GST_VIDEO_FRAME_COMP_STRIDE (src, 2);
+
+ destY = GST_VIDEO_FRAME_COMP_DATA (dest, 0);
+ destU = GST_VIDEO_FRAME_COMP_DATA (dest, 1);
+ destV = GST_VIDEO_FRAME_COMP_DATA (dest, 2);
+
+ srcY = GST_VIDEO_FRAME_COMP_DATA (src, 0);
+ srcU = GST_VIDEO_FRAME_COMP_DATA (src, 1);
+ srcV = GST_VIDEO_FRAME_COMP_DATA (src, 2);
- dest2 = dest + dest_width * 4;
+ destY = destY + dest_y * dest_strideY + dest_x;
+ destU = destU + (dest_y / 2) * dest_strideU + dest_x / 2;
+ destV = destV + (dest_y / 2) * dest_strideV + dest_x / 2;
- src_strideY *= 2;
+ srcY = srcY + src_y * src_strideY + src_x;
+ srcU = srcU + (src_y / 2) * src_strideU + src_x / 2;
+ srcV = srcV + (src_y / 2) * src_strideV + src_x / 2;
+ destY2 = destY + dest_strideY;
+ srcY2 = srcY + src_strideY;
+
+ h = dest_y + h;
+ w = dest_x + w;
+
+ if (src_sdtv != dest_sdtv)
memcpy (matrix,
dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
+ else
+ memcpy (matrix, cog_identity_matrix_8bit, 12 * sizeof (gint));
+
+ /* 1. Handle the first destination scanline specially if it
+ * doesn't start at the macro pixel boundary, i.e. blend
+ * with the background! */
+ if (dest_y % 2 == 1) {
+ /* 1.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = srcY[0];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] =
+ CLAMP ((3 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[0] =
+ CLAMP ((3 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 4, 0,
+ 255);
+
+ j = dest_x + 1;
+ src_y_idx = dest_y_idx = dest_uv_idx = 1;
+ src_uv_idx = (src_x % 2) + 1;
+ } else {
+ j = dest_x;
+ src_y_idx = dest_y_idx = dest_uv_idx = 0;
+ src_uv_idx = (src_x % 2);
+ }
- for (i = 0; i < hUV; i++) {
- if (i * 2 == hY) {
- srcY2 = srcY;
- }
+ /* 1.2. Copy all macro pixels from the source to the destination
+ * but blend with the background because we're only filling
+ * the lower part of the macro pixels. */
+ for (; j < w - 1; j += 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+ u2 = srcU[src_uv_idx / 2];
+ v2 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[dest_uv_idx] =
+ CLAMP ((2 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((2 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+
+ dest_y_idx += 2;
+ src_y_idx += 2;
+ dest_uv_idx++;
+ }
- 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;
+ /* 1.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0,
+ 255);
+ destV[dest_uv_idx] =
+ CLAMP ((destV[dest_uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (3 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4,
+ 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((3 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1)) / 4, 0, 255);
+ }
- u1 = u2 = u3 = u4 = srcU[j];
- v1 = v2 = v3 = v4 = srcV[j];
+ destY += dest_strideY;
+ destY2 += dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
+ srcY += src_strideY;
+ srcY2 += src_strideY;
+ src_y++;
+ if (src_y % 2 == 0) {
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
+ i = dest_y + 1;
+ } else {
+ i = dest_y;
+ }
- y1 = APPLY_MATRIX (matrix, 0, y1, u1, v1);
- u1 = APPLY_MATRIX (matrix, 1, y1, u1, v1);
- v1 = APPLY_MATRIX (matrix, 2, y1, u1, v1);
+ /* 2. Copy all macro pixel scanlines, the destination scanline
+ * now starts at macro pixel boundary. */
+ for (; i < h - 1; i += 2) {
+ /* 2.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+
+ srcU2 = srcU;
+ srcV2 = srcV;
+ if (src_y % 2 == 1) {
+ srcU2 += src_strideU;
+ srcV2 += src_strideV;
+ }
- 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 (dest_x % 2 == 1) {
+ y1 = srcY[0];
+ y2 = srcY2[0];
+ u1 = srcU[0];
+ v1 = srcV[0];
+ u2 = srcU2[0];
+ v2 = srcV2[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY2[0] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[0] = CLAMP (
+ (2 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[0] = CLAMP (
+ (2 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+ j = dest_x + 1;
+ src_y_idx = dest_y_idx = dest_uv_idx = 1;
+ src_uv_idx = (src_x % 2) + 1;
+ } else {
+ j = dest_x;
+ src_y_idx = dest_y_idx = dest_uv_idx = 0;
+ src_uv_idx = (src_x % 2);
+ }
- 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);
+ /* 2.2. Copy all macro pixels from the source to the destination.
+ * All pixels now start at macro pixel boundary, i.e. no
+ * blending with the background is necessary. */
+ for (; j < w - 1; j += 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+ y3 = srcY2[src_y_idx];
+ y4 = srcY2[src_y_idx + 1];
+
+ u1 = srcU[src_uv_idx / 2];
+ u3 = srcU2[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+ v3 = srcV2[src_uv_idx / 2];
+ src_uv_idx++;
+ u2 = srcU[src_uv_idx / 2];
+ u4 = srcU2[src_uv_idx / 2];
+ v2 = srcV[src_uv_idx / 2];
+ v4 = srcV2[src_uv_idx / 2];
+ src_uv_idx++;
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destY2[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y3, u3, v3), 0, 255);
+ destY2[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y4, u4, v4), 0, 255);
+
+ destU[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 1, y2,
+ u2, v2) + APPLY_MATRIX (matrix, 1, y3, u3,
+ v3) + APPLY_MATRIX (matrix, 1, y4, u4, v4)) / 4, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 2, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2) + APPLY_MATRIX (matrix, 2, y3, u3,
+ v3) + APPLY_MATRIX (matrix, 2, y4, u4, v4)) / 4, 0, 255);
+
+ dest_y_idx += 2;
+ src_y_idx += 2;
+ dest_uv_idx++;
+ }
- y4 = APPLY_MATRIX (matrix, 0, y4, u4, v4);
- u4 = APPLY_MATRIX (matrix, 1, y4, u4, v4);
- v4 = APPLY_MATRIX (matrix, 2, y4, u4, v4);
- }
+ /* 2.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY2[src_y_idx];
+
+ u1 = srcU[src_uv_idx / 2];
+ u2 = srcU2[src_uv_idx / 2];
+
+ v1 = srcV[src_uv_idx / 2];
+ v2 = srcV2[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY2[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2)) / 2, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (APPLY_MATRIX (matrix, 1, y1, u1, v1) + APPLY_MATRIX (matrix, 2, y2,
+ u2, v2)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY2[src_y_idx];
+
+ u1 = srcU[src_uv_idx / 2];
+ u2 = srcU2[src_uv_idx / 2];
+
+ v1 = srcV[src_uv_idx / 2];
+ v2 = srcV2[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY2[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (2 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (2 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+ }
- 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;
+ destY += 2 * dest_strideY;
+ destY2 += 2 * dest_strideY;
+ destU += dest_strideU;
+ destV += dest_strideV;
+ srcY += 2 * src_strideY;
+ srcY2 += 2 * src_strideY;
- srcU += src_strideUV;
- srcV += src_strideUV;
+ src_y += 2;
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
+
+ /* 3. Handle the last scanline if one exists. This again
+ * doesn't start at macro pixel boundary but should
+ * only fill the upper part of the macro pixels. */
+ if (i == h - 1 && i == dest_height - 1) {
+ /* 3.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = srcY[0];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] =
+ CLAMP ((destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0, 255);
+ destV[0] =
+ CLAMP ((destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 2, 0, 255);
+
+ j = dest_x + 1;
+ src_y_idx = dest_y_idx = dest_uv_idx = 1;
+ src_uv_idx = (src_x % 2) + 1;
+ } else {
+ j = dest_x;
+ src_y_idx = dest_y_idx = dest_uv_idx = 0;
+ src_uv_idx = (src_x % 2);
+ }
+
+ /* 3.2. Copy all macro pixels from the source to the destination
+ * but blend with the background because we're only filling
+ * the upper part of the macro pixels. */
+ for (; j < w - 1; j += 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+ u2 = srcU[src_uv_idx / 2];
+ v2 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+
+ destU[dest_uv_idx] = CLAMP (
+ (2 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (2 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+
+ dest_y_idx += 2;
+ src_y_idx += 2;
+ dest_uv_idx++;
+ }
+
+ /* 3.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0,
+ 255);
+ destV[dest_uv_idx] =
+ CLAMP ((destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (3 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4,
+ 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((3 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 4, 0, 255);
+ }
+ } else if (i == h - 1) {
+ /* 3.1. Handle the first destination pixel if it doesn't
+ * start at the macro pixel boundary, i.e. blend with
+ * the background! */
+ if (dest_x % 2 == 1) {
+ y1 = srcY[0];
+ u1 = srcU[0];
+ v1 = srcV[0];
+
+ destY[0] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[0] =
+ CLAMP ((3 * destU[0] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4, 0,
+ 255);
+ destV[0] =
+ CLAMP ((3 * destV[0] + APPLY_MATRIX (matrix, 2, y1, u1, v1)) / 4, 0,
+ 255);
+
+ j = dest_x + 1;
+ src_y_idx = dest_y_idx = dest_uv_idx = 1;
+ src_uv_idx = (src_x % 2) + 1;
+ } else {
+ j = dest_x;
+ src_y_idx = dest_y_idx = dest_uv_idx = 0;
+ src_uv_idx = (src_x % 2);
+ }
+
+ /* 3.2. Copy all macro pixels from the source to the destination
+ * but blend with the background because we're only filling
+ * the upper part of the macro pixels. */
+ for (; j < w - 1; j += 2) {
+ y1 = srcY[src_y_idx];
+ y2 = srcY[src_y_idx + 1];
+
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+ u2 = srcU[src_uv_idx / 2];
+ v2 = srcV[src_uv_idx / 2];
+ src_uv_idx++;
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destY[dest_y_idx + 1] =
+ CLAMP (APPLY_MATRIX (matrix, 0, y2, u2, v2), 0, 255);
+
+ destU[dest_uv_idx] = CLAMP (
+ (2 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 1, y2, u2, v2)) / 4, 0, 255);
+ destV[dest_uv_idx] = CLAMP (
+ (2 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 2, y1, u1,
+ v1) + APPLY_MATRIX (matrix, 2, y2, u2, v2)) / 4, 0, 255);
+
+ dest_y_idx += 2;
+ src_y_idx += 2;
+ dest_uv_idx++;
}
- } 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;
+ /* 3.3. Now copy the last pixel if one exists and blend it
+ * with the background because we only fill part of
+ * the macro pixel. In case this is the last pixel of
+ * the destination we will a larger part. */
+ if (j == w - 1 && j == dest_width - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 2, 0,
+ 255);
+ destV[dest_uv_idx] =
+ CLAMP ((destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 2, 0, 255);
+ } else if (j == w - 1) {
+ y1 = srcY[src_y_idx];
+ u1 = srcU[src_uv_idx / 2];
+ v1 = srcV[src_uv_idx / 2];
+
+ destY[dest_y_idx] = CLAMP (APPLY_MATRIX (matrix, 0, y1, u1, v1), 0, 255);
+ destU[dest_uv_idx] = CLAMP (
+ (3 * destU[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1, v1)) / 4,
+ 0, 255);
+ destV[dest_uv_idx] =
+ CLAMP ((3 * destV[dest_uv_idx] + APPLY_MATRIX (matrix, 1, y1, u1,
+ v1)) / 4, 0, 255);
+ }
+ }
+}
- src_strideY *= 2;
+static void
+copy_i420_ayuv (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ const guint8 *srcY, *srcU, *srcV;
+ gint src_strideY, src_strideU, src_strideV;
+ gint dest_stride;
+ guint8 *dest;
- for (i = 0; i < hUV; i++) {
- if (i * 2 == hY) {
- srcY2 = srcY;
- }
+ src_strideY = GST_VIDEO_FRAME_COMP_STRIDE (src_frame, 0);
+ src_strideU = GST_VIDEO_FRAME_COMP_STRIDE (src_frame, 1);
+ src_strideV = GST_VIDEO_FRAME_COMP_STRIDE (src_frame, 2);
- 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;
- }
+ srcY = GST_VIDEO_FRAME_COMP_DATA (src_frame, 0);
+ srcU = GST_VIDEO_FRAME_COMP_DATA (src_frame, 1);
+ srcV = GST_VIDEO_FRAME_COMP_DATA (src_frame, 2);
+
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest = dest + dest_y * dest_stride + dest_x * 4;
+
+ srcY = srcY + src_y * src_strideY + src_x;
+ srcU = srcU + (src_y / 2) * src_strideU + src_x / 2;
+ srcV = srcV + (src_y / 2) * src_strideV + src_x / 2;
+
+ i_alpha = CLAMP (i_alpha, 0, 255);
+
+ if (src_sdtv != dest_sdtv) {
+ gint i, j, uv_idx;
+ gint y, u, v;
+ gint y1, u1, v1;
+ gint matrix[12];
+
+ 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, uv_idx = src_x % 2; j < w; j++, uv_idx++) {
+ y = srcY[j];
+ u = srcU[uv_idx / 2];
+ v = srcV[uv_idx / 2];
+
+ y1 = APPLY_MATRIX (matrix, 0, y, u, v);
+ u1 = APPLY_MATRIX (matrix, 1, y, u, v);
+ v1 = APPLY_MATRIX (matrix, 2, y, u, v);
+
+ dest[4 * j + 0] = i_alpha;
+ dest[4 * j + 1] = y1;
+ dest[4 * j + 2] = u1;
+ dest[4 * j + 3] = v1;
}
- dest += dest_width * 8;
+ dest += dest_stride;
+
+ src_y++;
srcY += src_strideY;
- dest2 += dest_width * 8;
- srcY2 += src_strideY;
+ if (src_y % 2 == 0) {
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
+ }
+ } else {
+ gint i, j, uv_idx;
+ gint y, u, v;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0, uv_idx = src_x % 2; j < w; j++, uv_idx++) {
+ y = srcY[j];
+ u = srcU[uv_idx / 2];
+ v = srcV[uv_idx / 2];
+
+ dest[4 * j + 0] = i_alpha;
+ dest[4 * j + 1] = y;
+ dest[4 * j + 2] = u;
+ dest[4 * j + 3] = v;
+ }
+ dest += dest_stride;
- srcU += src_strideUV;
- srcV += src_strideUV;
+ src_y++;
+ srcY += src_strideY;
+ if (src_y % 2 == 0) {
+ srcU += src_strideU;
+ srcV += src_strideV;
+ }
}
}
}
static void
-fill_rgb32 (GstVideoBoxFill fill_type, guint b_alpha, GstVideoFormat format,
- guint8 * dest, gboolean sdtv, gint width, gint height)
+fill_rgb32 (GstVideoBoxFill fill_type, guint b_alpha,
+ GstVideoFrame * frame, gboolean sdtv)
{
guint32 empty_pixel;
- gint a_off, r_off, g_off, b_off;
+ gint p[4];
+ guint8 *dest;
+ guint stride;
+ gint width, height;
- switch (format) {
- case GST_VIDEO_FORMAT_ARGB:
- case GST_VIDEO_FORMAT_xRGB:
- a_off = 24;
- r_off = 16;
- g_off = 8;
- b_off = 0;
- break;
- case GST_VIDEO_FORMAT_ABGR:
- case GST_VIDEO_FORMAT_xBGR:
- a_off = 24;
- b_off = 16;
- g_off = 8;
- r_off = 0;
- break;
- case GST_VIDEO_FORMAT_RGBA:
- case GST_VIDEO_FORMAT_RGBx:
- r_off = 24;
- g_off = 16;
- b_off = 8;
- a_off = 0;
- break;
- case GST_VIDEO_FORMAT_BGRA:
- case GST_VIDEO_FORMAT_BGRx:
- b_off = 24;
- g_off = 16;
- r_off = 8;
- a_off = 0;
- break;
- default:
- g_assert_not_reached ();
+ width = GST_VIDEO_FRAME_WIDTH (frame);
+ height = GST_VIDEO_FRAME_HEIGHT (frame);
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
+
+ p[0] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 3);
+ p[1] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 0);
+ p[2] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 1);
+ p[3] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 2);
+
+ b_alpha = CLAMP (b_alpha, 0, 255);
+
+ empty_pixel = GUINT32_FROM_LE ((b_alpha << (p[0] * 8)) |
+ (rgb_colors_R[fill_type] << (p[1] * 8)) |
+ (rgb_colors_G[fill_type] << (p[2] * 8)) |
+ (rgb_colors_B[fill_type] << (p[3] * 8)));
+
+ if (stride == width * 4) {
+ video_box_orc_splat_u32 ((guint32 *) dest, empty_pixel, width * height);
+ } else if (height) {
+ for (; height; --height) {
+ video_box_orc_splat_u32 ((guint32 *) dest, empty_pixel, width);
+ dest += stride;
+ }
}
+}
+
+static void
+fill_rgb24 (GstVideoBoxFill fill_type, guint b_alpha,
+ GstVideoFrame * frame, gboolean sdtv)
+{
+ gint dest_stride;
+ gint p[4];
+ gint i, j;
+ guint8 *dest;
+ gint width, height;
- empty_pixel = GUINT32_FROM_BE ((b_alpha << a_off) |
- (rgb_colors_R[fill_type] << r_off) |
- (rgb_colors_G[fill_type] << g_off) | (rgb_colors_B[fill_type] << b_off));
+ width = GST_VIDEO_FRAME_WIDTH (frame);
+ height = GST_VIDEO_FRAME_HEIGHT (frame);
- oil_splat_u32_ns ((guint32 *) dest, &empty_pixel, width * height);
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
+
+ p[1] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 0);
+ p[2] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 1);
+ p[3] = GST_VIDEO_FRAME_COMP_OFFSET (frame, 2);
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ dest[3 * j + p[1]] = rgb_colors_R[fill_type];
+ dest[3 * j + p[2]] = rgb_colors_G[fill_type];
+ dest[3 * j + p[3]] = rgb_colors_B[fill_type];
+ }
+ dest += dest_stride;
+ }
}
static void
-copy_rgb32 (guint i_alpha, GstVideoFormat dest_format, guint8 * dest,
- gboolean dest_sdtv, gint dest_width, gint dest_height, gint dest_x,
- gint dest_y, GstVideoFormat src_format, const guint8 * src,
- gboolean src_sdtv, gint src_width, gint src_height, gint src_x, gint src_y,
- gint w, gint h)
+copy_rgb32 (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, 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;
+ gint src_stride, dest_stride;
gboolean in_alpha, out_alpha;
+ gint in_bpp, out_bpp;
gint p_out[4];
gint p_in[4];
+ gboolean packed_out;
+ gboolean packed_in;
+ guint8 *src, *dest;
+
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+ in_bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (src_frame, 0);
+ out_bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (dest_frame, 0);
+ packed_in = (in_bpp < 4);
+ packed_out = (out_bpp < 4);
+
+ out_alpha = GST_VIDEO_INFO_HAS_ALPHA (&dest_frame->info);
+ p_out[0] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 3);
+ p_out[1] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 0);
+ p_out[2] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 1);
+ p_out[3] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 2);
+
+ in_alpha = GST_VIDEO_INFO_HAS_ALPHA (&src_frame->info);
+ p_in[0] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 3);
+ p_in[1] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 0);
+ p_in[2] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 1);
+ p_in[3] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 2);
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest = dest + dest_y * dest_stride + dest_x * out_bpp;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src = src + src_y * src_stride + src_x * in_bpp;
- switch (dest_format) {
- case GST_VIDEO_FORMAT_ARGB:
- out_alpha = TRUE;
- case GST_VIDEO_FORMAT_xRGB:
- p_out[0] = 0;
- p_out[1] = 1;
- p_out[2] = 2;
- p_out[3] = 3;
- switch (src_format) {
- case GST_VIDEO_FORMAT_ARGB:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xRGB:
- p_in[0] = 0;
- p_in[1] = 1;
- p_in[2] = 2;
- p_in[3] = 3;
- break;
- case GST_VIDEO_FORMAT_ABGR:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xBGR:
- p_in[0] = 0;
- p_in[1] = 3;
- p_in[2] = 2;
- p_in[3] = 1;
- break;
- case GST_VIDEO_FORMAT_RGBA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_RGBx:
- p_in[0] = 3;
- p_in[1] = 0;
- p_in[2] = 1;
- p_in[3] = 2;
- break;
- case GST_VIDEO_FORMAT_BGRA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_BGRx:
- p_in[0] = 3;
- p_in[1] = 2;
- p_in[2] = 1;
- p_in[3] = 0;
- break;
- default:
- g_assert_not_reached ();
+ if (in_alpha && out_alpha) {
+ w *= 4;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 4) {
+ dest[j + p_out[0]] = (src[j + p_in[0]] * i_alpha) >> 8;
+ dest[j + p_out[1]] = src[j + p_in[1]];
+ dest[j + p_out[2]] = src[j + p_in[2]];
+ dest[j + p_out[3]] = src[j + p_in[3]];
}
- break;
- case GST_VIDEO_FORMAT_ABGR:
- out_alpha = TRUE;
- case GST_VIDEO_FORMAT_xBGR:
- p_out[0] = 0;
- p_out[1] = 3;
- p_out[2] = 2;
- p_out[3] = 1;
- switch (src_format) {
- case GST_VIDEO_FORMAT_ARGB:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xRGB:
- p_in[0] = 0;
- p_in[1] = 1;
- p_in[2] = 2;
- p_in[3] = 3;
- break;
- case GST_VIDEO_FORMAT_ABGR:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xBGR:
- p_in[0] = 0;
- p_in[1] = 3;
- p_in[2] = 2;
- p_in[3] = 1;
- break;
- case GST_VIDEO_FORMAT_RGBA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_RGBx:
- p_in[0] = 3;
- p_in[1] = 0;
- p_in[2] = 1;
- p_in[3] = 2;
- break;
- case GST_VIDEO_FORMAT_BGRA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_BGRx:
- p_in[0] = 3;
- p_in[1] = 2;
- p_in[2] = 1;
- p_in[3] = 0;
- break;
- default:
- g_assert_not_reached ();
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else if (out_alpha && !packed_in) {
+ w *= 4;
+ i_alpha = CLAMP (i_alpha, 0, 255);
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 4) {
+ dest[j + p_out[0]] = i_alpha;
+ dest[j + p_out[1]] = src[j + p_in[1]];
+ dest[j + p_out[2]] = src[j + p_in[2]];
+ dest[j + p_out[3]] = src[j + p_in[3]];
}
- break;
- case GST_VIDEO_FORMAT_RGBA:
- out_alpha = TRUE;
- case GST_VIDEO_FORMAT_RGBx:
- p_out[0] = 3;
- p_out[1] = 0;
- p_out[2] = 1;
- p_out[3] = 2;
- switch (src_format) {
- case GST_VIDEO_FORMAT_ARGB:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xRGB:
- p_in[0] = 0;
- p_in[1] = 1;
- p_in[2] = 2;
- p_in[3] = 3;
- break;
- case GST_VIDEO_FORMAT_ABGR:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xBGR:
- p_in[0] = 0;
- p_in[1] = 3;
- p_in[2] = 2;
- p_in[3] = 1;
- break;
- case GST_VIDEO_FORMAT_RGBA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_RGBx:
- p_in[0] = 3;
- p_in[1] = 0;
- p_in[2] = 1;
- p_in[3] = 2;
- break;
- case GST_VIDEO_FORMAT_BGRA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_BGRx:
- p_in[0] = 3;
- p_in[1] = 2;
- p_in[2] = 1;
- p_in[3] = 0;
- break;
- default:
- g_assert_not_reached ();
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else if (out_alpha && packed_in) {
+ i_alpha = CLAMP (i_alpha, 0, 255);
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ dest[4 * j + p_out[0]] = i_alpha;
+ dest[4 * j + p_out[1]] = src[in_bpp * j + p_in[1]];
+ dest[4 * j + p_out[2]] = src[in_bpp * j + p_in[2]];
+ dest[4 * j + p_out[3]] = src[in_bpp * j + p_in[3]];
}
- break;
- case GST_VIDEO_FORMAT_BGRA:
- out_alpha = TRUE;
- case GST_VIDEO_FORMAT_BGRx:
- p_out[0] = 3;
- p_out[1] = 2;
- p_out[2] = 1;
- p_out[3] = 0;
- switch (src_format) {
- case GST_VIDEO_FORMAT_ARGB:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xRGB:
- p_in[0] = 0;
- p_in[1] = 1;
- p_in[2] = 2;
- p_in[3] = 3;
- break;
- case GST_VIDEO_FORMAT_ABGR:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_xBGR:
- p_in[0] = 0;
- p_in[1] = 3;
- p_in[2] = 2;
- p_in[3] = 1;
- break;
- case GST_VIDEO_FORMAT_RGBA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_RGBx:
- p_in[0] = 3;
- p_in[1] = 0;
- p_in[2] = 1;
- p_in[3] = 2;
- break;
- case GST_VIDEO_FORMAT_BGRA:
- in_alpha = TRUE;
- case GST_VIDEO_FORMAT_BGRx:
- p_in[0] = 3;
- p_in[1] = 2;
- p_in[2] = 1;
- p_in[3] = 0;
- break;
- default:
- g_assert_not_reached ();
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else if (!packed_out && !packed_in) {
+ w *= 4;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 4) {
+ dest[j + p_out[1]] = src[j + p_in[1]];
+ dest[j + p_out[2]] = src[j + p_in[2]];
+ dest[j + p_out[3]] = src[j + p_in[3]];
}
- break;
- default:
- g_assert_not_reached ();
- break;
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else {
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ dest[out_bpp * j + p_out[1]] = src[in_bpp * j + p_in[1]];
+ dest[out_bpp * j + p_out[2]] = src[in_bpp * j + p_in[2]];
+ dest[out_bpp * j + p_out[3]] = src[in_bpp * j + p_in[3]];
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
}
+}
- dest = dest + dest_y * dest_width * 4 + dest_x * 4;
- src = src + src_y * src_width * 4 + src_x * 4;
-
- w *= 4;
+static void
+copy_rgb32_ayuv (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ gint i, j;
+ gint src_stride, dest_stride;
+ gboolean in_alpha;
+ gint in_bpp;
+ gint p_in[4];
+ gboolean packed_in;
+ gint matrix[12];
+ gint a;
+ gint y, u, v;
+ gint r, g, b;
+ guint8 *dest, *src;
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+ in_bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (src_frame, 0);
+ packed_in = (in_bpp < 4);
+
+ in_alpha = GST_VIDEO_INFO_HAS_ALPHA (&src_frame->info);
+ p_in[0] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 3);
+ p_in[1] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 0);
+ p_in[2] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 1);
+ p_in[3] = GST_VIDEO_FRAME_COMP_OFFSET (src_frame, 2);
+
+ memcpy (matrix,
+ (dest_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
+ cog_rgb_to_ycbcr_matrix_8bit_hdtv, 12 * sizeof (gint));
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest = dest + dest_y * dest_stride + dest_x * 4;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src = src + src_y * src_stride + src_x * in_bpp;
+
+ if (in_alpha) {
+ w *= 4;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 4) {
+ a = (src[j + p_in[0]] * i_alpha) >> 8;
+ r = src[j + p_in[1]];
+ g = src[j + p_in[2]];
+ b = src[j + p_in[3]];
+
+ y = APPLY_MATRIX (matrix, 0, r, g, b);
+ u = APPLY_MATRIX (matrix, 1, r, g, b);
+ v = APPLY_MATRIX (matrix, 2, r, g, b);
+
+ dest[j + 0] = a;
+ dest[j + 1] = CLAMP (y, 0, 255);
+ dest[j + 2] = CLAMP (u, 0, 255);
+ dest[j + 3] = CLAMP (v, 0, 255);
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else if (!packed_in) {
+ w *= 4;
+ i_alpha = CLAMP (i_alpha, 0, 255);
- if (in_alpha && out_alpha) {
for (i = 0; i < h; i++) {
for (j = 0; j < w; j += 4) {
- dest[j + p_out[0]] = (src[j + p_in[0]] * i_alpha) >> 8;
- dest[j + p_out[1]] = src[j + p_in[1]];
- dest[j + p_out[2]] = src[j + p_in[2]];
- dest[j + p_out[3]] = src[j + p_in[3]];
+ a = i_alpha;
+ r = src[j + p_in[1]];
+ g = src[j + p_in[2]];
+ b = src[j + p_in[3]];
+
+ y = APPLY_MATRIX (matrix, 0, r, g, b);
+ u = APPLY_MATRIX (matrix, 1, r, g, b);
+ v = APPLY_MATRIX (matrix, 2, r, g, b);
+
+ dest[j + 0] = a;
+ dest[j + 1] = CLAMP (y, 0, 255);
+ dest[j + 2] = CLAMP (u, 0, 255);
+ dest[j + 3] = CLAMP (v, 0, 255);
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else {
+ i_alpha = CLAMP (i_alpha, 0, 255);
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ a = i_alpha;
+ r = src[in_bpp * j + p_in[1]];
+ g = src[in_bpp * j + p_in[2]];
+ b = src[in_bpp * j + p_in[3]];
+
+ y = APPLY_MATRIX (matrix, 0, r, g, b);
+ u = APPLY_MATRIX (matrix, 1, r, g, b);
+ v = APPLY_MATRIX (matrix, 2, r, g, b);
+
+ dest[4 * j + 0] = a;
+ dest[4 * j + 1] = CLAMP (y, 0, 255);
+ dest[4 * j + 2] = CLAMP (u, 0, 255);
+ dest[4 * j + 3] = CLAMP (v, 0, 255);
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ }
+}
+
+static void
+copy_ayuv_rgb32 (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ gint i, j;
+ gint src_stride, dest_stride;
+ gboolean out_alpha;
+ gint out_bpp;
+ gint p_out[4];
+ gboolean packed_out;
+ gint matrix[12];
+ gint a;
+ gint y, u, v;
+ gint r, g, b;
+ guint8 *src, *dest;
+
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+ out_bpp = GST_VIDEO_FRAME_COMP_PSTRIDE (dest_frame, 0);
+ packed_out = (out_bpp < 4);
+
+ out_alpha = GST_VIDEO_INFO_HAS_ALPHA (&dest_frame->info);
+ p_out[0] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 3);
+ p_out[1] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 0);
+ p_out[2] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 1);
+ p_out[3] = GST_VIDEO_FRAME_COMP_OFFSET (dest_frame, 2);
+
+ memcpy (matrix,
+ (src_sdtv) ? cog_ycbcr_to_rgb_matrix_8bit_sdtv :
+ cog_ycbcr_to_rgb_matrix_8bit_hdtv, 12 * sizeof (gint));
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest = dest + dest_y * dest_stride + dest_x * out_bpp;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src = src + src_y * src_stride + src_x * 4;
+
+ if (out_alpha) {
+ w *= 4;
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 4) {
+ a = (src[j + 0] * i_alpha) >> 8;
+ y = src[j + 1];
+ u = src[j + 2];
+ v = src[j + 3];
+
+ r = APPLY_MATRIX (matrix, 0, y, u, v);
+ g = APPLY_MATRIX (matrix, 1, y, u, v);
+ b = APPLY_MATRIX (matrix, 2, y, u, v);
+
+ dest[j + p_out[0]] = a;
+ dest[j + p_out[1]] = CLAMP (r, 0, 255);
+ dest[j + p_out[2]] = CLAMP (g, 0, 255);
+ dest[j + p_out[3]] = CLAMP (b, 0, 255);
}
dest += dest_stride;
src += src_stride;
}
- } else if (out_alpha) {
+ } else if (!packed_out) {
+ w *= 4;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j += 4) {
- dest[j + p_out[0]] = i_alpha & 0xff;
- dest[j + p_out[1]] = src[j + p_in[1]];
- dest[j + p_out[2]] = src[j + p_in[2]];
- dest[j + p_out[3]] = src[j + p_in[3]];
+ y = src[j + 1];
+ u = src[j + 2];
+ v = src[j + 3];
+
+ r = APPLY_MATRIX (matrix, 0, y, u, v);
+ g = APPLY_MATRIX (matrix, 1, y, u, v);
+ b = APPLY_MATRIX (matrix, 2, y, u, v);
+
+ dest[j + p_out[1]] = CLAMP (r, 0, 255);
+ dest[j + p_out[2]] = CLAMP (g, 0, 255);
+ dest[j + p_out[3]] = CLAMP (b, 0, 255);
}
dest += dest_stride;
src += src_stride;
}
} else {
for (i = 0; i < h; i++) {
- for (j = 0; j < w; j += 4) {
- dest[j + p_out[1]] = src[j + p_in[1]];
- dest[j + p_out[2]] = src[j + p_in[2]];
- dest[j + p_out[3]] = src[j + p_in[3]];
+ for (j = 0; j < w; j++) {
+ y = src[4 * j + 1];
+ u = src[4 * j + 2];
+ v = src[4 * j + 3];
+
+ r = APPLY_MATRIX (matrix, 0, y, u, v);
+ g = APPLY_MATRIX (matrix, 1, y, u, v);
+ b = APPLY_MATRIX (matrix, 2, y, u, v);
+
+ dest[out_bpp * j + p_out[1]] = CLAMP (r, 0, 255);
+ dest[out_bpp * j + p_out[2]] = CLAMP (g, 0, 255);
+ dest[out_bpp * j + p_out[3]] = CLAMP (b, 0, 255);
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ }
+}
+
+static void
+fill_gray (GstVideoBoxFill fill_type, guint b_alpha,
+ GstVideoFrame * frame, gboolean sdtv)
+{
+ gint i, j;
+ gint dest_stride;
+ guint8 *dest;
+ gint width, height;
+ GstVideoFormat format;
+
+ format = GST_VIDEO_FRAME_FORMAT (frame);
+
+ width = GST_VIDEO_FRAME_WIDTH (frame);
+ height = GST_VIDEO_FRAME_WIDTH (frame);
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
+
+ if (format == GST_VIDEO_FORMAT_GRAY8) {
+ guint8 val = yuv_sdtv_colors_Y[fill_type];
+
+ for (i = 0; i < height; i++) {
+ memset (dest, val, width);
+ dest += dest_stride;
+ }
+ } else {
+ guint16 val = yuv_sdtv_colors_Y[fill_type] << 8;
+
+ if (format == GST_VIDEO_FORMAT_GRAY16_BE) {
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ GST_WRITE_UINT16_BE (dest + 2 * j, val);
+ }
+ dest += dest_stride;
+ }
+ } else {
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ GST_WRITE_UINT16_LE (dest + 2 * j, val);
+ }
+ dest += dest_stride;
+ }
+ }
+ }
+}
+
+static void
+copy_packed_simple (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ gint i;
+ gint src_stride, dest_stride;
+ gint pixel_stride, row_size;
+ guint8 *src, *dest;
+
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+ pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (dest_frame, 0);
+ row_size = w * pixel_stride;
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest = dest + dest_y * dest_stride + dest_x * pixel_stride;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src = src + src_y * src_stride + src_x * pixel_stride;
+
+ for (i = 0; i < h; i++) {
+ memcpy (dest, src, row_size);
+ dest += dest_stride;
+ src += src_stride;
+ }
+}
+
+static void
+fill_yuy2 (GstVideoBoxFill fill_type, guint b_alpha,
+ GstVideoFrame * frame, gboolean sdtv)
+{
+ guint8 y, u, v;
+ gint i, j;
+ gint stride;
+ gint width, height;
+ guint8 *dest;
+ GstVideoFormat format;
+
+ format = GST_VIDEO_FRAME_FORMAT (frame);
+
+ width = GST_VIDEO_FRAME_WIDTH (frame);
+ height = GST_VIDEO_FRAME_HEIGHT (frame);
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
+
+ y = (sdtv) ? yuv_sdtv_colors_Y[fill_type] : yuv_hdtv_colors_Y[fill_type];
+ u = (sdtv) ? yuv_sdtv_colors_U[fill_type] : yuv_hdtv_colors_U[fill_type];
+ v = (sdtv) ? yuv_sdtv_colors_V[fill_type] : yuv_hdtv_colors_V[fill_type];
+
+ width = width + (width % 2);
+
+ if (format == GST_VIDEO_FORMAT_YUY2) {
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j += 2) {
+ dest[j * 2 + 0] = y;
+ dest[j * 2 + 1] = u;
+ dest[j * 2 + 2] = y;
+ dest[j * 2 + 3] = v;
+ }
+
+ dest += stride;
+ }
+ } else if (format == GST_VIDEO_FORMAT_YVYU) {
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j += 2) {
+ dest[j * 2 + 0] = y;
+ dest[j * 2 + 1] = v;
+ dest[j * 2 + 2] = y;
+ dest[j * 2 + 3] = u;
+ }
+
+ dest += stride;
+ }
+ } else {
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j += 2) {
+ dest[j * 2 + 0] = u;
+ dest[j * 2 + 1] = y;
+ dest[j * 2 + 2] = v;
+ dest[j * 2 + 3] = y;
+ }
+
+ dest += stride;
+ }
+ }
+}
+
+static void
+copy_yuy2_yuy2 (guint i_alpha, GstVideoFrame * dest_frame,
+ gboolean dest_sdtv, gint dest_x, gint dest_y, GstVideoFrame * src_frame,
+ gboolean src_sdtv, gint src_x, gint src_y, gint w, gint h)
+{
+ gint i, j;
+ gint src_stride, dest_stride;
+ guint8 *src, *dest;
+ GstVideoFormat src_format;
+
+ src_format = GST_VIDEO_FRAME_FORMAT (src_frame);
+
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+
+ dest_x = (dest_x & ~1);
+ src_x = (src_x & ~1);
+
+ w = w + (w % 2);
+
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest = dest + dest_y * dest_stride + dest_x * 2;
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src = src + src_y * src_stride + src_x * 2;
+
+ if (src_sdtv != dest_sdtv) {
+ gint y1, u1, v1;
+ gint y2, u2, v2;
+ gint matrix[12];
+
+ memcpy (matrix,
+ dest_sdtv ? cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit :
+ cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit, 12 * sizeof (gint));
+
+ if (src_format == GST_VIDEO_FORMAT_YUY2) {
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 2) {
+ y1 = src[j * 2 + 0];
+ y2 = src[j * 2 + 2];
+ u1 = u2 = src[j * 2 + 1];
+ v1 = v2 = src[j * 2 + 3];
+
+ dest[j * 2 + 0] = APPLY_MATRIX (matrix, 0, y1, u1, v1);
+ dest[j * 2 + 1] = APPLY_MATRIX (matrix, 1, y1, u1, v1);
+ dest[j * 2 + 2] = APPLY_MATRIX (matrix, 0, y1, u2, v2);
+ dest[j * 2 + 3] = APPLY_MATRIX (matrix, 2, y2, u2, v2);
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else if (src_format == GST_VIDEO_FORMAT_YVYU) {
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 2) {
+ y1 = src[j * 2 + 0];
+ y2 = src[j * 2 + 2];
+ v1 = v2 = src[j * 2 + 1];
+ u1 = u2 = src[j * 2 + 3];
+
+ dest[j * 2 + 0] = APPLY_MATRIX (matrix, 0, y1, u1, v1);
+ dest[j * 2 + 1] = APPLY_MATRIX (matrix, 2, y1, u1, v1);
+ dest[j * 2 + 2] = APPLY_MATRIX (matrix, 0, y1, u2, v2);
+ dest[j * 2 + 3] = APPLY_MATRIX (matrix, 1, y2, u2, v2);
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+ } else {
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j += 2) {
+ u1 = u2 = src[j * 2 + 0];
+ v1 = v2 = src[j * 2 + 2];
+ y1 = src[j * 2 + 1];
+ y2 = src[j * 2 + 3];
+
+ dest[j * 2 + 1] = APPLY_MATRIX (matrix, 0, y1, u1, v1);
+ dest[j * 2 + 0] = APPLY_MATRIX (matrix, 1, y1, u1, v1);
+ dest[j * 2 + 3] = APPLY_MATRIX (matrix, 0, y1, u2, v2);
+ dest[j * 2 + 2] = APPLY_MATRIX (matrix, 2, y2, u2, v2);
+ }
+ dest += dest_stride;
+ src += src_stride;
}
+ }
+ } else {
+ for (i = 0; i < h; i++) {
+ memcpy (dest, src, w * 2);
dest += dest_stride;
src += src_stride;
}
};
static GstStaticPadTemplate gst_video_box_src_template =
- GST_STATIC_PAD_TEMPLATE ("src",
+GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";"
- GST_VIDEO_CAPS_YUV ("I420") ";"
- GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_BGRx ";"
- GST_VIDEO_CAPS_xBGR ";" GST_VIDEO_CAPS_RGBx ";"
- GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";"
- GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_RGBA)
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
+ "ARGB, BGRA, ABGR, RGBA, xRGB, BGRx, xBGR, RGBx, RGB, BGR, "
+ "Y444, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B, "
+ "GRAY8, GRAY16_BE, GRAY16_LE } "))
);
static GstStaticPadTemplate gst_video_box_sink_template =
- GST_STATIC_PAD_TEMPLATE ("sink",
+GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";"
- GST_VIDEO_CAPS_YUV ("I420") ";"
- GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_BGRx ";"
- GST_VIDEO_CAPS_xBGR ";" GST_VIDEO_CAPS_RGBx ";"
- GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_BGRA ";"
- GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_RGBA)
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ AYUV, "
+ "ARGB, BGRA, ABGR, RGBA, xRGB, BGRx, xBGR, RGBx, RGB, BGR, "
+ "Y444, Y42B, YUY2, YVYU, UYVY, I420, YV12, Y41B, "
+ "GRAY8, GRAY16_BE, GRAY16_LE } "))
);
-GST_BOILERPLATE (GstVideoBox, gst_video_box, GstBaseTransform,
- GST_TYPE_BASE_TRANSFORM);
+#define gst_video_box_parent_class parent_class
+G_DEFINE_TYPE (GstVideoBox, gst_video_box, GST_TYPE_VIDEO_FILTER);
static void gst_video_box_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
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 * in, GstCaps * out);
-static gboolean gst_video_box_get_unit_size (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);
+ GstPadDirection direction, GstCaps * from, GstCaps * filter);
+static void gst_video_box_before_transform (GstBaseTransform * trans,
+ GstBuffer * in);
+static gboolean gst_video_box_src_event (GstBaseTransform * trans,
+ GstEvent * event);
+
+static gboolean gst_video_box_set_info (GstVideoFilter * vfilter, GstCaps * in,
+ GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info);
+static GstFlowReturn gst_video_box_transform_frame (GstVideoFilter * vfilter,
+ GstVideoFrame * in_frame, GstVideoFrame * out_frame);
#define GST_TYPE_VIDEO_BOX_FILL (gst_video_box_fill_get_type())
static GType
static GType video_box_fill_type = 0;
static const GEnumValue video_box_fill[] = {
{VIDEO_BOX_FILL_BLACK, "Black", "black"},
- {VIDEO_BOX_FILL_GREEN, "Colorkey green", "green"},
- {VIDEO_BOX_FILL_BLUE, "Colorkey blue", "blue"},
+ {VIDEO_BOX_FILL_GREEN, "Green", "green"},
+ {VIDEO_BOX_FILL_BLUE, "Blue", "blue"},
+ {VIDEO_BOX_FILL_RED, "Red", "red"},
+ {VIDEO_BOX_FILL_YELLOW, "Yellow", "yellow"},
+ {VIDEO_BOX_FILL_WHITE, "White", "white"},
{0, NULL, NULL},
};
return video_box_fill_type;
}
-
-static void
-gst_video_box_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details_simple (element_class, "Video box filter",
- "Filter/Effect/Video",
- "Resizes a video by adding borders or cropping",
- "Wim Taymans <wim@fluendo.com>");
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_video_box_sink_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_video_box_src_template));
-}
-
static void
gst_video_box_finalize (GObject * object)
{
GstVideoBox *video_box = GST_VIDEO_BOX (object);
- if (video_box->mutex) {
- g_mutex_free (video_box->mutex);
- video_box->mutex = NULL;
- }
+ g_mutex_clear (&video_box->mutex);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
gst_video_box_class_init (GstVideoBoxClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstElementClass *element_class = (GstElementClass *) (klass);
GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
+ GstVideoFilterClass *vfilter_class = (GstVideoFilterClass *) klass;
gobject_class->set_property = gst_video_box_set_property;
gobject_class->get_property = gst_video_box_get_property;
g_param_spec_boolean ("autocrop", "Auto crop",
"Auto crop", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- trans_class->transform = GST_DEBUG_FUNCPTR (gst_video_box_transform);
+ trans_class->before_transform =
+ GST_DEBUG_FUNCPTR (gst_video_box_before_transform);
trans_class->transform_caps =
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);
+ trans_class->src_event = GST_DEBUG_FUNCPTR (gst_video_box_src_event);
+
+ vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_box_set_info);
+ vfilter_class->transform_frame =
+ GST_DEBUG_FUNCPTR (gst_video_box_transform_frame);
+
+ gst_element_class_set_static_metadata (element_class, "Video box filter",
+ "Filter/Effect/Video",
+ "Resizes a video by adding borders or cropping",
+ "Wim Taymans <wim@fluendo.com>");
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_video_box_sink_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_video_box_src_template));
}
static void
-gst_video_box_init (GstVideoBox * video_box, GstVideoBoxClass * g_class)
+gst_video_box_init (GstVideoBox * video_box)
{
video_box->box_right = DEFAULT_RIGHT;
video_box->box_left = DEFAULT_LEFT;
video_box->border_alpha = DEFAULT_BORDER_ALPHA;
video_box->autocrop = FALSE;
- video_box->mutex = g_mutex_new ();
+ g_mutex_init (&video_box->mutex);
}
static void
{
GstVideoBox *video_box = GST_VIDEO_BOX (object);
- g_mutex_lock (video_box->mutex);
+ g_mutex_lock (&video_box->mutex);
switch (prop_id) {
case PROP_LEFT:
video_box->box_left = g_value_get_int (value);
gst_video_box_recalc_transform (video_box);
GST_DEBUG_OBJECT (video_box, "Calling reconfigure");
- gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (video_box));
+ gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (video_box));
- g_mutex_unlock (video_box->mutex);
+ g_mutex_unlock (&video_box->mutex);
}
static void
}
}
-static GstCaps *
-gst_video_box_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * from)
+static inline gint
+gst_video_box_transform_dimension (gint val, gint delta)
{
- GstVideoBox *video_box = GST_VIDEO_BOX (trans);
- GstCaps *to, *ret;
- const GstCaps *templ;
- const gchar *name;
- GstStructure *structure;
- GstPad *other;
- gint width, height;
+ gint64 new_val = (gint64) val + (gint64) delta;
- to = gst_caps_copy (from);
- structure = gst_caps_get_structure (to, 0);
+ new_val = CLAMP (new_val, 1, G_MAXINT);
- /* For I420/AYUV we support conversion, for all
- * 32bpp RGBs we support conversion and for
- * everything else we only support passthrough
- */
- name = gst_structure_get_name (structure);
- if (g_str_equal (name, "video/x-raw-yuv")) {
- guint32 fourcc;
+ return (gint) new_val;
+}
- if (gst_structure_get_fourcc (structure, "format", &fourcc) &&
- (fourcc == GST_STR_FOURCC ("AYUV") ||
- fourcc == GST_STR_FOURCC ("I420"))) {
- GValue list = { 0, };
- GValue val = { 0, };
+static gboolean
+gst_video_box_transform_dimension_value (const GValue * src_val,
+ gint delta, GValue * dest_val)
+{
+ gboolean ret = TRUE;
- /* get rid of format */
- gst_structure_remove_field (structure, "format");
- gst_structure_remove_field (structure, "color-matrix");
- gst_structure_remove_field (structure, "chroma-site");
+ g_value_init (dest_val, G_VALUE_TYPE (src_val));
- g_value_init (&list, GST_TYPE_LIST);
- g_value_init (&val, GST_TYPE_FOURCC);
- gst_value_set_fourcc (&val, GST_STR_FOURCC ("AYUV"));
- gst_value_list_append_value (&list, &val);
- g_value_reset (&val);
- gst_value_set_fourcc (&val, GST_STR_FOURCC ("I420"));
- gst_value_list_append_value (&list, &val);
- g_value_reset (&val);
- gst_structure_set_value (structure, "format", &list);
- g_value_unset (&list);
+ if (G_VALUE_HOLDS_INT (src_val)) {
+ gint ival = g_value_get_int (src_val);
+
+ ival = gst_video_box_transform_dimension (ival, delta);
+ g_value_set_int (dest_val, ival);
+ } else if (GST_VALUE_HOLDS_INT_RANGE (src_val)) {
+ gint min = gst_value_get_int_range_min (src_val);
+ gint max = gst_value_get_int_range_max (src_val);
+
+ min = gst_video_box_transform_dimension (min, delta);
+ max = gst_video_box_transform_dimension (max, delta);
+ if (min > max) {
+ ret = FALSE;
+ g_value_unset (dest_val);
+ } else {
+ gst_value_set_int_range (dest_val, min, max);
}
- } else if (g_str_equal (name, "video/x-raw-rgb")) {
- gint bpp;
+ } else if (GST_VALUE_HOLDS_LIST (src_val)) {
+ gint i;
- if (gst_structure_get_int (structure, "bpp", &bpp) && bpp == 32) {
- GValue list = { 0, };
- GValue val = { 0, };
+ for (i = 0; i < gst_value_list_get_size (src_val); ++i) {
+ const GValue *list_val;
+ GValue newval = { 0, };
- /* get rid of format */
- gst_structure_remove_field (structure, "depth");
- gst_structure_remove_field (structure, "red_mask");
- gst_structure_remove_field (structure, "green_mask");
- gst_structure_remove_field (structure, "blue_mask");
- gst_structure_remove_field (structure, "alpha_mask");
+ list_val = gst_value_list_get_value (src_val, i);
+ if (gst_video_box_transform_dimension_value (list_val, delta, &newval))
+ gst_value_list_append_value (dest_val, &newval);
+ g_value_unset (&newval);
+ }
- g_value_init (&list, GST_TYPE_LIST);
- g_value_init (&val, G_TYPE_INT);
- g_value_set_int (&val, 32);
- gst_value_list_append_value (&list, &val);
- g_value_reset (&val);
- g_value_set_int (&val, 24);
- gst_value_list_append_value (&list, &val);
- g_value_reset (&val);
- gst_structure_set_value (structure, "depth", &list);
- g_value_unset (&list);
+ if (gst_value_list_get_size (dest_val) == 0) {
+ g_value_unset (dest_val);
+ ret = FALSE;
}
+ } else {
+ g_value_unset (dest_val);
+ ret = FALSE;
}
- /* otherwise caps nego will fail: */
- if (video_box->autocrop) {
- gst_structure_remove_field (structure, "width");
- gst_structure_remove_field (structure, "height");
- } else {
- /* calculate width and height */
- if (gst_structure_get_int (structure, "width", &width)) {
+ return ret;
+}
+
+static GstCaps *
+gst_video_box_transform_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * from, GstCaps * filter)
+{
+ GstVideoBox *video_box = GST_VIDEO_BOX (trans);
+ GstCaps *to, *ret;
+ GstCaps *templ;
+ GstStructure *structure;
+ GstPad *other;
+ gint i, j;
+
+ to = gst_caps_new_empty ();
+ for (i = 0; i < gst_caps_get_size (from); i++) {
+ const GValue *fval, *lval;
+ GValue list = { 0, };
+ GValue val = { 0, };
+ gboolean seen_yuv = FALSE, seen_rgb = FALSE;
+ const gchar *str;
+
+ structure = gst_structure_copy (gst_caps_get_structure (from, i));
+
+ /* Transform width/height */
+ if (video_box->autocrop) {
+ gst_structure_remove_field (structure, "width");
+ gst_structure_remove_field (structure, "height");
+ } else {
+ gint dw = 0, dh = 0;
+ const GValue *v;
+ GValue w_val = { 0, };
+ GValue h_val = { 0, };
+
+ /* calculate width and height */
if (direction == GST_PAD_SINK) {
- width -= video_box->box_left;
- width -= video_box->box_right;
+ dw -= video_box->box_left;
+ dw -= video_box->box_right;
} else {
- width += video_box->box_left;
- width += video_box->box_right;
+ dw += video_box->box_left;
+ dw += video_box->box_right;
}
- if (width <= 0)
- width = 1;
-
- GST_DEBUG_OBJECT (trans, "New caps width: %d", width);
- gst_structure_set (structure, "width", G_TYPE_INT, width, NULL);
- }
- if (gst_structure_get_int (structure, "height", &height)) {
if (direction == GST_PAD_SINK) {
- height -= video_box->box_top;
- height -= video_box->box_bottom;
+ dh -= video_box->box_top;
+ dh -= video_box->box_bottom;
} else {
- height += video_box->box_top;
- height += video_box->box_bottom;
+ dh += video_box->box_top;
+ dh += video_box->box_bottom;
+ }
+
+ v = gst_structure_get_value (structure, "width");
+ if (!gst_video_box_transform_dimension_value (v, dw, &w_val)) {
+ GST_WARNING_OBJECT (video_box,
+ "could not tranform width value with dw=%d" ", caps structure=%"
+ GST_PTR_FORMAT, dw, structure);
+ goto bail;
+ }
+ gst_structure_set_value (structure, "width", &w_val);
+
+ v = gst_structure_get_value (structure, "height");
+ if (!gst_video_box_transform_dimension_value (v, dh, &h_val)) {
+ g_value_unset (&w_val);
+ GST_WARNING_OBJECT (video_box,
+ "could not tranform height value with dh=%d" ", caps structure=%"
+ GST_PTR_FORMAT, dh, structure);
+ goto bail;
+ }
+ gst_structure_set_value (structure, "height", &h_val);
+ g_value_unset (&w_val);
+ g_value_unset (&h_val);
+ }
+
+ /* Supported conversions:
+ * I420->AYUV
+ * I420->YV12
+ * YV12->AYUV
+ * YV12->I420
+ * AYUV->I420
+ * AYUV->YV12
+ * AYUV->xRGB (24bpp, 32bpp, incl. alpha)
+ * xRGB->xRGB (24bpp, 32bpp, from/to all variants, incl. alpha)
+ * xRGB->AYUV (24bpp, 32bpp, incl. alpha)
+ *
+ * Passthrough only for everything else.
+ */
+ fval = gst_structure_get_value (structure, "format");
+ if (fval && GST_VALUE_HOLDS_LIST (fval)) {
+ for (j = 0; j < gst_value_list_get_size (fval); j++) {
+ lval = gst_value_list_get_value (fval, j);
+ if ((str = g_value_get_string (lval))) {
+ if (strstr (str, "RGB") || strstr (str, "BGR") ||
+ strcmp (str, "AYUV") == 0)
+ seen_rgb = TRUE;
+ else if (strcmp (str, "I420") == 0 || strcmp (str, "YV12") == 0 ||
+ strcmp (str, "AYUV") == 0)
+ seen_yuv = TRUE;
+ }
}
+ } else if (fval && G_VALUE_HOLDS_STRING (fval)) {
+ if ((str = g_value_get_string (fval))) {
+ if (strstr (str, "RGB") || strstr (str, "BGR") ||
+ strcmp (str, "AYUV") == 0)
+ seen_rgb = TRUE;
+ else if (strcmp (str, "I420") == 0 || strcmp (str, "YV12") == 0 ||
+ strcmp (str, "AYUV") == 0)
+ seen_yuv = TRUE;
+ }
+ }
- if (height <= 0)
- height = 1;
+ if (seen_yuv || seen_rgb) {
+ g_value_init (&list, GST_TYPE_LIST);
- GST_DEBUG_OBJECT (trans, "New caps height: %d", height);
- gst_structure_set (structure, "height", G_TYPE_INT, height, NULL);
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, "AYUV");
+ gst_value_list_append_value (&list, &val);
+ g_value_unset (&val);
+
+ if (seen_yuv) {
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, "I420");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "YV12");
+ gst_value_list_append_value (&list, &val);
+ g_value_unset (&val);
+ }
+ if (seen_rgb) {
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, "RGBx");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "BGRx");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "xRGB");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "xBGR");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "RGBA");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "BGRA");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "ARGB");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "ABGR");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "RGB");
+ gst_value_list_append_value (&list, &val);
+ g_value_reset (&val);
+ g_value_set_string (&val, "BGR");
+ gst_value_list_append_value (&list, &val);
+ g_value_unset (&val);
+ }
+ gst_value_list_merge (&val, fval, &list);
+ gst_structure_set_value (structure, "format", &val);
+ g_value_unset (&val);
+ g_value_unset (&list);
}
+
+ gst_structure_remove_field (structure, "colorimetry");
+ gst_structure_remove_field (structure, "chroma-site");
+
+ gst_caps_append_structure (to, structure);
}
/* filter against set allowed caps on the pad */
other = (direction == GST_PAD_SINK) ? trans->srcpad : trans->sinkpad;
-
templ = gst_pad_get_pad_template_caps (other);
ret = gst_caps_intersect (to, templ);
gst_caps_unref (to);
+ gst_caps_unref (templ);
GST_DEBUG_OBJECT (video_box, "direction %d, transformed %" GST_PTR_FORMAT
" to %" GST_PTR_FORMAT, direction, from, ret);
+ if (ret && filter) {
+ GstCaps *intersection;
+
+ GST_DEBUG_OBJECT (video_box, "Using filter caps %" GST_PTR_FORMAT, filter);
+ intersection =
+ gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (ret);
+ ret = intersection;
+ GST_DEBUG_OBJECT (video_box, "Intersection %" GST_PTR_FORMAT, ret);
+ }
+
return ret;
+
+ /* ERRORS */
+bail:
+ {
+ gst_structure_free (structure);
+ gst_caps_unref (to);
+ to = gst_caps_new_empty ();
+ return to;
+ }
}
static gboolean
video_box->copy = copy_ayuv_ayuv;
break;
case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
video_box->copy = copy_i420_ayuv;
break;
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_xRGB:
+ case GST_VIDEO_FORMAT_xBGR:
+ case GST_VIDEO_FORMAT_RGBx:
+ case GST_VIDEO_FORMAT_BGRx:
+ case GST_VIDEO_FORMAT_RGB:
+ case GST_VIDEO_FORMAT_BGR:
+ video_box->copy = copy_rgb32_ayuv;
+ break;
default:
break;
}
break;
case GST_VIDEO_FORMAT_I420:
- video_box->fill = fill_i420;
+ case GST_VIDEO_FORMAT_YV12:
+ video_box->fill = fill_planar_yuv;
switch (video_box->in_format) {
case GST_VIDEO_FORMAT_AYUV:
video_box->copy = copy_ayuv_i420;
break;
case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
video_box->copy = copy_i420_i420;
break;
default:
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_BGRx:
- video_box->fill = fill_rgb32;
+ case GST_VIDEO_FORMAT_RGB:
+ case GST_VIDEO_FORMAT_BGR:
+ video_box->fill = (video_box->out_format == GST_VIDEO_FORMAT_BGR
+ || video_box->out_format ==
+ GST_VIDEO_FORMAT_RGB) ? fill_rgb24 : fill_rgb32;
switch (video_box->in_format) {
case GST_VIDEO_FORMAT_ARGB:
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_BGRx:
+ case GST_VIDEO_FORMAT_RGB:
+ case GST_VIDEO_FORMAT_BGR:
video_box->copy = copy_rgb32;
+ break;
+ case GST_VIDEO_FORMAT_AYUV:
+ video_box->copy = copy_ayuv_rgb32;
+ default:
+ break;
+ }
+ break;
+ case GST_VIDEO_FORMAT_GRAY8:
+ case GST_VIDEO_FORMAT_GRAY16_BE:
+ case GST_VIDEO_FORMAT_GRAY16_LE:
+ video_box->fill = fill_gray;
+ switch (video_box->in_format) {
+ case GST_VIDEO_FORMAT_GRAY8:
+ case GST_VIDEO_FORMAT_GRAY16_BE:
+ case GST_VIDEO_FORMAT_GRAY16_LE:
+ video_box->copy = copy_packed_simple;
+ break;
+ default:
+ break;
+ }
+ break;
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_YVYU:
+ case GST_VIDEO_FORMAT_UYVY:
+ video_box->fill = fill_yuy2;
+ switch (video_box->in_format) {
+ case GST_VIDEO_FORMAT_YUY2:
+ case GST_VIDEO_FORMAT_YVYU:
+ case GST_VIDEO_FORMAT_UYVY:
+ video_box->copy = copy_yuy2_yuy2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case GST_VIDEO_FORMAT_Y444:
+ case GST_VIDEO_FORMAT_Y42B:
+ case GST_VIDEO_FORMAT_Y41B:
+ video_box->fill = fill_planar_yuv;
+ switch (video_box->in_format) {
+ case GST_VIDEO_FORMAT_Y444:
+ video_box->copy = copy_y444_y444;
+ break;
+ case GST_VIDEO_FORMAT_Y42B:
+ video_box->copy = copy_y42b_y42b;
+ break;
+ case GST_VIDEO_FORMAT_Y41B:
+ video_box->copy = copy_y41b_y41b;
+ break;
default:
break;
}
}
static gboolean
-gst_video_box_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
+gst_video_box_set_info (GstVideoFilter * vfilter, GstCaps * in,
+ GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info)
{
- GstVideoBox *video_box = GST_VIDEO_BOX (trans);
+ GstVideoBox *video_box = GST_VIDEO_BOX (vfilter);
gboolean ret;
- const gchar *matrix;
- g_mutex_lock (video_box->mutex);
+ g_mutex_lock (&video_box->mutex);
- ret =
- gst_video_format_parse_caps (in, &video_box->in_format,
- &video_box->in_width, &video_box->in_height);
- ret &=
- gst_video_format_parse_caps (out, &video_box->out_format,
- &video_box->out_width, &video_box->out_height);
+ video_box->in_format = GST_VIDEO_INFO_FORMAT (in_info);
+ video_box->in_width = GST_VIDEO_INFO_WIDTH (in_info);
+ video_box->in_height = GST_VIDEO_INFO_HEIGHT (in_info);
- 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;
+ video_box->out_format = GST_VIDEO_INFO_FORMAT (in_info);
+ video_box->out_width = GST_VIDEO_INFO_WIDTH (in_info);
+ video_box->out_height = GST_VIDEO_INFO_HEIGHT (in_info);
- /* something wrong getting the caps */
- if (!ret)
- goto no_caps;
+ video_box->in_sdtv =
+ in_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
+ video_box->out_sdtv =
+ out_info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_BT601;
- GST_DEBUG_OBJECT (trans, "Input w: %d h: %d", video_box->in_width,
+ GST_DEBUG_OBJECT (video_box, "Input w: %d h: %d", video_box->in_width,
video_box->in_height);
- GST_DEBUG_OBJECT (trans, "Output w: %d h: %d", video_box->out_width,
+ GST_DEBUG_OBJECT (video_box, "Output w: %d h: %d", video_box->out_width,
video_box->out_height);
if (video_box->autocrop)
if (ret)
ret = gst_video_box_select_processing_functions (video_box);
- g_mutex_unlock (video_box->mutex);
+ g_mutex_unlock (&video_box->mutex);
return ret;
-
- /* ERRORS */
-no_caps:
- {
- GST_DEBUG_OBJECT (video_box,
- "Invalid caps: %" GST_PTR_FORMAT " -> %" GST_PTR_FORMAT, in, out);
- g_mutex_unlock (video_box->mutex);
- return FALSE;
- }
}
static gboolean
-gst_video_box_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
- guint * size)
+gst_video_box_src_event (GstBaseTransform * trans, GstEvent * event)
{
GstVideoBox *video_box = GST_VIDEO_BOX (trans);
- GstVideoFormat format;
- gint width, height;
- gboolean ret;
-
- g_assert (size);
-
- ret = gst_video_format_parse_caps (caps, &format, &width, &height);
- if (!ret) {
- GST_ERROR_OBJECT (video_box, "Invalid caps: %" GST_PTR_FORMAT, caps);
- return FALSE;
+ GstStructure *new_structure;
+ const GstStructure *structure;
+ const gchar *event_name;
+ gdouble pointer_x;
+ gdouble pointer_y;
+
+ GST_OBJECT_LOCK (video_box);
+ if (GST_EVENT_TYPE (event) == GST_EVENT_NAVIGATION &&
+ (video_box->box_left != 0 || video_box->box_top != 0)) {
+ structure = gst_event_get_structure (event);
+ event_name = gst_structure_get_string (structure, "event");
+
+ if (event_name &&
+ (strcmp (event_name, "mouse-move") == 0 ||
+ strcmp (event_name, "mouse-button-press") == 0 ||
+ strcmp (event_name, "mouse-button-release") == 0)) {
+ if (gst_structure_get_double (structure, "pointer_x", &pointer_x) &&
+ gst_structure_get_double (structure, "pointer_y", &pointer_y)) {
+ gdouble new_pointer_x, new_pointer_y;
+ GstEvent *new_event;
+
+ new_pointer_x = pointer_x + video_box->box_left;
+ new_pointer_y = pointer_y + video_box->box_top;
+
+ new_structure = gst_structure_copy (structure);
+ gst_structure_set (new_structure,
+ "pointer_x", G_TYPE_DOUBLE, (gdouble) (new_pointer_x),
+ "pointer_y", G_TYPE_DOUBLE, (gdouble) (new_pointer_y), NULL);
+
+ new_event = gst_event_new_navigation (new_structure);
+ gst_event_unref (event);
+ event = new_event;
+ } else {
+ GST_WARNING_OBJECT (video_box, "Failed to read navigation event");
+ }
+ }
}
+ GST_OBJECT_UNLOCK (video_box);
- *size = gst_video_format_get_size (format, width, height);
-
- GST_LOG_OBJECT (video_box, "Returning from _unit_size %d", *size);
-
- return TRUE;
-}
-
-static void
-gst_video_box_fixate_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
-{
- gint width, height;
- GstStructure *s;
- gboolean ret;
-
- ret = gst_video_format_parse_caps (caps, NULL, &width, &height);
- if (!ret)
- return;
-
- 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);
+ return GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event);
}
static void
-gst_video_box_process (GstVideoBox * video_box, const guint8 * src,
- guint8 * dest)
+gst_video_box_process (GstVideoBox * video_box, GstVideoFrame * in,
+ GstVideoFrame * out)
{
- guint b_alpha = CLAMP ((guint) video_box->border_alpha * 256, 0, 256);
- guint i_alpha = CLAMP ((guint) video_box->alpha * 256, 0, 256);
+ guint b_alpha = CLAMP (video_box->border_alpha * 256, 0, 255);
+ guint i_alpha = CLAMP (video_box->alpha * 256, 0, 255);
GstVideoBoxFill fill_type = video_box->fill_type;
gint br, bl, bt, bb, crop_w, crop_h;
i_alpha, b_alpha);
if (crop_h < 0 || crop_w < 0) {
- video_box->fill (fill_type, b_alpha, video_box->out_format, dest,
- video_box->out_sdtv, video_box->out_width, video_box->out_height);
+ video_box->fill (fill_type, b_alpha, out, video_box->out_sdtv);
} else if (bb == 0 && bt == 0 && br == 0 && bl == 0) {
- video_box->copy (i_alpha, video_box->out_format, dest, video_box->out_sdtv,
- video_box->out_width, video_box->out_height, 0, 0, video_box->in_format,
- src, video_box->in_sdtv, video_box->in_width, video_box->in_height, 0,
- 0, crop_w, crop_h);
+ video_box->copy (i_alpha, out, video_box->out_sdtv, 0, 0, in,
+ video_box->in_sdtv, 0, 0, crop_w, crop_h);
} else {
gint src_x = 0, src_y = 0;
gint dest_x = 0, dest_y = 0;
/* Fill everything if a border should be added somewhere */
if (bt < 0 || bb < 0 || br < 0 || bl < 0)
- video_box->fill (fill_type, b_alpha, video_box->out_format, dest,
- video_box->out_sdtv, video_box->out_width, video_box->out_height);
+ video_box->fill (fill_type, b_alpha, out, video_box->out_sdtv);
/* Top border */
if (bt < 0) {
}
/* Frame */
- video_box->copy (i_alpha, video_box->out_format, dest, video_box->out_sdtv,
- video_box->out_width, video_box->out_height, dest_x, dest_y,
- video_box->in_format, src, video_box->in_sdtv, video_box->in_width,
- video_box->in_height, src_x, src_y, crop_w, crop_h);
+ video_box->copy (i_alpha, out, video_box->out_sdtv, dest_x, dest_y,
+ in, video_box->in_sdtv, src_x, src_y, crop_w, crop_h);
}
GST_LOG_OBJECT (video_box, "image created");
}
-static GstFlowReturn
-gst_video_box_transform (GstBaseTransform * trans, GstBuffer * in,
- GstBuffer * out)
+static void
+gst_video_box_before_transform (GstBaseTransform * trans, GstBuffer * in)
{
GstVideoBox *video_box = GST_VIDEO_BOX (trans);
- const guint8 *indata;
- guint8 *outdata;
GstClockTime timestamp, stream_time;
timestamp = GST_BUFFER_TIMESTAMP (in);
GST_TIME_ARGS (timestamp));
if (GST_CLOCK_TIME_IS_VALID (stream_time))
- gst_object_sync_values (G_OBJECT (video_box), stream_time);
+ gst_object_sync_values (GST_OBJECT (video_box), stream_time);
+}
- indata = GST_BUFFER_DATA (in);
- outdata = GST_BUFFER_DATA (out);
+static GstFlowReturn
+gst_video_box_transform_frame (GstVideoFilter * vfilter,
+ GstVideoFrame * in_frame, GstVideoFrame * out_frame)
+{
+ GstVideoBox *video_box = GST_VIDEO_BOX (vfilter);
- g_mutex_lock (video_box->mutex);
- gst_video_box_process (video_box, indata, outdata);
- g_mutex_unlock (video_box->mutex);
+ g_mutex_lock (&video_box->mutex);
+ gst_video_box_process (video_box, in_frame, out_frame);
+ g_mutex_unlock (&video_box->mutex);
return GST_FLOW_OK;
}
static gboolean
plugin_init (GstPlugin * plugin)
{
- oil_init ();
-
- gst_controller_init (NULL, NULL);
-
GST_DEBUG_CATEGORY_INIT (videobox_debug, "videobox", 0,
"Resizes a video by adding borders or cropping");
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
- "videobox",
+ videobox,
"resizes a video by adding borders or cropping",
plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)