From ce0e34a0d5c745b87e7b07a79b471753947d18fd Mon Sep 17 00:00:00 2001 From: Carsten Kroll Date: Thu, 24 Feb 2011 14:00:37 +0100 Subject: [PATCH] deinterlace: Add support for NV12 colorspace Fixes bug #642961. --- gst/deinterlace/gstdeinterlace.c | 2 +- gst/deinterlace/gstdeinterlacemethod.c | 65 +++++++++++++++++++++++++- gst/deinterlace/gstdeinterlacemethod.h | 4 ++ gst/deinterlace/tvtime/linear.c | 1 + gst/deinterlace/tvtime/linearblend.c | 2 + gst/deinterlace/tvtime/scalerbob.c | 2 + gst/deinterlace/tvtime/vfir.c | 3 ++ gst/deinterlace/tvtime/weave.c | 2 + gst/deinterlace/tvtime/weavebff.c | 2 + gst/deinterlace/tvtime/weavetff.c | 2 + 10 files changed, 83 insertions(+), 2 deletions(-) diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c index 12b1dd6315..7cc4121be5 100644 --- a/gst/deinterlace/gstdeinterlace.c +++ b/gst/deinterlace/gstdeinterlace.c @@ -161,7 +161,7 @@ gst_deinterlace_modes_get_type (void) } #define DEINTERLACE_CAPS \ - GST_VIDEO_CAPS_YUV ("{ AYUV, Y444, YUY2, YVYU, UYVY, Y42B, I420, YV12, Y41B }") ";" \ + GST_VIDEO_CAPS_YUV ("{ AYUV, Y444, YUY2, YVYU, UYVY, Y42B, I420, YV12, Y41B, NV12 }") ";" \ GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_ABGR ";" \ GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";" \ GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" \ diff --git a/gst/deinterlace/gstdeinterlacemethod.c b/gst/deinterlace/gstdeinterlacemethod.c index a5d1058e74..7a74978f2b 100644 --- a/gst/deinterlace/gstdeinterlacemethod.c +++ b/gst/deinterlace/gstdeinterlacemethod.c @@ -69,6 +69,8 @@ gst_deinterlace_method_supported_impl (GstDeinterlaceMethodClass * klass, return (klass->deinterlace_frame_y41b != NULL); case GST_VIDEO_FORMAT_AYUV: return (klass->deinterlace_frame_ayuv != NULL); + case GST_VIDEO_FORMAT_NV12: + return (klass->deinterlace_frame_nv12 != NULL); case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_xRGB: return (klass->deinterlace_frame_argb != NULL); @@ -152,6 +154,9 @@ gst_deinterlace_method_setup_impl (GstDeinterlaceMethod * self, case GST_VIDEO_FORMAT_AYUV: self->deinterlace_frame = klass->deinterlace_frame_ayuv; break; + case GST_VIDEO_FORMAT_NV12: + self->deinterlace_frame = klass->deinterlace_frame_nv12; + break; case GST_VIDEO_FORMAT_ARGB: case GST_VIDEO_FORMAT_xRGB: self->deinterlace_frame = klass->deinterlace_frame_argb; @@ -268,6 +273,9 @@ gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass, case GST_VIDEO_FORMAT_AYUV: return (klass->interpolate_scanline_ayuv != NULL && klass->copy_scanline_ayuv != NULL); + case GST_VIDEO_FORMAT_NV12: + return (klass->interpolate_scanline_nv12 != NULL + && klass->copy_scanline_nv12 != NULL); case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y444: @@ -545,6 +553,52 @@ gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod * } } +static void +gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod * + method, const GstDeinterlaceField * history, guint history_count, + GstBuffer * outbuf) +{ + GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method); + GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); + guint8 *out; + const guint8 *field0, *field1, *field2, *field3; + gint cur_field_idx = history_count - dm_class->fields_required; + guint cur_field_flags = history[cur_field_idx].flags; + gint i, offset; + + g_assert (self->interpolate_scanline_packed != NULL); + g_assert (self->copy_scanline_packed != NULL); + + for (i = 0; i < 2; i++) { + offset = self->parent.offset[i]; + + out = GST_BUFFER_DATA (outbuf) + offset; + + field0 = GST_BUFFER_DATA (history[cur_field_idx].buf) + offset; + + g_assert (dm_class->fields_required <= 4); + + field1 = NULL; + if (dm_class->fields_required >= 2) { + field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf) + offset; + } + + field2 = NULL; + if (dm_class->fields_required >= 3) { + field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf) + offset; + } + + field3 = NULL; + if (dm_class->fields_required >= 4) { + field3 = GST_BUFFER_DATA (history[cur_field_idx + 3].buf) + offset; + } + + gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out, + field0, field1, field2, field3, cur_field_flags, i, + self->copy_scanline_packed, self->interpolate_scanline_packed); + } +} + static void gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method, GstVideoFormat format, gint width, gint height) @@ -615,6 +669,10 @@ gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method, self->interpolate_scanline_packed = klass->interpolate_scanline_bgr; self->copy_scanline_packed = klass->copy_scanline_bgr; break; + case GST_VIDEO_FORMAT_NV12: + self->interpolate_scanline_packed = klass->interpolate_scanline_nv12; + self->copy_scanline_packed = klass->copy_scanline_nv12; + break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_Y444: @@ -671,6 +729,8 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass gst_deinterlace_simple_method_deinterlace_frame_planar; dm_class->deinterlace_frame_y41b = gst_deinterlace_simple_method_deinterlace_frame_planar; + dm_class->deinterlace_frame_nv12 = + gst_deinterlace_simple_method_deinterlace_frame_nv12; dm_class->fields_required = 2; dm_class->setup = gst_deinterlace_simple_method_setup; dm_class->supported = gst_deinterlace_simple_method_supported; @@ -691,6 +751,10 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass gst_deinterlace_simple_method_interpolate_scanline_packed; klass->copy_scanline_uyvy = gst_deinterlace_simple_method_copy_scanline_packed; + klass->interpolate_scanline_nv12 = + gst_deinterlace_simple_method_interpolate_scanline_packed; + klass->copy_scanline_nv12 = + gst_deinterlace_simple_method_copy_scanline_packed; klass->interpolate_scanline_argb = gst_deinterlace_simple_method_interpolate_scanline_packed; @@ -709,7 +773,6 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass gst_deinterlace_simple_method_interpolate_scanline_packed; klass->copy_scanline_bgra = gst_deinterlace_simple_method_copy_scanline_packed; - klass->interpolate_scanline_rgb = gst_deinterlace_simple_method_interpolate_scanline_packed; klass->copy_scanline_rgb = gst_deinterlace_simple_method_copy_scanline_packed; diff --git a/gst/deinterlace/gstdeinterlacemethod.h b/gst/deinterlace/gstdeinterlacemethod.h index d8d3343619..f8a047ed51 100644 --- a/gst/deinterlace/gstdeinterlacemethod.h +++ b/gst/deinterlace/gstdeinterlacemethod.h @@ -95,6 +95,7 @@ struct _GstDeinterlaceMethodClass { GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y42b; GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y41b; GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_ayuv; + GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_nv12; GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_argb; GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_abgr; GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_rgba; @@ -198,6 +199,9 @@ struct _GstDeinterlaceSimpleMethodClass { GstDeinterlaceSimpleMethodFunction copy_scanline_rgb; GstDeinterlaceSimpleMethodFunction interpolate_scanline_bgr; GstDeinterlaceSimpleMethodFunction copy_scanline_bgr; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_nv12; + GstDeinterlaceSimpleMethodFunction copy_scanline_nv12; + /* Planar formats */ GstDeinterlaceSimpleMethodFunction copy_scanline_planar_y; diff --git a/gst/deinterlace/tvtime/linear.c b/gst/deinterlace/tvtime/linear.c index 97bb7e517f..ff4c2787f4 100644 --- a/gst/deinterlace/tvtime/linear.c +++ b/gst/deinterlace/tvtime/linear.c @@ -112,6 +112,7 @@ gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass * dism_class->interpolate_scanline_bgra = deinterlace_scanline_linear_packed_c; dism_class->interpolate_scanline_rgb = deinterlace_scanline_linear_packed_c; dism_class->interpolate_scanline_bgr = deinterlace_scanline_linear_packed_c; + dism_class->interpolate_scanline_nv12 = deinterlace_scanline_linear_packed_c; dism_class->interpolate_scanline_planar_y = deinterlace_scanline_linear_planar_y_c; dism_class->interpolate_scanline_planar_u = diff --git a/gst/deinterlace/tvtime/linearblend.c b/gst/deinterlace/tvtime/linearblend.c index 548ce7c9f0..1c2ccbc075 100644 --- a/gst/deinterlace/tvtime/linearblend.c +++ b/gst/deinterlace/tvtime/linearblend.c @@ -167,6 +167,8 @@ static void deinterlace_scanline_linear_blend_packed_c; dism_class->interpolate_scanline_bgr = deinterlace_scanline_linear_blend_packed_c; + dism_class->interpolate_scanline_nv12 = + deinterlace_scanline_linear_blend_packed_c; dism_class->interpolate_scanline_planar_y = deinterlace_scanline_linear_blend_planar_y_c; diff --git a/gst/deinterlace/tvtime/scalerbob.c b/gst/deinterlace/tvtime/scalerbob.c index 4612ef05dc..16f12bc002 100644 --- a/gst/deinterlace/tvtime/scalerbob.c +++ b/gst/deinterlace/tvtime/scalerbob.c @@ -90,6 +90,8 @@ gst_deinterlace_method_scaler_bob_class_init (GstDeinterlaceMethodScalerBobClass deinterlace_scanline_scaler_bob_packed; dism_class->interpolate_scanline_uyvy = deinterlace_scanline_scaler_bob_packed; + dism_class->interpolate_scanline_nv12 = + deinterlace_scanline_scaler_bob_packed; dism_class->interpolate_scanline_argb = deinterlace_scanline_scaler_bob_packed; dism_class->interpolate_scanline_abgr = diff --git a/gst/deinterlace/tvtime/vfir.c b/gst/deinterlace/tvtime/vfir.c index da32bf69fb..32c06c0bf6 100644 --- a/gst/deinterlace/tvtime/vfir.c +++ b/gst/deinterlace/tvtime/vfir.c @@ -259,6 +259,7 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_mmx; dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_mmx; dism_class->interpolate_scanline_uyvy = deinterlace_line_packed_mmx; + dism_class->interpolate_scanline_nv12 = deinterlace_line_packed_mmx; dism_class->interpolate_scanline_argb = deinterlace_line_packed_mmx; dism_class->interpolate_scanline_abgr = deinterlace_line_packed_mmx; dism_class->interpolate_scanline_rgba = deinterlace_line_packed_mmx; @@ -273,6 +274,7 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c; dism_class->interpolate_scanline_uyvy = deinterlace_line_packed_c; dism_class->interpolate_scanline_ayuv = deinterlace_line_packed_c; + dism_class->interpolate_scanline_nv12 = deinterlace_line_packed_c; dism_class->interpolate_scanline_argb = deinterlace_line_packed_c; dism_class->interpolate_scanline_abgr = deinterlace_line_packed_c; dism_class->interpolate_scanline_rgba = deinterlace_line_packed_c; @@ -288,6 +290,7 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_c; dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c; dism_class->interpolate_scanline_uyvy = deinterlace_line_packed_c; + dism_class->interpolate_scanline_nv12 = deinterlace_line_packed_c; dism_class->interpolate_scanline_argb = deinterlace_line_packed_c; dism_class->interpolate_scanline_abgr = deinterlace_line_packed_c; dism_class->interpolate_scanline_rgba = deinterlace_line_packed_c; diff --git a/gst/deinterlace/tvtime/weave.c b/gst/deinterlace/tvtime/weave.c index 0f9714235a..c44b624311 100644 --- a/gst/deinterlace/tvtime/weave.c +++ b/gst/deinterlace/tvtime/weave.c @@ -119,6 +119,7 @@ gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass) dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_uyvy = deinterlace_scanline_weave_packed; + dism_class->interpolate_scanline_nv12 = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_argb = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_abgr = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_rgba = deinterlace_scanline_weave_packed; @@ -136,6 +137,7 @@ gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass) dism_class->copy_scanline_yuy2 = copy_scanline_packed; dism_class->copy_scanline_yvyu = copy_scanline_packed; dism_class->copy_scanline_uyvy = copy_scanline_packed; + dism_class->copy_scanline_nv12 = copy_scanline_packed; dism_class->copy_scanline_argb = copy_scanline_packed; dism_class->copy_scanline_abgr = copy_scanline_packed; dism_class->copy_scanline_rgba = copy_scanline_packed; diff --git a/gst/deinterlace/tvtime/weavebff.c b/gst/deinterlace/tvtime/weavebff.c index 9c95ba816a..664d2c826f 100644 --- a/gst/deinterlace/tvtime/weavebff.c +++ b/gst/deinterlace/tvtime/weavebff.c @@ -140,6 +140,7 @@ gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass * dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_uyvy = deinterlace_scanline_weave_packed; + dism_class->interpolate_scanline_nv12 = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_argb = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_abgr = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_rgba = deinterlace_scanline_weave_packed; @@ -157,6 +158,7 @@ gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass * dism_class->copy_scanline_yuy2 = copy_scanline_packed; dism_class->copy_scanline_yvyu = copy_scanline_packed; dism_class->copy_scanline_uyvy = copy_scanline_packed; + dism_class->copy_scanline_nv12 = copy_scanline_packed; dism_class->copy_scanline_argb = copy_scanline_packed; dism_class->copy_scanline_abgr = copy_scanline_packed; dism_class->copy_scanline_rgba = copy_scanline_packed; diff --git a/gst/deinterlace/tvtime/weavetff.c b/gst/deinterlace/tvtime/weavetff.c index 2df0863856..cf0875394c 100644 --- a/gst/deinterlace/tvtime/weavetff.c +++ b/gst/deinterlace/tvtime/weavetff.c @@ -141,6 +141,7 @@ gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass * dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_uyvy = deinterlace_scanline_weave_packed; + dism_class->interpolate_scanline_nv12 = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_argb = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_abgr = deinterlace_scanline_weave_packed; dism_class->interpolate_scanline_rgba = deinterlace_scanline_weave_packed; @@ -158,6 +159,7 @@ gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass * dism_class->copy_scanline_yuy2 = copy_scanline_packed; dism_class->copy_scanline_yvyu = copy_scanline_packed; dism_class->copy_scanline_uyvy = copy_scanline_packed; + dism_class->copy_scanline_nv12 = copy_scanline_packed; dism_class->copy_scanline_argb = copy_scanline_packed; dism_class->copy_scanline_abgr = copy_scanline_packed; dism_class->copy_scanline_rgba = copy_scanline_packed;