mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-26 07:56:38 +00:00
videoscale: Add support for adding black borders to keep the DAR if necessary
Fixes bug #617506.
This commit is contained in:
parent
619e5b6e44
commit
52e711b11d
7 changed files with 804 additions and 198 deletions
|
@ -7,7 +7,8 @@ libgstvideoscale_la_SOURCES = \
|
||||||
gstvideoscale.c \
|
gstvideoscale.c \
|
||||||
vs_image.c \
|
vs_image.c \
|
||||||
vs_scanline.c \
|
vs_scanline.c \
|
||||||
vs_4tap.c
|
vs_4tap.c \
|
||||||
|
vs_fill_borders.c
|
||||||
|
|
||||||
nodist_libgstvideoscale_la_SOURCES = $(ORC_NODIST_SOURCES)
|
nodist_libgstvideoscale_la_SOURCES = $(ORC_NODIST_SOURCES)
|
||||||
|
|
||||||
|
@ -22,6 +23,6 @@ noinst_HEADERS = \
|
||||||
gstvideoscale.h \
|
gstvideoscale.h \
|
||||||
vs_image.h \
|
vs_image.h \
|
||||||
vs_scanline.h \
|
vs_scanline.h \
|
||||||
vs_4tap.h
|
vs_4tap.h \
|
||||||
|
vs_fill_borders.h
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,26 @@
|
||||||
* Last reviewed on 2006-03-02 (0.10.4)
|
* Last reviewed on 2006-03-02 (0.10.4)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Formulas for PAR, DAR, width and height relations:
|
||||||
|
*
|
||||||
|
* dar_n w par_n
|
||||||
|
* ----- = - * -----
|
||||||
|
* dar_d h par_d
|
||||||
|
*
|
||||||
|
* par_n h dar_n
|
||||||
|
* ----- = - * -----
|
||||||
|
* par_d w dar_d
|
||||||
|
*
|
||||||
|
* dar_n par_d
|
||||||
|
* w = h * ----- * -----
|
||||||
|
* dar_d par_n
|
||||||
|
*
|
||||||
|
* dar_d par_n
|
||||||
|
* h = w * ----- * -----
|
||||||
|
* dar_n par_d
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -61,17 +81,19 @@
|
||||||
#include "gstvideoscale.h"
|
#include "gstvideoscale.h"
|
||||||
#include "vs_image.h"
|
#include "vs_image.h"
|
||||||
#include "vs_4tap.h"
|
#include "vs_4tap.h"
|
||||||
|
#include "vs_fill_borders.h"
|
||||||
|
|
||||||
/* debug variable definition */
|
/* debug variable definition */
|
||||||
GST_DEBUG_CATEGORY (video_scale_debug);
|
GST_DEBUG_CATEGORY (video_scale_debug);
|
||||||
|
|
||||||
#define DEFAULT_PROP_METHOD GST_VIDEO_SCALE_BILINEAR
|
#define DEFAULT_PROP_METHOD GST_VIDEO_SCALE_BILINEAR
|
||||||
|
#define DEFAULT_PROP_ADD_BORDERS FALSE
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_METHOD
|
PROP_METHOD,
|
||||||
|
PROP_ADD_BORDERS
|
||||||
/* FILL ME */
|
/* FILL ME */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -220,6 +242,12 @@ gst_video_scale_class_init (GstVideoScaleClass * klass)
|
||||||
GST_TYPE_VIDEO_SCALE_METHOD, DEFAULT_PROP_METHOD,
|
GST_TYPE_VIDEO_SCALE_METHOD, DEFAULT_PROP_METHOD,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ADD_BORDERS,
|
||||||
|
g_param_spec_boolean ("borders", "Add Borders",
|
||||||
|
"Add black borders if necessary to keep the display aspect ratio",
|
||||||
|
DEFAULT_PROP_ADD_BORDERS,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
trans_class->transform_caps =
|
trans_class->transform_caps =
|
||||||
GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps);
|
GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps);
|
||||||
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_scale_set_caps);
|
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_scale_set_caps);
|
||||||
|
@ -235,6 +263,7 @@ gst_video_scale_init (GstVideoScale * videoscale, GstVideoScaleClass * klass)
|
||||||
{
|
{
|
||||||
videoscale->tmp_buf = NULL;
|
videoscale->tmp_buf = NULL;
|
||||||
videoscale->method = DEFAULT_PROP_METHOD;
|
videoscale->method = DEFAULT_PROP_METHOD;
|
||||||
|
videoscale->add_borders = DEFAULT_PROP_ADD_BORDERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -258,6 +287,12 @@ gst_video_scale_set_property (GObject * object, guint prop_id,
|
||||||
vscale->method = g_value_get_enum (value);
|
vscale->method = g_value_get_enum (value);
|
||||||
GST_OBJECT_UNLOCK (vscale);
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -276,6 +311,11 @@ gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
g_value_set_enum (value, vscale->method);
|
g_value_set_enum (value, vscale->method);
|
||||||
GST_OBJECT_UNLOCK (vscale);
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
break;
|
break;
|
||||||
|
case PROP_ADD_BORDERS:
|
||||||
|
GST_OBJECT_LOCK (vscale);
|
||||||
|
g_value_set_boolean (value, vscale->add_borders);
|
||||||
|
GST_OBJECT_UNLOCK (vscale);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -313,17 +353,6 @@ gst_video_scale_transform_caps (GstBaseTransform * trans,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_scale_setup_vs_image (VSImage * image, GstVideoFormat format,
|
|
||||||
gint component, gint width, gint height)
|
|
||||||
{
|
|
||||||
image->width =
|
|
||||||
gst_video_format_get_component_width (format, component, width);
|
|
||||||
image->height =
|
|
||||||
gst_video_format_get_component_height (format, component, height);
|
|
||||||
image->stride = gst_video_format_get_row_stride (format, component, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
|
gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
|
||||||
{
|
{
|
||||||
|
@ -341,21 +370,11 @@ gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
|
||||||
videoscale->src_size = gst_video_format_get_size (videoscale->format,
|
videoscale->src_size = gst_video_format_get_size (videoscale->format,
|
||||||
videoscale->from_width, videoscale->from_height);
|
videoscale->from_width, videoscale->from_height);
|
||||||
videoscale->dest_size = gst_video_format_get_size (videoscale->format,
|
videoscale->dest_size = gst_video_format_get_size (videoscale->format,
|
||||||
videoscale->to_width, videoscale->to_height);
|
videoscale->to_width, videoscale->to_height);
|
||||||
|
|
||||||
gst_video_scale_setup_vs_image (&videoscale->src, videoscale->format, 0,
|
|
||||||
videoscale->from_width, videoscale->from_height);
|
|
||||||
gst_video_scale_setup_vs_image (&videoscale->dest, videoscale->format, 0,
|
|
||||||
videoscale->to_width, videoscale->to_height);
|
|
||||||
|
|
||||||
if (videoscale->tmp_buf)
|
|
||||||
g_free (videoscale->tmp_buf);
|
|
||||||
videoscale->tmp_buf = g_malloc (videoscale->dest.stride * 4);
|
|
||||||
|
|
||||||
if (!gst_video_parse_caps_pixel_aspect_ratio (in, &from_par_n, &from_par_d))
|
if (!gst_video_parse_caps_pixel_aspect_ratio (in, &from_par_n, &from_par_d))
|
||||||
from_par_n = from_par_d = 1;
|
from_par_n = from_par_d = 1;
|
||||||
if (!gst_video_parse_caps_pixel_aspect_ratio (out, &to_par_n, &to_par_d))
|
if (!gst_video_parse_caps_pixel_aspect_ratio (out, &to_par_n, &to_par_d))
|
||||||
|
@ -367,24 +386,53 @@ gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
|
||||||
from_dar_n = from_dar_d = -1;
|
from_dar_n = from_dar_d = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_util_fraction_multiply (videoscale->to_width, videoscale->to_height,
|
if (!gst_util_fraction_multiply (videoscale->to_width,
|
||||||
to_par_n, to_par_d, &to_dar_n, &to_dar_d)) {
|
videoscale->to_height, to_par_n, to_par_d, &to_dar_n, &to_dar_d)) {
|
||||||
to_dar_n = to_dar_d = -1;
|
to_dar_n = to_dar_d = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_dar_n != from_dar_n || to_dar_d != from_dar_d)
|
videoscale->borders_w = videoscale->borders_h = 0;
|
||||||
GST_WARNING_OBJECT (videoscale, "Can't keep DAR!");
|
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 (gst_video_format_get_row_stride (videoscale->format, 0,
|
||||||
|
videoscale->to_width) * 4);
|
||||||
|
|
||||||
gst_base_transform_set_passthrough (trans,
|
gst_base_transform_set_passthrough (trans,
|
||||||
(videoscale->from_width == videoscale->to_width
|
(videoscale->from_width == videoscale->to_width
|
||||||
&& videoscale->from_height == videoscale->to_height));
|
&& videoscale->from_height == videoscale->to_height));
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %d "
|
GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %d "
|
||||||
"-> to=%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,
|
videoscale->from_width, videoscale->from_height, from_par_n, from_par_d,
|
||||||
from_dar_n, from_dar_d, videoscale->src_size, videoscale->to_width,
|
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->to_height, to_par_n, to_par_d, to_dar_n, to_dar_d,
|
||||||
videoscale->dest_size);
|
videoscale->borders_w, videoscale->borders_h, videoscale->dest_size);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -814,33 +862,113 @@ done:
|
||||||
g_value_unset (&tpar);
|
g_value_unset (&tpar);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
gst_video_scale_prepare_image (gint format, GstBuffer * buf,
|
gst_video_scale_setup_vs_image (VSImage * image, GstVideoFormat format,
|
||||||
VSImage * img, VSImage * img_u, VSImage * img_v)
|
gint component, gint width, gint height, gint b_w, gint b_h, uint8_t * data)
|
||||||
{
|
{
|
||||||
gboolean res = TRUE;
|
image->real_width =
|
||||||
|
gst_video_format_get_component_width (format, component, width);
|
||||||
|
image->real_height =
|
||||||
|
gst_video_format_get_component_height (format, component, height);
|
||||||
|
image->width =
|
||||||
|
gst_video_format_get_component_width (format, component, MAX (1,
|
||||||
|
width - b_w));
|
||||||
|
image->height =
|
||||||
|
gst_video_format_get_component_height (format, component, MAX (1,
|
||||||
|
height - b_h));
|
||||||
|
image->stride = gst_video_format_get_row_stride (format, component, width);
|
||||||
|
|
||||||
|
image->border_top = (image->real_height - image->height) / 2;
|
||||||
|
image->border_bottom = image->real_height - image->height - image->border_top;
|
||||||
|
|
||||||
|
if (format == GST_VIDEO_FORMAT_YUY2 || format == GST_VIDEO_FORMAT_YVYU
|
||||||
|
|| format == GST_VIDEO_FORMAT_UYVY) {
|
||||||
|
g_assert (component == 0);
|
||||||
|
|
||||||
|
image->border_left = (image->real_width - image->width) / 2;
|
||||||
|
|
||||||
|
if (image->border_left % 2 == 1)
|
||||||
|
image->border_left--;
|
||||||
|
image->border_right = image->real_width - image->width - image->border_left;
|
||||||
|
} else {
|
||||||
|
image->border_left = (image->real_width - image->width) / 2;
|
||||||
|
image->border_right = image->real_width - image->width - image->border_left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == GST_VIDEO_FORMAT_I420
|
||||||
|
|| format == GST_VIDEO_FORMAT_YV12
|
||||||
|
|| format == GST_VIDEO_FORMAT_Y444
|
||||||
|
|| format == GST_VIDEO_FORMAT_Y42B || format == GST_VIDEO_FORMAT_Y41B) {
|
||||||
|
image->real_pixels = data + gst_video_format_get_component_offset (format,
|
||||||
|
component, width, height);
|
||||||
|
} else {
|
||||||
|
g_assert (component == 0);
|
||||||
|
image->real_pixels = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->pixels =
|
||||||
|
image->real_pixels + image->border_top * image->stride +
|
||||||
|
image->border_left * gst_video_format_get_pixel_stride (format,
|
||||||
|
component);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const guint8 *
|
||||||
|
_get_black_for_format (GstVideoFormat format)
|
||||||
|
{
|
||||||
|
static const guint8 black[][4] = {
|
||||||
|
{255, 0, 0, 0}, /* 0 = ARGB, ABGR, xRGB, xBGR */
|
||||||
|
{0, 0, 0, 255}, /* 1 = RGBA, BGRA, RGBx, BGRx */
|
||||||
|
{255, 16, 128, 128}, /* 2 = AYUV */
|
||||||
|
{0, 0, 0, 0}, /* 3 = RGB and BGR */
|
||||||
|
{16, 128, 128, 0}, /* 4 = v301 */
|
||||||
|
{16, 128, 16, 128}, /* 5 = YUY2, YUYV */
|
||||||
|
{128, 16, 128, 16}, /* 6 = UYVY */
|
||||||
|
{16, 0, 0, 0}, /* 7 = Y */
|
||||||
|
{0, 0, 0, 0} /* 8 = RGB565, RGB666 */
|
||||||
|
};
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
case GST_VIDEO_FORMAT_ARGB:
|
||||||
|
case GST_VIDEO_FORMAT_ABGR:
|
||||||
|
case GST_VIDEO_FORMAT_xRGB:
|
||||||
|
case GST_VIDEO_FORMAT_xBGR:
|
||||||
|
return black[0];
|
||||||
|
case GST_VIDEO_FORMAT_RGBA:
|
||||||
|
case GST_VIDEO_FORMAT_BGRA:
|
||||||
|
case GST_VIDEO_FORMAT_RGBx:
|
||||||
|
case GST_VIDEO_FORMAT_BGRx:
|
||||||
|
return black[1];
|
||||||
|
case GST_VIDEO_FORMAT_AYUV:
|
||||||
|
return black[2];
|
||||||
|
case GST_VIDEO_FORMAT_RGB:
|
||||||
|
case GST_VIDEO_FORMAT_BGR:
|
||||||
|
return black[3];
|
||||||
|
case GST_VIDEO_FORMAT_v308:
|
||||||
|
return black[4];
|
||||||
|
case GST_VIDEO_FORMAT_YUY2:
|
||||||
|
case GST_VIDEO_FORMAT_YVYU:
|
||||||
|
return black[5];
|
||||||
|
case GST_VIDEO_FORMAT_UYVY:
|
||||||
|
return black[6];
|
||||||
|
case GST_VIDEO_FORMAT_Y800:
|
||||||
|
case GST_VIDEO_FORMAT_GRAY8:
|
||||||
|
return black[7];
|
||||||
|
case GST_VIDEO_FORMAT_GRAY16_LE:
|
||||||
|
case GST_VIDEO_FORMAT_GRAY16_BE:
|
||||||
|
case GST_VIDEO_FORMAT_Y16:
|
||||||
|
return NULL; /* Handled by the caller */
|
||||||
case GST_VIDEO_FORMAT_I420:
|
case GST_VIDEO_FORMAT_I420:
|
||||||
case GST_VIDEO_FORMAT_YV12:
|
case GST_VIDEO_FORMAT_YV12:
|
||||||
case GST_VIDEO_FORMAT_Y444:
|
case GST_VIDEO_FORMAT_Y444:
|
||||||
case GST_VIDEO_FORMAT_Y42B:
|
case GST_VIDEO_FORMAT_Y42B:
|
||||||
case GST_VIDEO_FORMAT_Y41B:
|
case GST_VIDEO_FORMAT_Y41B:
|
||||||
gst_video_scale_setup_vs_image (img_u, format, 1, img->width,
|
return black[4]; /* Y, U, V, 0 */
|
||||||
img->height);
|
case GST_VIDEO_FORMAT_RGB16:
|
||||||
gst_video_scale_setup_vs_image (img_v, format, 2, img->width,
|
case GST_VIDEO_FORMAT_RGB15:
|
||||||
img->height);
|
return black[8];
|
||||||
img_u->pixels =
|
|
||||||
GST_BUFFER_DATA (buf) + gst_video_format_get_component_offset (format,
|
|
||||||
1, img->width, img->height);
|
|
||||||
img_v->pixels =
|
|
||||||
GST_BUFFER_DATA (buf) + gst_video_format_get_component_offset (format,
|
|
||||||
2, img->width, img->height);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
return NULL;
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -849,195 +977,230 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
|
||||||
{
|
{
|
||||||
GstVideoScale *videoscale = GST_VIDEO_SCALE (trans);
|
GstVideoScale *videoscale = GST_VIDEO_SCALE (trans);
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
VSImage dest = videoscale->dest;
|
VSImage dest = { NULL, };
|
||||||
VSImage src = videoscale->src;
|
VSImage src = { NULL, };
|
||||||
VSImage dest_u = { NULL, };
|
VSImage dest_u = { NULL, };
|
||||||
VSImage dest_v = { NULL, };
|
VSImage dest_v = { NULL, };
|
||||||
VSImage src_u = { NULL, };
|
VSImage src_u = { NULL, };
|
||||||
VSImage src_v = { NULL, };
|
VSImage src_v = { NULL, };
|
||||||
gint method;
|
gint method;
|
||||||
|
const guint8 *black = _get_black_for_format (videoscale->format);
|
||||||
|
gboolean add_borders;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (videoscale);
|
GST_OBJECT_LOCK (videoscale);
|
||||||
method = videoscale->method;
|
method = videoscale->method;
|
||||||
|
add_borders = videoscale->add_borders;
|
||||||
GST_OBJECT_UNLOCK (videoscale);
|
GST_OBJECT_UNLOCK (videoscale);
|
||||||
|
|
||||||
src.pixels = GST_BUFFER_DATA (in);
|
gst_video_scale_setup_vs_image (&src, videoscale->format, 0,
|
||||||
dest.pixels = GST_BUFFER_DATA (out);
|
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 (src.height < 4 && method == GST_VIDEO_SCALE_4TAP)
|
if (videoscale->format == GST_VIDEO_FORMAT_I420
|
||||||
method = GST_VIDEO_SCALE_BILINEAR;
|
|| 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));
|
||||||
|
}
|
||||||
|
|
||||||
gst_video_scale_prepare_image (videoscale->format, in, &videoscale->src,
|
switch (videoscale->format) {
|
||||||
&src_u, &src_v);
|
case GST_VIDEO_FORMAT_RGBx:
|
||||||
gst_video_scale_prepare_image (videoscale->format, out, &videoscale->dest,
|
case GST_VIDEO_FORMAT_xRGB:
|
||||||
&dest_u, &dest_v);
|
case GST_VIDEO_FORMAT_BGRx:
|
||||||
|
case GST_VIDEO_FORMAT_xBGR:
|
||||||
switch (method) {
|
case GST_VIDEO_FORMAT_RGBA:
|
||||||
case GST_VIDEO_SCALE_NEAREST:
|
case GST_VIDEO_FORMAT_ARGB:
|
||||||
GST_LOG_OBJECT (videoscale, "doing nearest scaling");
|
case GST_VIDEO_FORMAT_BGRA:
|
||||||
switch (videoscale->format) {
|
case GST_VIDEO_FORMAT_ABGR:
|
||||||
case GST_VIDEO_FORMAT_RGBx:
|
case GST_VIDEO_FORMAT_AYUV:
|
||||||
case GST_VIDEO_FORMAT_xRGB:
|
if (add_borders)
|
||||||
case GST_VIDEO_FORMAT_BGRx:
|
vs_fill_borders_RGBA (&dest, black);
|
||||||
case GST_VIDEO_FORMAT_xBGR:
|
switch (method) {
|
||||||
case GST_VIDEO_FORMAT_RGBA:
|
case GST_VIDEO_SCALE_NEAREST:
|
||||||
case GST_VIDEO_FORMAT_ARGB:
|
|
||||||
case GST_VIDEO_FORMAT_BGRA:
|
|
||||||
case GST_VIDEO_FORMAT_ABGR:
|
|
||||||
case GST_VIDEO_FORMAT_AYUV:
|
|
||||||
vs_image_scale_nearest_RGBA (&dest, &src, videoscale->tmp_buf);
|
vs_image_scale_nearest_RGBA (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_RGB:
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
case GST_VIDEO_FORMAT_BGR:
|
vs_image_scale_linear_RGBA (&dest, &src, videoscale->tmp_buf);
|
||||||
case GST_VIDEO_FORMAT_v308:
|
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_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);
|
vs_image_scale_nearest_RGB (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_YUY2:
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
case GST_VIDEO_FORMAT_YVYU:
|
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);
|
vs_image_scale_nearest_YUYV (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_UYVY:
|
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);
|
vs_image_scale_nearest_UYVY (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_Y800:
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
case GST_VIDEO_FORMAT_GRAY8:
|
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);
|
vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_GRAY16_LE:
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
case GST_VIDEO_FORMAT_GRAY16_BE:
|
vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
|
||||||
case GST_VIDEO_FORMAT_Y16:
|
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);
|
vs_image_scale_nearest_Y16 (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_I420:
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
case GST_VIDEO_FORMAT_YV12:
|
vs_image_scale_linear_Y16 (&dest, &src, videoscale->tmp_buf);
|
||||||
case GST_VIDEO_FORMAT_Y444:
|
break;
|
||||||
case GST_VIDEO_FORMAT_Y42B:
|
case GST_VIDEO_SCALE_4TAP:
|
||||||
case GST_VIDEO_FORMAT_Y41B:
|
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, &src, videoscale->tmp_buf);
|
||||||
vs_image_scale_nearest_Y (&dest_u, &src_u, 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);
|
vs_image_scale_nearest_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_RGB16:
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
vs_image_scale_nearest_RGB565 (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_RGB15:
|
|
||||||
vs_image_scale_nearest_RGB555 (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto unsupported;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_SCALE_BILINEAR:
|
|
||||||
GST_LOG_OBJECT (videoscale, "doing bilinear scaling");
|
|
||||||
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:
|
|
||||||
vs_image_scale_linear_RGBA (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_RGB:
|
|
||||||
case GST_VIDEO_FORMAT_BGR:
|
|
||||||
case GST_VIDEO_FORMAT_v308:
|
|
||||||
vs_image_scale_linear_RGB (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_YUY2:
|
|
||||||
case GST_VIDEO_FORMAT_YVYU:
|
|
||||||
vs_image_scale_linear_YUYV (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_UYVY:
|
|
||||||
vs_image_scale_linear_UYVY (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_Y800:
|
|
||||||
case GST_VIDEO_FORMAT_GRAY8:
|
|
||||||
vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_GRAY16_LE:
|
|
||||||
case GST_VIDEO_FORMAT_GRAY16_BE:
|
|
||||||
case GST_VIDEO_FORMAT_Y16:
|
|
||||||
vs_image_scale_linear_Y16 (&dest, &src, videoscale->tmp_buf);
|
|
||||||
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_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
|
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_u, &src_u, videoscale->tmp_buf);
|
||||||
vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_RGB16:
|
case GST_VIDEO_SCALE_4TAP:
|
||||||
vs_image_scale_linear_RGB565 (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_RGB15:
|
|
||||||
vs_image_scale_linear_RGB555 (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto unsupported;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_SCALE_4TAP:
|
|
||||||
GST_LOG_OBJECT (videoscale, "doing 4tap scaling");
|
|
||||||
|
|
||||||
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:
|
|
||||||
vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_RGB:
|
|
||||||
case GST_VIDEO_FORMAT_BGR:
|
|
||||||
case GST_VIDEO_FORMAT_v308:
|
|
||||||
vs_image_scale_4tap_RGB (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_YUY2:
|
|
||||||
case GST_VIDEO_FORMAT_YVYU:
|
|
||||||
vs_image_scale_4tap_YUYV (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_UYVY:
|
|
||||||
vs_image_scale_4tap_UYVY (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_Y800:
|
|
||||||
case GST_VIDEO_FORMAT_GRAY8:
|
|
||||||
vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf);
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_FORMAT_GRAY16_LE:
|
|
||||||
case GST_VIDEO_FORMAT_GRAY16_BE:
|
|
||||||
case GST_VIDEO_FORMAT_Y16:
|
|
||||||
vs_image_scale_4tap_Y16 (&dest, &src, videoscale->tmp_buf);
|
|
||||||
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_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf);
|
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_u, &src_u, videoscale->tmp_buf);
|
||||||
vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_RGB16:
|
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);
|
vs_image_scale_4tap_RGB565 (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_RGB15:
|
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);
|
vs_image_scale_4tap_RGB555 (&dest, &src, videoscale->tmp_buf);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto unsupported;
|
goto unknown_mode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto unknown_mode;
|
goto unsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (videoscale, "pushing buffer of %d bytes",
|
GST_LOG_OBJECT (videoscale, "pushing buffer of %d bytes",
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct _GstVideoScale {
|
||||||
GstVideoFilter element;
|
GstVideoFilter element;
|
||||||
|
|
||||||
GstVideoScaleMethod method;
|
GstVideoScaleMethod method;
|
||||||
|
gboolean add_borders;
|
||||||
|
|
||||||
/* negotiated stuff */
|
/* negotiated stuff */
|
||||||
GstVideoFormat format;
|
GstVideoFormat format;
|
||||||
|
@ -78,8 +79,8 @@ struct _GstVideoScale {
|
||||||
guint src_size;
|
guint src_size;
|
||||||
guint dest_size;
|
guint dest_size;
|
||||||
|
|
||||||
VSImage src;
|
gint borders_h;
|
||||||
VSImage dest;
|
gint borders_w;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
guint8 *tmp_buf;
|
guint8 *tmp_buf;
|
||||||
|
|
|
@ -30,3 +30,15 @@ addl t1, t1, t2
|
||||||
shrul t1, t1, 16
|
shrul t1, t1, 16
|
||||||
convlw d1, t1
|
convlw d1, t1
|
||||||
|
|
||||||
|
.function orc_splat_u16
|
||||||
|
.dest 2 d1
|
||||||
|
.param 2 p1
|
||||||
|
|
||||||
|
copyw d1, p1
|
||||||
|
|
||||||
|
.function orc_splat_u32
|
||||||
|
.dest 4 d1
|
||||||
|
.param 4 p1
|
||||||
|
|
||||||
|
copyl d1, p1
|
||||||
|
|
||||||
|
|
381
gst/videoscale/vs_fill_borders.c
Normal file
381
gst/videoscale/vs_fill_borders.c
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
/*
|
||||||
|
* Image Scaling Functions
|
||||||
|
* Copyright (c) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "vs_fill_borders.h"
|
||||||
|
#include "gstvideoscaleorc.h"
|
||||||
|
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
#define READ_UINT32(ptr) GST_READ_UINT32_LE(ptr)
|
||||||
|
#define READ_UINT16(ptr) GST_READ_UINT16_LE(ptr)
|
||||||
|
#else
|
||||||
|
#define READ_UINT32(ptr) GST_READ_UINT32_BE(ptr)
|
||||||
|
#define READ_UINT16(ptr) GST_READ_UINT16_BE(ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_RGBA (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
uint32_t v = READ_UINT32 (val);
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
orc_splat_u32 ((uint32_t *) data, v, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 4;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
orc_splat_u32 ((uint32_t *) data, v, left);
|
||||||
|
orc_splat_u32 ((uint32_t *) (data + tmp2), v, right);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
orc_splat_u32 ((uint32_t *) data, v, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_memset_u24 (uint8_t * data, uint8_t val1, uint8_t val2, uint8_t val3,
|
||||||
|
unsigned int n)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
data[0] = val1;
|
||||||
|
data[1] = val2;
|
||||||
|
data[2] = val3;
|
||||||
|
data += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_RGB (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
_memset_u24 (data, val[0], val[1], val[2], real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 3;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
_memset_u24 (data, val[0], val[1], val[2], left);
|
||||||
|
_memset_u24 (data + tmp2, val[0], val[1], val[2], right);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
_memset_u24 (data, val[0], val[1], val[2], real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_YUYV (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
for (j = 0; j < real_width; j++) {
|
||||||
|
data[2 * j] = val[0];
|
||||||
|
data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 2;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
for (j = 0; j < left; j++) {
|
||||||
|
data[2 * j] = val[0];
|
||||||
|
data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
|
||||||
|
}
|
||||||
|
for (j = 0; j < right; j++) {
|
||||||
|
data[tmp2 + 2 * j] = val[0];
|
||||||
|
data[tmp2 + 2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
for (j = 0; j < real_width; j++) {
|
||||||
|
data[2 * j] = val[0];
|
||||||
|
data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3];
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_UYVY (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
for (j = 0; j < real_width; j++) {
|
||||||
|
data[2 * j] = (j % 2 == 0) ? val[0] : val[2];
|
||||||
|
data[2 * j + 1] = val[1];
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 2;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
for (j = 0; j < left; j++) {
|
||||||
|
data[2 * j] = (j % 2 == 0) ? val[0] : val[2];
|
||||||
|
data[2 * j + 1] = val[1];
|
||||||
|
}
|
||||||
|
for (j = 0; j < right; j++) {
|
||||||
|
data[tmp2 + 2 * j] = (j % 2 == 0) ? val[0] : val[2];
|
||||||
|
data[tmp2 + 2 * j + 1] = val[1];
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
for (j = 0; j < real_width; j++) {
|
||||||
|
data[2 * j] = (j % 2 == 0) ? val[0] : val[2];
|
||||||
|
data[2 * j + 1] = val[1];
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_Y (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
memset (data, *val, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = left + width;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
memset (data, *val, left);
|
||||||
|
memset (data + tmp2, *val, right);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
memset (data, *val, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_Y16 (const VSImage * dest, const uint16_t val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, val, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 2;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, val, left);
|
||||||
|
orc_splat_u16 ((uint16_t *) (data + tmp2), val, right);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, val, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_RGB565 (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
uint16_t v = READ_UINT16 (val);
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, v, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 2;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, v, left);
|
||||||
|
orc_splat_u16 ((uint16_t *) (data + tmp2), v, right);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, v, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_fill_borders_RGB555 (const VSImage * dest, const uint8_t * val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int top = dest->border_top, bottom = dest->border_bottom;
|
||||||
|
int left = dest->border_left, right = dest->border_right;
|
||||||
|
int width = dest->width;
|
||||||
|
int height = dest->height;
|
||||||
|
int real_width = dest->real_width;
|
||||||
|
int stride = dest->stride;
|
||||||
|
int tmp, tmp2;
|
||||||
|
uint8_t *data;
|
||||||
|
uint16_t v = READ_UINT16 (val);
|
||||||
|
|
||||||
|
data = dest->real_pixels;
|
||||||
|
for (i = 0; i < top; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, v, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left || right) {
|
||||||
|
tmp = height;
|
||||||
|
tmp2 = (left + width) * 2;
|
||||||
|
for (i = 0; i < tmp; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, v, left);
|
||||||
|
orc_splat_u16 ((uint16_t *) (data + tmp2), v, right);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data += stride * height;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bottom; i++) {
|
||||||
|
orc_splat_u16 ((uint16_t *) data, v, real_width);
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
}
|
43
gst/videoscale/vs_fill_borders.h
Normal file
43
gst/videoscale/vs_fill_borders.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Image Scaling Functions
|
||||||
|
* Copyright (c) 2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VS_FILL_BORDERS_H__
|
||||||
|
#define __VS_FILL_BORDERS_H__
|
||||||
|
|
||||||
|
#include <_stdint.h>
|
||||||
|
#include "vs_image.h"
|
||||||
|
|
||||||
|
void vs_fill_borders_RGBA (const VSImage *dest, const uint8_t *val);
|
||||||
|
void vs_fill_borders_RGB (const VSImage *dest, const uint8_t *val);
|
||||||
|
void vs_fill_borders_YUYV (const VSImage *dest, const uint8_t *val);
|
||||||
|
void vs_fill_borders_UYVY (const VSImage *dest, const uint8_t *val);
|
||||||
|
void vs_fill_borders_Y (const VSImage *dest, const uint8_t *val);
|
||||||
|
void vs_fill_borders_Y16 (const VSImage *dest, const uint16_t val);
|
||||||
|
void vs_fill_borders_RGB565 (const VSImage *dest, const uint8_t *val);
|
||||||
|
void vs_fill_borders_RGB555 (const VSImage *dest, const uint8_t *val);
|
||||||
|
|
||||||
|
#endif /* __VS_FILL_BORDERS_H__ */
|
|
@ -33,6 +33,11 @@
|
||||||
typedef struct _VSImage VSImage;
|
typedef struct _VSImage VSImage;
|
||||||
|
|
||||||
struct _VSImage {
|
struct _VSImage {
|
||||||
|
uint8_t *real_pixels;
|
||||||
|
int real_width;
|
||||||
|
int real_height;
|
||||||
|
int border_left, border_right;
|
||||||
|
int border_top, border_bottom;
|
||||||
uint8_t *pixels;
|
uint8_t *pixels;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
Loading…
Reference in a new issue