video-converter: fix interlaced scaling some more
authorWim Taymans <wtaymans@redhat.com>
Wed, 22 Jun 2016 14:02:37 +0000 (16:02 +0200)
committerWim Taymans <wtaymans@redhat.com>
Wed, 22 Jun 2016 14:21:13 +0000 (16:21 +0200)
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
gst-libs/gst/video/video-resampler.c
gst-libs/gst/video/video-resampler.h
gst-libs/gst/video/video-scaler.c

index ccdee43..de9bab4 100644 (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;
index 07dddc9..0848961 100644 (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;
 
index 699f382..3338046 100644 (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;
 
 /**
index b633cb4..d1b4b27 100644 (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;
+
+    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);