Commit ee8327b9 authored by Sebastian Dröge's avatar Sebastian Dröge 🍵 Committed by Sebastian Dröge
Browse files

[MOVED FROM BAD 17/56] gst/deinterlace2/tvtime/greedy.c: Don't use scanlines...

[MOVED FROM BAD 17/56] gst/deinterlace2/tvtime/greedy.c: Don't use scanlines function from gstdeinterlace2 as it's not appropiate for this m...

Original commit message from CVS:
* gst/deinterlace2/tvtime/greedy.c:
(deinterlace_greedy_packed422_scanline_c),
(deinterlace_greedy_packed422_scanline_mmx),
(deinterlace_greedy_packed422_scanline_mmxext),
(deinterlace_frame_di_greedy):
Don't use scanlines function from gstdeinterlace2 as it's
not appropiate for this method. Instead implement deinterlace_frame
function by taking the one from greedyh.
* gst/deinterlace2/tvtime/greedyh.c: (greedyDScaler_C):
Small fix for the C implementation.
* gst/deinterlace2/tvtime/vfir.c: (deinterlace_frame_vfir):
Don't use the scanlines function from gstdeinterlace2 as it's only
used for this method and will be removed. Instead implement
deinterlace_frame function and make it a bit more efficient.
* gst/deinterlace2/gstdeinterlace2.c:
(gst_deinterlace2_class_init), (gst_deinterlace2_set_method),
(gst_deinterlace2_push_history), (gst_deinterlace2_chain),
(gst_deinterlace2_setcaps), (gst_deinterlace2_sink_event),
(gst_deinterlace2_change_state), (gst_deinterlace2_src_event),
(gst_deinterlace2_src_query):
Fix coding style and remove scanlines function as it's unused now.
parent 57dd0e85
......@@ -125,29 +125,21 @@ static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
);
static void gst_deinterlace2_finalize (GObject * object);
static void gst_deinterlace2_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_deinterlace2_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps);
static gboolean gst_deinterlace2_sink_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_deinterlace2_chain (GstPad * pad, GstBuffer * buffer);
static GstStateChangeReturn gst_deinterlace2_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_deinterlace2_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_deinterlace2_src_query (GstPad * pad, GstQuery * query);
static const GstQueryType *gst_deinterlace2_src_query_types (GstPad * pad);
static void gst_deinterlace2_deinterlace_scanlines (GstDeinterlace2 * object);
static void gst_deinterlace2_reset (GstDeinterlace2 * object);
GST_BOILERPLATE (GstDeinterlace2, gst_deinterlace2, GstElement,
......@@ -198,7 +190,6 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
GST_DEINTERLACE2_ALL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_FIELDS,
g_param_spec_enum ("tff",
"tff",
......@@ -314,14 +305,9 @@ gst_deinterlace2_set_method (GstDeinterlace2 * object,
GST_WARNING ("Invalid Deinterlacer Method");
}
if (object->method->deinterlace_frame == NULL)
object->method->deinterlace_frame = gst_deinterlace2_deinterlace_scanlines;
/* TODO: if current method requires less fields in the history,
pop the diff from field_history.
*/
}
static void
......@@ -422,9 +408,7 @@ static void
gst_deinterlace2_push_history (GstDeinterlace2 * object, GstBuffer * buffer)
{
int i = 1;
GstClockTime timestamp;
GstClockTime field_diff;
g_assert (object->history_count < MAX_FIELD_HISTORY - 2);
......@@ -470,122 +454,11 @@ gst_deinterlace2_push_history (GstDeinterlace2 * object, GstBuffer * buffer)
GST_DEBUG ("push, size(history): %d", object->history_count);
}
/* some methods support only deinterlace_/copy_scanline functions.
This funtion calls them in the right manner. */
static void
gst_deinterlace2_deinterlace_scanlines (GstDeinterlace2 * object)
{
gint line = 1;
gint cur_field_idx = object->history_count - object->method->fields_required;
GST_INFO ("cur_field_idx: %d", cur_field_idx);
guint8 *out_data = GST_BUFFER_DATA (object->out_buf);
guint8 *cur_field =
GST_BUFFER_DATA (object->field_history[cur_field_idx].buf);
guint8 *last_field = NULL;
guint8 *second_last_field = NULL;
/* method can just handle up to 3 history fields,
bcs until now there isn't a plugin (with interp./copy scanline methods)
that uses more */
g_assert (object->method->fields_required <= 3);
if (object->method->fields_required >= 2) {
last_field = GST_BUFFER_DATA (object->field_history[cur_field_idx + 1].buf);
}
if (object->method->fields_required >= 3) {
second_last_field =
GST_BUFFER_DATA (object->field_history[cur_field_idx + 2].buf);
}
if (object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM) {
/* double the first scanline of the bottom field */
blit_packed422_scanline (out_data, cur_field, object->frame_width);
out_data += object->output_stride;
}
blit_packed422_scanline (out_data, cur_field, object->frame_width);
out_data += object->output_stride;
line++;
for (; line <= object->field_height;) {
deinterlace_scanline_data_t data;
/* interp. scanline */
data.t0 = cur_field;
data.b0 = cur_field + object->field_stride;
if (last_field != NULL) {
data.tt1 = last_field;
data.m1 = last_field + object->field_stride;
data.bb1 = last_field + (object->field_stride * 2);
last_field += object->field_stride;
}
if (second_last_field != NULL) {
data.t2 = second_last_field;
data.b2 = second_last_field + object->field_stride;
}
/* set valid data for corner cases */
if (line == 2) {
data.tt1 = data.bb1;
} else if (line == object->field_height) {
data.bb1 = data.tt1;
}
object->method->interpolate_scanline (object, &data, out_data);
out_data += object->output_stride;
/* copy a scanline */
data.tt0 = cur_field;
data.m0 = cur_field + (object->field_stride);
data.bb0 = cur_field + (object->field_stride * 2);
cur_field += object->field_stride;
if (last_field != NULL) {
data.t1 = last_field;
data.b1 = last_field + object->field_stride;
}
if (second_last_field != NULL) {
data.tt2 = second_last_field;
data.m2 = second_last_field + (object->field_stride);
data.bb2 = second_last_field + (object->field_stride * 2);
second_last_field += object->field_stride;
}
/* set valid data for corner cases */
if (line == object->field_height) {
data.bb0 = data.tt0;
data.bb2 = data.tt2;
data.b1 = data.t1;
}
object->method->copy_scanline (object, &data, out_data);
out_data += object->output_stride;
line++;
}
if (object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP) {
/* double the last scanline of the top field */
blit_packed422_scanline (out_data, cur_field, object->frame_width);
}
}
static GstFlowReturn
gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
{
GstDeinterlace2 *object = NULL;
GstClockTime timestamp;
GstFlowReturn ret = GST_FLOW_OK;
object = GST_DEINTERLACE2 (GST_PAD_PARENT (pad));
......@@ -750,8 +623,7 @@ gst_deinterlace2_setcaps (GstPad * pad, GstCaps * caps)
othercaps = gst_caps_ref (caps);
}
if ( /*!gst_pad_accept_caps (otherpad, othercaps)
|| */ !gst_pad_set_caps (otherpad, othercaps))
if (!gst_pad_set_caps (otherpad, othercaps))
goto caps_not_accepted;
gst_caps_unref (othercaps);
......@@ -797,7 +669,6 @@ static gboolean
gst_deinterlace2_sink_event (GstPad * pad, GstEvent * event)
{
gboolean res = TRUE;
GstDeinterlace2 *object = GST_DEINTERLACE2 (gst_pad_get_parent (pad));
GST_LOG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
......@@ -822,7 +693,6 @@ static GstStateChangeReturn
gst_deinterlace2_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
GstDeinterlace2 *object = GST_DEINTERLACE2 (element);
switch (transition) {
......@@ -858,7 +728,6 @@ static gboolean
gst_deinterlace2_src_event (GstPad * pad, GstEvent * event)
{
GstDeinterlace2 *object = GST_DEINTERLACE2 (gst_pad_get_parent (pad));
gboolean res;
GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
......@@ -878,7 +747,6 @@ static gboolean
gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
{
GstDeinterlace2 *object = GST_DEINTERLACE2 (gst_pad_get_parent (pad));
gboolean res = FALSE;
GST_LOG_OBJECT (object, "%s query", GST_QUERY_TYPE_NAME (query));
......@@ -887,9 +755,7 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
case GST_QUERY_LATENCY:
{
GstClockTime min, max;
gboolean live;
GstPad *peer;
if ((peer = gst_pad_get_peer (object->sinkpad))) {
......
......@@ -53,19 +53,11 @@
// I'd intended this to be part of a larger more elaborate method added to
// Blended Clip but this give too good results for the CPU to ignore here.
static void
copy_scanline (GstDeinterlace2 * object,
deinterlace_scanline_data_t * data, uint8_t * output)
{
blit_packed422_scanline (output, data->m1, object->frame_width);
}
static const int GreedyMaxComb = 15;
static inline void
deinterlace_greedy_packed422_scanline_c (GstDeinterlace2 * object,
uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, uint8_t * output,
int width)
deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
int avg, l2_diff, lp2_diff, max, min, best;
......@@ -112,9 +104,8 @@ deinterlace_greedy_packed422_scanline_c (GstDeinterlace2 * object,
#ifdef HAVE_CPU_I386
#include "mmx.h"
static void
deinterlace_greedy_packed422_scanline_mmx (GstDeinterlace2 * object,
uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, uint8_t * output,
int width)
deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
mmx_t MaxComb;
......@@ -222,16 +213,14 @@ deinterlace_greedy_packed422_scanline_mmx (GstDeinterlace2 * object,
}
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (object, m0, t1, b1, m2, output,
width);
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
}
#include "sse.h"
static void
deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlace2 * object,
uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2, uint8_t * output,
int width)
deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
mmx_t MaxComb;
......@@ -316,47 +305,104 @@ deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlace2 * object,
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (object, m0, t1, b1, m2, output,
width);
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
}
#endif
static void
deinterlace_greedy_packed422_scanline (GstDeinterlace2 * object,
deinterlace_scanline_data_t * data, uint8_t * output)
deinterlace_frame_di_greedy (GstDeinterlace2 * object)
{
void (*func) (uint8_t * L2, uint8_t * L1, uint8_t * L3, uint8_t * L2P,
uint8_t * Dest, int size);
int InfoIsOdd = 0;
int Line;
unsigned int Pitch = object->field_stride;
unsigned char *L1; // ptr to Line1, of 3
unsigned char *L2; // ptr to Line2, the weave line
unsigned char *L3; // ptr to Line3
unsigned char *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
#ifdef HAVE_CPU_I386
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMXEXT) {
deinterlace_greedy_packed422_scanline_mmxext (object, data->m0, data->t1,
data->b1, data->m2, output, 2 * object->frame_width);
func = deinterlace_greedy_packed422_scanline_mmxext;
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
deinterlace_greedy_packed422_scanline_mmx (object, data->m0, data->t1,
data->b1, data->m2, output, 2 * object->frame_width);
func = deinterlace_greedy_packed422_scanline_mmx;
} else {
deinterlace_greedy_packed422_scanline_c (object, data->m0, data->t1,
data->b1, data->m2, output, 2 * object->frame_width);
func = deinterlace_greedy_packed422_scanline_c;
}
#else
deinterlace_greedy_packed422_scanline_c (object, data->m0, data->t1, data->b1,
data->m2, output, 2 * object->frame_width);
func = deinterlace_greedy_packed422_scanline_c;
#endif
}
// 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 (object->field_history[object->history_count - 1].flags ==
PICTURE_INTERLACED_BOTTOM) {
InfoIsOdd = 1;
L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
L3 = L1 + Pitch;
L2P =
GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf);
// copy first even line
object->pMemcpy (Dest, L1, object->line_length);
Dest += object->output_stride;
} else {
InfoIsOdd = 0;
L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
L2 = GST_BUFFER_DATA (object->field_history[object->history_count -
1].buf) + Pitch;
L3 = L1 + Pitch;
L2P =
GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) +
Pitch;
// copy first even line
object->pMemcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf),
object->line_length);
Dest += object->output_stride;
// then first odd line
object->pMemcpy (Dest, L1, object->line_length);
Dest += object->output_stride;
}
for (Line = 0; Line < (object->field_height - 1); ++Line) {
func (L2, L1, L3, L2P, Dest, object->line_length);
Dest += object->output_stride;
object->pMemcpy (Dest, L3, object->line_length);
Dest += object->output_stride;
L1 += Pitch;
L2 += Pitch;
L3 += Pitch;
L2P += Pitch;
}
if (InfoIsOdd) {
object->pMemcpy (Dest, L2, object->line_length);
}
}
static deinterlace_method_t greedyl_method = {
0, //DEINTERLACE_PLUGIN_API_VERSION,
"Motion Adaptive: Simple Detection",
"AdaptiveSimple",
3,
4,
0,
0,
0,
0,
1,
copy_scanline,
deinterlace_greedy_packed422_scanline,
0,
0,
deinterlace_frame_di_greedy,
{"Uses heuristics to detect motion in the input",
"frames and reconstruct image detail where",
"possible. Use this for high quality output",
......
......@@ -85,6 +85,11 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
avg_l = (l1_l + l3_l) / 2;
avg_c = (l1_c + l3_c) / 2;
if (Pos == 0) {
avg_l__1 = avg_l;
avg_c__1 = avg_c;
}
/* Average of next L1 and next L3 */
avg_l_1 = (l1_1_l + l3_1_l) / 2;
avg_c_1 = (l1_1_c + l3_1_c) / 2;
......
......@@ -127,45 +127,73 @@ deinterlace_line_mmx (uint8_t * dst, uint8_t * lum_m4,
}
#endif
/*
* The commented-out method below that uses the bottom_field member is more
* like the filter as specified in the MPEG2 spec, but it doesn't seem to
* have the desired effect.
*/
static void
deinterlace_scanline_vfir (GstDeinterlace2 * object,
deinterlace_scanline_data_t * data, uint8_t * output)
deinterlace_frame_vfir (GstDeinterlace2 * object)
{
void (*func) (uint8_t * dst, uint8_t * lum_m4,
uint8_t * lum_m3, uint8_t * lum_m2,
uint8_t * lum_m1, uint8_t * lum, int size);
gint line = 0;
uint8_t *cur_field, *last_field;
uint8_t *t0, *b0, *tt1, *m1, *bb1, *out_data;
#ifdef HAVE_CPU_I386
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
deinterlace_line_mmx (output, data->tt1, data->t0, data->m1, data->b0,
data->bb1, object->frame_width * 2);
func = deinterlace_line_mmx;
} else {
deinterlace_line_c (output, data->tt1, data->t0, data->m1, data->b0,
data->bb1, object->frame_width * 2);
func = deinterlace_line_c;
}
#else
deinterlace_line_c (output, data->tt1, data->t0, data->m1, data->b0,
data->bb1, object->frame_width * 2);
func = deinterlace_line_c;
#endif
// blit_packed422_scanline( output, data->m1, width );
}
static void
copy_scanline (GstDeinterlace2 * object,
deinterlace_scanline_data_t * data, uint8_t * output)
{
blit_packed422_scanline (output, data->m0, object->frame_width);
/*
if( data->bottom_field ) {
deinterlace_line( output, data->tt2, data->t1, data->m2, data->b1, data->bb2, width*2 );
} else {
deinterlace_line( output, data->tt0, data->t1, data->m0, data->b1, data->bb0, width*2 );
}
*/
}
cur_field =
GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
last_field =
GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
out_data = GST_BUFFER_DATA (object->out_buf);
if (object->field_history[object->history_count - 2].flags ==
PICTURE_INTERLACED_BOTTOM) {
blit_packed422_scanline (out_data, cur_field, object->frame_width);
out_data += object->output_stride;
}
blit_packed422_scanline (out_data, cur_field, object->frame_width);
out_data += object->output_stride;
line++;
for (; line < object->field_height; line++) {
t0 = cur_field;
b0 = cur_field + object->field_stride;
tt1 = last_field;
m1 = last_field + object->field_stride;
bb1 = last_field + (object->field_stride * 2);
/* set valid data for corner cases */
if (line == 1) {
tt1 = bb1;
} else if (line == object->field_height - 1) {
bb1 = tt1;
}
func (out_data, tt1, t0, m1, b0, bb1, object->line_length);
out_data += object->output_stride;
cur_field += object->field_stride;
last_field += object->field_stride;
blit_packed422_scanline (out_data, cur_field, object->frame_width);
out_data += object->output_stride;
}
if (object->field_history[object->history_count - 2].flags ==
PICTURE_INTERLACED_TOP) {
/* double the last scanline of the top field */
blit_packed422_scanline (out_data, cur_field, object->frame_width);
}
}
static deinterlace_method_t vfirmethod = {
0, //DEINTERLACE_PLUGIN_API_VERSION,
......@@ -177,9 +205,9 @@ static deinterlace_method_t vfirmethod = {
0,
0,
1,
deinterlace_scanline_vfir,
copy_scanline,
0,
0,
deinterlace_frame_vfir,
{"Avoids flicker by blurring consecutive frames",
"of input. Use this if you want to run your",
"monitor at an arbitrary refresh rate and not",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment