diff options
| -rw-r--r-- | gst/deinterlace2/gstdeinterlace2.c | 136 | ||||
| -rw-r--r-- | gst/deinterlace2/tvtime/greedy.c | 114 | ||||
| -rw-r--r-- | gst/deinterlace2/tvtime/greedyh.c | 5 | ||||
| -rw-r--r-- | gst/deinterlace2/tvtime/vfir.c | 90 | 
4 files changed, 145 insertions, 200 deletions
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",  | 
