#define M_PI 3.14159265358979323846
#endif
+/* Generated by -bad/ext/cog/generate_tables */
+static const int cog_ycbcr_to_rgb_matrix_8bit_hdtv[] = {
+ 298, 0, 459, -63514,
+ 298, -55, -136, 19681,
+ 298, 541, 0, -73988,
+};
+
+static const int cog_ycbcr_to_rgb_matrix_8bit_sdtv[] = {
+ 298, 0, 409, -57068,
+ 298, -100, -208, 34707,
+ 298, 516, 0, -70870,
+};
+
+static const gint cog_rgb_to_ycbcr_matrix_8bit_hdtv[] = {
+ 47, 157, 16, 4096,
+ -26, -87, 112, 32768,
+ 112, -102, -10, 32768,
+};
+
+static const gint cog_rgb_to_ycbcr_matrix_8bit_sdtv[] = {
+ 66, 129, 25, 4096,
+ -38, -74, 112, 32768,
+ 112, -94, -18, 32768,
+};
+
+static const gint cog_ycbcr_sdtv_to_ycbcr_hdtv_matrix_8bit[] = {
+ 256, -30, -53, 10600,
+ 0, 261, 29, -4367,
+ 0, 19, 262, -3289,
+};
+
+static const gint cog_ycbcr_hdtv_to_ycbcr_sdtv_matrix_8bit[] = {
+ 256, 25, 49, -9536,
+ 0, 253, -28, 3958,
+ 0, -19, 252, 2918,
+};
+
/* Alpha signals and args */
enum
{
GstBuffer * in, GstBuffer * out);
static void gst_alpha_init_params (GstAlpha * alpha);
+static gboolean gst_alpha_set_process_function (GstAlpha * alpha);
static void gst_alpha_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
default:
break;
}
+ gst_alpha_set_process_function (alpha);
gst_alpha_init_params (alpha);
break;
case PROP_ALPHA:
GstStructure *structure;
gint i;
- ret = gst_caps_copy (caps);
+ ret = gst_caps_new_empty ();
/* When going from the SINK pad to the src, we just need to make sure the
* format is AYUV */
if (direction == GST_PAD_SINK) {
- for (i = 0; i < gst_caps_get_size (ret); i++) {
- structure = gst_caps_get_structure (ret, i);
+ for (i = 0; i < gst_caps_get_size (caps); i++) {
+ structure = gst_structure_copy (gst_caps_get_structure (caps, i));
gst_structure_set (structure, "format",
GST_TYPE_FOURCC, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), NULL);
+ gst_structure_remove_field (structure, "chroma-site");
+ gst_structure_remove_field (structure, "color-matrix");
+ gst_caps_append_structure (ret, structure);
}
} else {
- GstCaps *ayuv_caps;
-
/* In the other direction, prepend a copy of the caps with format AYUV,
* and set the first to I420 */
- ayuv_caps = gst_caps_copy (ret);
- for (i = 0; i < gst_caps_get_size (ret); i++) {
- structure = gst_caps_get_structure (ret, i);
+ for (i = 0; i < gst_caps_get_size (caps); i++) {
+ structure = gst_structure_copy (gst_caps_get_structure (caps, i));
+ gst_structure_remove_field (structure, "color-matrix");
+
gst_structure_set (structure, "format",
GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL);
- }
+ gst_caps_append_structure (ret, gst_structure_copy (structure));
- gst_caps_append (ret, ayuv_caps);
+ gst_structure_set (structure, "format",
+ GST_TYPE_FOURCC, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), NULL);
+ gst_structure_remove_field (structure, "chroma-site");
+ gst_caps_append_structure (ret, structure);
+ }
}
gst_caps_do_simplify (ret);
GstCaps * incaps, GstCaps * outcaps)
{
GstAlpha *alpha = GST_ALPHA (btrans);
+ const gchar *matrix;
+
+ GST_OBJECT_LOCK (alpha);
- if (!gst_video_format_parse_caps (incaps, &alpha->format,
- &alpha->width, &alpha->height))
+ if (!gst_video_format_parse_caps (incaps, &alpha->in_format,
+ &alpha->width, &alpha->height) ||
+ !gst_video_format_parse_caps (incaps, &alpha->out_format,
+ &alpha->width, &alpha->height)) {
+ GST_OBJECT_UNLOCK (alpha);
return FALSE;
+ }
+
+ if (!gst_alpha_set_process_function (alpha)) {
+ GST_OBJECT_UNLOCK (alpha);
+ return FALSE;
+ }
+
+ matrix = gst_video_parse_caps_color_matrix (incaps);
+ alpha->in_sdtv = matrix ? g_str_equal (matrix, "sdtv") : TRUE;
+
+ matrix = gst_video_parse_caps_color_matrix (outcaps);
+ alpha->out_sdtv = matrix ? g_str_equal (matrix, "sdtv") : TRUE;
+
+ gst_alpha_init_params (alpha);
+ GST_OBJECT_UNLOCK (alpha);
return TRUE;
}
static void
-gst_alpha_set_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
- gdouble alpha)
+gst_alpha_set_ayuv (const guint8 * src, guint8 * dest, gint width, gint height,
+ GstAlpha * alpha)
{
- gint s_alpha = CLAMP ((gint) (alpha * 256), 0, 256);
+ gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
gint y, x;
for (y = 0; y < height; y++) {
}
static void
-gst_alpha_set_i420 (guint8 * src, guint8 * dest, gint width, gint height,
- gdouble alpha)
+gst_alpha_set_i420 (const guint8 * src, guint8 * dest, gint width, gint height,
+ GstAlpha * alpha)
{
- gint b_alpha = CLAMP ((gint) (alpha * 255), 0, 255);
- guint8 *srcY;
- guint8 *srcU;
- guint8 *srcV;
+ gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
+ const guint8 *srcY;
+ const guint8 *srcU;
+ const guint8 *srcV;
gint i, j;
gint src_wrap, src_uv_wrap;
gint y_stride, uv_stride;
}
static void
-gst_alpha_chroma_key_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
- GstAlpha * alpha)
+gst_alpha_chroma_key_ayuv (const guint8 * src, guint8 * dest, gint width,
+ gint height, GstAlpha * alpha)
{
- guint8 *src1;
+ const guint8 *src1;
guint8 *dest1;
gint i, j;
gint a, y, u, v;
static inline void
gst_alpha_chromakey_row_i420 (GstAlpha * alpha, guint8 * dest1, guint8 * dest2,
- guint8 * srcY1, guint8 * srcY2, guint8 * srcU, guint8 * srcV, gint width)
+ const guint8 * srcY1, const guint8 * srcY2, const guint8 * srcU,
+ const guint8 * srcV, gint width)
{
gint xpos;
gint a, a2, y[4], u, v;
}
static void
-gst_alpha_chroma_key_i420 (guint8 * src, guint8 * dest, gint width, gint height,
- GstAlpha * alpha)
+gst_alpha_chroma_key_i420 (const guint8 * src, guint8 * dest, gint width,
+ gint height, GstAlpha * alpha)
{
- guint8 *srcY1, *srcY2, *srcU, *srcV;
+ const guint8 *srcY1, *srcY2, *srcU, *srcV;
guint8 *dest1, *dest2;
gint ypos;
gint dest_stride, src_y_stride, src_uv_stride;
float kgl;
float tmp;
float tmp1, tmp2;
+ const gint *matrix;
+
+ matrix =
+ (alpha->out_sdtv) ? cog_rgb_to_ycbcr_matrix_8bit_sdtv :
+ cog_rgb_to_ycbcr_matrix_8bit_hdtv;
alpha->y =
- 0.257 * alpha->target_r + 0.504 * alpha->target_g +
- 0.098 * alpha->target_b;
+ (matrix[0] * ((gint) alpha->target_r) +
+ matrix[1] * ((gint) alpha->target_g) +
+ matrix[2] * ((gint) alpha->target_b) + matrix[3]) >> 8;
+ /* Cb,Cr without offset here because the chroma keying
+ * works with them being in range [-128,127]
+ */
tmp1 =
- -0.148 * alpha->target_r - 0.291 * alpha->target_g +
- 0.439 * alpha->target_b;
+ (matrix[4] * ((gint) alpha->target_r) +
+ matrix[5] * ((gint) alpha->target_g) +
+ matrix[6] * ((gint) alpha->target_b)) >> 8;
tmp2 =
- 0.439 * alpha->target_r - 0.368 * alpha->target_g -
- 0.071 * alpha->target_b;
+ (matrix[8] * ((gint) alpha->target_r) +
+ matrix[9] * ((gint) alpha->target_g) +
+ matrix[10] * ((gint) alpha->target_b)) >> 8;
+
kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
alpha->cb = 127 * (tmp1 / kgl);
alpha->cr = 127 * (tmp2 / kgl);
alpha->noise_level2 = alpha->noise_level * alpha->noise_level;
}
+static gboolean
+gst_alpha_set_process_function (GstAlpha * alpha)
+{
+ alpha->process = NULL;
+ switch (alpha->method) {
+ case ALPHA_METHOD_SET:
+ switch (alpha->out_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ switch (alpha->in_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ alpha->process = gst_alpha_set_ayuv;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ alpha->process = gst_alpha_set_i420;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ case ALPHA_METHOD_GREEN:
+ case ALPHA_METHOD_BLUE:
+ case ALPHA_METHOD_CUSTOM:
+ switch (alpha->out_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ switch (alpha->in_format) {
+ case GST_VIDEO_FORMAT_AYUV:
+ alpha->process = gst_alpha_chroma_key_ayuv;
+ break;
+ case GST_VIDEO_FORMAT_I420:
+ alpha->process = gst_alpha_chroma_key_i420;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return alpha->process != NULL;
+}
+
static gboolean
gst_alpha_start (GstBaseTransform * btrans)
{
gst_object_sync_values (G_OBJECT (alpha), timestamp);
GST_OBJECT_LOCK (alpha);
- switch (alpha->method) {
- case ALPHA_METHOD_SET:
- if (alpha->format == GST_VIDEO_FORMAT_AYUV) {
- gst_alpha_set_ayuv (GST_BUFFER_DATA (in),
- GST_BUFFER_DATA (out), width, height, alpha->alpha);
- } else {
- gst_alpha_set_i420 (GST_BUFFER_DATA (in),
- GST_BUFFER_DATA (out), width, height, alpha->alpha);
- }
- break;
- case ALPHA_METHOD_GREEN:
- case ALPHA_METHOD_BLUE:
- case ALPHA_METHOD_CUSTOM:
- if (alpha->format == GST_VIDEO_FORMAT_AYUV) {
- gst_alpha_chroma_key_ayuv (GST_BUFFER_DATA (in),
- GST_BUFFER_DATA (out), width, height, alpha);
- } else {
- gst_alpha_chroma_key_i420 (GST_BUFFER_DATA (in),
- GST_BUFFER_DATA (out), width, height, alpha);
- }
- break;
- default:
- break;
+ if (G_UNLIKELY (!alpha->process)) {
+ GST_ERROR_OBJECT (alpha, "Not negotiated yet");
+ GST_OBJECT_UNLOCK (alpha);
+ return GST_FLOW_NOT_NEGOTIATED;
}
+
+ alpha->process (GST_BUFFER_DATA (in),
+ GST_BUFFER_DATA (out), width, height, alpha);
GST_OBJECT_UNLOCK (alpha);
return GST_FLOW_OK;