deinterlace: Port greedyl to GstDeinterlaceSimpleMethod

The main goal of this change is to reuse the complex but now neatly
written scanline pointer calculation code from the simple methods.
This commit is contained in:
Robert Swain 2011-01-24 12:48:18 +01:00
parent 98501f6f45
commit 6402556157

View File

@ -49,20 +49,12 @@ GType gst_deinterlace_method_greedy_l_get_type (void);
typedef struct typedef struct
{ {
GstDeinterlaceMethod parent; GstDeinterlaceSimpleMethod parent;
guint max_comb; guint max_comb;
} GstDeinterlaceMethodGreedyL; } GstDeinterlaceMethodGreedyL;
typedef void (*GreedyLScanlineFunction) (GstDeinterlaceMethodGreedyL * self, typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodGreedyLClass;
const guint8 * L2, const guint8 * L1, const guint8 * L3, const guint8 * L2P,
guint8 * Dest, gint width);
typedef struct
{
GstDeinterlaceMethodClass parent_class;
GreedyLScanlineFunction scanline;
} GstDeinterlaceMethodGreedyLClass;
// This is a simple lightweight DeInterlace method that uses little CPU time // This is a simple lightweight DeInterlace method that uses little CPU time
// but gives very good results for low or intermedite motion. // but gives very good results for low or intermedite motion.
@ -77,186 +69,61 @@ typedef struct
// Blended Clip but this give too good results for the CPU to ignore here. // Blended Clip but this give too good results for the CPU to ignore here.
static inline void static inline void
deinterlace_greedy_scanline_orc (GstDeinterlaceMethodGreedyL * self, deinterlace_greedy_interpolate_scanline_orc (GstDeinterlaceSimpleMethod * self,
const guint8 * m0, const guint8 * t1, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
const guint8 * b1, const guint8 * m2, guint8 * output, gint width)
{ {
deinterlace_line_greedy (output, m0, t1, b1, m2, self->max_comb, width); /* FIXME - is this safe or just a hack? */
guint max_comb = GST_DEINTERLACE_METHOD_GREEDY_L (self)->max_comb;
deinterlace_line_greedy (out, scanlines->m3, scanlines->t2, scanlines->b2,
scanlines->m1, max_comb, self->parent.row_stride[0]);
}
static inline void
deinterlace_greedy_interpolate_scanline_orc_planar_u (GstDeinterlaceSimpleMethod
* self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
/* FIXME - is this safe or just a hack? */
guint max_comb = GST_DEINTERLACE_METHOD_GREEDY_L (self)->max_comb;
deinterlace_line_greedy (out, scanlines->m3, scanlines->t2, scanlines->b2,
scanlines->m1, max_comb, self->parent.row_stride[1]);
}
static inline void
deinterlace_greedy_interpolate_scanline_orc_planar_v (GstDeinterlaceSimpleMethod
* self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
/* FIXME - is this safe or just a hack? */
guint max_comb = GST_DEINTERLACE_METHOD_GREEDY_L (self)->max_comb;
deinterlace_line_greedy (out, scanlines->m3, scanlines->t2, scanlines->b2,
scanlines->m1, max_comb, self->parent.row_stride[2]);
} }
static void static void
deinterlace_frame_di_greedy_packed (GstDeinterlaceMethod * method, deinterlace_greedy_copy_scanline (GstDeinterlaceSimpleMethod * self,
const GstDeinterlaceField * history, guint history_count, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
GstBuffer * outbuf)
{ {
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (method); memcpy (out, scanlines->m2, self->parent.row_stride[0]);
GstDeinterlaceMethodGreedyLClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self);
gint InfoIsOdd = 0;
gint Line;
gint RowStride = method->row_stride[0];
gint FieldHeight = method->frame_height / 2;
gint Pitch = method->row_stride[0] * 2;
const guint8 *L1; // ptr to Line1, of 3
const guint8 *L2; // ptr to Line2, the weave line
const guint8 *L3; // ptr to Line3
const guint8 *L2P; // ptr to prev Line2
guint8 *Dest = GST_BUFFER_DATA (outbuf);
// copy first even line no matter what, and the first odd line if we're
// processing an EVEN field. (note diff from other deint rtns.)
if (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM) {
InfoIsOdd = 1;
L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf);
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P = GST_BUFFER_DATA (history[history_count - 3].buf);
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
// copy first even line
memcpy (Dest, L1, RowStride);
Dest += RowStride;
} else {
InfoIsOdd = 0;
L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Pitch;
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Pitch;
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
// copy first even line
memcpy (Dest, L1, RowStride);
Dest += RowStride;
// then first odd line
memcpy (Dest, L1, RowStride);
Dest += RowStride;
}
for (Line = 0; Line < (FieldHeight - 1); ++Line) {
klass->scanline (self, L2, L1, L3, L2P, Dest, RowStride);
Dest += RowStride;
memcpy (Dest, L3, RowStride);
Dest += RowStride;
L1 += Pitch;
L2 += Pitch;
L3 += Pitch;
L2P += Pitch;
}
if (InfoIsOdd) {
memcpy (Dest, L2, RowStride);
}
} }
static void static void
deinterlace_frame_di_greedy_planar_plane (GstDeinterlaceMethodGreedyL * self, deinterlace_greedy_copy_scanline_planar_u (GstDeinterlaceSimpleMethod * self,
const guint8 * L1, const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
guint8 * Dest, gint RowStride, gint FieldHeight, gint Pitch, gint InfoIsOdd,
GreedyLScanlineFunction scanline)
{ {
gint Line; memcpy (out, scanlines->m2, self->parent.row_stride[1]);
// copy first even line no matter what, and the first odd line if we're
// processing an EVEN field. (note diff from other deint rtns.)
if (InfoIsOdd) {
// copy first even line
memcpy (Dest, L1, RowStride);
Dest += RowStride;
} else {
// copy first even line
memcpy (Dest, L1, RowStride);
Dest += RowStride;
// then first odd line
memcpy (Dest, L1, RowStride);
Dest += RowStride;
}
for (Line = 0; Line < (FieldHeight - 1); ++Line) {
scanline (self, L2, L1, L3, L2P, Dest, RowStride);
Dest += RowStride;
memcpy (Dest, L3, RowStride);
Dest += RowStride;
L1 += Pitch;
L2 += Pitch;
L3 += Pitch;
L2P += Pitch;
}
if (InfoIsOdd) {
memcpy (Dest, L2, RowStride);
}
} }
static void static void
deinterlace_frame_di_greedy_planar (GstDeinterlaceMethod * method, deinterlace_greedy_copy_scanline_planar_v (GstDeinterlaceSimpleMethod * self,
const GstDeinterlaceField * history, guint history_count, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
GstBuffer * outbuf)
{ {
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (method); memcpy (out, scanlines->m2, self->parent.row_stride[2]);
GstDeinterlaceMethodGreedyLClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self);
gint InfoIsOdd;
gint RowStride;
gint FieldHeight;
gint Pitch;
const guint8 *L1; // ptr to Line1, of 3
const guint8 *L2; // ptr to Line2, the weave line
const guint8 *L3; // ptr to Line3
const guint8 *L2P; // ptr to prev Line2
guint8 *Dest;
gint i;
gint Offset;
GreedyLScanlineFunction scanline = klass->scanline;
for (i = 0; i < 3; i++) {
Offset = method->offset[i];
InfoIsOdd = (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM);
RowStride = method->row_stride[i];
FieldHeight = method->height[i] / 2;
Pitch = method->row_stride[i] * 2;
Dest = GST_BUFFER_DATA (outbuf) + Offset;
L1 = GST_BUFFER_DATA (history[history_count - 2].buf) + Offset;
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Offset;
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Offset;
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
deinterlace_frame_di_greedy_planar_plane (self, L1, L2, L3, L2P, Dest,
RowStride, FieldHeight, Pitch, InfoIsOdd, scanline);
}
} }
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l, G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l,
GST_TYPE_DEINTERLACE_METHOD); GST_TYPE_DEINTERLACE_SIMPLE_METHOD);
enum enum
{ {
@ -299,6 +166,8 @@ gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
klass) klass)
{ {
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass; GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
GstDeinterlaceSimpleMethodClass *dism_class =
(GstDeinterlaceSimpleMethodClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass; GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->set_property = gst_deinterlace_method_greedy_l_set_property; gobject_class->set_property = gst_deinterlace_method_greedy_l_set_property;
@ -315,23 +184,48 @@ gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
dim_class->nick = "greedyl"; dim_class->nick = "greedyl";
dim_class->latency = 1; dim_class->latency = 1;
dim_class->deinterlace_frame_yuy2 = deinterlace_frame_di_greedy_packed; dism_class->interpolate_scanline_ayuv =
dim_class->deinterlace_frame_yvyu = deinterlace_frame_di_greedy_packed; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_uyvy = deinterlace_frame_di_greedy_packed; dism_class->interpolate_scanline_yuy2 =
dim_class->deinterlace_frame_y444 = deinterlace_frame_di_greedy_planar; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_y42b = deinterlace_frame_di_greedy_planar; dism_class->interpolate_scanline_yvyu =
dim_class->deinterlace_frame_i420 = deinterlace_frame_di_greedy_planar; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_yv12 = deinterlace_frame_di_greedy_planar; dism_class->interpolate_scanline_uyvy =
dim_class->deinterlace_frame_y41b = deinterlace_frame_di_greedy_planar; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_ayuv = deinterlace_frame_di_greedy_planar; dism_class->interpolate_scanline_argb =
dim_class->deinterlace_frame_argb = deinterlace_frame_di_greedy_packed; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_rgba = deinterlace_frame_di_greedy_packed; dism_class->interpolate_scanline_abgr =
dim_class->deinterlace_frame_abgr = deinterlace_frame_di_greedy_packed; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_bgra = deinterlace_frame_di_greedy_packed; dism_class->interpolate_scanline_rgba =
dim_class->deinterlace_frame_rgb = deinterlace_frame_di_greedy_packed; deinterlace_greedy_interpolate_scanline_orc;
dim_class->deinterlace_frame_bgr = deinterlace_frame_di_greedy_packed; dism_class->interpolate_scanline_bgra =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_rgb =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_bgr =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_planar_y =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_planar_u =
deinterlace_greedy_interpolate_scanline_orc_planar_u;
dism_class->interpolate_scanline_planar_v =
deinterlace_greedy_interpolate_scanline_orc_planar_v;
klass->scanline = deinterlace_greedy_scanline_orc; dism_class->copy_scanline_ayuv = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_yuy2 = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_yvyu = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_uyvy = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_argb = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_abgr = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_rgba = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_bgra = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_rgb = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_bgr = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_planar_y = deinterlace_greedy_copy_scanline;
dism_class->copy_scanline_planar_u =
deinterlace_greedy_copy_scanline_planar_u;
dism_class->copy_scanline_planar_v =
deinterlace_greedy_copy_scanline_planar_v;
} }
static void static void