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
{
GstDeinterlaceMethod parent;
GstDeinterlaceSimpleMethod parent;
guint max_comb;
} GstDeinterlaceMethodGreedyL;
typedef void (*GreedyLScanlineFunction) (GstDeinterlaceMethodGreedyL * self,
const guint8 * L2, const guint8 * L1, const guint8 * L3, const guint8 * L2P,
guint8 * Dest, gint width);
typedef struct
{
GstDeinterlaceMethodClass parent_class;
GreedyLScanlineFunction scanline;
} GstDeinterlaceMethodGreedyLClass;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodGreedyLClass;
// This is a simple lightweight DeInterlace method that uses little CPU time
// 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.
static inline void
deinterlace_greedy_scanline_orc (GstDeinterlaceMethodGreedyL * self,
const guint8 * m0, const guint8 * t1,
const guint8 * b1, const guint8 * m2, guint8 * output, gint width)
deinterlace_greedy_interpolate_scanline_orc (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
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
deinterlace_frame_di_greedy_packed (GstDeinterlaceMethod * method,
const GstDeinterlaceField * history, guint history_count,
GstBuffer * outbuf)
deinterlace_greedy_copy_scanline (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (method);
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);
}
memcpy (out, scanlines->m2, self->parent.row_stride[0]);
}
static void
deinterlace_frame_di_greedy_planar_plane (GstDeinterlaceMethodGreedyL * self,
const guint8 * L1, const guint8 * L2, const guint8 * L3, const guint8 * L2P,
guint8 * Dest, gint RowStride, gint FieldHeight, gint Pitch, gint InfoIsOdd,
GreedyLScanlineFunction scanline)
deinterlace_greedy_copy_scanline_planar_u (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
gint Line;
// 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);
}
memcpy (out, scanlines->m2, self->parent.row_stride[1]);
}
static void
deinterlace_frame_di_greedy_planar (GstDeinterlaceMethod * method,
const GstDeinterlaceField * history, guint history_count,
GstBuffer * outbuf)
deinterlace_greedy_copy_scanline_planar_v (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (method);
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);
}
memcpy (out, scanlines->m2, self->parent.row_stride[2]);
}
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l,
GST_TYPE_DEINTERLACE_METHOD);
GST_TYPE_DEINTERLACE_SIMPLE_METHOD);
enum
{
@ -299,6 +166,8 @@ gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
klass)
{
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
GstDeinterlaceSimpleMethodClass *dism_class =
(GstDeinterlaceSimpleMethodClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
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->latency = 1;
dim_class->deinterlace_frame_yuy2 = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_yvyu = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_uyvy = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_y444 = deinterlace_frame_di_greedy_planar;
dim_class->deinterlace_frame_y42b = deinterlace_frame_di_greedy_planar;
dim_class->deinterlace_frame_i420 = deinterlace_frame_di_greedy_planar;
dim_class->deinterlace_frame_yv12 = deinterlace_frame_di_greedy_planar;
dim_class->deinterlace_frame_y41b = deinterlace_frame_di_greedy_planar;
dim_class->deinterlace_frame_ayuv = deinterlace_frame_di_greedy_planar;
dim_class->deinterlace_frame_argb = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_rgba = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_abgr = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_bgra = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_rgb = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_bgr = deinterlace_frame_di_greedy_packed;
dism_class->interpolate_scanline_ayuv =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_yuy2 =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_yvyu =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_uyvy =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_argb =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_abgr =
deinterlace_greedy_interpolate_scanline_orc;
dism_class->interpolate_scanline_rgba =
deinterlace_greedy_interpolate_scanline_orc;
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