mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 18:05:37 +00:00
alpha: Some preparations for supporting more color formats
This commit is contained in:
parent
b019a78ab8
commit
6b0c535e8d
2 changed files with 171 additions and 58 deletions
|
@ -34,6 +34,43 @@
|
|||
#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
|
||||
{
|
||||
|
@ -92,6 +129,7 @@ static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans,
|
|||
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);
|
||||
|
@ -235,6 +273,7 @@ gst_alpha_set_property (GObject * object, guint prop_id,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
gst_alpha_set_process_function (alpha);
|
||||
gst_alpha_init_params (alpha);
|
||||
break;
|
||||
case PROP_ALPHA:
|
||||
|
@ -339,30 +378,36 @@ gst_alpha_transform_caps (GstBaseTransform * btrans,
|
|||
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);
|
||||
|
@ -375,19 +420,40 @@ gst_alpha_set_caps (GstBaseTransform * btrans,
|
|||
GstCaps * incaps, GstCaps * outcaps)
|
||||
{
|
||||
GstAlpha *alpha = GST_ALPHA (btrans);
|
||||
const gchar *matrix;
|
||||
|
||||
if (!gst_video_format_parse_caps (incaps, &alpha->format,
|
||||
&alpha->width, &alpha->height))
|
||||
GST_OBJECT_LOCK (alpha);
|
||||
|
||||
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++) {
|
||||
|
@ -401,13 +467,13 @@ gst_alpha_set_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -537,10 +603,10 @@ chroma_keying_yuv (gint a, gint * y, guint ny, gint * u,
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -578,7 +644,8 @@ gst_alpha_chroma_key_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
|
|||
|
||||
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;
|
||||
|
@ -624,10 +691,10 @@ gst_alpha_chromakey_row_i420 (GstAlpha * alpha, guint8 * dest1, guint8 * dest2,
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -673,16 +740,28 @@ gst_alpha_init_params (GstAlpha * alpha)
|
|||
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);
|
||||
|
@ -705,6 +784,53 @@ gst_alpha_init_params (GstAlpha * alpha)
|
|||
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)
|
||||
{
|
||||
|
@ -734,30 +860,14 @@ gst_alpha_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
|
|||
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;
|
||||
|
|
|
@ -61,8 +61,9 @@ struct _GstAlpha
|
|||
GstVideoFilter parent;
|
||||
|
||||
/* caps */
|
||||
GstVideoFormat format;
|
||||
GstVideoFormat in_format, out_format;
|
||||
gint width, height;
|
||||
gboolean in_sdtv, out_sdtv;
|
||||
|
||||
gdouble alpha;
|
||||
|
||||
|
@ -87,6 +88,8 @@ struct _GstAlpha
|
|||
guint8 accept_angle_ctg;
|
||||
guint8 one_over_kc;
|
||||
guint8 kfgy_scale;
|
||||
|
||||
void (*process) (const guint8 *src, guint8 *dest, gint width, gint height, GstAlpha *alpha);
|
||||
};
|
||||
|
||||
struct _GstAlphaClass
|
||||
|
|
Loading…
Reference in a new issue