[vlc-devel] [PATCH 3/6] transcode: rework the encoding size computing

Steve Lhomme robux4 at ycbcr.xyz
Thu Jan 14 13:54:25 UTC 2021


The transcode_video_size_config_apply() and transcode_video_scale_apply() calls
should give consistent results regardless of what width/height were previously
set on the output video_format_t.

The 16 pixels horizontal alignment was never done since the i_visible_width/height
was always set. Now we do it on the coded values, not the visible values. In the
end the encoder should tell which alignment it wants on the input.
The coded size is deduced from the actual visible sizes that will be used.
The visible width/height is still forced to the even values. Even though
it should be up to the encoder to tell if it can't support odd dimensions.

The width/height configured by the user are applied even if there's only one of
them (fixes Chromecast rescaling), and only if there's no user scaling.
---
 modules/stream_out/transcode/encoder/video.c | 96 ++++++++++----------
 1 file changed, 47 insertions(+), 49 deletions(-)

diff --git a/modules/stream_out/transcode/encoder/video.c b/modules/stream_out/transcode/encoder/video.c
index 4de9f3965a0..d2513c68c43 100644
--- a/modules/stream_out/transcode/encoder/video.c
+++ b/modules/stream_out/transcode/encoder/video.c
@@ -64,61 +64,28 @@ static void transcode_video_scale_apply( vlc_object_t *p_obj,
 {
     /* Calculate scaling
      * width/height of source */
-    unsigned i_src_width = p_src->i_visible_width ? p_src->i_visible_width : p_src->i_width;
-    unsigned i_src_height = p_src->i_visible_height ? p_src->i_visible_height : p_src->i_height;
+    const unsigned i_src_width = p_src->i_visible_width;
+    const unsigned i_src_height = p_src->i_visible_height;
 
     /* with/height scaling */
     float f_scale_width = 1;
     float f_scale_height = 1;
 
     /* aspect ratio */
-    float f_aspect = (double)p_src->i_sar_num * p_src->i_width /
-                             p_src->i_sar_den / p_src->i_height;
+    float f_aspect = (double)p_src->i_sar_num * i_src_width /
+                            (p_src->i_sar_den * i_src_height);
 
     msg_Dbg( p_obj, "decoder aspect is %f:1", f_aspect );
 
     /* Change f_aspect from source frame to source pixel */
-    f_aspect = f_aspect * i_src_height / i_src_width;
+    f_aspect = (float)p_src->i_sar_num / p_src->i_sar_den;
     msg_Dbg( p_obj, "source pixel aspect is %f:1", f_aspect );
 
     /* Calculate scaling factor for specified parameters */
-    if( p_dst->i_visible_width == 0 && p_dst->i_visible_height == 0 && f_scale )
-    {
-        /* Global scaling. Make sure width will remain a factor of 16 */
-        float f_real_scale;
-        unsigned i_new_height;
-        unsigned i_new_width = i_src_width * f_scale;
-
-        if( i_new_width % 16 <= 7 && i_new_width >= 16 )
-            i_new_width -= i_new_width % 16;
-        else
-            i_new_width += 16 - i_new_width % 16;
+    unsigned i_new_height = __MAX( 16, i_src_height * f_scale );
 
-        f_real_scale = (float)( i_new_width ) / (float) i_src_width;
-
-        i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
-
-        f_scale_width = f_real_scale;
-        f_scale_height = (float) i_new_height / (float) i_src_height;
-    }
-    else if( p_dst->i_visible_width && p_dst->i_visible_height == 0 )
-    {
-        /* Only width specified */
-        f_scale_width = (float)p_dst->i_visible_width / i_src_width;
-        f_scale_height = f_scale_width;
-    }
-    else if( p_dst->i_visible_width == 0 && p_dst->i_visible_height )
-    {
-         /* Only height specified */
-         f_scale_height = (float)p_dst->i_visible_height / i_src_height;
-         f_scale_width = f_scale_height;
-     }
-     else if( p_dst->i_visible_width && p_dst->i_visible_height )
-     {
-         /* Width and height specified */
-         f_scale_width = (float)p_dst->i_visible_width / i_src_width;
-         f_scale_height = (float)p_dst->i_visible_height / i_src_height;
-     }
+    f_scale_width = f_scale;
+    f_scale_height = (float) i_new_height / (float) i_src_height;
 
      /* check maxwidth and maxheight */
      if( i_maxwidth && f_scale_width > (float)i_maxwidth / i_src_width )
@@ -143,13 +110,10 @@ static void transcode_video_scale_apply( vlc_object_t *p_obj,
      /* width/height of output stream */
      unsigned i_dst_visible_width =  lroundf(f_scale_width*i_src_width);
      unsigned i_dst_visible_height = lroundf(f_scale_height*i_src_height);
-     unsigned i_dst_width =  lroundf(f_scale_width*p_src->i_width);
-     unsigned i_dst_height = lroundf(f_scale_height*p_src->i_height);
-
-     if( i_dst_visible_width & 1 ) ++i_dst_visible_width;
-     if( i_dst_visible_height & 1 ) ++i_dst_visible_height;
-     if( i_dst_width & 1 ) ++i_dst_width;
-     if( i_dst_height & 1 ) ++i_dst_height;
+     if( i_dst_visible_width & 1 ) --i_dst_visible_width;
+     if( i_dst_visible_height & 1 ) --i_dst_visible_height;
+     unsigned i_dst_width =  (i_dst_visible_width  + 0x0F) & ~0x0F;
+     unsigned i_dst_height = (i_dst_visible_height + 0x01) & ~0x01;
 
      /* Store calculated values */
      p_dst->i_width = i_dst_width;
@@ -188,7 +152,7 @@ static void transcode_video_size_config_apply( vlc_object_t *p_obj,
                                                video_format_t *p_dst )
 {
     if( !p_cfg->video.f_scale &&
-        (p_cfg->video.i_width & ~1) && (p_cfg->video.i_width & ~1) )
+        (p_cfg->video.i_width & ~1) && (p_cfg->video.i_height & ~1) )
     {
         p_dst->i_width = p_dst->i_visible_width = p_cfg->video.i_width & ~1;
         p_dst->i_height = p_dst->i_visible_height = p_cfg->video.i_height & ~1;
@@ -202,6 +166,40 @@ static void transcode_video_size_config_apply( vlc_object_t *p_obj,
                                      p_cfg->video.i_maxheight,
                                      p_dst );
     }
+    else if( p_cfg->video.i_height || p_cfg->video.i_width )
+    {
+        if ( !p_cfg->video.i_height )
+        {
+            transcode_video_scale_apply( p_obj,
+                                        p_srcref,
+                                        (float)p_cfg->video.i_width / p_srcref->i_visible_width,
+                                        p_cfg->video.i_maxwidth,
+                                        p_cfg->video.i_maxheight,
+                                        p_dst );
+        }
+        else if ( !p_cfg->video.i_width )
+        {
+            transcode_video_scale_apply( p_obj,
+                                        p_srcref,
+                                        (float)p_cfg->video.i_height / p_srcref->i_visible_height,
+                                        p_cfg->video.i_maxwidth,
+                                        p_cfg->video.i_maxheight,
+                                        p_dst );
+        }
+        else
+        {
+            p_dst->i_visible_width = p_cfg->video.i_width;
+            p_dst->i_visible_height = p_cfg->video.i_height;
+
+            if( p_cfg->video.i_maxwidth && p_dst->i_visible_width > p_cfg->video.i_maxwidth )
+                p_dst->i_visible_width = p_cfg->video.i_maxwidth;
+            if( p_cfg->video.i_maxheight && p_dst->i_visible_height > p_cfg->video.i_maxheight )
+                p_dst->i_visible_height = p_cfg->video.i_maxheight;
+
+            p_dst->i_width  = (p_dst->i_visible_width  + 1) & ~1;
+            p_dst->i_height = (p_dst->i_visible_height + 1) & ~1;
+        }
+    }
     else
     {
         p_dst->i_width = p_srcref->i_width;
-- 
2.29.2



More information about the vlc-devel mailing list