Merge branch 'master' into 0.11

Conflicts:
	ext/vorbis/gstvorbisparse.c
	gst-libs/gst/video/video.c
	gst/videoscale/gstvideoscale.c
	sys/v4l/gstv4lxoverlay.c
	sys/v4l/v4l_calls.c
	sys/v4l/v4lsrc_calls.c
	tests/check/libs/video.c
This commit is contained in:
Wim Taymans 2012-02-10 15:41:06 +01:00
commit c3478b2da0
14 changed files with 461 additions and 39 deletions

View file

@ -1,6 +1,12 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
olddir=`pwd`
cd "$srcdir"
DIE=0
package=gst-plugins-base
srcfile=gst/audiotestsrc/gstaudiotestsrc.c
@ -106,13 +112,15 @@ test -n "$NOCONFIGURE" && {
exit 0
}
cd "$olddir"
echo "+ running configure ... "
test ! -z "$CONFIGURE_DEF_OPT" && echo " ./configure default flags: $CONFIGURE_DEF_OPT"
test ! -z "$CONFIGURE_EXT_OPT" && echo " ./configure external flags: $CONFIGURE_EXT_OPT"
test ! -z "$CONFIGURE_FILE_OPT" && echo " ./configure enable/disable flags: $CONFIGURE_FILE_OPT"
test ! -z "$CONFIGURE_DEF_OPT" && echo " $srcdir/configure default flags: $CONFIGURE_DEF_OPT"
test ! -z "$CONFIGURE_EXT_OPT" && echo " $srcdir/configure external flags: $CONFIGURE_EXT_OPT"
test ! -z "$CONFIGURE_FILE_OPT" && echo " $srcdir/configure enable/disable flags: $CONFIGURE_FILE_OPT"
echo
./configure $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT $CONFIGURE_FILE_OPT || {
"$srcdir/configure" $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT $CONFIGURE_FILE_OPT || {
echo " configure failed"
exit 1
}

View file

@ -554,6 +554,9 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
pad->current_granule);
} else if (ogg->segment.rate > 0.0 && pad->current_granule != -1) {
pad->current_granule += duration;
if (gst_ogg_stream_packet_is_key_frame (&pad->map, packet)) {
pad->keyframe_granule = pad->current_granule;
}
GST_DEBUG_OBJECT (ogg, "interpolating granule %" G_GUINT64_FORMAT,
pad->current_granule);
}

View file

@ -47,9 +47,13 @@ typedef gint64 (*GstOggMapToGranuleposFunc) (GstOggStream * pad,
gint64 granule, gint64 keyframe_granule);
/* returns TRUE if the granulepos denotes a key frame */
typedef gboolean (*GstOggMapIsKeyFrameFunc) (GstOggStream * pad,
typedef gboolean (*GstOggMapIsGranuleposKeyFrameFunc) (GstOggStream * pad,
gint64 granulepos);
/* returns TRUE if the packet is a key frame */
typedef gboolean (*GstOggMapIsPacketKeyFrameFunc) (GstOggStream * pad,
ogg_packet * packet);
/* returns TRUE if the given packet is a stream header packet */
typedef gboolean (*GstOggMapIsHeaderPacketFunc) (GstOggStream * pad,
ogg_packet * packet);
@ -74,7 +78,8 @@ struct _GstOggMap
GstOggMapSetupFunc setup_func;
GstOggMapToGranuleFunc granulepos_to_granule_func;
GstOggMapToGranuleposFunc granule_to_granulepos_func;
GstOggMapIsKeyFrameFunc is_key_frame_func;
GstOggMapIsGranuleposKeyFrameFunc is_granulepos_key_frame_func;
GstOggMapIsPacketKeyFrameFunc is_packet_key_frame_func;
GstOggMapIsHeaderPacketFunc is_header_func;
GstOggMapPacketDurationFunc packet_duration_func;
GstOggMapGranuleposToKeyGranuleFunc granulepos_to_key_granule_func;
@ -189,13 +194,25 @@ gst_ogg_stream_granulepos_is_key_frame (GstOggStream * pad, gint64 granulepos)
return FALSE;
}
if (mappers[pad->map].is_key_frame_func == NULL) {
if (mappers[pad->map].is_granulepos_key_frame_func == NULL) {
GST_WARNING ("Failed to determine keyframeness for %s granulepos",
gst_ogg_stream_get_media_type (pad));
return FALSE;
}
return mappers[pad->map].is_key_frame_func (pad, granulepos);
return mappers[pad->map].is_granulepos_key_frame_func (pad, granulepos);
}
gboolean
gst_ogg_stream_packet_is_key_frame (GstOggStream * pad, ogg_packet * packet)
{
if (mappers[pad->map].is_packet_key_frame_func == NULL) {
GST_WARNING ("Failed to determine keyframeness of %s packet",
gst_ogg_stream_get_media_type (pad));
return FALSE;
}
return mappers[pad->map].is_packet_key_frame_func (pad, packet);
}
gboolean
@ -250,7 +267,13 @@ gst_ogg_stream_get_media_type (GstOggStream * pad)
/* some generic functions */
static gboolean
is_keyframe_true (GstOggStream * pad, gint64 granulepos)
is_granulepos_keyframe_true (GstOggStream * pad, gint64 granulepos)
{
return TRUE;
}
static gboolean
is_packet_keyframe_true (GstOggStream * pad, ogg_packet * packet)
{
return TRUE;
}
@ -383,6 +406,7 @@ setup_theora_mapper (GstOggStream * pad, ogg_packet * packet)
/* 2 bits + 3 bits = 5 bits KFGSHIFT */
pad->granuleshift = ((GST_READ_UINT8 (data + 40) & 0x03) << 3) +
(GST_READ_UINT8 (data + 41) >> 5);
GST_LOG ("granshift: %d", pad->granuleshift);
pad->is_video = TRUE;
pad->n_header_packets = 3;
@ -439,7 +463,7 @@ granulepos_to_granule_theora (GstOggStream * pad, gint64 granulepos)
}
static gboolean
is_keyframe_theora (GstOggStream * pad, gint64 granulepos)
is_granulepos_keyframe_theora (GstOggStream * pad, gint64 granulepos)
{
gint64 frame_mask;
@ -451,6 +475,14 @@ is_keyframe_theora (GstOggStream * pad, gint64 granulepos)
return ((granulepos & frame_mask) == 0);
}
static gboolean
is_packet_keyframe_theora (GstOggStream * pad, ogg_packet * packet)
{
if (packet->bytes == 0)
return FALSE;
return (packet->packet[0] & 0xc0) == 0x00;
}
static gboolean
is_header_theora (GstOggStream * pad, ogg_packet * packet)
{
@ -1935,7 +1967,8 @@ const GstOggMap mappers[] = {
setup_theora_mapper,
granulepos_to_granule_theora,
granule_to_granulepos_default,
is_keyframe_theora,
is_granulepos_keyframe_theora,
is_packet_keyframe_theora,
is_header_theora,
packet_duration_constant,
NULL,
@ -1947,7 +1980,8 @@ const GstOggMap mappers[] = {
setup_vorbis_mapper,
granulepos_to_granule_default,
granule_to_granulepos_default,
is_keyframe_true,
is_granulepos_keyframe_true,
is_packet_keyframe_true,
is_header_vorbis,
packet_duration_vorbis,
NULL,
@ -1959,7 +1993,8 @@ const GstOggMap mappers[] = {
setup_speex_mapper,
granulepos_to_granule_default,
granule_to_granulepos_default,
is_keyframe_true,
is_granulepos_keyframe_true,
is_packet_keyframe_true,
is_header_count,
packet_duration_constant,
NULL,
@ -1972,6 +2007,7 @@ const GstOggMap mappers[] = {
NULL,
NULL,
NULL,
NULL,
is_header_count,
NULL,
NULL,
@ -1984,6 +2020,7 @@ const GstOggMap mappers[] = {
NULL,
NULL,
NULL,
NULL,
is_header_count,
NULL,
NULL,
@ -1996,6 +2033,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_default,
granule_to_granulepos_default,
NULL,
NULL,
is_header_count,
NULL,
NULL,
@ -2008,6 +2046,7 @@ const GstOggMap mappers[] = {
NULL,
NULL,
NULL,
NULL,
is_header_true,
NULL,
NULL,
@ -2019,7 +2058,8 @@ const GstOggMap mappers[] = {
setup_fLaC_mapper,
granulepos_to_granule_default,
granule_to_granulepos_default,
is_keyframe_true,
is_granulepos_keyframe_true,
is_packet_keyframe_true,
is_header_fLaC,
packet_duration_flac,
NULL,
@ -2031,7 +2071,8 @@ const GstOggMap mappers[] = {
setup_flac_mapper,
granulepos_to_granule_default,
granule_to_granulepos_default,
is_keyframe_true,
is_granulepos_keyframe_true,
is_packet_keyframe_true,
is_header_flac,
packet_duration_flac,
NULL,
@ -2046,6 +2087,7 @@ const GstOggMap mappers[] = {
NULL,
NULL,
NULL,
NULL,
NULL
},
{
@ -2055,6 +2097,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_default,
granule_to_granulepos_default,
NULL,
NULL,
is_header_count,
packet_duration_constant,
NULL,
@ -2067,6 +2110,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_default,
granule_to_granulepos_default,
NULL,
NULL,
is_header_count,
packet_duration_kate,
NULL,
@ -2079,6 +2123,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_dirac,
granule_to_granulepos_dirac,
is_keyframe_dirac,
NULL,
is_header_count,
packet_duration_constant,
granulepos_to_key_granule_dirac,
@ -2091,6 +2136,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_vp8,
granule_to_granulepos_vp8,
is_keyframe_vp8,
NULL,
is_header_vp8,
packet_duration_vp8,
granulepos_to_key_granule_vp8,
@ -2103,6 +2149,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_default,
granule_to_granulepos_default,
NULL,
NULL,
is_header_opus,
packet_duration_opus,
NULL,
@ -2114,7 +2161,8 @@ const GstOggMap mappers[] = {
setup_ogmaudio_mapper,
granulepos_to_granule_default,
granule_to_granulepos_default,
is_keyframe_true,
is_granulepos_keyframe_true,
is_packet_keyframe_true,
is_header_ogm,
packet_duration_ogm,
NULL,
@ -2127,6 +2175,7 @@ const GstOggMap mappers[] = {
granulepos_to_granule_default,
granule_to_granulepos_default,
NULL,
NULL,
is_header_ogm,
packet_duration_constant,
NULL,
@ -2138,7 +2187,8 @@ const GstOggMap mappers[] = {
setup_ogmtext_mapper,
granulepos_to_granule_default,
granule_to_granulepos_default,
is_keyframe_true,
is_granulepos_keyframe_true,
is_packet_keyframe_true,
is_header_ogm,
packet_duration_ogm,
NULL,

View file

@ -124,6 +124,7 @@ GstClockTime gst_ogg_stream_get_packet_start_time (GstOggStream *pad,
gboolean gst_ogg_stream_granulepos_is_key_frame (GstOggStream *pad,
gint64 granulepos);
gboolean gst_ogg_stream_packet_is_header (GstOggStream *pad, ogg_packet *packet);
gboolean gst_ogg_stream_packet_is_key_frame (GstOggStream *pad, ogg_packet *packet);
gint64 gst_ogg_stream_get_packet_duration (GstOggStream * pad, ogg_packet *packet);
void gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet);
const char *gst_ogg_stream_get_media_type (GstOggStream * pad);

View file

@ -1338,6 +1338,11 @@ theora_enc_encode_and_push (GstTheoraEnc * enc, ogg_packet op,
goto multipass_read_failed;
}
}
#ifdef TH_ENCCTL_SET_DUPLICATE_FLAG
if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_GAP)) {
th_encode_ctl (enc->encoder, TH_ENCCTL_SET_DUPLICATE_FLAG, NULL, 0);
}
#endif
res = th_encode_ycbcr_in (enc->encoder, ycbcr);
/* none of the failure cases can happen here */

View file

@ -400,7 +400,7 @@ vorbis_parse_parse_packet (GstVorbisParse * parse, GstBuffer * buf)
have_header = FALSE;
gst_buffer_map (buf, &map, GST_MAP_READ);
if (map.size >= 1) {
if (map.data[0] >= 0x01 && map.data[0] <= 0x05)
if (map.data[0] & 1)
have_header = TRUE;
}
gst_buffer_unmap (buf, &map);

View file

@ -2402,6 +2402,9 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
/* Stream consists of: a series of sync codes (00 00 00 01) followed
* by NALs
*/
gboolean seen_idr = FALSE;
gboolean seen_sps = FALSE;
gboolean seen_pps = FALSE;
int nut, ref;
int good = 0;
int bad = 0;
@ -2426,6 +2429,13 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
((nut == 6 || (nut >= 9 && nut <= 12)) && ref != 0)) {
bad++;
} else {
if (nut == 7)
seen_sps = TRUE;
else if (nut == 8)
seen_pps = TRUE;
else if (nut == 5)
seen_idr = TRUE;
good++;
}
} else if (nut >= 14 && nut <= 33) {
@ -2439,9 +2449,10 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
/* don't consider these bad */
}
GST_DEBUG ("good %d bad %d", good, bad);
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, idr:%d", good, bad, seen_pps,
seen_sps, seen_idr);
if (good >= 10 && bad < 4) {
if (seen_sps && seen_pps && seen_idr && good >= 10 && bad < 4) {
gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS);
return;
}
@ -2451,9 +2462,11 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
data_scan_ctx_advance (tf, &c, 1);
}
if (good >= 2 && bad < 1) {
GST_LOG ("good:%d, bad:%d, pps:%d, sps:%d, idr:%d", good, bad, seen_pps,
seen_sps, seen_idr);
if (good >= 2 && bad == 0) {
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H264_VIDEO_CAPS);
return;
}
}

View file

@ -1,6 +1,6 @@
/* GStreamer
* 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
* modify it under the terms of the GNU Library General Public
@ -112,10 +112,10 @@ enum
#undef GST_VIDEO_SIZE_RANGE
#define GST_VIDEO_SIZE_RANGE "(int) [ 1, 32767]"
#define GST_VIDEO_FORMATS "{ \"I420\", \"YV12\", \"YUY2\", \"UYVY\", \"AYUV\", \"RGBx\", " \
"\"BGRx\", \"xRGB\", \"xBGR\", \"RGBA\", \"BGRA\", \"ARGB\", \"ABGR\", \"RGB\", " \
"\"BGR\", \"Y41B\", \"Y42B\", \"YVYU\", \"Y444\", \"GRAY8\", \"GRAY16_BE\", \"GRAY16_LE\", " \
"\"v308\", \"Y800\", \"Y16\", \"RGB16\", \"RGB15\", \"ARGB64\", \"AYUV64\" } "
#define GST_VIDEO_FORMATS "{ I420, YV12, YUY2, UYVY, AYUV, RGBx, " \
"BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, " \
"BGR, Y41B, Y42B, YVYU, Y444, GRAY8, GRAY16_BE, GRAY16_LE, " \
"v308, Y800, Y16, RGB16, RGB15, ARGB64, AYUV64, NV12 } "
static GstStaticCaps gst_video_scale_format_caps[] = {
@ -1042,6 +1042,7 @@ _get_black_for_format (GstVideoFormat format)
case GST_VIDEO_FORMAT_Y444:
case GST_VIDEO_FORMAT_Y42B:
case GST_VIDEO_FORMAT_Y41B:
case GST_VIDEO_FORMAT_NV12:
return black[4]; /* Y, U, V, 0 */
case GST_VIDEO_FORMAT_RGB16:
case GST_VIDEO_FORMAT_RGB15:
@ -1136,6 +1137,11 @@ gst_video_scale_transform_frame (GstVideoFilter * filter,
case GST_VIDEO_SCALE_4TAP:
vs_image_scale_4tap_AYUV64 (&dest[0], &src[0], videoscale->tmp_buf);
break;
case GST_VIDEO_SCALE_LANCZOS:
vs_image_scale_lanczos_AYUV64 (&dest[0], &src[0], videoscale->tmp_buf,
videoscale->sharpness, videoscale->dither, videoscale->submethod,
videoscale->envelope, videoscale->sharpen);
break;
default:
goto unknown_mode;
}
@ -1272,6 +1278,20 @@ gst_video_scale_transform_frame (GstVideoFilter * filter,
goto unknown_mode;
}
break;
case GST_VIDEO_FORMAT_NV12:
switch (method) {
case GST_VIDEO_SCALE_NEAREST:
vs_image_scale_nearest_Y (&dest[0], &src[0], videoscale->tmp_buf);
vs_image_scale_nearest_NV12 (&dest[1], &src[1], videoscale->tmp_buf);
break;
case GST_VIDEO_SCALE_BILINEAR:
vs_image_scale_linear_Y (&dest[0], &src[0], videoscale->tmp_buf);
vs_image_scale_linear_NV12 (&dest[1], &src[1], videoscale->tmp_buf);
break;
default:
goto unknown_mode;
}
break;
case GST_VIDEO_FORMAT_RGB16:
if (add_borders)
vs_fill_borders_RGB565 (&dest[0], black);

View file

@ -1,6 +1,6 @@
/*
* 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.
*
* 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 */
void

View file

@ -52,6 +52,9 @@ void vs_image_scale_linear_RGBA (const VSImage *dest, const VSImage *src,
void vs_image_scale_lanczos_AYUV (const VSImage * dest, const VSImage * src,
uint8_t * tmpbuf, double sharpness, gboolean dither, int submethod,
double a, double sharpen);
void vs_image_scale_lanczos_AYUV64 (const VSImage * dest, const VSImage * src,
uint8_t * tmpbuf, double sharpness, gboolean dither, int submethod,
double a, double sharpen);
void vs_image_scale_nearest_RGB (const VSImage *dest, const VSImage *src,
uint8_t *tmpbuf);
@ -68,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,
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,
uint8_t *tmpbuf);
void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src,

View file

@ -204,6 +204,9 @@ static void vs_image_scale_lanczos_AYUV_float (const VSImage * dest,
static void vs_image_scale_lanczos_AYUV_double (const VSImage * dest,
const VSImage * src, uint8_t * tmpbuf, double sharpness, gboolean dither,
double a, double sharpen);
static void vs_image_scale_lanczos_AYUV64_double (const VSImage * dest,
const VSImage * src, uint8_t * tmpbuf, double sharpness, gboolean dither,
double a, double sharpen);
static double
sinc (double x)
@ -590,6 +593,15 @@ vs_image_scale_lanczos_AYUV (const VSImage * dest, const VSImage * src,
}
}
void
vs_image_scale_lanczos_AYUV64 (const VSImage * dest, const VSImage * src,
uint8_t * tmpbuf, double sharpness, gboolean dither, int submethod,
double a, double sharpen)
{
vs_image_scale_lanczos_AYUV64_double (dest, src, tmpbuf, sharpness, dither,
a, sharpen);
}
#define RESAMPLE_HORIZ_FLOAT(function, dest_type, tap_type, src_type, _n_taps) \
@ -813,9 +825,9 @@ RESAMPLE_VERT_DITHER (resample_vert_dither_int16_generic, gint16, gint16,
n_taps, shift)
/* *INDENT-ON* */
#define RESAMPLE_VERT_FLOAT(function, tap_type, src_type, _n_taps, _shift) \
#define RESAMPLE_VERT_FLOAT(function, dest_type, clamp, tap_type, src_type, _n_taps, _shift) \
static void \
function (guint8 *dest, \
function (dest_type *dest, \
const tap_type *taps, const src_type *src, int stride, int n_taps, \
int shift, int n) \
{ \
@ -828,13 +840,13 @@ function (guint8 *dest, \
const src_type *line = PTR_OFFSET(src, stride * l); \
sum_y += line[i] * taps[l]; \
} \
dest[i] = CLAMP (floor(0.5 + sum_y), 0, 255); \
dest[i] = CLAMP (floor(0.5 + sum_y), 0, clamp); \
} \
}
#define RESAMPLE_VERT_FLOAT_DITHER(function, tap_type, src_type, _n_taps, _shift) \
#define RESAMPLE_VERT_FLOAT_DITHER(function, dest_type, clamp, tap_type, src_type, _n_taps, _shift) \
static void \
function (guint8 *dest, \
function (dest_type *dest, \
const tap_type *taps, const src_type *src, int stride, int n_taps, \
int shift, int n) \
{ \
@ -849,19 +861,24 @@ function (guint8 *dest, \
sum_y += line[i] * taps[l]; \
} \
err_y += sum_y; \
dest[i] = CLAMP (floor (err_y), 0, 255); \
dest[i] = CLAMP (floor (err_y), 0, clamp); \
err_y -= floor (err_y); \
} \
}
/* *INDENT-OFF* */
RESAMPLE_VERT_FLOAT (resample_vert_double_generic, double, double, n_taps,
RESAMPLE_VERT_FLOAT (resample_vert_double_generic, guint8, 255, double, double, n_taps,
shift)
RESAMPLE_VERT_FLOAT_DITHER (resample_vert_dither_double_generic, double, double,
RESAMPLE_VERT_FLOAT_DITHER (resample_vert_dither_double_generic, guint8, 255, double, double,
n_taps, shift)
RESAMPLE_VERT_FLOAT (resample_vert_float_generic, float, float, n_taps, shift)
RESAMPLE_VERT_FLOAT_DITHER (resample_vert_dither_float_generic, float, float,
RESAMPLE_VERT_FLOAT (resample_vert_double_generic_u16, guint16, 65535, double, double, n_taps,
shift)
RESAMPLE_VERT_FLOAT_DITHER (resample_vert_dither_double_generic_u16, guint16, 65535, double, double,
n_taps, shift)
RESAMPLE_VERT_FLOAT (resample_vert_float_generic, guint8, 255, float, float, n_taps, shift)
RESAMPLE_VERT_FLOAT_DITHER (resample_vert_dither_float_generic, guint8, 255, float, float,
n_taps, shift)
/* *INDENT-ON* */
@ -1556,3 +1573,77 @@ vs_image_scale_lanczos_AYUV_float (const VSImage * dest, const VSImage * src,
scale1d_cleanup (&scale->y_scale1d);
g_free (scale->tmpdata);
}
static void
vs_scale_lanczos_AYUV64_double (Scale * scale)
{
int j;
int yi;
int tmp_yi;
tmp_yi = 0;
for (j = 0; j < scale->dest->height; j++) {
guint16 *destline;
double *taps;
destline = (guint16 *) (scale->dest->pixels + scale->dest->stride * j);
yi = scale->y_scale1d.offsets[j];
while (tmp_yi < yi + scale->y_scale1d.n_taps) {
scale->horiz_resample_func (TMP_LINE_DOUBLE_AYUV (tmp_yi),
scale->x_scale1d.offsets, scale->x_scale1d.taps, SRC_LINE (tmp_yi),
scale->x_scale1d.n_taps, 0, scale->dest->width);
tmp_yi++;
}
taps = (double *) scale->y_scale1d.taps + j * scale->y_scale1d.n_taps;
if (scale->dither) {
resample_vert_dither_double_generic_u16 (destline,
taps, TMP_LINE_DOUBLE_AYUV (scale->y_scale1d.offsets[j]),
sizeof (double) * 4 * scale->dest->width,
scale->y_scale1d.n_taps, 0, scale->dest->width * 4);
} else {
resample_vert_double_generic_u16 (destline,
taps, TMP_LINE_DOUBLE_AYUV (scale->y_scale1d.offsets[j]),
sizeof (double) * 4 * scale->dest->width,
scale->y_scale1d.n_taps, 0, scale->dest->width * 4);
}
}
}
void
vs_image_scale_lanczos_AYUV64_double (const VSImage * dest, const VSImage * src,
uint8_t * tmpbuf, double sharpness, gboolean dither, double a,
double sharpen)
{
Scale s = { 0 };
Scale *scale = &s;
int n_taps;
scale->dest = dest;
scale->src = src;
n_taps = scale1d_get_n_taps (src->width, dest->width, a, sharpness);
scale1d_calculate_taps (&scale->x_scale1d,
src->width, dest->width, n_taps, a, sharpness, sharpen);
n_taps = scale1d_get_n_taps (src->height, dest->height, a, sharpness);
scale1d_calculate_taps (&scale->y_scale1d,
src->height, dest->height, n_taps, a, sharpness, sharpen);
scale->dither = dither;
scale->horiz_resample_func =
(HorizResampleFunc) resample_horiz_double_ayuv_generic;
scale->tmpdata =
g_malloc (sizeof (double) * scale->dest->width * scale->src->height * 4);
vs_scale_lanczos_AYUV64_double (scale);
scale1d_cleanup (&scale->x_scale1d);
scale1d_cleanup (&scale->y_scale1d);
g_free (scale->tmpdata);
}

View file

@ -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 */
/* note that src and dest are uint16_t, and thus endian dependent */

View file

@ -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_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_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);

View file

@ -607,7 +607,13 @@ GST_START_TEST (test_parse_caps_rgb)
GST_VIDEO_CAPS_MAKE ("RGBA"), GST_VIDEO_FORMAT_RGBA}, {
GST_VIDEO_CAPS_MAKE ("ARGB"), GST_VIDEO_FORMAT_ARGB}, {
GST_VIDEO_CAPS_MAKE ("BGRA"), GST_VIDEO_FORMAT_BGRA}, {
GST_VIDEO_CAPS_MAKE ("ABGR"), GST_VIDEO_FORMAT_ABGR}
GST_VIDEO_CAPS_MAKE ("ABGR"), GST_VIDEO_FORMAT_ABGR},
/* 16 bit */
{
GST_VIDEO_CAPS_MAKE ("RGB16"), GST_VIDEO_FORMAT_RGB16}, {
GST_VIDEO_CAPS_MAKE ("BGR16"), GST_VIDEO_FORMAT_BGR16}, {
GST_VIDEO_CAPS_MAKE ("RGB15"), GST_VIDEO_FORMAT_RGB15}, {
GST_VIDEO_CAPS_MAKE ("BGR15"), GST_VIDEO_FORMAT_BGR15}
};
gint i;