From 5e752f4edad15cb090608f45c10161398ba58fee Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 22 Jun 2016 16:02:37 +0200 Subject: [PATCH] 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 --- gst-libs/gst/video/video-converter.c | 8 +++----- gst-libs/gst/video/video-resampler.c | 2 ++ gst-libs/gst/video/video-resampler.h | 4 ++++ gst-libs/gst/video/video-scaler.c | 12 +++++++++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/gst-libs/gst/video/video-converter.c b/gst-libs/gst/video/video-converter.c index ccdee43..de9bab4 100644 --- a/gst-libs/gst/video/video-converter.c +++ b/gst-libs/gst/video/video-converter.c @@ -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; diff --git a/gst-libs/gst/video/video-resampler.c b/gst-libs/gst/video/video-resampler.c index 07dddc9..0848961 100644 --- a/gst-libs/gst/video/video-resampler.c +++ b/gst-libs/gst/video/video-resampler.c @@ -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; diff --git a/gst-libs/gst/video/video-resampler.h b/gst-libs/gst/video/video-resampler.h index 699f382..3338046 100644 --- a/gst-libs/gst/video/video-resampler.h +++ b/gst-libs/gst/video/video-resampler.h @@ -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; /** diff --git a/gst-libs/gst/video/video-scaler.c b/gst-libs/gst/video/video-scaler.c index b633cb4..d1b4b27 100644 --- a/gst-libs/gst/video/video-scaler.c +++ b/gst-libs/gst/video/video-scaler.c @@ -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; + + shift = (INTERLACE_SHIFT * out_size) / in_size; - gst_video_resampler_init (&tresamp, method, 0, (out_size + 1) / 2, n_taps, - -0.5, (in_size + 1) / 2, (out_size + 1) / 2, options); + 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); -- 2.7.4