mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-07-10 08:35:58 +00:00
video-converter: add dithering
Use the new dither object to perform dithering. Add option to select dithering method. Add option to quantize to a specific value
This commit is contained in:
parent
dfb202a117
commit
d03136f1ea
|
@ -149,9 +149,8 @@ struct _GstVideoConverter
|
||||||
gint current_bits;
|
gint current_bits;
|
||||||
|
|
||||||
GstStructure *config;
|
GstStructure *config;
|
||||||
GstVideoDitherMethod dither;
|
|
||||||
|
|
||||||
guint16 *errline;
|
guint16 *tmpline;
|
||||||
|
|
||||||
gboolean fill_border;
|
gboolean fill_border;
|
||||||
gpointer borderline;
|
gpointer borderline;
|
||||||
|
@ -159,7 +158,6 @@ struct _GstVideoConverter
|
||||||
|
|
||||||
void (*convert) (GstVideoConverter * convert, const GstVideoFrame * src,
|
void (*convert) (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
GstVideoFrame * dest);
|
GstVideoFrame * dest);
|
||||||
void (*dither16) (GstVideoConverter * convert, guint16 * pixels, int j);
|
|
||||||
|
|
||||||
/* data for unpack */
|
/* data for unpack */
|
||||||
GstLineCache *unpack_lines;
|
GstLineCache *unpack_lines;
|
||||||
|
@ -214,6 +212,10 @@ struct _GstVideoConverter
|
||||||
guint down_n_lines;
|
guint down_n_lines;
|
||||||
gint down_offset;
|
gint down_offset;
|
||||||
|
|
||||||
|
/* dither */
|
||||||
|
GstLineCache *dither_lines;
|
||||||
|
GstVideoDither *dither;
|
||||||
|
|
||||||
/* pack */
|
/* pack */
|
||||||
GstLineCache *pack_lines;
|
GstLineCache *pack_lines;
|
||||||
guint pack_nlines;
|
guint pack_nlines;
|
||||||
|
@ -396,6 +398,8 @@ static gboolean do_vscale_lines (GstLineCache * cache, gint out_line,
|
||||||
gint in_line, gpointer user_data);
|
gint in_line, gpointer user_data);
|
||||||
static gboolean do_hscale_lines (GstLineCache * cache, gint out_line,
|
static gboolean do_hscale_lines (GstLineCache * cache, gint out_line,
|
||||||
gint in_line, gpointer user_data);
|
gint in_line, gpointer user_data);
|
||||||
|
static gboolean do_dither_lines (GstLineCache * cache, gint out_line,
|
||||||
|
gint in_line, gpointer user_data);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -530,6 +534,8 @@ get_opt_str (GstVideoConverter * convert, const gchar * opt, const gchar * def)
|
||||||
#define DEFAULT_OPT_PRIMARIES_MODE "none"
|
#define DEFAULT_OPT_PRIMARIES_MODE "none"
|
||||||
#define DEFAULT_OPT_RESAMPLER_METHOD GST_VIDEO_RESAMPLER_METHOD_CUBIC
|
#define DEFAULT_OPT_RESAMPLER_METHOD GST_VIDEO_RESAMPLER_METHOD_CUBIC
|
||||||
#define DEFAULT_OPT_RESAMPLER_TAPS 0
|
#define DEFAULT_OPT_RESAMPLER_TAPS 0
|
||||||
|
#define DEFAULT_OPT_DITHER_METHOD GST_VIDEO_DITHER_BAYER
|
||||||
|
#define DEFAULT_OPT_DITHER_QUANTIZATION 1
|
||||||
|
|
||||||
#define GET_OPT_FILL_BORDER(c) get_opt_bool(c, \
|
#define GET_OPT_FILL_BORDER(c) get_opt_bool(c, \
|
||||||
GST_VIDEO_CONVERTER_OPT_FILL_BORDER, DEFAULT_OPT_FILL_BORDER)
|
GST_VIDEO_CONVERTER_OPT_FILL_BORDER, DEFAULT_OPT_FILL_BORDER)
|
||||||
|
@ -546,6 +552,11 @@ get_opt_str (GstVideoConverter * convert, const gchar * opt, const gchar * def)
|
||||||
DEFAULT_OPT_RESAMPLER_METHOD)
|
DEFAULT_OPT_RESAMPLER_METHOD)
|
||||||
#define GET_OPT_RESAMPLER_TAPS(c) get_opt_uint(c, \
|
#define GET_OPT_RESAMPLER_TAPS(c) get_opt_uint(c, \
|
||||||
GST_VIDEO_CONVERTER_OPT_RESAMPLER_TAPS, DEFAULT_OPT_RESAMPLER_TAPS)
|
GST_VIDEO_CONVERTER_OPT_RESAMPLER_TAPS, DEFAULT_OPT_RESAMPLER_TAPS)
|
||||||
|
#define GET_OPT_DITHER_METHOD(c) get_opt_enum(c, \
|
||||||
|
GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD, \
|
||||||
|
DEFAULT_OPT_DITHER_METHOD)
|
||||||
|
#define GET_OPT_DITHER_QUANTIZATION(c) get_opt_uint(c, \
|
||||||
|
GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION, DEFAULT_OPT_DITHER_QUANTIZATION)
|
||||||
|
|
||||||
#define CHECK_MATRIX_FULL(c) (!g_strcmp0(GET_OPT_MATRIX_MODE(c), "full"))
|
#define CHECK_MATRIX_FULL(c) (!g_strcmp0(GET_OPT_MATRIX_MODE(c), "full"))
|
||||||
#define CHECK_MATRIX_NO_YUV(c) (!g_strcmp0(GET_OPT_MATRIX_MODE(c), "no-yuv"))
|
#define CHECK_MATRIX_NO_YUV(c) (!g_strcmp0(GET_OPT_MATRIX_MODE(c), "no-yuv"))
|
||||||
|
@ -1419,6 +1430,65 @@ chain_downsample (GstVideoConverter * convert, GstLineCache * prev)
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstLineCache *
|
||||||
|
chain_dither (GstVideoConverter * convert, GstLineCache * prev)
|
||||||
|
{
|
||||||
|
gint i;
|
||||||
|
gboolean do_dither = FALSE;
|
||||||
|
GstVideoDitherFlags flags = 0;
|
||||||
|
GstVideoDitherMethod method;
|
||||||
|
guint quant[4], target_quant;
|
||||||
|
|
||||||
|
method = GET_OPT_DITHER_METHOD (convert);
|
||||||
|
target_quant = GET_OPT_DITHER_QUANTIZATION (convert);
|
||||||
|
GST_DEBUG ("method %d, target-quantization %d", method, target_quant);
|
||||||
|
|
||||||
|
if (convert->pack_pal) {
|
||||||
|
quant[0] = 47;
|
||||||
|
quant[1] = 47;
|
||||||
|
quant[2] = 47;
|
||||||
|
quant[3] = 1;
|
||||||
|
do_dither = TRUE;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < GST_VIDEO_MAX_COMPONENTS; i++) {
|
||||||
|
gint depth;
|
||||||
|
|
||||||
|
depth = convert->out_info.finfo->depth[i];
|
||||||
|
|
||||||
|
if (depth == 0) {
|
||||||
|
quant[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convert->current_bits >= depth) {
|
||||||
|
quant[i] = 1 << (convert->current_bits - depth);
|
||||||
|
if (target_quant > quant[i]) {
|
||||||
|
flags |= GST_VIDEO_DITHER_FLAG_QUANTIZE;
|
||||||
|
quant[i] = target_quant;
|
||||||
|
}
|
||||||
|
do_dither = TRUE;
|
||||||
|
} else {
|
||||||
|
quant[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_dither) {
|
||||||
|
GST_DEBUG ("chain dither");
|
||||||
|
|
||||||
|
convert->dither = gst_video_dither_new (method,
|
||||||
|
flags, convert->pack_format, quant, convert->current_width);
|
||||||
|
|
||||||
|
prev = convert->dither_lines = gst_line_cache_new (prev);
|
||||||
|
prev->write_input = TRUE;
|
||||||
|
prev->pass_alloc = TRUE;
|
||||||
|
prev->n_lines = 1;
|
||||||
|
prev->stride = convert->current_pstride * convert->current_width;
|
||||||
|
gst_line_cache_set_need_line_func (prev, do_dither_lines, convert, NULL);
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
static GstLineCache *
|
static GstLineCache *
|
||||||
chain_pack (GstVideoConverter * convert, GstLineCache * prev)
|
chain_pack (GstVideoConverter * convert, GstLineCache * prev)
|
||||||
{
|
{
|
||||||
|
@ -1536,9 +1606,7 @@ gst_video_converter_new (GstVideoInfo * in_info, GstVideoInfo * out_info,
|
||||||
convert->out_info = *out_info;
|
convert->out_info = *out_info;
|
||||||
|
|
||||||
/* default config */
|
/* default config */
|
||||||
convert->config = gst_structure_new ("GstVideoConverter",
|
convert->config = gst_structure_new_empty ("GstVideoConverter");
|
||||||
GST_VIDEO_CONVERTER_OPT_DITHER_METHOD, GST_TYPE_VIDEO_DITHER_METHOD,
|
|
||||||
GST_VIDEO_DITHER_NONE, NULL);
|
|
||||||
if (config)
|
if (config)
|
||||||
gst_video_converter_set_config (convert, config);
|
gst_video_converter_set_config (convert, config);
|
||||||
|
|
||||||
|
@ -1616,12 +1684,13 @@ gst_video_converter_new (GstVideoInfo * in_info, GstVideoInfo * out_info,
|
||||||
prev = chain_convert_to_YUV (convert, prev);
|
prev = chain_convert_to_YUV (convert, prev);
|
||||||
/* downsample chroma */
|
/* downsample chroma */
|
||||||
prev = chain_downsample (convert, prev);
|
prev = chain_downsample (convert, prev);
|
||||||
|
/* dither */
|
||||||
|
prev = chain_dither (convert, prev);
|
||||||
/* pack into final format */
|
/* pack into final format */
|
||||||
convert->pack_lines = chain_pack (convert, prev);
|
convert->pack_lines = chain_pack (convert, prev);
|
||||||
|
|
||||||
width = MAX (convert->in_maxwidth, convert->out_maxwidth);
|
width = MAX (convert->in_maxwidth, convert->out_maxwidth);
|
||||||
width += convert->out_x;
|
width += convert->out_x;
|
||||||
convert->errline = g_malloc0 (sizeof (guint16) * width * 4);
|
|
||||||
|
|
||||||
if (convert->fill_border && (convert->out_height < convert->out_maxheight ||
|
if (convert->fill_border && (convert->out_height < convert->out_maxheight ||
|
||||||
convert->out_width < convert->out_maxwidth)) {
|
convert->out_width < convert->out_maxwidth)) {
|
||||||
|
@ -1711,10 +1780,13 @@ gst_video_converter_free (GstVideoConverter * convert)
|
||||||
if (convert->downsample_lines)
|
if (convert->downsample_lines)
|
||||||
gst_line_cache_free (convert->downsample_lines);
|
gst_line_cache_free (convert->downsample_lines);
|
||||||
|
|
||||||
|
if (convert->dither)
|
||||||
|
gst_video_dither_free (convert->dither);
|
||||||
|
|
||||||
g_free (convert->gamma_dec.gamma_table);
|
g_free (convert->gamma_dec.gamma_table);
|
||||||
g_free (convert->gamma_enc.gamma_table);
|
g_free (convert->gamma_enc.gamma_table);
|
||||||
|
|
||||||
g_free (convert->errline);
|
g_free (convert->tmpline);
|
||||||
g_free (convert->borderline);
|
g_free (convert->borderline);
|
||||||
|
|
||||||
if (convert->config)
|
if (convert->config)
|
||||||
|
@ -1723,46 +1795,6 @@ gst_video_converter_free (GstVideoConverter * convert)
|
||||||
g_slice_free (GstVideoConverter, convert);
|
g_slice_free (GstVideoConverter, convert);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
video_dither_verterr (GstVideoConverter * convert, guint16 * pixels, int j)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
guint16 *errline = convert->errline;
|
|
||||||
unsigned int mask = 0xff;
|
|
||||||
|
|
||||||
for (i = 0; i < 4 * convert->in_width; i++) {
|
|
||||||
int x = pixels[i] + errline[i];
|
|
||||||
if (x > 65535)
|
|
||||||
x = 65535;
|
|
||||||
pixels[i] = x;
|
|
||||||
errline[i] = x & mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
video_dither_halftone (GstVideoConverter * convert, guint16 * pixels, int j)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
static guint16 halftone[8][8] = {
|
|
||||||
{0, 128, 32, 160, 8, 136, 40, 168},
|
|
||||||
{192, 64, 224, 96, 200, 72, 232, 104},
|
|
||||||
{48, 176, 16, 144, 56, 184, 24, 152},
|
|
||||||
{240, 112, 208, 80, 248, 120, 216, 88},
|
|
||||||
{12, 240, 44, 172, 4, 132, 36, 164},
|
|
||||||
{204, 76, 236, 108, 196, 68, 228, 100},
|
|
||||||
{60, 188, 28, 156, 52, 180, 20, 148},
|
|
||||||
{252, 142, 220, 92, 244, 116, 212, 84}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; i < convert->in_width * 4; i++) {
|
|
||||||
int x;
|
|
||||||
x = pixels[i] + halftone[(i >> 2) & 7][j & 7];
|
|
||||||
if (x > 65535)
|
|
||||||
x = 65535;
|
|
||||||
pixels[i] = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
copy_config (GQuark field_id, const GValue * value, gpointer user_data)
|
copy_config (GQuark field_id, const GValue * value, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -1795,42 +1827,13 @@ gboolean
|
||||||
gst_video_converter_set_config (GstVideoConverter * convert,
|
gst_video_converter_set_config (GstVideoConverter * convert,
|
||||||
GstStructure * config)
|
GstStructure * config)
|
||||||
{
|
{
|
||||||
gint dither;
|
|
||||||
gboolean res = TRUE;
|
|
||||||
|
|
||||||
g_return_val_if_fail (convert != NULL, FALSE);
|
g_return_val_if_fail (convert != NULL, FALSE);
|
||||||
g_return_val_if_fail (config != NULL, FALSE);
|
g_return_val_if_fail (config != NULL, FALSE);
|
||||||
|
|
||||||
if (gst_structure_get_enum (config, GST_VIDEO_CONVERTER_OPT_DITHER_METHOD,
|
|
||||||
GST_TYPE_VIDEO_DITHER_METHOD, &dither)) {
|
|
||||||
gboolean update = TRUE;
|
|
||||||
|
|
||||||
switch (dither) {
|
|
||||||
case GST_VIDEO_DITHER_NONE:
|
|
||||||
convert->dither16 = NULL;
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_DITHER_VERTERR:
|
|
||||||
convert->dither16 = video_dither_verterr;
|
|
||||||
break;
|
|
||||||
case GST_VIDEO_DITHER_HALFTONE:
|
|
||||||
convert->dither16 = video_dither_halftone;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
update = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (update)
|
|
||||||
gst_structure_set (convert->config, GST_VIDEO_CONVERTER_OPT_DITHER_METHOD,
|
|
||||||
GST_TYPE_VIDEO_DITHER_METHOD, dither, NULL);
|
|
||||||
else
|
|
||||||
res = FALSE;
|
|
||||||
}
|
|
||||||
if (res)
|
|
||||||
gst_structure_foreach (config, copy_config, convert);
|
gst_structure_foreach (config, copy_config, convert);
|
||||||
|
|
||||||
gst_structure_free (config);
|
gst_structure_free (config);
|
||||||
|
|
||||||
return res;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1964,7 +1967,6 @@ video_converter_compute_resample (GstVideoConverter * convert)
|
||||||
src, 0, frame->data, frame->info.stride, \
|
src, 0, frame->data, frame->info.stride, \
|
||||||
frame->info.chroma_site, line, width);
|
frame->info.chroma_site, line, width);
|
||||||
|
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
get_dest_line (GstLineCache * cache, gint idx, gpointer user_data)
|
get_dest_line (GstLineCache * cache, gint idx, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
@ -2151,9 +2153,8 @@ do_convert_lines (GstLineCache * cache, gint out_line, gint in_line,
|
||||||
GST_DEBUG ("matrix line %d %p", in_line, srcline);
|
GST_DEBUG ("matrix line %d %p", in_line, srcline);
|
||||||
data->matrix_func (data, srcline);
|
data->matrix_func (data, srcline);
|
||||||
}
|
}
|
||||||
if (convert->dither16)
|
|
||||||
convert->dither16 (convert, srcline, in_line);
|
|
||||||
|
|
||||||
|
/* FIXME, dither here */
|
||||||
if (out_bits == 8) {
|
if (out_bits == 8) {
|
||||||
GST_DEBUG ("16->8 line %d %p->%p", in_line, srcline, destline);
|
GST_DEBUG ("16->8 line %d %p->%p", in_line, srcline, destline);
|
||||||
video_orc_convert_u16_to_u8 (destline, srcline, width * 4);
|
video_orc_convert_u16_to_u8 (destline, srcline, width * 4);
|
||||||
|
@ -2221,6 +2222,26 @@ do_downsample_lines (GstLineCache * cache, gint out_line, gint in_line,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
do_dither_lines (GstLineCache * cache, gint out_line, gint in_line,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GstVideoConverter *convert = user_data;
|
||||||
|
gpointer *lines, destline;
|
||||||
|
|
||||||
|
lines = gst_line_cache_get_lines (cache->prev, out_line, in_line, 1);
|
||||||
|
destline = lines[0];
|
||||||
|
|
||||||
|
if (convert->dither) {
|
||||||
|
GST_DEBUG ("Dither line %d %p", in_line, destline);
|
||||||
|
gst_video_dither_line (convert->dither, destline, 0, out_line,
|
||||||
|
convert->out_width);
|
||||||
|
}
|
||||||
|
gst_line_cache_add_line (cache, in_line, destline);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
video_converter_generic (GstVideoConverter * convert, const GstVideoFrame * src,
|
video_converter_generic (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
GstVideoFrame * dest)
|
GstVideoFrame * dest)
|
||||||
|
@ -2338,8 +2359,8 @@ convert_I420_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2366,8 +2387,8 @@ convert_I420_UYVY (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2393,8 +2414,8 @@ convert_I420_AYUV (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2443,8 +2464,8 @@ convert_I420_Y444 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2470,8 +2491,8 @@ convert_YUY2_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2538,8 +2559,8 @@ convert_UYVY_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2690,8 +2711,8 @@ convert_Y42B_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2781,8 +2802,8 @@ convert_Y444_I420 (GstVideoConverter * convert, const GstVideoFrame * src,
|
||||||
|
|
||||||
/* now handle last line */
|
/* now handle last line */
|
||||||
if (height & 1) {
|
if (height & 1) {
|
||||||
UNPACK_FRAME (src, convert->errline, height - 1, convert->in_x, width);
|
UNPACK_FRAME (src, convert->tmpline, height - 1, convert->in_x, width);
|
||||||
PACK_FRAME (dest, convert->errline, height - 1, width);
|
PACK_FRAME (dest, convert->tmpline, height - 1, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3070,6 +3091,9 @@ video_converter_lookup_fastpath (GstVideoConverter * convert)
|
||||||
if (width != convert->out_width || height != convert->out_height)
|
if (width != convert->out_width || height != convert->out_height)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (GET_OPT_DITHER_QUANTIZATION (convert) != 1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* we don't do gamma conversion in fastpath */
|
/* we don't do gamma conversion in fastpath */
|
||||||
in_transf = convert->in_info.colorimetry.transfer;
|
in_transf = convert->in_info.colorimetry.transfer;
|
||||||
out_transf = convert->out_info.colorimetry.transfer;
|
out_transf = convert->out_info.colorimetry.transfer;
|
||||||
|
@ -3113,6 +3137,7 @@ video_converter_lookup_fastpath (GstVideoConverter * convert)
|
||||||
if (transforms[i].needs_color_matrix)
|
if (transforms[i].needs_color_matrix)
|
||||||
video_converter_compute_matrix (convert);
|
video_converter_compute_matrix (convert);
|
||||||
convert->convert = transforms[i].convert;
|
convert->convert = transforms[i].convert;
|
||||||
|
convert->tmpline = g_malloc0 (sizeof (guint16) * (width + 8) * 4);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,22 +24,6 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
|
||||||
* GstVideoDitherMethod:
|
|
||||||
* @GST_VIDEO_DITHER_NONE: no dithering
|
|
||||||
* @GST_VIDEO_DITHER_VERTERR: propagate rounding errors downwards
|
|
||||||
* @GST_VIDEO_DITHER_HALFTONE: Dither with halftone pattern
|
|
||||||
* @GST_VIDEO_DITHER_HORIZERR: propagate rounding errors right
|
|
||||||
*
|
|
||||||
* Different dithering methods to use.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
GST_VIDEO_DITHER_NONE,
|
|
||||||
GST_VIDEO_DITHER_VERTERR,
|
|
||||||
GST_VIDEO_DITHER_HALFTONE,
|
|
||||||
GST_VIDEO_DITHER_HORIZERR
|
|
||||||
} GstVideoDitherMethod;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD:
|
* GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD:
|
||||||
*
|
*
|
||||||
|
@ -65,6 +49,15 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
#define GST_VIDEO_CONVERTER_OPT_DITHER_METHOD "GstVideoConverter.dither-method"
|
#define GST_VIDEO_CONVERTER_OPT_DITHER_METHOD "GstVideoConverter.dither-method"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION:
|
||||||
|
*
|
||||||
|
* #G_TYPE_UINT, The quantization amount to dither to. Components will be
|
||||||
|
* quantized to multiples of this value.
|
||||||
|
* Default is 1
|
||||||
|
*/
|
||||||
|
#define GST_VIDEO_CONVERTER_OPT_DITHER_QUANTIZATION "GstVideoConverter.dither-quantization"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GST_VIDEO_CONVERTER_OPT_SRC_X:
|
* GST_VIDEO_CONVERTER_OPT_SRC_X:
|
||||||
*
|
*
|
||||||
|
|
|
@ -477,7 +477,7 @@ gst_video_dither_line (GstVideoDither * dither, gpointer line, guint x, guint y,
|
||||||
guint width)
|
guint width)
|
||||||
{
|
{
|
||||||
g_return_if_fail (dither != NULL);
|
g_return_if_fail (dither != NULL);
|
||||||
g_return_if_fail (x + width < dither->width);
|
g_return_if_fail (x + width <= dither->width);
|
||||||
|
|
||||||
if (dither->func)
|
if (dither->func)
|
||||||
dither->func (dither, line, x, y, width);
|
dither->func (dither, line, x, y, width);
|
||||||
|
|
Loading…
Reference in a new issue