video-converter: Add support for 16 bits formats
authorWim Taymans <wtaymans@redhat.com>
Mon, 3 Nov 2014 14:33:24 +0000 (15:33 +0100)
committerWim Taymans <wtaymans@redhat.com>
Mon, 3 Nov 2014 14:41:02 +0000 (15:41 +0100)
Rework the way we track the current state of the video through the
different conversion phases and use this to make sure we use the right
format and pstride where needed.

gst-libs/gst/video/video-converter.c

index d94b98c..24496f5 100644 (file)
@@ -74,7 +74,10 @@ struct _GstVideoConverter
   gint out_height;
   gint out_maxwidth;
   gint out_maxheight;
-  gint v_scale_width;
+
+  gint current_pstride;
+  gint current_width;
+  GstVideoFormat current_format;
 
   gint in_bits;
   gint out_bits;
@@ -117,7 +120,11 @@ struct _GstVideoConverter
   GstLineCache *pack_lines;
 
   GstVideoScaler *h_scaler;
+  gint h_scale_format;
   GstVideoScaler *v_scaler;
+  gint v_scale_width;
+  gint v_scale_format;
+  gint pack_pstride;
 
   const GstVideoFrame *src;
   GstVideoFrame *dest;
@@ -290,19 +297,33 @@ get_temp_line (GstVideoConverter * convert, gint offset)
 {
   gpointer tmpline;
 
-  tmpline = (guint32 *) convert->tmplines[convert->tmplines_idx] + offset;
+  tmpline = (guint8 *) convert->tmplines[convert->tmplines_idx] +
+      (offset * convert->pack_pstride);
   convert->tmplines_idx = (convert->tmplines_idx + 1) % convert->n_tmplines;
 
   return tmpline;
 }
 
 static GstLineCacheNeedLineFunc
+chain_unpack_line (GstVideoConverter * convert)
+{
+  convert->current_format = convert->in_info.finfo->format;
+  convert->current_pstride = convert->in_bits >> 1;
+  return (GstLineCacheNeedLineFunc) do_unpack_lines;
+}
+
+static GstLineCacheNeedLineFunc
 chain_upsample (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
 {
-  convert->upsample_lines = gst_line_cache_new ();
-  gst_line_cache_set_need_line_func (convert->upsample_lines,
-      need_line, convert, NULL);
-  return (GstLineCacheNeedLineFunc) do_upsample_lines;
+  video_converter_compute_resample (convert);
+
+  if (convert->upsample) {
+    convert->upsample_lines = gst_line_cache_new ();
+    gst_line_cache_set_need_line_func (convert->upsample_lines,
+        need_line, convert, NULL);
+    need_line = (GstLineCacheNeedLineFunc) do_upsample_lines;
+  }
+  return need_line;
 }
 
 static GstLineCacheNeedLineFunc
@@ -311,6 +332,8 @@ chain_convert (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
   convert->convert_lines = gst_line_cache_new ();
   gst_line_cache_set_need_line_func (convert->convert_lines,
       need_line, convert, NULL);
+  convert->current_format = convert->out_info.finfo->format;
+  convert->current_pstride = convert->out_bits >> 1;
   return (GstLineCacheNeedLineFunc) do_convert_lines;
 }
 
@@ -336,6 +359,9 @@ chain_hscale (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
       gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_NONE, taps,
       convert->in_width, convert->out_width, convert->config);
 
+  convert->current_width = convert->out_width;
+  convert->h_scale_format = convert->current_format;
+
   return (GstLineCacheNeedLineFunc) do_hscale_lines;
 }
 
@@ -364,6 +390,8 @@ chain_vscale (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
   convert->v_scaler =
       gst_video_scaler_new (method, flags, taps, convert->in_height,
       convert->out_height, convert->config);
+  convert->v_scale_width = convert->current_width;
+  convert->v_scale_format = convert->current_format;
 
   return (GstLineCacheNeedLineFunc) do_vscale_lines;
 }
@@ -372,10 +400,13 @@ static GstLineCacheNeedLineFunc
 chain_downsample (GstVideoConverter * convert,
     GstLineCacheNeedLineFunc need_line)
 {
-  convert->downsample_lines = gst_line_cache_new ();
-  gst_line_cache_set_need_line_func (convert->downsample_lines,
-      need_line, convert, NULL);
-  return (GstLineCacheNeedLineFunc) do_downsample_lines;
+  if (convert->downsample) {
+    convert->downsample_lines = gst_line_cache_new ();
+    gst_line_cache_set_need_line_func (convert->downsample_lines,
+        need_line, convert, NULL);
+    need_line = (GstLineCacheNeedLineFunc) do_downsample_lines;
+  }
+  return need_line;
 }
 
 static GstLineCacheNeedLineFunc
@@ -386,6 +417,7 @@ chain_pack (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
       need_line, convert, NULL);
   gst_line_cache_set_free_line_func (convert->pack_lines,
       (GstLineCacheFreeLineFunc) free_pack_line, convert, NULL);
+  convert->pack_pstride = convert->current_pstride;
   return NULL;
 }
 
@@ -505,17 +537,16 @@ gst_video_converter_new (GstVideoInfo * in_info, GstVideoInfo * out_info,
 
   s2 = convert->in_width * convert->out_height;
   s3 = convert->out_width * convert->in_height;
-  convert->v_scale_width = convert->in_width;
 
   video_converter_compute_matrix (convert);
-  video_converter_compute_resample (convert);
 
-  /* unpack */
-  need_line = (GstLineCacheNeedLineFunc) do_unpack_lines;
+  convert->current_format = GST_VIDEO_INFO_FORMAT (in_info);
+  convert->current_width = convert->in_width;
 
+  /* unpack */
+  need_line = chain_unpack_line (convert);
   /* upsample chroma */
-  if (convert->upsample)
-    need_line = chain_upsample (convert, need_line);
+  need_line = chain_upsample (convert, need_line);
 
   if (s3 <= s2) {
     /* horizontal scaling first produces less pixels */
@@ -525,7 +556,6 @@ gst_video_converter_new (GstVideoInfo * in_info, GstVideoInfo * out_info,
     }
     if (convert->in_width != convert->out_width) {
       need_line = chain_hscale (convert, need_line);
-      convert->v_scale_width = convert->out_width;
     }
     if (convert->in_width > convert->out_width) {
       /* downscaling, convert after scaling then */
@@ -551,8 +581,7 @@ gst_video_converter_new (GstVideoInfo * in_info, GstVideoInfo * out_info,
     }
   }
   /* downsample chroma */
-  if (convert->downsample)
-    need_line = chain_downsample (convert, need_line);
+  need_line = chain_downsample (convert, need_line);
   /* pack into final format */
   need_line = chain_pack (convert, need_line);
 
@@ -1270,7 +1299,7 @@ do_hscale_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
   destline = get_temp_line (convert, convert->out_x);
 
   GST_DEBUG ("hresample line %d", line);
-  gst_video_scaler_horizontal (convert->h_scaler, GST_VIDEO_FORMAT_AYUV,
+  gst_video_scaler_horizontal (convert->h_scaler, convert->h_scale_format,
       lines[0], destline, 0, convert->out_width);
 
   gst_line_cache_add_line (cache, line, destline);
@@ -1295,7 +1324,7 @@ do_vscale_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
   /* FIXME with 1-tap (nearest), we can simply copy the input line. We need
    * to be careful to not do in-place modifications later */
   GST_DEBUG ("vresample line %d %d-%d", line, sline, sline + n_lines - 1);
-  gst_video_scaler_vertical (convert->v_scaler, GST_VIDEO_FORMAT_AYUV,
+  gst_video_scaler_vertical (convert->v_scaler, convert->v_scale_format,
       lines, destline, cline, convert->v_scale_width);
 
   gst_line_cache_add_line (cache, line, destline);
@@ -1372,8 +1401,8 @@ video_converter_generic (GstVideoConverter * convert, const GstVideoFrame * src,
   gint i;
   gint out_maxwidth, out_maxheight;
   gint out_x, out_y, out_height;
-  gint pack_lines;
-  gint r_border, out_width;
+  gint pack_lines, pstride;
+  gint r_border, out_width, lb_width, rb_width;
 
   out_width = convert->out_width;
   out_height = convert->out_height;
@@ -1383,12 +1412,15 @@ video_converter_generic (GstVideoConverter * convert, const GstVideoFrame * src,
   out_x = convert->out_x;
   out_y = convert->out_y;
 
-  r_border = out_x + out_width;
-
   convert->src = src;
   convert->dest = dest;
 
   pack_lines = convert->lines;  /* only 1 for now */
+  pstride = convert->pack_pstride;
+
+  r_border = (out_x + out_width) * pstride;
+  rb_width = out_maxwidth * pstride - r_border;
+  lb_width = out_x * pstride;
 
   if (convert->borderline) {
     /* FIXME we should try to avoid PACK_FRAME */
@@ -1398,19 +1430,19 @@ video_converter_generic (GstVideoConverter * convert, const GstVideoFrame * src,
 
   for (i = 0; i < out_height; i += pack_lines) {
     gpointer *lines;
-    guint32 *l;
+    guint8 *l;
 
     /* load the lines needed to pack */
     lines = gst_line_cache_get_lines (convert->pack_lines, i, pack_lines);
 
     /* take away the border */
-    l = ((guint32 *) lines[0]) - out_x;
+    l = ((guint8 *) lines[0]) - lb_width;
 
     if (convert->borderline) {
       /* FIXME this can be optimized if we make separate temp lines with
        * border for the output lines */
-      memcpy (l, convert->borderline, out_x * 4);
-      memcpy (l + r_border, convert->borderline, (out_maxwidth - r_border) * 4);
+      memcpy (l, convert->borderline, lb_width);
+      memcpy (l + r_border, convert->borderline, rb_width);
     }
     /* and pack into destination */
     /* FIXME, we should be able to convert directly into the destination line