From f30962901cd5528b2d3951591789ff079e03f95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 28 Jun 2008 18:10:52 +0000 Subject: 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. --- gst/deinterlace2/gstdeinterlace2.c | 136 +------------------------------------ gst/deinterlace2/tvtime/greedy.c | 114 +++++++++++++++++++++---------- gst/deinterlace2/tvtime/greedyh.c | 5 ++ gst/deinterlace2/tvtime/vfir.c | 90 +++++++++++++++--------- 4 files changed, 145 insertions(+), 200 deletions(-) (limited to 'gst') diff --git a/gst/deinterlace2/gstdeinterlace2.c b/gst/deinterlace2/gstdeinterlace2.c index 04ba4f01..64557d48 100644 --- a/gst/deinterlace2/gstdeinterlace2.c +++ b/gst/deinterlace2/gstdeinterlace2.c @@ -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))) { diff --git a/gst/deinterlace2/tvtime/greedy.c b/gst/deinterlace2/tvtime/greedy.c index 16b98312..2448d1dc 100644 --- a/gst/deinterlace2/tvtime/greedy.c +++ b/gst/deinterlace2/tvtime/greedy.c @@ -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", diff --git a/gst/deinterlace2/tvtime/greedyh.c b/gst/deinterlace2/tvtime/greedyh.c index f9d33e74..5cda7d53 100644 --- a/gst/deinterlace2/tvtime/greedyh.c +++ b/gst/deinterlace2/tvtime/greedyh.c @@ -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; diff --git a/gst/deinterlace2/tvtime/vfir.c b/gst/deinterlace2/tvtime/vfir.c index 4b7a0c09..53d233e1 100644 --- a/gst/deinterlace2/tvtime/vfir.c +++ b/gst/deinterlace2/tvtime/vfir.c @@ -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", -- cgit v1.2.1