Ejemplo n.º 1
0
static gboolean
gst_video_scale_src_event (GstBaseTransform * trans, GstEvent * event)
{
  GstVideoScale *videoscale = GST_VIDEO_SCALE (trans);
  gboolean ret;
  gdouble a;
  GstStructure *structure;

  GST_DEBUG_OBJECT (videoscale, "handling %s event",
      GST_EVENT_TYPE_NAME (event));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NAVIGATION:
      event =
          GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event)));

      structure = (GstStructure *) gst_event_get_structure (event);
      if (gst_structure_get_double (structure, "pointer_x", &a)) {
        gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
            a * videoscale->from_width / videoscale->to_width, NULL);
      }
      if (gst_structure_get_double (structure, "pointer_y", &a)) {
        gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
            a * videoscale->from_height / videoscale->to_height, NULL);
      }
      break;
    default:
      break;
  }

  ret = GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event);

  return ret;
}
static void
gst_video_scale_set_property (GObject * object, guint prop_id,
                              const GValue * value, GParamSpec * pspec)
{
    GstVideoScale *vscale = GST_VIDEO_SCALE (object);

    switch (prop_id) {
    case PROP_METHOD:
        GST_OBJECT_LOCK (vscale);
        vscale->method = g_value_get_enum (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    case PROP_ADD_BORDERS:
        GST_OBJECT_LOCK (vscale);
        vscale->add_borders = g_value_get_boolean (value);
        GST_OBJECT_UNLOCK (vscale);
        gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM_CAST (vscale));
        break;
    case PROP_SHARPNESS:
        GST_OBJECT_LOCK (vscale);
        vscale->sharpness = g_value_get_double (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    case PROP_SHARPEN:
        GST_OBJECT_LOCK (vscale);
        vscale->sharpen = g_value_get_double (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    case PROP_DITHER:
        GST_OBJECT_LOCK (vscale);
        vscale->dither = g_value_get_boolean (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    case PROP_SUBMETHOD:
        GST_OBJECT_LOCK (vscale);
        vscale->submethod = g_value_get_int (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    case PROP_ENVELOPE:
        GST_OBJECT_LOCK (vscale);
        vscale->envelope = g_value_get_double (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    case PROP_GAMMA_DECODE:
        GST_OBJECT_LOCK (vscale);
        vscale->gamma_decode = g_value_get_boolean (value);
        GST_OBJECT_UNLOCK (vscale);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}
Ejemplo n.º 3
0
static void
gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstVideoScale *vscale = GST_VIDEO_SCALE (object);

  switch (prop_id) {
    case PROP_METHOD:
      GST_OBJECT_LOCK (vscale);
      g_value_set_enum (value, vscale->method);
      GST_OBJECT_UNLOCK (vscale);
      break;
    case PROP_ADD_BORDERS:
      GST_OBJECT_LOCK (vscale);
      g_value_set_boolean (value, vscale->add_borders);
      GST_OBJECT_UNLOCK (vscale);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Ejemplo n.º 4
0
static void
gst_video_scale_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstVideoScale *vscale = GST_VIDEO_SCALE (object);

  switch (prop_id) {
    case PROP_METHOD:
      GST_OBJECT_LOCK (vscale);
      vscale->method = g_value_get_enum (value);
      GST_OBJECT_UNLOCK (vscale);
      break;
    case PROP_ADD_BORDERS:
      GST_OBJECT_LOCK (vscale);
      vscale->add_borders = g_value_get_boolean (value);
      GST_OBJECT_UNLOCK (vscale);
      gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (vscale));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static gboolean
gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in,
                          GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info)
{
    GstVideoScale *videoscale = GST_VIDEO_SCALE (filter);
    gint from_dar_n, from_dar_d, to_dar_n, to_dar_d;

    if (!gst_util_fraction_multiply (in_info->width,
                                     in_info->height, in_info->par_n, in_info->par_d, &from_dar_n,
                                     &from_dar_d)) {
        from_dar_n = from_dar_d = -1;
    }

    if (!gst_util_fraction_multiply (out_info->width,
                                     out_info->height, out_info->par_n, out_info->par_d, &to_dar_n,
                                     &to_dar_d)) {
        to_dar_n = to_dar_d = -1;
    }

    videoscale->borders_w = videoscale->borders_h = 0;
    if (to_dar_n != from_dar_n || to_dar_d != from_dar_d) {
        if (videoscale->add_borders) {
            gint n, d, to_h, to_w;

            if (from_dar_n != -1 && from_dar_d != -1
                    && gst_util_fraction_multiply (from_dar_n, from_dar_d,
                                                   out_info->par_d, out_info->par_n, &n, &d)) {
                to_h = gst_util_uint64_scale_int (out_info->width, d, n);
                if (to_h <= out_info->height) {
                    videoscale->borders_h = out_info->height - to_h;
                    videoscale->borders_w = 0;
                } else {
                    to_w = gst_util_uint64_scale_int (out_info->height, n, d);
                    g_assert (to_w <= out_info->width);
                    videoscale->borders_h = 0;
                    videoscale->borders_w = out_info->width - to_w;
                }
            } else {
                GST_WARNING_OBJECT (videoscale, "Can't calculate borders");
            }
        } else {
            GST_WARNING_OBJECT (videoscale, "Can't keep DAR!");
        }
    }

    if (in_info->width == out_info->width && in_info->height == out_info->height
            && videoscale->borders_w == 0 && videoscale->borders_h == 0) {
        gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), TRUE);
    } else {
        GstStructure *options;
        GST_CAT_DEBUG_OBJECT (CAT_PERFORMANCE, filter, "setup videoscaling");
        gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), FALSE);

        options = gst_structure_new_empty ("videoscale");

        switch (videoscale->method) {
        case GST_VIDEO_SCALE_NEAREST:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_NEAREST,
                               NULL);
            break;
        case GST_VIDEO_SCALE_BILINEAR:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_LINEAR,
                               GST_VIDEO_RESAMPLER_OPT_MAX_TAPS, G_TYPE_INT, 2, NULL);
            break;
        case GST_VIDEO_SCALE_4TAP:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_SINC,
                               GST_VIDEO_RESAMPLER_OPT_MAX_TAPS, G_TYPE_INT, 4, NULL);
            break;
        case GST_VIDEO_SCALE_LANCZOS:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_LANCZOS,
                               NULL);
            break;
        case GST_VIDEO_SCALE_BILINEAR2:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_LINEAR,
                               NULL);
            break;
        case GST_VIDEO_SCALE_SINC:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_SINC,
                               NULL);
            break;
        case GST_VIDEO_SCALE_HERMITE:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 0.0,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 0.0,
                               NULL);
            break;
        case GST_VIDEO_SCALE_SPLINE:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 1.0,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 0.0,
                               NULL);
            break;
        case GST_VIDEO_SCALE_CATROM:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 0.0,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 0.5,
                               NULL);
            break;
        case GST_VIDEO_SCALE_MITCHELL:
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
                               GST_TYPE_VIDEO_RESAMPLER_METHOD, GST_VIDEO_RESAMPLER_METHOD_CUBIC,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_B, G_TYPE_DOUBLE, (gdouble) 1.0 / 3.0,
                               GST_VIDEO_RESAMPLER_OPT_CUBIC_C, G_TYPE_DOUBLE, (gdouble) 1.0 / 3.0,
                               NULL);
            break;
        }
        gst_structure_set (options,
                           GST_VIDEO_RESAMPLER_OPT_ENVELOPE, G_TYPE_DOUBLE, videoscale->envelope,
                           GST_VIDEO_RESAMPLER_OPT_SHARPNESS, G_TYPE_DOUBLE, videoscale->sharpness,
                           GST_VIDEO_RESAMPLER_OPT_SHARPEN, G_TYPE_DOUBLE, videoscale->sharpen,
                           GST_VIDEO_CONVERTER_OPT_DEST_X, G_TYPE_INT, videoscale->borders_w / 2,
                           GST_VIDEO_CONVERTER_OPT_DEST_Y, G_TYPE_INT, videoscale->borders_h / 2,
                           GST_VIDEO_CONVERTER_OPT_DEST_WIDTH, G_TYPE_INT,
                           out_info->width - videoscale->borders_w,
                           GST_VIDEO_CONVERTER_OPT_DEST_HEIGHT, G_TYPE_INT,
                           out_info->height - videoscale->borders_h,
                           GST_VIDEO_CONVERTER_OPT_MATRIX_MODE, GST_TYPE_VIDEO_MATRIX_MODE,
                           GST_VIDEO_MATRIX_MODE_NONE, GST_VIDEO_CONVERTER_OPT_DITHER_METHOD,
                           GST_TYPE_VIDEO_DITHER_METHOD, GST_VIDEO_DITHER_NONE,
                           GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, GST_TYPE_VIDEO_CHROMA_MODE,
                           GST_VIDEO_CHROMA_MODE_NONE, NULL);

        if (videoscale->gamma_decode) {
            gst_structure_set (options,
                               GST_VIDEO_CONVERTER_OPT_GAMMA_MODE, GST_TYPE_VIDEO_GAMMA_MODE,
                               GST_VIDEO_GAMMA_MODE_REMAP, NULL);
        }

        if (videoscale->convert)
            gst_video_converter_free (videoscale->convert);
        videoscale->convert = gst_video_converter_new (in_info, out_info, options);
    }

    GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %"
                      G_GSIZE_FORMAT " -> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), "
                      "size %" G_GSIZE_FORMAT,
                      in_info->width, in_info->height, in_info->par_n, in_info->par_d,
                      from_dar_n, from_dar_d, in_info->size, out_info->width,
                      out_info->height, out_info->par_n, out_info->par_d, to_dar_n, to_dar_d,
                      videoscale->borders_w, videoscale->borders_h, out_info->size);

    return TRUE;
}
Ejemplo n.º 6
0
static gboolean
gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
{
  GstVideoScale *videoscale = GST_VIDEO_SCALE (trans);
  gboolean ret;
  gint from_dar_n, from_dar_d, to_dar_n, to_dar_d;
  gint from_par_n, from_par_d, to_par_n, to_par_d;

  ret =
      gst_video_format_parse_caps (in, &videoscale->format,
      &videoscale->from_width, &videoscale->from_height);
  ret &=
      gst_video_format_parse_caps (out, NULL, &videoscale->to_width,
      &videoscale->to_height);
  if (!ret)
    goto done;

  videoscale->src_size = gst_video_format_get_size (videoscale->format,
      videoscale->from_width, videoscale->from_height);
  videoscale->dest_size = gst_video_format_get_size (videoscale->format,
      videoscale->to_width, videoscale->to_height);

  if (!gst_video_parse_caps_pixel_aspect_ratio (in, &from_par_n, &from_par_d))
    from_par_n = from_par_d = 1;
  if (!gst_video_parse_caps_pixel_aspect_ratio (out, &to_par_n, &to_par_d))
    to_par_n = to_par_d = 1;

  if (!gst_util_fraction_multiply (videoscale->from_width,
          videoscale->from_height, from_par_n, from_par_d, &from_dar_n,
          &from_dar_d)) {
    from_dar_n = from_dar_d = -1;
  }

  if (!gst_util_fraction_multiply (videoscale->to_width,
          videoscale->to_height, to_par_n, to_par_d, &to_dar_n, &to_dar_d)) {
    to_dar_n = to_dar_d = -1;
  }

  videoscale->borders_w = videoscale->borders_h = 0;
  if (to_dar_n != from_dar_n || to_dar_d != from_dar_d) {
    if (videoscale->add_borders) {
      gint n, d, to_h, to_w;

      if (from_dar_n != -1 && from_dar_d != -1
          && gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n,
              to_par_d, &n, &d)) {
        to_h = gst_util_uint64_scale_int (videoscale->to_width, d, n);
        if (to_h <= videoscale->to_height) {
          videoscale->borders_h = videoscale->to_height - to_h;
          videoscale->borders_w = 0;
        } else {
          to_w = gst_util_uint64_scale_int (videoscale->to_height, n, d);
          g_assert (to_w <= videoscale->to_width);
          videoscale->borders_h = 0;
          videoscale->borders_w = videoscale->to_width - to_w;
        }
      } else {
        GST_WARNING_OBJECT (videoscale, "Can't calculate borders");
      }
    } else {
      GST_WARNING_OBJECT (videoscale, "Can't keep DAR!");
    }
  }

  if (videoscale->tmp_buf)
    g_free (videoscale->tmp_buf);
  videoscale->tmp_buf = g_malloc (videoscale->to_width * 8 * 4);

  gst_base_transform_set_passthrough (trans,
      (videoscale->from_width == videoscale->to_width
          && videoscale->from_height == videoscale->to_height));

  GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %d "
      "-> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), size %d",
      videoscale->from_width, videoscale->from_height, from_par_n, from_par_d,
      from_dar_n, from_dar_d, videoscale->src_size, videoscale->to_width,
      videoscale->to_height, to_par_n, to_par_d, to_dar_n, to_dar_d,
      videoscale->borders_w, videoscale->borders_h, videoscale->dest_size);

done:
  return ret;
}
Ejemplo n.º 7
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;
  }
}