videoscale: Add nearest/linear scaling for NV12
This commit is contained in:
parent
e4f01106d0
commit
beacccc396
@ -1,6 +1,6 @@
|
|||||||
/* GStreamer
|
/* GStreamer
|
||||||
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
* Copyright (C) 2005 David Schleef <ds@schleef.org>
|
* Copyright (C) 2005-2012 David Schleef <ds@schleef.org>
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Library General Public
|
* modify it under the terms of the GNU Library General Public
|
||||||
@ -140,7 +140,8 @@ static GstStaticCaps gst_video_scale_format_caps[] = {
|
|||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y8 ")),
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y8 ")),
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("GREY")),
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("GREY")),
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AY64")),
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AY64")),
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_ARGB_64)
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_ARGB_64),
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("NV12"))
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GST_TYPE_VIDEO_SCALE_METHOD (gst_video_scale_method_get_type())
|
#define GST_TYPE_VIDEO_SCALE_METHOD (gst_video_scale_method_get_type())
|
||||||
@ -1024,7 +1025,8 @@ gst_video_scale_setup_vs_image (VSImage * image, GstVideoFormat format,
|
|||||||
if (format == GST_VIDEO_FORMAT_I420
|
if (format == GST_VIDEO_FORMAT_I420
|
||||||
|| format == GST_VIDEO_FORMAT_YV12
|
|| format == GST_VIDEO_FORMAT_YV12
|
||||||
|| format == GST_VIDEO_FORMAT_Y444
|
|| format == GST_VIDEO_FORMAT_Y444
|
||||||
|| format == GST_VIDEO_FORMAT_Y42B || format == GST_VIDEO_FORMAT_Y41B) {
|
|| format == GST_VIDEO_FORMAT_Y42B || format == GST_VIDEO_FORMAT_Y41B
|
||||||
|
|| format == GST_VIDEO_FORMAT_NV12) {
|
||||||
image->real_pixels = data + gst_video_format_get_component_offset (format,
|
image->real_pixels = data + gst_video_format_get_component_offset (format,
|
||||||
component, width, height);
|
component, width, height);
|
||||||
} else {
|
} else {
|
||||||
@ -1090,6 +1092,7 @@ _get_black_for_format (GstVideoFormat format)
|
|||||||
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:
|
||||||
|
case GST_VIDEO_FORMAT_NV12:
|
||||||
return black[4]; /* Y, U, V, 0 */
|
return black[4]; /* Y, U, V, 0 */
|
||||||
case GST_VIDEO_FORMAT_RGB16:
|
case GST_VIDEO_FORMAT_RGB16:
|
||||||
case GST_VIDEO_FORMAT_RGB15:
|
case GST_VIDEO_FORMAT_RGB15:
|
||||||
@ -1153,6 +1156,14 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
|
|||||||
videoscale->to_width, videoscale->to_height, videoscale->borders_w,
|
videoscale->to_width, videoscale->to_height, videoscale->borders_w,
|
||||||
videoscale->borders_h, GST_BUFFER_DATA (out));
|
videoscale->borders_h, GST_BUFFER_DATA (out));
|
||||||
}
|
}
|
||||||
|
if (videoscale->format == GST_VIDEO_FORMAT_NV12) {
|
||||||
|
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 (&dest_u, videoscale->format, 1,
|
||||||
|
videoscale->to_width, videoscale->to_height, videoscale->borders_w,
|
||||||
|
videoscale->borders_h, GST_BUFFER_DATA (out));
|
||||||
|
}
|
||||||
|
|
||||||
switch (videoscale->format) {
|
switch (videoscale->format) {
|
||||||
case GST_VIDEO_FORMAT_RGBx:
|
case GST_VIDEO_FORMAT_RGBx:
|
||||||
@ -1340,6 +1351,20 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
|
|||||||
goto unknown_mode;
|
goto unknown_mode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_NV12:
|
||||||
|
switch (method) {
|
||||||
|
case GST_VIDEO_SCALE_NEAREST:
|
||||||
|
vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf);
|
||||||
|
vs_image_scale_nearest_NV12 (&dest_u, &src_u, videoscale->tmp_buf);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_SCALE_BILINEAR:
|
||||||
|
vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
|
||||||
|
vs_image_scale_linear_NV12 (&dest_u, &src_u, videoscale->tmp_buf);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto unknown_mode;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GST_VIDEO_FORMAT_RGB16:
|
case GST_VIDEO_FORMAT_RGB16:
|
||||||
if (add_borders)
|
if (add_borders)
|
||||||
vs_fill_borders_RGB565 (&dest, black);
|
vs_fill_borders_RGB565 (&dest, black);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Image Scaling Functions
|
* Image Scaling Functions
|
||||||
* Copyright (c) 2005 David A. Schleef <ds@schleef.org>
|
* Copyright (c) 2005-2012 David A. Schleef <ds@schleef.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -522,6 +522,136 @@ vs_image_scale_linear_UYVY (const VSImage * dest, const VSImage * src,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NV12 */
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_image_scale_nearest_NV12 (const VSImage * dest, const VSImage * src,
|
||||||
|
uint8_t * tmpbuf)
|
||||||
|
{
|
||||||
|
int acc;
|
||||||
|
int y_increment;
|
||||||
|
int x_increment;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int xacc;
|
||||||
|
|
||||||
|
if (dest->height == 1)
|
||||||
|
y_increment = 0;
|
||||||
|
else
|
||||||
|
y_increment = ((src->height - 1) << 16) / (dest->height - 1);
|
||||||
|
|
||||||
|
if (dest->width == 1)
|
||||||
|
x_increment = 0;
|
||||||
|
else
|
||||||
|
x_increment = ((src->width - 1) << 16) / (dest->width - 1);
|
||||||
|
|
||||||
|
acc = 0;
|
||||||
|
for (i = 0; i < dest->height; i++) {
|
||||||
|
j = acc >> 16;
|
||||||
|
|
||||||
|
xacc = 0;
|
||||||
|
vs_scanline_resample_nearest_NV12 (dest->pixels + i * dest->stride,
|
||||||
|
src->pixels + j * src->stride, src->width, dest->width, &xacc,
|
||||||
|
x_increment);
|
||||||
|
|
||||||
|
acc += y_increment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_image_scale_linear_NV12 (const VSImage * dest, const VSImage * src,
|
||||||
|
uint8_t * tmpbuf)
|
||||||
|
{
|
||||||
|
int acc;
|
||||||
|
int y_increment;
|
||||||
|
int x_increment;
|
||||||
|
uint8_t *tmp1;
|
||||||
|
uint8_t *tmp2;
|
||||||
|
int y1;
|
||||||
|
int y2;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int x;
|
||||||
|
int dest_size;
|
||||||
|
int xacc;
|
||||||
|
|
||||||
|
if (dest->height == 1)
|
||||||
|
y_increment = 0;
|
||||||
|
else
|
||||||
|
y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1;
|
||||||
|
|
||||||
|
if (dest->width == 1)
|
||||||
|
x_increment = 0;
|
||||||
|
else
|
||||||
|
x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1;
|
||||||
|
|
||||||
|
dest_size = ROUND_UP_4 (dest->width * 2);
|
||||||
|
|
||||||
|
tmp1 = tmpbuf;
|
||||||
|
tmp2 = tmpbuf + dest_size;
|
||||||
|
|
||||||
|
acc = 0;
|
||||||
|
xacc = 0;
|
||||||
|
y2 = -1;
|
||||||
|
vs_scanline_resample_linear_NV12 (tmp1, src->pixels, src->width, dest->width,
|
||||||
|
&xacc, x_increment);
|
||||||
|
y1 = 0;
|
||||||
|
for (i = 0; i < dest->height; i++) {
|
||||||
|
j = acc >> 16;
|
||||||
|
x = acc & 0xffff;
|
||||||
|
|
||||||
|
if (x == 0) {
|
||||||
|
if (j == y1) {
|
||||||
|
memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
|
||||||
|
} else if (j == y2) {
|
||||||
|
memcpy (dest->pixels + i * dest->stride, tmp2, dest_size);
|
||||||
|
} else {
|
||||||
|
xacc = 0;
|
||||||
|
vs_scanline_resample_linear_NV12 (tmp1, src->pixels + j * src->stride,
|
||||||
|
src->width, dest->width, &xacc, x_increment);
|
||||||
|
y1 = j;
|
||||||
|
memcpy (dest->pixels + i * dest->stride, tmp1, dest_size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (j == y1) {
|
||||||
|
if (j + 1 != y2) {
|
||||||
|
xacc = 0;
|
||||||
|
vs_scanline_resample_linear_NV12 (tmp2,
|
||||||
|
src->pixels + (j + 1) * src->stride, src->width, dest->width,
|
||||||
|
&xacc, x_increment);
|
||||||
|
y2 = j + 1;
|
||||||
|
}
|
||||||
|
vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
|
||||||
|
tmp1, tmp2, dest->width, x);
|
||||||
|
} else if (j == y2) {
|
||||||
|
if (j + 1 != y1) {
|
||||||
|
xacc = 0;
|
||||||
|
vs_scanline_resample_linear_NV12 (tmp1,
|
||||||
|
src->pixels + (j + 1) * src->stride, src->width, dest->width,
|
||||||
|
&xacc, x_increment);
|
||||||
|
y1 = j + 1;
|
||||||
|
}
|
||||||
|
vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
|
||||||
|
tmp2, tmp1, dest->width, x);
|
||||||
|
} else {
|
||||||
|
xacc = 0;
|
||||||
|
vs_scanline_resample_linear_NV12 (tmp1, src->pixels + j * src->stride,
|
||||||
|
src->width, dest->width, &xacc, x_increment);
|
||||||
|
y1 = j;
|
||||||
|
xacc = 0;
|
||||||
|
vs_scanline_resample_linear_NV12 (tmp2,
|
||||||
|
src->pixels + (j + 1) * src->stride, src->width, dest->width,
|
||||||
|
&xacc, x_increment);
|
||||||
|
y2 = (j + 1);
|
||||||
|
vs_scanline_merge_linear_NV12 (dest->pixels + i * dest->stride,
|
||||||
|
tmp1, tmp2, dest->width, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acc += y_increment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* greyscale */
|
/* greyscale */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -71,6 +71,11 @@ void vs_image_scale_nearest_UYVY (const VSImage *dest, const VSImage *src,
|
|||||||
void vs_image_scale_linear_UYVY (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_linear_UYVY (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
|
|
||||||
|
void vs_image_scale_nearest_NV12 (const VSImage *dest, const VSImage *src,
|
||||||
|
uint8_t *tmpbuf);
|
||||||
|
void vs_image_scale_linear_NV12 (const VSImage *dest, const VSImage *src,
|
||||||
|
uint8_t *tmpbuf);
|
||||||
|
|
||||||
void vs_image_scale_nearest_Y (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_nearest_Y (const VSImage *dest, const VSImage *src,
|
||||||
uint8_t *tmpbuf);
|
uint8_t *tmpbuf);
|
||||||
void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,
|
void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,
|
||||||
|
@ -519,6 +519,88 @@ vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* NV12 */
|
||||||
|
|
||||||
|
/* n is the number of bi-pixels */
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_scanline_downsample_NV12 (uint8_t * dest, uint8_t * src, int n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
dest[i * 2 + 0] = (src[i * 4 + 0] + src[i * 4 + 2]) / 2;
|
||||||
|
dest[i * 2 + 1] = (src[i * 4 + 1] + src[i * 4 + 3]) / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_scanline_resample_nearest_NV12 (uint8_t * dest, uint8_t * src, int src_width,
|
||||||
|
int n, int *accumulator, int increment)
|
||||||
|
{
|
||||||
|
int acc = *accumulator;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
j = acc >> 16;
|
||||||
|
x = acc & 0xffff;
|
||||||
|
|
||||||
|
dest[i * 2 + 0] = (x < 32768
|
||||||
|
|| j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2];
|
||||||
|
dest[i * 2 + 1] = (x < 32768
|
||||||
|
|| j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3];
|
||||||
|
|
||||||
|
acc += increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
*accumulator = acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_scanline_resample_linear_NV12 (uint8_t * dest, uint8_t * src, int src_width,
|
||||||
|
int n, int *accumulator, int increment)
|
||||||
|
{
|
||||||
|
int acc = *accumulator;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
j = acc >> 16;
|
||||||
|
x = acc & 0xffff;
|
||||||
|
|
||||||
|
if (j + 1 < src_width) {
|
||||||
|
dest[i * 2 + 0] =
|
||||||
|
(src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16;
|
||||||
|
dest[i * 2 + 1] =
|
||||||
|
(src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16;
|
||||||
|
} else {
|
||||||
|
dest[i * 4 + 0] = src[j * 2 + 0];
|
||||||
|
dest[i * 4 + 1] = src[j * 2 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
acc += increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
*accumulator = acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vs_scanline_merge_linear_NV12 (uint8_t * dest, uint8_t * src1,
|
||||||
|
uint8_t * src2, int n, int x)
|
||||||
|
{
|
||||||
|
uint32_t value = x >> 8;
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
memcpy (dest, src1, n * 2);
|
||||||
|
} else {
|
||||||
|
orc_merge_linear_u8 (dest, src1, src2, value, n * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* RGB565 */
|
/* RGB565 */
|
||||||
|
|
||||||
/* note that src and dest are uint16_t, and thus endian dependent */
|
/* note that src and dest are uint16_t, and thus endian dependent */
|
||||||
|
@ -55,6 +55,11 @@ void vs_scanline_resample_nearest_UYVY (uint8_t *dest, uint8_t *src, int src_wid
|
|||||||
void vs_scanline_resample_linear_UYVY (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
void vs_scanline_resample_linear_UYVY (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
||||||
void vs_scanline_merge_linear_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
|
void vs_scanline_merge_linear_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
|
||||||
|
|
||||||
|
void vs_scanline_downsample_NV12 (uint8_t *dest, uint8_t *src, int n);
|
||||||
|
void vs_scanline_resample_nearest_NV12 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
||||||
|
void vs_scanline_resample_linear_NV12 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
||||||
|
void vs_scanline_merge_linear_NV12 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x);
|
||||||
|
|
||||||
void vs_scanline_downsample_RGB565 (uint8_t *dest, uint8_t *src, int n);
|
void vs_scanline_downsample_RGB565 (uint8_t *dest, uint8_t *src, int n);
|
||||||
void vs_scanline_resample_nearest_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
void vs_scanline_resample_nearest_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
||||||
void vs_scanline_resample_linear_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
void vs_scanline_resample_linear_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user