Example #1
0
static void
deinterlace_frame_di_greedyh_planar (GstDeinterlaceMethod * method,
    const GstDeinterlaceField * history, guint history_count,
    GstVideoFrame * outframe, int cur_field_idx)
{
  GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
  GstDeinterlaceMethodGreedyHClass *klass =
      GST_DEINTERLACE_METHOD_GREEDY_H_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;
  ScanlineFunction scanline;

  if (cur_field_idx + 2 > history_count || cur_field_idx < 1) {
    GstDeinterlaceMethod *backup_method;

    backup_method = g_object_new (gst_deinterlace_method_linear_get_type (),
        NULL);

    gst_deinterlace_method_setup (backup_method, method->vinfo);
    gst_deinterlace_method_deinterlace_frame (backup_method,
        history, history_count, outframe, cur_field_idx);

    g_object_unref (backup_method);
    return;
  }

  cur_field_idx += 2;

  for (i = 0; i < 3; i++) {
    InfoIsOdd = (history[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM);
    RowStride = GST_VIDEO_FRAME_PLANE_STRIDE (outframe, i);
    FieldHeight = GST_VIDEO_FRAME_HEIGHT (outframe) / 2;
    Pitch = RowStride * 2;

    if (i == 0)
      scanline = klass->scanline_planar_y;
    else
      scanline = klass->scanline_planar_uv;

    Dest = GST_VIDEO_FRAME_PLANE_DATA (outframe, i);

    L1 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx - 2].frame, i);
    if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
      L1 += RowStride;

    L2 = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx - 1].frame, i);
    if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
      L2 += RowStride;

    L3 = L1 + Pitch;
    L2P = GST_VIDEO_FRAME_PLANE_DATA (history[cur_field_idx - 3].frame, i);
    if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM)
      L2P += RowStride;

    deinterlace_frame_di_greedyh_planar_plane (self, L1, L2, L3, L2P, Dest,
        RowStride, FieldHeight, Pitch, InfoIsOdd, scanline);
  }
}
Example #2
0
static void
deinterlace_frame_di_greedyh_planar (GstDeinterlaceMethod * method,
    const GstDeinterlaceField * history, guint history_count,
    GstBuffer * outbuf, int cur_field_idx)
{
  GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
  GstDeinterlaceMethodGreedyHClass *klass =
      GST_DEINTERLACE_METHOD_GREEDY_H_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;
  ScanlineFunction scanline;

  if (cur_field_idx + 2 > history_count || cur_field_idx < 1) {
    GstDeinterlaceMethod *backup_method;

    backup_method = g_object_new (gst_deinterlace_method_linear_get_type (),
        NULL);

    gst_deinterlace_method_setup (backup_method, method->format,
        method->frame_width, method->frame_height);
    gst_deinterlace_method_deinterlace_frame (backup_method,
        history, history_count, outbuf, cur_field_idx);

    g_object_unref (backup_method);
    return;
  }

  cur_field_idx += 2;

  for (i = 0; i < 3; i++) {
    Offset = method->offset[i];

    InfoIsOdd = (history[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM);
    RowStride = method->row_stride[i];
    FieldHeight = method->height[i] / 2;
    Pitch = method->row_stride[i] * 2;

    if (i == 0)
      scanline = klass->scanline_planar_y;
    else
      scanline = klass->scanline_planar_uv;

    Dest = GST_BUFFER_DATA (outbuf) + Offset;

    L1 = GST_BUFFER_DATA (history[cur_field_idx - 2].buf) + Offset;
    if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
      L1 += RowStride;

    L2 = GST_BUFFER_DATA (history[cur_field_idx - 1].buf) + Offset;
    if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
      L2 += RowStride;

    L3 = L1 + Pitch;
    L2P = GST_BUFFER_DATA (history[cur_field_idx - 3].buf) + Offset;
    if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM)
      L2P += RowStride;

    deinterlace_frame_di_greedyh_planar_plane (self, L1, L2, L3, L2P, Dest,
        RowStride, FieldHeight, Pitch, InfoIsOdd, scanline);
  }
}
Example #3
0
static void
deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method,
    const GstDeinterlaceField * history, guint history_count,
    GstVideoFrame * outframe, int cur_field_idx)
{
  GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
  GstDeinterlaceMethodGreedyHClass *klass =
      GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
  gint InfoIsOdd = 0;
  gint Line;
  gint RowStride = GST_VIDEO_FRAME_COMP_STRIDE (outframe, 0);
  gint FieldHeight = GST_VIDEO_INFO_HEIGHT (method->vinfo) / 2;
  gint Pitch = RowStride * 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_VIDEO_FRAME_COMP_DATA (outframe, 0);
  ScanlineFunction scanline;

  if (cur_field_idx + 2 > history_count || cur_field_idx < 1) {
    GstDeinterlaceMethod *backup_method;

    backup_method = g_object_new (gst_deinterlace_method_linear_get_type (),
        NULL);

    gst_deinterlace_method_setup (backup_method, method->vinfo);
    gst_deinterlace_method_deinterlace_frame (backup_method,
        history, history_count, outframe, cur_field_idx);

    g_object_unref (backup_method);
    return;
  }

  cur_field_idx += 2;

  switch (GST_VIDEO_INFO_FORMAT (method->vinfo)) {
    case GST_VIDEO_FORMAT_YUY2:
    case GST_VIDEO_FORMAT_YVYU:
      scanline = klass->scanline_yuy2;
      break;
    case GST_VIDEO_FORMAT_UYVY:
      scanline = klass->scanline_uyvy;
      break;
    case GST_VIDEO_FORMAT_AYUV:
      scanline = klass->scanline_ayuv;
      break;
    default:
      g_assert_not_reached ();
      return;
  }

  // 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[cur_field_idx - 1].flags == PICTURE_INTERLACED_BOTTOM) {
    InfoIsOdd = 1;

    L1 = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx - 2].frame, 0);
    if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
      L1 += RowStride;

    L2 = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx - 1].frame, 0);
    if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
      L2 += RowStride;

    L3 = L1 + Pitch;
    L2P = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx - 3].frame, 0);
    if (history[cur_field_idx - 3].flags & PICTURE_INTERLACED_BOTTOM)
      L2P += RowStride;

    // copy first even line
    memcpy (Dest, L1, RowStride);
    Dest += RowStride;
  } else {
    InfoIsOdd = 0;
    L1 = GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx - 2].frame, 0);
    if (history[cur_field_idx - 2].flags & PICTURE_INTERLACED_BOTTOM)
      L1 += RowStride;

    L2 = (guint8 *) GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx -
            1].frame, 0) + Pitch;
    if (history[cur_field_idx - 1].flags & PICTURE_INTERLACED_BOTTOM)
      L2 += RowStride;

    L3 = L1 + Pitch;
    L2P =
        (guint8 *) GST_VIDEO_FRAME_COMP_DATA (history[cur_field_idx - 3].frame,
        0) + Pitch;
    if (history[cur_field_idx - 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) {
    scanline (self, L1, L2, 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);
  }
}
static GstFlowReturn
gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
{
  GstDeinterlace2 *self = NULL;
  GstClockTime timestamp;
  GstFlowReturn ret = GST_FLOW_OK;
  gint fields_required = 0;
  gint cur_field_idx = 0;

  self = GST_DEINTERLACE2 (GST_PAD_PARENT (pad));

  gst_deinterlace2_push_history (self, buf);
  buf = NULL;

  fields_required = gst_deinterlace_method_get_fields_required (self->method);

  /* Not enough fields in the history */
  if (self->history_count < fields_required + 1) {
    /* TODO: do bob or just forward frame */
    GST_DEBUG ("HistoryCount=%d", self->history_count);
    return GST_FLOW_OK;
  }

  while (self->history_count >= fields_required) {
    if (self->fields == GST_DEINTERLACE2_ALL)
      GST_DEBUG ("All fields");
    if (self->fields == GST_DEINTERLACE2_TF)
      GST_DEBUG ("Top fields");
    if (self->fields == GST_DEINTERLACE2_BF)
      GST_DEBUG ("Bottom fields");

    cur_field_idx = self->history_count - fields_required;

    if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP
            && self->fields == GST_DEINTERLACE2_TF) ||
        self->fields == GST_DEINTERLACE2_ALL) {
      GST_DEBUG ("deinterlacing top field");

      /* create new buffer */
      ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
          GST_BUFFER_OFFSET_NONE, self->frame_size,
          GST_PAD_CAPS (self->srcpad), &self->out_buf);
      if (ret != GST_FLOW_OK)
        return ret;

      /* do magic calculus */
      gst_deinterlace_method_deinterlace_frame (self->method, self);

      g_assert (self->history_count - 1 -
          gst_deinterlace_method_get_latency (self->method) >= 0);
      buf =
          self->field_history[self->history_count - 1 -
          gst_deinterlace_method_get_latency (self->method)].buf;
      timestamp = GST_BUFFER_TIMESTAMP (buf);

      gst_buffer_unref (gst_deinterlace2_pop_history (self));

      GST_BUFFER_TIMESTAMP (self->out_buf) = timestamp;
      if (self->fields == GST_DEINTERLACE2_ALL)
        GST_BUFFER_DURATION (self->out_buf) = self->field_duration;
      else
        GST_BUFFER_DURATION (self->out_buf) = 2 * self->field_duration;

      ret = gst_pad_push (self->srcpad, self->out_buf);
      self->out_buf = NULL;
      if (ret != GST_FLOW_OK)
        return ret;
    }
    /* no calculation done: remove excess field */
    else if (self->field_history[cur_field_idx].flags ==
        PICTURE_INTERLACED_TOP && self->fields == GST_DEINTERLACE2_BF) {
      GST_DEBUG ("Removing unused top field");
      gst_buffer_unref (gst_deinterlace2_pop_history (self));
    }

    cur_field_idx = self->history_count - fields_required;
    if (self->history_count < fields_required)
      break;

    /* deinterlace bottom_field */
    if ((self->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM
            && self->fields == GST_DEINTERLACE2_BF) ||
        self->fields == GST_DEINTERLACE2_ALL) {
      GST_DEBUG ("deinterlacing bottom field");

      /* create new buffer */
      ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad,
          GST_BUFFER_OFFSET_NONE, self->frame_size,
          GST_PAD_CAPS (self->srcpad), &self->out_buf);
      if (ret != GST_FLOW_OK)
        return ret;

      /* do magic calculus */
      gst_deinterlace_method_deinterlace_frame (self->method, self);

      g_assert (self->history_count - 1 -
          gst_deinterlace_method_get_latency (self->method) >= 0);
      buf =
          self->field_history[self->history_count - 1 -
          gst_deinterlace_method_get_latency (self->method)].buf;
      timestamp = GST_BUFFER_TIMESTAMP (buf);

      gst_buffer_unref (gst_deinterlace2_pop_history (self));

      GST_BUFFER_TIMESTAMP (self->out_buf) = timestamp;
      if (self->fields == GST_DEINTERLACE2_ALL)
        GST_BUFFER_DURATION (self->out_buf) = self->field_duration;
      else
        GST_BUFFER_DURATION (self->out_buf) = 2 * self->field_duration;

      ret = gst_pad_push (self->srcpad, self->out_buf);
      self->out_buf = NULL;

      if (ret != GST_FLOW_OK)
        return ret;
    }
    /* no calculation done: remove excess field */
    else if (self->field_history[cur_field_idx].flags ==
        PICTURE_INTERLACED_BOTTOM && self->fields == GST_DEINTERLACE2_TF) {
      GST_DEBUG ("Removing unused bottom field");
      gst_buffer_unref (gst_deinterlace2_pop_history (self));
    }
  }

  GST_DEBUG ("----chain end ----\n\n");

  return ret;
}