Skip to content

Incorrect SPU scaling when physical size != visible size

On a video with padding (physical size != visible size), SPU are wrongly scaled due to confusion between the visible and physical size. The issue also exists in VLC3.

For example, download Big Buck Bunny 720p (source):

  • i_visible_width: 1280
  • i_visible_height: 720
  • i_width: 1280
  • i_height: 738 (!= 720)

Create a SRT file with the same name in the same folder (Big_Buck_Bunny_720_10s_1MB.srt):

1
00:00:06,000 --> 00:00:07,000
Here is a subtitle

2
00:00:08,000 --> 00:00:09,000
Big Buck Bunny

(The first subtitle is not before 6 seconds to avoid confusion with the video title SPU on start)

And some logs:

diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index 312ccd3492..c0a285d682 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -967,6 +967,12 @@ static void SpuRenderRegion(spu_t *spu,
         const unsigned dst_width  = spu_scale_w(region->fmt.i_visible_width,  scale_size);
         const unsigned dst_height = spu_scale_h(region->fmt.i_visible_height, scale_size);
 
+        fprintf(stderr, "scale w=%u/10000 h=%u/10000: %ux%u -> %ux%u\n",
+                        scale_size.w, scale_size.h,
+                        region->fmt.i_visible_width,
+                        region->fmt.i_visible_height,
+                        dst_width, dst_height);
+
         /* Destroy the cache if unusable */
         if (region->p_private) {
             subpicture_region_private_t *private = region->p_private;
@@ -1038,6 +1044,11 @@ static void SpuRenderRegion(spu_t *spu,
                 scale->fmt_out.video.i_visible_height =
                     spu_scale_h(region->fmt.i_visible_height, scale_size);
 
+                fprintf(stderr, "swscale %ux%u -> %ux%u\n",
+                                scale->fmt_in.video.i_visible_width,
+                                scale->fmt_in.video.i_visible_height,
+                                scale->fmt_out.video.i_visible_width,
+                                scale->fmt_out.video.i_visible_height);
                 picture = scale->ops->filter_video(scale, picture);
                 assert(picture == NULL || !picture_HasChainedPics(picture)); // no chaining
                 if (!picture)
@@ -1209,6 +1220,8 @@ static subpicture_t *SpuRenderSubpictures(spu_t *spu,
         const int i_original_width = subpic->i_original_picture_width;
         const int i_original_height = subpic->i_original_picture_height;
 
+        fprintf(stderr, "original wxh = %ux%u\n", i_original_width, i_original_height);
+
         /* Render all regions
          * We always transform non absolute subtitle into absolute one on the
          * first rendering to allow good subtitle overlap support.
@@ -1971,6 +1984,10 @@ subpicture_t *spu_Render(spu_t *spu,
         spu_render_entry_t *entry = &subpicture_array[i];
         subpicture_t *subpic = entry->subpic;
 
+        const int i_original_width = subpic->i_original_picture_width;
+        const int i_original_height = subpic->i_original_picture_height;
+        fprintf(stderr, "[subpic] %ux%u\n", i_original_width, i_original_height);
+
         spu_PrerenderSync(sys, entry->subpic);
 
         /* Update time to clock */

Here is the output:

[subpic] 1280x720
original wxh = 1280x720
[subpic] 1280x720
original wxh = 1280x720
… repeated many time (it's the video title SPU on start)
[subpic] 1280x738
original wxh = 1280x738
scale w=9756/10000 h=9756/10000: 390x41 -> 380x39
swscale 390x41 -> 380x39
[subpic] 1280x738
original wxh = 1280x738
scale w=9756/10000 h=9756/10000: 390x41 -> 380x39
… repeated many times
[subpic] 1280x738
original wxh = 1280x738
scale w=9756/10000 h=9756/10000: 363x51 -> 354x49
swscale 363x51 -> 354x49
[subpic] 1280x738
original wxh = 1280x738
scale w=9756/10000 h=9756/10000: 363x51 -> 354x49
… repeated many times
Edited by Romain Vimont
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information