mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-23 14:36:24 +00:00
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:
parent
98501f6f45
commit
6402556157
1 changed files with 84 additions and 190 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue