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
|
#define M_PI 3.14159265358979323846
|
||||||
#endif
|
#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 */
|
/* Alpha signals and args */
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -92,6 +129,7 @@ static GstFlowReturn gst_alpha_transform (GstBaseTransform * btrans,
|
||||||
GstBuffer * in, GstBuffer * out);
|
GstBuffer * in, GstBuffer * out);
|
||||||
|
|
||||||
static void gst_alpha_init_params (GstAlpha * alpha);
|
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,
|
static void gst_alpha_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -235,6 +273,7 @@ gst_alpha_set_property (GObject * object, guint prop_id,
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gst_alpha_set_process_function (alpha);
|
||||||
gst_alpha_init_params (alpha);
|
gst_alpha_init_params (alpha);
|
||||||
break;
|
break;
|
||||||
case PROP_ALPHA:
|
case PROP_ALPHA:
|
||||||
|
@ -339,30 +378,36 @@ gst_alpha_transform_caps (GstBaseTransform * btrans,
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
gint i;
|
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
|
/* When going from the SINK pad to the src, we just need to make sure the
|
||||||
* format is AYUV */
|
* format is AYUV */
|
||||||
if (direction == GST_PAD_SINK) {
|
if (direction == GST_PAD_SINK) {
|
||||||
for (i = 0; i < gst_caps_get_size (ret); i++) {
|
for (i = 0; i < gst_caps_get_size (caps); i++) {
|
||||||
structure = gst_caps_get_structure (ret, i);
|
structure = gst_structure_copy (gst_caps_get_structure (caps, i));
|
||||||
gst_structure_set (structure, "format",
|
gst_structure_set (structure, "format",
|
||||||
GST_TYPE_FOURCC, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), NULL);
|
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 {
|
} else {
|
||||||
GstCaps *ayuv_caps;
|
|
||||||
|
|
||||||
/* In the other direction, prepend a copy of the caps with format AYUV,
|
/* In the other direction, prepend a copy of the caps with format AYUV,
|
||||||
* and set the first to I420 */
|
* and set the first to I420 */
|
||||||
ayuv_caps = gst_caps_copy (ret);
|
|
||||||
|
|
||||||
for (i = 0; i < gst_caps_get_size (ret); i++) {
|
for (i = 0; i < gst_caps_get_size (caps); i++) {
|
||||||
structure = gst_caps_get_structure (ret, i);
|
structure = gst_structure_copy (gst_caps_get_structure (caps, i));
|
||||||
|
gst_structure_remove_field (structure, "color-matrix");
|
||||||
|
|
||||||
gst_structure_set (structure, "format",
|
gst_structure_set (structure, "format",
|
||||||
GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL);
|
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);
|
gst_caps_do_simplify (ret);
|
||||||
|
@ -375,19 +420,40 @@ gst_alpha_set_caps (GstBaseTransform * btrans,
|
||||||
GstCaps * incaps, GstCaps * outcaps)
|
GstCaps * incaps, GstCaps * outcaps)
|
||||||
{
|
{
|
||||||
GstAlpha *alpha = GST_ALPHA (btrans);
|
GstAlpha *alpha = GST_ALPHA (btrans);
|
||||||
|
const gchar *matrix;
|
||||||
|
|
||||||
if (!gst_video_format_parse_caps (incaps, &alpha->format,
|
GST_OBJECT_LOCK (alpha);
|
||||||
&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;
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alpha_set_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
|
gst_alpha_set_ayuv (const guint8 * src, guint8 * dest, gint width, gint height,
|
||||||
gdouble alpha)
|
GstAlpha * alpha)
|
||||||
{
|
{
|
||||||
gint s_alpha = CLAMP ((gint) (alpha * 256), 0, 256);
|
gint s_alpha = CLAMP ((gint) (alpha->alpha * 256), 0, 256);
|
||||||
gint y, x;
|
gint y, x;
|
||||||
|
|
||||||
for (y = 0; y < height; y++) {
|
for (y = 0; y < height; y++) {
|
||||||
|
@ -401,13 +467,13 @@ gst_alpha_set_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alpha_set_i420 (guint8 * src, guint8 * dest, gint width, gint height,
|
gst_alpha_set_i420 (const guint8 * src, guint8 * dest, gint width, gint height,
|
||||||
gdouble alpha)
|
GstAlpha * alpha)
|
||||||
{
|
{
|
||||||
gint b_alpha = CLAMP ((gint) (alpha * 255), 0, 255);
|
gint b_alpha = CLAMP ((gint) (alpha->alpha * 255), 0, 255);
|
||||||
guint8 *srcY;
|
const guint8 *srcY;
|
||||||
guint8 *srcU;
|
const guint8 *srcU;
|
||||||
guint8 *srcV;
|
const guint8 *srcV;
|
||||||
gint i, j;
|
gint i, j;
|
||||||
gint src_wrap, src_uv_wrap;
|
gint src_wrap, src_uv_wrap;
|
||||||
gint y_stride, uv_stride;
|
gint y_stride, uv_stride;
|
||||||
|
@ -537,10 +603,10 @@ chroma_keying_yuv (gint a, gint * y, guint ny, gint * u,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alpha_chroma_key_ayuv (guint8 * src, guint8 * dest, gint width, gint height,
|
gst_alpha_chroma_key_ayuv (const guint8 * src, guint8 * dest, gint width,
|
||||||
GstAlpha * alpha)
|
gint height, GstAlpha * alpha)
|
||||||
{
|
{
|
||||||
guint8 *src1;
|
const guint8 *src1;
|
||||||
guint8 *dest1;
|
guint8 *dest1;
|
||||||
gint i, j;
|
gint i, j;
|
||||||
gint a, y, u, v;
|
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
|
static inline void
|
||||||
gst_alpha_chromakey_row_i420 (GstAlpha * alpha, guint8 * dest1, guint8 * dest2,
|
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 xpos;
|
||||||
gint a, a2, y[4], u, v;
|
gint a, a2, y[4], u, v;
|
||||||
|
@ -624,10 +691,10 @@ gst_alpha_chromakey_row_i420 (GstAlpha * alpha, guint8 * dest1, guint8 * dest2,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_alpha_chroma_key_i420 (guint8 * src, guint8 * dest, gint width, gint height,
|
gst_alpha_chroma_key_i420 (const guint8 * src, guint8 * dest, gint width,
|
||||||
GstAlpha * alpha)
|
gint height, GstAlpha * alpha)
|
||||||
{
|
{
|
||||||
guint8 *srcY1, *srcY2, *srcU, *srcV;
|
const guint8 *srcY1, *srcY2, *srcU, *srcV;
|
||||||
guint8 *dest1, *dest2;
|
guint8 *dest1, *dest2;
|
||||||
gint ypos;
|
gint ypos;
|
||||||
gint dest_stride, src_y_stride, src_uv_stride;
|
gint dest_stride, src_y_stride, src_uv_stride;
|
||||||
|
@ -673,16 +740,28 @@ gst_alpha_init_params (GstAlpha * alpha)
|
||||||
float kgl;
|
float kgl;
|
||||||
float tmp;
|
float tmp;
|
||||||
float tmp1, tmp2;
|
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 =
|
alpha->y =
|
||||||
0.257 * alpha->target_r + 0.504 * alpha->target_g +
|
(matrix[0] * ((gint) alpha->target_r) +
|
||||||
0.098 * alpha->target_b;
|
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 =
|
tmp1 =
|
||||||
-0.148 * alpha->target_r - 0.291 * alpha->target_g +
|
(matrix[4] * ((gint) alpha->target_r) +
|
||||||
0.439 * alpha->target_b;
|
matrix[5] * ((gint) alpha->target_g) +
|
||||||
|
matrix[6] * ((gint) alpha->target_b)) >> 8;
|
||||||
tmp2 =
|
tmp2 =
|
||||||
0.439 * alpha->target_r - 0.368 * alpha->target_g -
|
(matrix[8] * ((gint) alpha->target_r) +
|
||||||
0.071 * alpha->target_b;
|
matrix[9] * ((gint) alpha->target_g) +
|
||||||
|
matrix[10] * ((gint) alpha->target_b)) >> 8;
|
||||||
|
|
||||||
kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
|
kgl = sqrt (tmp1 * tmp1 + tmp2 * tmp2);
|
||||||
alpha->cb = 127 * (tmp1 / kgl);
|
alpha->cb = 127 * (tmp1 / kgl);
|
||||||
alpha->cr = 127 * (tmp2 / 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;
|
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
|
static gboolean
|
||||||
gst_alpha_start (GstBaseTransform * btrans)
|
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_sync_values (G_OBJECT (alpha), timestamp);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (alpha);
|
GST_OBJECT_LOCK (alpha);
|
||||||
switch (alpha->method) {
|
if (G_UNLIKELY (!alpha->process)) {
|
||||||
case ALPHA_METHOD_SET:
|
GST_ERROR_OBJECT (alpha, "Not negotiated yet");
|
||||||
if (alpha->format == GST_VIDEO_FORMAT_AYUV) {
|
GST_OBJECT_UNLOCK (alpha);
|
||||||
gst_alpha_set_ayuv (GST_BUFFER_DATA (in),
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alpha->process (GST_BUFFER_DATA (in),
|
||||||
|
GST_BUFFER_DATA (out), width, height, alpha);
|
||||||
GST_OBJECT_UNLOCK (alpha);
|
GST_OBJECT_UNLOCK (alpha);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
|
@ -61,8 +61,9 @@ struct _GstAlpha
|
||||||
GstVideoFilter parent;
|
GstVideoFilter parent;
|
||||||
|
|
||||||
/* caps */
|
/* caps */
|
||||||
GstVideoFormat format;
|
GstVideoFormat in_format, out_format;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
gboolean in_sdtv, out_sdtv;
|
||||||
|
|
||||||
gdouble alpha;
|
gdouble alpha;
|
||||||
|
|
||||||
|
@ -87,6 +88,8 @@ struct _GstAlpha
|
||||||
guint8 accept_angle_ctg;
|
guint8 accept_angle_ctg;
|
||||||
guint8 one_over_kc;
|
guint8 one_over_kc;
|
||||||
guint8 kfgy_scale;
|
guint8 kfgy_scale;
|
||||||
|
|
||||||
|
void (*process) (const guint8 *src, guint8 *dest, gint width, gint height, GstAlpha *alpha);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstAlphaClass
|
struct _GstAlphaClass
|
||||||
|
|
Loading…
Reference in a new issue