video-converter: fix interlaced scaling some more

Fix problem with the line cache where it would forget the first line in
the cache in some cases.
Keep as much backlog as we have taps. This generally works better and we
could do even better by calculating the overlap in all taps.
Allocated enough lines for the line cache.
Use only half the number of taps for the interlaced lines because we
only have half the number of lines.
The pixel shift should be relative to the new output pixel size so scale
it.
Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=767921
This commit is contained in:
Wim Taymans 2016-06-22 16:02:37 +02:00
parent 950c73af43
commit 5e752f4eda
4 changed files with 18 additions and 8 deletions

View file

@ -395,8 +395,6 @@ gst_line_cache_get_lines (GstLineCache * cache, gint out_line, gint in_line,
g_ptr_array_remove_range (cache->lines, 0, to_remove);
}
cache->first += to_remove;
if (cache->first < in_line)
cache->first = in_line;
} else if (in_line < cache->first) {
gst_line_cache_clear (cache);
cache->first = in_line;
@ -1457,7 +1455,7 @@ chain_vscale (GstVideoConverter * convert, GstLineCache * prev)
taps, convert->in_height, convert->out_height, convert->config);
gst_video_scaler_get_coeff (convert->v_scaler_i, 0, NULL, &taps_i);
backlog = BACKLOG;
backlog = taps_i;
}
convert->v_scaler_p =
gst_video_scaler_new (method, 0, taps, convert->in_height,
@ -1909,8 +1907,8 @@ setup_allocators (GstVideoConverter * convert)
if (!cache->pass_alloc) {
/* can't pass allocator, make new temp line allocator */
user_data =
converter_alloc_new (sizeof (guint16) * width * 4, n_lines + BACKLOG,
convert, NULL);
converter_alloc_new (sizeof (guint16) * width * 4,
n_lines + cache->backlog, convert, NULL);
notify = (GDestroyNotify) converter_alloc_free;
alloc_line = get_temp_line;
alloc_writable = FALSE;

View file

@ -410,6 +410,8 @@ gst_video_resampler_init (GstVideoResampler * resampler,
params.dx = ceil (2.0 * params.envelope / params.fx);
n_taps = CLAMP (params.dx, 0, max_taps);
}
if (flags & GST_VIDEO_RESAMPLER_FLAG_HALF_TAPS && n_taps > 3)
n_taps /= 2;
params.fx = 2.0 * params.envelope / n_taps;
params.ex = 2.0 / n_taps;

View file

@ -116,6 +116,9 @@ typedef enum {
/**
* GstVideoResamplerFlags:
* @GST_VIDEO_RESAMPLER_FLAG_NONE: no flags
* @GST_VIDEO_RESAMPLER_FLAG_HALF_TAPS: when no taps are given, half the
* number of calculated taps. This can be used when making scalers
* for the different fields of an interlaced picture. Since 1.10
*
* Different resampler flags.
*
@ -123,6 +126,7 @@ typedef enum {
*/
typedef enum {
GST_VIDEO_RESAMPLER_FLAG_NONE = (0),
GST_VIDEO_RESAMPLER_FLAG_HALF_TAPS = (1 << 0),
} GstVideoResamplerFlags;
/**

View file

@ -185,6 +185,8 @@ scaler_dump (GstVideoScaler * scale)
#endif
}
#define INTERLACE_SHIFT 0.5
/**
* gst_video_scaler_new: (skip)
* @method: a #GstVideoResamplerMethod
@ -221,14 +223,18 @@ gst_video_scaler_new (GstVideoResamplerMethod method, GstVideoScalerFlags flags,
if (flags & GST_VIDEO_SCALER_FLAG_INTERLACED) {
GstVideoResampler tresamp, bresamp;
gdouble shift;
gst_video_resampler_init (&tresamp, method, 0, (out_size + 1) / 2, n_taps,
-0.5, (in_size + 1) / 2, (out_size + 1) / 2, options);
shift = (INTERLACE_SHIFT * out_size) / in_size;
gst_video_resampler_init (&tresamp, method,
GST_VIDEO_RESAMPLER_FLAG_HALF_TAPS, (out_size + 1) / 2, n_taps, shift,
(in_size + 1) / 2, (out_size + 1) / 2, options);
n_taps = tresamp.max_taps;
gst_video_resampler_init (&bresamp, method, 0, out_size - tresamp.out_size,
n_taps, 0.5, in_size - tresamp.in_size,
n_taps, -shift, in_size - tresamp.in_size,
out_size - tresamp.out_size, options);
resampler_zip (&scale->resampler, &tresamp, &bresamp);