Esempio n. 1
0
static GstFlowReturn
gst_ffmpegscale_transform(GstBaseTransform* trans, GstBuffer* inbuf,
                          GstBuffer* outbuf) {
    GstFFMpegScale* scale = GST_FFMPEGSCALE(trans);
    guint8* in_data[3] = { NULL, NULL, NULL };
    guint8* out_data[3] = { NULL, NULL, NULL };
    gint i;
    FFVSImage dest = { NULL, };
    FFVSImage dest_u = { NULL, };
    FFVSImage dest_v = { NULL, };

    for (i = 0; i < 3; i++) {
        /* again; stay close to the ffmpeg offset way */
        if (!i || scale->in_offset[i]) {
            in_data[i] = GST_BUFFER_DATA(inbuf) + scale->in_offset[i];
        }

        if (!i || scale->out_offset[i]) {
            out_data[i] = GST_BUFFER_DATA(outbuf) + scale->out_offset[i];
        }
    }

    if (scale->add_borders) {
        const guint8* black = get_black_for_format(scale->out_format);

        gst_video_scale_setup_vs_image(&dest, scale->out_format, 0,
                                       scale->out_width, scale->out_height, scale->borders_w,
                                       scale->borders_h, GST_BUFFER_DATA(outbuf));

        if (scale->out_format == GST_VIDEO_FORMAT_I420
                || scale->out_format == GST_VIDEO_FORMAT_YV12
                || scale->out_format == GST_VIDEO_FORMAT_Y444
                || scale->out_format == GST_VIDEO_FORMAT_Y42B
                || scale->out_format == GST_VIDEO_FORMAT_Y41B) {

            gst_video_scale_setup_vs_image(&dest_u, scale->out_format, 1,
                                           scale->out_width, scale->out_height, scale->borders_w,
                                           scale->borders_h, GST_BUFFER_DATA(outbuf));
            gst_video_scale_setup_vs_image(&dest_v, scale->out_format, 2,
                                           scale->out_width, scale->out_height, scale->borders_w,
                                           scale->borders_h, GST_BUFFER_DATA(outbuf));
        }

        switch (scale->out_format) {
        case GST_VIDEO_FORMAT_RGBx:
        case GST_VIDEO_FORMAT_xRGB:
        case GST_VIDEO_FORMAT_BGRx:
        case GST_VIDEO_FORMAT_xBGR:
        case GST_VIDEO_FORMAT_RGBA:
        case GST_VIDEO_FORMAT_ARGB:
        case GST_VIDEO_FORMAT_BGRA:
        case GST_VIDEO_FORMAT_ABGR:
        case GST_VIDEO_FORMAT_AYUV:
            vs_fill_borders_RGBA(&dest, black);
            break;

        case GST_VIDEO_FORMAT_ARGB64:
        case GST_VIDEO_FORMAT_AYUV64:
            vs_fill_borders_AYUV64(&dest, black);
            break;

        case GST_VIDEO_FORMAT_RGB:
        case GST_VIDEO_FORMAT_BGR:
        case GST_VIDEO_FORMAT_v308:

            vs_fill_borders_RGB(&dest, black);
            break;

        case GST_VIDEO_FORMAT_YUY2:
        case GST_VIDEO_FORMAT_YVYU:
            vs_fill_borders_YUYV(&dest, black);
            break;

        case GST_VIDEO_FORMAT_UYVY:
            vs_fill_borders_UYVY(&dest, black);
            break;

        case GST_VIDEO_FORMAT_GRAY8:
            vs_fill_borders_Y(&dest, black);
            break;

        case GST_VIDEO_FORMAT_GRAY16_LE:
        case GST_VIDEO_FORMAT_GRAY16_BE:
            vs_fill_borders_Y16(&dest, 0);
            break;

        case GST_VIDEO_FORMAT_I420:
        case GST_VIDEO_FORMAT_YV12:
        case GST_VIDEO_FORMAT_Y444:
        case GST_VIDEO_FORMAT_Y42B:
        case GST_VIDEO_FORMAT_Y41B:
            vs_fill_borders_Y(&dest, black);
            vs_fill_borders_Y(&dest_u, black + 1);
            vs_fill_borders_Y(&dest_v, black + 2);
            break;

        case GST_VIDEO_FORMAT_RGB16:
            vs_fill_borders_RGB565(&dest, black);
            break;

        case GST_VIDEO_FORMAT_RGB15:
            vs_fill_borders_RGB555(&dest, black);
            break;

        default:
            break;
        }
    }

    sws_scale(scale->ctx, (const guint8**) in_data, scale->in_stride, 0,
              scale->in_height, out_data, scale->out_stride);

    return GST_FLOW_OK;
}
Esempio n. 2
0
static GstFlowReturn
gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
    GstBuffer * out)
{
  GstVideoScale *videoscale = GST_VIDEO_SCALE (trans);
  GstFlowReturn ret = GST_FLOW_OK;
  VSImage dest = { NULL, };
  VSImage src = { NULL, };
  VSImage dest_u = { NULL, };
  VSImage dest_v = { NULL, };
  VSImage src_u = { NULL, };
  VSImage src_v = { NULL, };
  gint method;
  const guint8 *black = _get_black_for_format (videoscale->format);
  gboolean add_borders;

  GST_OBJECT_LOCK (videoscale);
  method = videoscale->method;
  add_borders = videoscale->add_borders;
  GST_OBJECT_UNLOCK (videoscale);

  if (videoscale->from_width == 1) {
    method = GST_VIDEO_SCALE_NEAREST;
  }
  if (method == GST_VIDEO_SCALE_4TAP &&
      (videoscale->from_width < 4 || videoscale->from_height < 4)) {
    method = GST_VIDEO_SCALE_BILINEAR;
  }

  gst_video_scale_setup_vs_image (&src, videoscale->format, 0,
      videoscale->from_width, videoscale->from_height, 0, 0,
      GST_BUFFER_DATA (in));
  gst_video_scale_setup_vs_image (&dest, videoscale->format, 0,
      videoscale->to_width, videoscale->to_height, videoscale->borders_w,
      videoscale->borders_h, GST_BUFFER_DATA (out));

  if (videoscale->format == GST_VIDEO_FORMAT_I420
      || videoscale->format == GST_VIDEO_FORMAT_YV12
      || videoscale->format == GST_VIDEO_FORMAT_Y444
      || videoscale->format == GST_VIDEO_FORMAT_Y42B
      || videoscale->format == GST_VIDEO_FORMAT_Y41B) {
    gst_video_scale_setup_vs_image (&src_u, videoscale->format, 1,
        videoscale->from_width, videoscale->from_height, 0, 0,
        GST_BUFFER_DATA (in));
    gst_video_scale_setup_vs_image (&src_v, videoscale->format, 2,
        videoscale->from_width, videoscale->from_height, 0, 0,
        GST_BUFFER_DATA (in));
    gst_video_scale_setup_vs_image (&dest_u, videoscale->format, 1,
        videoscale->to_width, videoscale->to_height, videoscale->borders_w,
        videoscale->borders_h, GST_BUFFER_DATA (out));
    gst_video_scale_setup_vs_image (&dest_v, videoscale->format, 2,
        videoscale->to_width, videoscale->to_height, videoscale->borders_w,
        videoscale->borders_h, GST_BUFFER_DATA (out));
  }

  switch (videoscale->format) {
    case GST_VIDEO_FORMAT_RGBx:
    case GST_VIDEO_FORMAT_xRGB:
    case GST_VIDEO_FORMAT_BGRx:
    case GST_VIDEO_FORMAT_xBGR:
    case GST_VIDEO_FORMAT_RGBA:
    case GST_VIDEO_FORMAT_ARGB:
    case GST_VIDEO_FORMAT_BGRA:
    case GST_VIDEO_FORMAT_ABGR:
    case GST_VIDEO_FORMAT_AYUV:
      if (add_borders)
        vs_fill_borders_RGBA (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_RGBA (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_RGBA (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_ARGB64:
    case GST_VIDEO_FORMAT_AYUV64:
      if (add_borders)
        vs_fill_borders_AYUV64 (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_AYUV64 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_AYUV64 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_AYUV64 (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_RGB:
    case GST_VIDEO_FORMAT_BGR:
    case GST_VIDEO_FORMAT_v308:
      if (add_borders)
        vs_fill_borders_RGB (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_RGB (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_RGB (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_RGB (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_YUY2:
    case GST_VIDEO_FORMAT_YVYU:
      if (add_borders)
        vs_fill_borders_YUYV (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_YUYV (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_YUYV (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_YUYV (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_UYVY:
      if (add_borders)
        vs_fill_borders_UYVY (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_UYVY (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_UYVY (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_UYVY (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_Y800:
    case GST_VIDEO_FORMAT_GRAY8:
      if (add_borders)
        vs_fill_borders_Y (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_GRAY16_LE:
    case GST_VIDEO_FORMAT_GRAY16_BE:
    case GST_VIDEO_FORMAT_Y16:
      if (add_borders)
        vs_fill_borders_Y16 (&dest, 0);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_Y16 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_Y16 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_Y16 (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_YV12:
    case GST_VIDEO_FORMAT_Y444:
    case GST_VIDEO_FORMAT_Y42B:
    case GST_VIDEO_FORMAT_Y41B:
      if (add_borders) {
        vs_fill_borders_Y (&dest, black);
        vs_fill_borders_Y (&dest_u, black + 1);
        vs_fill_borders_Y (&dest_v, black + 2);
      }
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf);
          vs_image_scale_nearest_Y (&dest_u, &src_u, videoscale->tmp_buf);
          vs_image_scale_nearest_Y (&dest_v, &src_v, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
          vs_image_scale_linear_Y (&dest_u, &src_u, videoscale->tmp_buf);
          vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf);
          vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf);
          vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_RGB16:
      if (add_borders)
        vs_fill_borders_RGB565 (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_RGB565 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_RGB565 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_RGB565 (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    case GST_VIDEO_FORMAT_RGB15:
      if (add_borders)
        vs_fill_borders_RGB555 (&dest, black);
      switch (method) {
        case GST_VIDEO_SCALE_NEAREST:
          vs_image_scale_nearest_RGB555 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_BILINEAR:
          vs_image_scale_linear_RGB555 (&dest, &src, videoscale->tmp_buf);
          break;
        case GST_VIDEO_SCALE_4TAP:
          vs_image_scale_4tap_RGB555 (&dest, &src, videoscale->tmp_buf);
          break;
        default:
          goto unknown_mode;
      }
      break;
    default:
      goto unsupported;
  }

  GST_LOG_OBJECT (videoscale, "pushing buffer of %d bytes",
      GST_BUFFER_SIZE (out));

  return ret;

  /* ERRORS */
unsupported:
  {
    GST_ELEMENT_ERROR (videoscale, STREAM, NOT_IMPLEMENTED, (NULL),
        ("Unsupported format %d for scaling method %d",
            videoscale->format, method));
    return GST_FLOW_ERROR;
  }
unknown_mode:
  {
    GST_ELEMENT_ERROR (videoscale, STREAM, NOT_IMPLEMENTED, (NULL),
        ("Unknown scaling method %d", videoscale->method));
    return GST_FLOW_ERROR;
  }
}