[vlc-commits] [Git][videolan/vlc][master] 35 commits: subpicture: merge pf_validate and pf_update calls

Steve Lhomme (@robUx4) gitlab at videolan.org
Thu Nov 16 11:56:05 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
2fcc5179 by Steve Lhomme at 2023-11-16T10:57:02+00:00
subpicture: merge pf_validate and pf_update calls

pf_validate is supposed to tell if the regions need to be redone or not.
But since pf_update is going to write the regions, it can also reset the
container by itself. It's the owner of these regions.

- - - - -
e3318976 by Steve Lhomme at 2023-11-16T10:57:02+00:00
vout/osd: simplify pf_update code

We only need to check if the destination format has changed.

- - - - -
138d084c by Steve Lhomme at 2023-11-16T10:57:02+00:00
subsdelay: simplify code

pf_update is mandatory

- - - - -
0de9fa20 by Steve Lhomme at 2023-11-16T10:57:02+00:00
subsdelay: merge SubpicValidateWrapper into SubpicUpdateWrapper

SubpicValidateWrapper was always returning VLC_SUCCESS.

- - - - -
7a3514c0 by Steve Lhomme at 2023-11-16T10:57:02+00:00
ttml: simplify pf_update code

We only need to check if the destination format has changed.

- - - - -
cfcb595c by Steve Lhomme at 2023-11-16T10:57:02+00:00
aribcaption: merge SubpictureValidate into SubpictureUpdate

- - - - -
55b5bec5 by Steve Lhomme at 2023-11-16T10:57:02+00:00
substext: merge SubpictureTextValidate into SubpictureTextUpdate

- - - - -
a2f92d80 by Steve Lhomme at 2023-11-16T10:57:02+00:00
substext: only keep the local SAR

No need to create an empty video format with just these fields.

The regions format are already initialized with video_format_Init(0).

- - - - -
d5ae2f72 by Steve Lhomme at 2023-11-16T10:57:02+00:00
libass: merge SubpictureValidate into SubpictureUpdate

- - - - -
f026e44c by Steve Lhomme at 2023-11-16T10:57:02+00:00
libass: don't keep the ASS_Image

It's only used inside SubpictureUpdate()

- - - - -
33d6f509 by Steve Lhomme at 2023-11-16T10:57:02+00:00
libass: don't keep the rendering format

It's only used inside SubpictureUpdate()

- - - - -
b7ce4340 by Steve Lhomme at 2023-11-16T10:57:02+00:00
kate: merge TigerValidateSubpicture into TigerUpdateSubpicture

- - - - -
3fd26156 by Steve Lhomme at 2023-11-16T10:57:02+00:00
kate: fix indentation

- - - - -
d9f74ab4 by Steve Lhomme at 2023-11-16T10:57:02+00:00
arib/substext: simplify pf_update code

We only need to check if the source/destination format has changed.

The check is suspicious since the source format is never used.

- - - - -
b7cabf4b by Steve Lhomme at 2023-11-16T10:57:02+00:00
arib/substext: don't check has_src_changed to update regions

The input format is never used. We only need to update if the output format
changed.

- - - - -
2f054d8f by Steve Lhomme at 2023-11-16T10:57:02+00:00
bluray: return proper error codes in subpictureUpdaterValidate()

- - - - -
2345f09e by Steve Lhomme at 2023-11-16T10:57:02+00:00
bluray: merge subpictureUpdaterValidate into subpictureUpdaterUpdate

- - - - -
844deb71 by Steve Lhomme at 2023-11-16T10:57:02+00:00
bluray: fix overlay status when there's no region left

Otherwise it remains perpetually to Outdated.

If p_overlay->regions is empty then no copy will be done and
p_subpic->regions will remain empty.

- - - - -
a987b446 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
vlc_subpicture: rename p_sys to sys

Uniformize the subpicture updater structure with the rest of the new
code, by removing the hungarian notation. The operations will also be
updated later with the introduction of a dedicated operation table.

- - - - -
c3b92800 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
vlc_subpicture: create new table for operations

This removes the hungarian notation on the function pointers and gather
them into a single table which can be referenced by the updaters.

- - - - -
b1f4db5b by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
misc: subpicture: use new operation table

- - - - -
6e601881 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
bluray: use new spu updater operation

- - - - -
9b0b3069 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
libaribcaption: use new spu updater operations

- - - - -
25df0472 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
arib: substext: use new spu updater operations

- - - - -
ad738986 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
codec: kate: use new spu updater operations

- - - - -
3f995ff3 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
codec: libass: use new spu updater operations

- - - - -
a7cdbb24 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
codec: substext: use new spu updater operations

- - - - -
cf26eb19 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
codec: ttml: use new spu updater operations

- - - - -
e441e551 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
spu: subsdelay: use new spu updater operations

- - - - -
e095c8ce by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
video_epg: use new spu updater operation table

- - - - -
61f288c2 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
video_text: use new spu updater operation table

- - - - -
c6dbdf96 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
video_widgets: use new spu updater operation table

- - - - -
d099f7dd by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
spu: subsdelay: remove legacy operation support

- - - - -
80fe17f2 by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
misc: subpicture: remove legacy operation

- - - - -
c1a15d6e by Alexandre Janniaux at 2023-11-16T10:57:02+00:00
vlc_subpicture: remove legacy operations table

The new operation table, found in updater->ops, allow to reference
external virtual tables in a better way.

- - - - -


25 changed files:

- include/vlc_subpicture.h
- modules/access/bluray.c
- modules/codec/arib/aribsub.c
- modules/codec/arib/libaribcaption.c
- modules/codec/arib/substext.h
- modules/codec/cc.c
- modules/codec/cea708.c
- modules/codec/kate.c
- modules/codec/libass.c
- modules/codec/scte18.c
- modules/codec/stl.c
- modules/codec/subsdec.c
- modules/codec/substext.h
- modules/codec/substx3g.c
- modules/codec/textst.c
- modules/codec/ttml/imageupdater.h
- modules/codec/ttml/substtml.c
- modules/codec/webvtt/subsvtt.c
- modules/codec/zvbi.c
- modules/spu/subsdelay.c
- src/misc/subpicture.c
- src/video_output/video_epg.c
- src/video_output/video_text.c
- src/video_output/video_widgets.c
- src/video_output/vout_subpictures.c


Changes:

=====================================
include/vlc_subpicture.h
=====================================
@@ -166,6 +166,25 @@ VLC_API void subpicture_region_Delete( subpicture_region_t *p_region );
  */
 VLC_API void vlc_spu_regions_Clear( vlc_spu_regions * );
 
+/**
+ * Subpicture updater operation virtual table.
+ *
+ * This structure gathers the operations that are implemented by a
+ * subpicture_updater_t instance. */
+struct vlc_spu_updater_ops
+{
+    /** Mandatory callback called after pf_validate and doing
+      * the main job of creating the subpicture regions for the
+      * current video_format */
+    void (*update)(subpicture_t *,
+                   bool has_src_changed, const video_format_t *p_fmt_src,
+                   bool has_dst_changed, const video_format_t *p_fmt_dst,
+                   vlc_tick_t);
+
+    /** Optional callback for subpicture private data cleanup */
+    void (*destroy)(subpicture_t *);
+};
+
 /**
  * Tells if the region is a text-based region.
  */
@@ -177,23 +196,8 @@ VLC_API void vlc_spu_regions_Clear( vlc_spu_regions * );
  */
 typedef struct
 {
-    /** Optional pre update callback, usually useful on video format change.
-      * Will skip pf_update on VLC_SUCCESS, or will delete every region before
-      * the call to pf_update */
-    int  (*pf_validate)( subpicture_t *,
-                         bool has_src_changed, const video_format_t *p_fmt_src,
-                         bool has_dst_changed, const video_format_t *p_fmt_dst,
-                         vlc_tick_t);
-    /** Mandatory callback called after pf_validate and doing
-      * the main job of creating the subpicture regions for the
-      * current video_format */
-    void (*pf_update)  ( subpicture_t *,
-                         const video_format_t *p_fmt_src,
-                         const video_format_t *p_fmt_dst,
-                         vlc_tick_t );
-    /** Optional callback for subpicture private data cleanup */
-    void (*pf_destroy) ( subpicture_t * );
-    void *p_sys;
+    void *sys;
+    const struct vlc_spu_updater_ops *ops;
 } subpicture_updater_t;
 
 typedef struct subpicture_private_t subpicture_private_t;


=====================================
modules/access/bluray.c
=====================================
@@ -1630,56 +1630,35 @@ static void updater_unlock_overlay(bluray_spu_updater_sys_t *p_upd_sys)
     vlc_mutex_unlock(&p_upd_sys->lock);
 }
 
-static int subpictureUpdaterValidate(subpicture_t *p_subpic,
-                                      bool b_fmt_src, const video_format_t *p_fmt_src,
-                                      bool b_fmt_dst, const video_format_t *p_fmt_dst,
-                                      vlc_tick_t i_ts)
+static void subpictureUpdaterUpdate(subpicture_t *p_subpic,
+                                    bool b_fmt_src, const video_format_t *p_fmt_src,
+                                    bool b_fmt_dst, const video_format_t *p_fmt_dst,
+                                    vlc_tick_t i_ts)
 {
-    VLC_UNUSED(b_fmt_src);
-    VLC_UNUSED(b_fmt_dst);
     VLC_UNUSED(p_fmt_src);
     VLC_UNUSED(p_fmt_dst);
     VLC_UNUSED(i_ts);
 
-    bluray_spu_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
+    bluray_spu_updater_sys_t *p_upd_sys = p_subpic->updater.sys;
     bluray_overlay_t         *p_overlay = updater_lock_overlay(p_upd_sys);
 
     if (!p_overlay) {
-        return 1;
+        return;
     }
 
-    int res = p_overlay->status == Outdated;
-
-    updater_unlock_overlay(p_upd_sys);
-
-    return res;
-}
-
-static void subpictureUpdaterUpdate(subpicture_t *p_subpic,
-                                    const video_format_t *p_fmt_src,
-                                    const video_format_t *p_fmt_dst,
-                                    vlc_tick_t i_ts)
-{
-    VLC_UNUSED(p_fmt_src);
-    VLC_UNUSED(p_fmt_dst);
-    VLC_UNUSED(i_ts);
-    bluray_spu_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
-    bluray_overlay_t         *p_overlay = updater_lock_overlay(p_upd_sys);
-
-    if (!p_overlay) {
+    if (p_overlay->status != Outdated)
+    {
+        updater_unlock_overlay(p_upd_sys);
         return;
     }
 
+    vlc_spu_regions_Clear( &p_subpic->regions );
+
     /*
      * When this function is called, all p_subpic regions are gone.
      * We need to duplicate our regions (stored internally) to this subpic.
      */
     const subpicture_region_t *p_src;
-    if (vlc_spu_regions_is_empty(&p_overlay->regions)) {
-        updater_unlock_overlay(p_upd_sys);
-        return;
-    }
-
     subpicture_region_t *p_dst;
     vlc_spu_regions_foreach_const(p_src, &p_overlay->regions) {
         p_dst = subpicture_region_ForPicture(&p_src->fmt, p_src->p_picture);
@@ -1703,7 +1682,7 @@ static void subpictureUpdaterUpdate(subpicture_t *p_subpic,
 
 static void subpictureUpdaterDestroy(subpicture_t *p_subpic)
 {
-    bluray_spu_updater_sys_t *p_upd_sys = p_subpic->updater.p_sys;
+    bluray_spu_updater_sys_t *p_upd_sys = p_subpic->updater.sys;
     bluray_overlay_t         *p_overlay = updater_lock_overlay(p_upd_sys);
 
     if (p_overlay) {
@@ -1725,11 +1704,15 @@ static subpicture_t *bluraySubpictureCreate(bluray_overlay_t *p_ov)
 
     p_upd_sys->p_overlay = p_ov;
 
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = subpictureUpdaterUpdate,
+        .destroy  = subpictureUpdaterDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = subpictureUpdaterValidate,
-        .pf_update   = subpictureUpdaterUpdate,
-        .pf_destroy  = subpictureUpdaterDestroy,
-        .p_sys       = p_upd_sys,
+        .sys = p_upd_sys,
+        .ops = &spu_ops,
     };
 
     subpicture_t *p_pic = subpicture_New(&updater);


=====================================
modules/codec/arib/aribsub.c
=====================================
@@ -266,7 +266,7 @@ static subpicture_t *render( decoder_t *p_dec, arib_parser_t *p_parser,
     p_spu->b_ephemer  = (p_spu->i_start == p_spu->i_stop);
     p_spu->b_absolute = true;
 
-    arib_spu_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+    arib_spu_updater_sys_t *p_spu_sys = p_spu->updater.sys;
 
     arib_text_region_t *p_region = p_spu_sys->p_region =
         (arib_text_region_t*) calloc( 1, sizeof(arib_text_region_t) );


=====================================
modules/codec/arib/libaribcaption.c
=====================================
@@ -99,12 +99,28 @@ static void DecSysRelease(decoder_sys_t *p_sys)
 /****************************************************************************
  *
  ****************************************************************************/
-static int SubpictureValidate(subpicture_t *p_subpic,
-                              bool b_src_changed, const video_format_t *p_src_format,
-                              bool b_dst_changed, const video_format_t *p_dst_format,
-                              vlc_tick_t i_ts)
+static void CopyImageToRegion(picture_t *dst_pic, const aribcc_image_t *image)
+{
+    if(image->pixel_format != ARIBCC_PIXELFORMAT_RGBA8888)
+        return;
+
+    plane_t *p_dstplane = &dst_pic->p[0];
+    plane_t srcplane;
+    srcplane.i_lines = image->height;
+    srcplane.i_pitch = image->stride;
+    srcplane.i_pixel_pitch = p_dstplane->i_pixel_pitch;
+    srcplane.i_visible_lines = image->height;
+    srcplane.i_visible_pitch = image->width /* in pixels */ * p_dstplane->i_pixel_pitch;
+    srcplane.p_pixels = image->bitmap;
+    plane_CopyPixels( p_dstplane, &srcplane );
+}
+
+static void SubpictureUpdate(subpicture_t *p_subpic,
+                             bool b_src_changed, const video_format_t *p_src_format,
+                             bool b_dst_changed, const video_format_t *p_dst_format,
+                             vlc_tick_t i_ts)
 {
-    libaribcaption_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    libaribcaption_spu_updater_sys_t *p_spusys = p_subpic->updater.sys;
     decoder_sys_t *p_sys = p_spusys->p_dec_sys;
 
     if (b_src_changed || b_dst_changed) {
@@ -125,7 +141,7 @@ static int SubpictureValidate(subpicture_t *p_subpic,
     if (status == ARIBCC_RENDER_STATUS_GOT_IMAGE_UNCHANGED) {
         /* Skip rendering since images were not changed */
         if (!b_src_changed && !b_dst_changed) {
-            return VLC_SUCCESS;
+            return;
         }
     }
 
@@ -133,36 +149,10 @@ static int SubpictureValidate(subpicture_t *p_subpic,
                                     MS_FROM_VLC_TICK(i_stream_date),
                                     &p_spusys->render_result);
     if (status == ARIBCC_RENDER_STATUS_ERROR) {
-        return VLC_SUCCESS;
-    }
-
-    return VLC_EGENERIC;
-}
-
-static void CopyImageToRegion(picture_t *dst_pic, const aribcc_image_t *image)
-{
-    if(image->pixel_format != ARIBCC_PIXELFORMAT_RGBA8888)
         return;
+    }
 
-    plane_t *p_dstplane = &dst_pic->p[0];
-    plane_t srcplane;
-    srcplane.i_lines = image->height;
-    srcplane.i_pitch = image->stride;
-    srcplane.i_pixel_pitch = p_dstplane->i_pixel_pitch;
-    srcplane.i_visible_lines = image->height;
-    srcplane.i_visible_pitch = image->width /* in pixels */ * p_dstplane->i_pixel_pitch;
-    srcplane.p_pixels = image->bitmap;
-    plane_CopyPixels( p_dstplane, &srcplane );
-}
-
-static void SubpictureUpdate(subpicture_t *p_subpic,
-                             const video_format_t *p_src_format,
-                             const video_format_t *p_dst_format,
-                             vlc_tick_t i_ts)
-{
-    VLC_UNUSED(p_src_format); VLC_UNUSED(p_dst_format); VLC_UNUSED(i_ts);
-
-    libaribcaption_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    vlc_spu_regions_Clear( &p_subpic->regions );
 
     video_format_t  fmt = *p_dst_format;
     fmt.i_chroma         = VLC_CODEC_RGBA;
@@ -209,7 +199,7 @@ static void SubpictureUpdate(subpicture_t *p_subpic,
 
 static void SubpictureDestroy(subpicture_t *p_subpic)
 {
-    libaribcaption_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    libaribcaption_spu_updater_sys_t *p_spusys = p_subpic->updater.sys;
     DecSysRelease(p_spusys->p_dec_sys);
     free(p_spusys);
 }
@@ -257,11 +247,15 @@ static int Decode(decoder_t *p_dec, block_t *p_block)
     p_spusys->i_pts = p_block->i_pts;
     memset(&p_spusys->render_result, 0, sizeof(p_spusys->render_result));
 
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = SubpictureUpdate,
+        .destroy  = SubpictureDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = SubpictureValidate,
-        .pf_update   = SubpictureUpdate,
-        .pf_destroy  = SubpictureDestroy,
-        .p_sys       = p_spusys,
+        .sys = p_spusys,
+        .ops = &spu_ops,
     };
 
     subpicture_t *p_spu = decoder_NewSubpicture(p_dec, &updater);


=====================================
modules/codec/arib/substext.h
=====================================
@@ -45,28 +45,19 @@ typedef struct
     arib_text_region_t *p_region;
 } arib_spu_updater_sys_t;
 
-static int SubpictureTextValidate(subpicture_t *subpic,
-                                  bool has_src_changed, const video_format_t *fmt_src,
-                                  bool has_dst_changed, const video_format_t *fmt_dst,
-                                  vlc_tick_t ts)
-{
-    arib_spu_updater_sys_t *sys = subpic->updater.p_sys;
-    VLC_UNUSED(fmt_src); VLC_UNUSED(fmt_dst); VLC_UNUSED(ts);
-    VLC_UNUSED(sys);
-
-    if (!has_src_changed && !has_dst_changed)
-    {
-        return VLC_SUCCESS;
-    }
-    return VLC_EGENERIC;
-}
 static void SubpictureTextUpdate(subpicture_t *subpic,
-                                 const video_format_t *fmt_src,
-                                 const video_format_t *fmt_dst,
+                                 bool has_src_changed, const video_format_t *fmt_src,
+                                 bool has_dst_changed, const video_format_t *fmt_dst,
                                  vlc_tick_t ts)
 {
-    arib_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    arib_spu_updater_sys_t *sys = subpic->updater.sys;
     VLC_UNUSED(fmt_src); VLC_UNUSED(ts);
+    VLC_UNUSED(has_src_changed);
+
+    if (!has_dst_changed)
+        return;
+
+    vlc_spu_regions_Clear( &subpic->regions );
 
     if (fmt_dst->i_sar_num <= 0 || fmt_dst->i_sar_den <= 0)
     {
@@ -112,7 +103,7 @@ static void SubpictureTextUpdate(subpicture_t *subpic,
 }
 static void SubpictureTextDestroy(subpicture_t *subpic)
 {
-    arib_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    arib_spu_updater_sys_t *sys = subpic->updater.sys;
 
     arib_text_region_t *p_region, *p_region_next;
     for( p_region = sys->p_region; p_region; p_region = p_region_next )
@@ -130,11 +121,16 @@ static inline subpicture_t *decoder_NewSubpictureText(decoder_t *decoder)
 {
     arib_spu_updater_sys_t *sys = (arib_spu_updater_sys_t*)
         calloc( 1, sizeof(arib_spu_updater_sys_t) );
+
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = SubpictureTextUpdate,
+        .destroy  = SubpictureTextDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = SubpictureTextValidate,
-        .pf_update   = SubpictureTextUpdate,
-        .pf_destroy  = SubpictureTextDestroy,
-        .p_sys       = sys,
+        .sys = sys,
+        .ops = &spu_ops,
     };
     subpicture_t *subpic = decoder_NewSubpicture(decoder, &updater);
     if( subpic == NULL )


=====================================
modules/codec/cc.c
=====================================
@@ -506,7 +506,7 @@ static subpicture_t *Subtitle( decoder_t *p_dec, eia608_t *h, vlc_tick_t i_pts )
     p_spu->b_ephemer  = true;
     p_spu->b_absolute = false;
 
-    subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+    subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
     decoder_sys_t *p_dec_sys = p_dec->p_sys;
 
     /* Set first region defaults */


=====================================
modules/codec/cea708.c
=====================================
@@ -1084,7 +1084,7 @@ static subpicture_t *CEA708_BuildSubtitle( cea708_t *p_cea708 )
     if( !p_spu )
         return NULL;
 
-    subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+    subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
     substext_updater_region_t *p_region = &p_spu_sys->region;
 
     p_spu_sys->margin_ratio = CEA708_SCREEN_SAFE_MARGIN_RATIO;


=====================================
modules/codec/kate.c
=====================================
@@ -740,7 +740,7 @@ static void SetupText( decoder_t *p_dec, subpicture_region_t *p_region, const ka
 
 static void TigerDestroySubpicture( subpicture_t *p_subpic )
 {
-    kate_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    kate_spu_updater_sys_t *p_spusys = p_subpic->updater.sys;
     DecSysRelease( p_spusys->p_dec_sys );
     free( p_spusys );
 }
@@ -795,64 +795,51 @@ static void PostprocessTigerImage( plane_t *p_plane, unsigned int i_width )
     PROFILE_STOP( tiger_renderer_postprocess );
 }
 
-static int TigerValidateSubpicture( subpicture_t *p_subpic,
-                                    bool b_fmt_src, const video_format_t *p_fmt_src,
-                                    bool b_fmt_dst, const video_format_t *p_fmt_dst,
-                                    vlc_tick_t ts )
-{
-    VLC_UNUSED(p_fmt_src); VLC_UNUSED(p_fmt_dst);
-
-    kate_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
-    decoder_sys_t *p_sys = p_spusys->p_dec_sys;
-
-    if( b_fmt_src || b_fmt_dst )
-        return VLC_EGENERIC;
-
-    PROFILE_START( TigerValidateSubpicture );
-
-    /* time in seconds from the start of the stream */
-    kate_float t = (p_spusys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
-
-    /* it is likely that the current region (if any) can be kept as is; test for this */
-    vlc_mutex_lock( &p_sys->lock );
-    int i_ret;
-    if( p_sys->b_dirty || tiger_renderer_is_dirty( p_sys->p_tr ) )
-    {
-        i_ret = VLC_EGENERIC;
-        goto exit;
-    }
-    if( tiger_renderer_update( p_sys->p_tr, t, 1 ) >= 0 &&
-        tiger_renderer_is_dirty( p_sys->p_tr ) )
-    {
-        i_ret = VLC_EGENERIC;
-        goto exit;
-    }
-
-    i_ret = VLC_SUCCESS;
-exit:
-    vlc_mutex_unlock( &p_sys->lock );
-    PROFILE_STOP( TigerValidateSubpicture );
-    return i_ret;
-}
-
 /* Tiger renders can end up looking a bit crap since they get overlaid on top of
    a subsampled YUV image, so there can be a fair amount of chroma bleeding.
    Looks good with white though since it's all luma. Hopefully that will be the
    common case. */
 static void TigerUpdateSubpicture( subpicture_t *p_subpic,
-                                   const video_format_t *p_fmt_src,
-                                   const video_format_t *p_fmt_dst,
+                                   bool b_fmt_src, const video_format_t *p_fmt_src,
+                                   bool b_fmt_dst, const video_format_t *p_fmt_dst,
                                    vlc_tick_t ts )
 {
-    kate_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    kate_spu_updater_sys_t *p_spusys = p_subpic->updater.sys;
     decoder_sys_t *p_sys = p_spusys->p_dec_sys;
     plane_t *p_plane;
-    kate_float t;
-    int i_ret;
+    /* time in seconds from the start of the stream */
+    kate_float t = (p_spusys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
 
+    bool new_regions = false;
+    if( b_fmt_src || b_fmt_dst )
+        new_regions = true;
 
-    /* time in seconds from the start of the stream */
-    t = (p_spusys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
+    if (!new_regions)
+    {
+        PROFILE_START( TigerValidateSubpicture );
+
+        /* it is likely that the current region (if any) can be kept as is; test for this */
+        vlc_mutex_lock( &p_sys->lock );
+        if( p_sys->b_dirty || tiger_renderer_is_dirty( p_sys->p_tr ) )
+        {
+            new_regions = true;
+            goto exit;
+        }
+        if( tiger_renderer_update( p_sys->p_tr, t, 1 ) >= 0 &&
+            tiger_renderer_is_dirty( p_sys->p_tr ) )
+        {
+            new_regions = true;
+            goto exit;
+        }
+exit:
+        vlc_mutex_unlock( &p_sys->lock );
+        PROFILE_STOP( TigerValidateSubpicture );
+    }
+
+    if (!new_regions)
+        return;
+
+    vlc_spu_regions_Clear( &p_subpic->regions );
 
     PROFILE_START( TigerUpdateSubpicture );
 
@@ -875,6 +862,7 @@ static void TigerUpdateSubpicture( subpicture_t *p_subpic,
 
     vlc_mutex_lock( &p_sys->lock );
 
+    int i_ret;
     p_plane = &p_r->p_picture->p[0];
     i_ret = tiger_renderer_set_buffer( p_sys->p_tr, p_plane->p_pixels, fmt.i_width, p_plane->i_lines, p_plane->i_pitch, 1 );
     if( i_ret < 0 )
@@ -1028,13 +1016,20 @@ static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t
         if( !p_spu_sys )
             return NULL;
     }
-    subpicture_updater_t updater = {
+
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
 #ifdef HAVE_TIGER
-        .pf_validate = TigerValidateSubpicture,
-        .pf_update   = TigerUpdateSubpicture,
-        .pf_destroy  = TigerDestroySubpicture,
+        .update   = TigerUpdateSubpicture,
+        .destroy  = TigerDestroySubpicture,
+#else
+        .update = NULL, .destroy = NULL,
 #endif
-        .p_sys       = p_spu_sys,
+    };
+
+    subpicture_updater_t updater = {
+        .sys = p_spu_sys,
+        .ops = &spu_ops,
     };
     p_spu = decoder_NewSubpicture( p_dec, p_sys->b_use_tiger ? &updater : NULL );
     if( !p_spu )


=====================================
modules/codec/libass.c
=====================================
@@ -86,7 +86,6 @@ typedef struct
     /* */
     ASS_Library    *p_library;
     ASS_Renderer   *p_renderer;
-    video_format_t fmt;
 
     /* */
     ASS_Track      *p_track;
@@ -95,13 +94,9 @@ static void DecSysRelease( decoder_sys_t *p_sys );
 static void DecSysHold( decoder_sys_t *p_sys );
 
 /* */
-static int SubpictureValidate( subpicture_t *,
-                               bool, const video_format_t *,
-                               bool, const video_format_t *,
-                               vlc_tick_t );
 static void SubpictureUpdate( subpicture_t *,
-                              const video_format_t *,
-                              const video_format_t *,
+                              bool, const video_format_t *,
+                              bool, const video_format_t *,
                               vlc_tick_t );
 static void SubpictureDestroy( subpicture_t * );
 
@@ -109,8 +104,6 @@ typedef struct
 {
     decoder_sys_t *p_dec_sys;
     vlc_tick_t    i_pts;
-
-    ASS_Image     *p_img;
 } libass_spu_updater_sys_t;
 
 typedef struct
@@ -148,7 +141,6 @@ static int Create( vlc_object_t *p_this )
     /* */
     vlc_mutex_init( &p_sys->lock );
     p_sys->i_refcount = 1;
-    video_format_Init( &p_sys->fmt, 0 );
     p_sys->i_last_pts = VLC_TICK_INVALID;
     p_sys->i_max_stop = VLC_TICK_INVALID;
     p_sys->p_library  = NULL;
@@ -371,11 +363,15 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
             return VLCDEC_SUCCESS;
         }
 
+        static const struct vlc_spu_updater_ops spu_ops =
+        {
+            .update   = SubpictureUpdate,
+            .destroy  = SubpictureDestroy,
+        };
+
         subpicture_updater_t updater = {
-            .pf_validate = SubpictureValidate,
-            .pf_update   = SubpictureUpdate,
-            .pf_destroy  = SubpictureDestroy,
-            .p_sys       = p_spu_sys,
+            .sys = p_spu_sys,
+            .ops = &spu_ops,
         };
 
         p_spu = decoder_NewSubpicture( p_dec, &updater );
@@ -387,7 +383,6 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
             return VLCDEC_SUCCESS;
         }
 
-        p_spu_sys->p_img = NULL;
         p_spu_sys->p_dec_sys = p_sys;
         p_spu_sys->i_pts = p_block->i_pts;
         p_spu->i_start = p_block->i_pts;
@@ -421,12 +416,12 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
 /****************************************************************************
  *
  ****************************************************************************/
-static int SubpictureValidate( subpicture_t *p_subpic,
-                               bool b_fmt_src, const video_format_t *p_fmt_src,
-                               bool b_fmt_dst, const video_format_t *p_fmt_dst,
-                               vlc_tick_t i_ts )
+static void SubpictureUpdate( subpicture_t *p_subpic,
+                              bool b_fmt_src, const video_format_t *p_fmt_src,
+                              bool b_fmt_dst, const video_format_t *p_fmt_dst,
+                              vlc_tick_t i_ts )
 {
-    libass_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    libass_spu_updater_sys_t *p_spusys = p_subpic->updater.sys;
     decoder_sys_t *p_sys = p_spusys->p_dec_sys;
 
     vlc_mutex_lock( &p_sys->lock );
@@ -444,7 +439,6 @@ static int SubpictureValidate( subpicture_t *p_subpic,
         const double src_ratio = (double)p_fmt_src->i_visible_width / p_fmt_src->i_visible_height;
         const double dst_ratio = (double)p_fmt_dst->i_visible_width / p_fmt_dst->i_visible_height;
         ass_set_aspect_ratio( p_sys->p_renderer, dst_ratio / src_ratio, 1 );
-        p_sys->fmt = fmt;
     }
 
     /* */
@@ -457,26 +451,10 @@ static int SubpictureValidate( subpicture_t *p_subpic,
         (p_img != NULL) == (!vlc_spu_regions_is_empty(&p_subpic->regions)) )
     {
         vlc_mutex_unlock( &p_sys->lock );
-        return VLC_SUCCESS;
+        return;
     }
-    p_spusys->p_img = p_img;
-
-    /* The lock is released by SubpictureUpdate */
-    return VLC_EGENERIC;
-}
-
-static void SubpictureUpdate( subpicture_t *p_subpic,
-                              const video_format_t *p_fmt_src,
-                              const video_format_t *p_fmt_dst,
-                              vlc_tick_t i_ts )
-{
-    VLC_UNUSED( p_fmt_src ); VLC_UNUSED( p_fmt_dst ); VLC_UNUSED( i_ts );
-
-    libass_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
-    decoder_sys_t *p_sys = p_spusys->p_dec_sys;
 
-    video_format_t fmt = p_sys->fmt;
-    ASS_Image *p_img = p_spusys->p_img;
+    vlc_spu_regions_Clear( &p_subpic->regions );
 
     /* */
     p_subpic->i_original_picture_height = fmt.i_visible_height;
@@ -529,7 +507,7 @@ static void SubpictureUpdate( subpicture_t *p_subpic,
 }
 static void SubpictureDestroy( subpicture_t *p_subpic )
 {
-    libass_spu_updater_sys_t *p_spusys = p_subpic->updater.p_sys;
+    libass_spu_updater_sys_t *p_spusys = p_subpic->updater.sys;
 
     DecSysRelease( p_spusys->p_dec_sys );
     free( p_spusys );


=====================================
modules/codec/scte18.c
=====================================
@@ -185,7 +185,7 @@ static int Decode( decoder_t *p_dec, block_t *p_block )
         p_spu = decoder_NewSubpictureText( p_dec );
         if( p_spu )
         {
-            subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+            subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
 
             p_spu->i_start = p_block->i_pts;
             if( p_cea->alert_message_time_remaining )


=====================================
modules/codec/stl.c
=====================================
@@ -407,7 +407,7 @@ static int Decode(decoder_t *p_dec, block_t *p_block)
             subpicture_t *p_sub = decoder_NewSubpictureText(p_dec);
             if( p_sub )
             {
-                FillSubpictureUpdater(p_group, p_sub->updater.p_sys );
+                FillSubpictureUpdater(p_group, p_sub->updater.sys );
 
                 p_sub->b_absolute = false;
 


=====================================
modules/codec/subsdec.c
=====================================
@@ -457,7 +457,7 @@ static subpicture_t *ParseText( decoder_t *p_dec, block_t *p_block )
     p_spu->b_ephemer  = (p_block->i_length == VLC_TICK_INVALID);
     p_spu->b_absolute = false;
 
-    subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+    subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
 
     int i_inline_align = -1;
     p_spu_sys->region.p_segments = ParseSubtitles( &i_inline_align, psz_subtitle );


=====================================
modules/codec/substext.h
=====================================
@@ -95,17 +95,17 @@ static inline void SubpictureUpdaterSysRegionAdd(substext_updater_region_t *p_pr
     *pp_next = p_new;
 }
 
-static int SubpictureTextValidate(subpicture_t *subpic,
-                                  bool has_src_changed, const video_format_t *fmt_src,
-                                  bool has_dst_changed, const video_format_t *fmt_dst,
-                                  vlc_tick_t ts)
+static void SubpictureTextUpdate(subpicture_t *subpic,
+                                 bool has_src_changed, const video_format_t *fmt_src,
+                                 bool has_dst_changed, const video_format_t *fmt_dst,
+                                 vlc_tick_t ts)
 {
-    subtext_updater_sys_t *sys = subpic->updater.p_sys;
+    subtext_updater_sys_t *sys = subpic->updater.sys;
     VLC_UNUSED(fmt_src); VLC_UNUSED(fmt_dst);
 
     if (!has_src_changed && !has_dst_changed &&
         (sys->i_next_update == VLC_TICK_INVALID || sys->i_next_update > ts))
-        return VLC_SUCCESS;
+        return;
 
     substext_updater_region_t *p_updtregion = &sys->region;
 
@@ -124,23 +124,12 @@ static int SubpictureTextValidate(subpicture_t *subpic,
         p_updtregion->flags &= ~(UPDT_REGION_ORIGIN_X_IS_RATIO|UPDT_REGION_ORIGIN_Y_IS_RATIO|
                                  UPDT_REGION_EXTENT_X_IS_RATIO|UPDT_REGION_EXTENT_Y_IS_RATIO);
     }
-
-    return VLC_EGENERIC;
-}
-
-static void SubpictureTextUpdate(subpicture_t *subpic,
-                                 const video_format_t *fmt_src,
-                                 const video_format_t *fmt_dst,
-                                 vlc_tick_t ts)
-{
-    subtext_updater_sys_t *sys = subpic->updater.p_sys;
-    VLC_UNUSED(fmt_src);
+    vlc_spu_regions_Clear( &subpic->regions );
 
     if (fmt_dst->i_sar_num <= 0 || fmt_dst->i_sar_den <= 0)
         return;
 
-    video_format_t fmt;
-    video_format_Init(&fmt, 0);
+    vlc_rational_t sar;
 
     /* NOTE about fmt_dst:
      * fmt_dst area and A/R will change to display once WxH of the
@@ -151,17 +140,17 @@ static void SubpictureTextUpdate(subpicture_t *subpic,
 
     if( sys->region.flags & UPDT_REGION_USES_GRID_COORDINATES )
     {
-        fmt.i_sar_num = 4;
-        fmt.i_sar_den = 3;
-        subpic->i_original_picture_width  = fmt_dst->i_visible_height * fmt.i_sar_num / fmt.i_sar_den;
+        sar.num = 4;
+        sar.den = 3;
+        subpic->i_original_picture_width  = fmt_dst->i_visible_height * sar.num / sar.den;
         subpic->i_original_picture_height = fmt_dst->i_visible_height;
     }
     else
     {
         subpic->i_original_picture_width  = fmt_dst->i_width * fmt_dst->i_sar_num / fmt_dst->i_sar_den;
         subpic->i_original_picture_height = fmt_dst->i_height;
-        fmt.i_sar_num = 1;
-        fmt.i_sar_den = 1;
+        sar.num = 1;
+        sar.den = 1;
     }
 
     bool b_schedule_blink_update = false;
@@ -173,7 +162,8 @@ static void SubpictureTextUpdate(subpicture_t *subpic,
         if (!r)
             return;
         vlc_spu_regions_push(&subpic->regions, r);
-        video_format_Copy( &r->fmt, &fmt );
+        r->fmt.i_sar_num = sar.num;
+        r->fmt.i_sar_den = sar.den;
 
         r->p_text = text_segment_Copy( p_updtregion->p_segments );
         r->i_align = p_updtregion->align;
@@ -279,7 +269,7 @@ static void SubpictureTextUpdate(subpicture_t *subpic,
 }
 static void SubpictureTextDestroy(subpicture_t *subpic)
 {
-    subtext_updater_sys_t *sys = subpic->updater.p_sys;
+    subtext_updater_sys_t *sys = subpic->updater.sys;
 
     SubpictureUpdaterSysRegionClean( &sys->region );
     substext_updater_region_t *p_region = sys->region.p_next;
@@ -297,12 +287,18 @@ static void SubpictureTextDestroy(subpicture_t *subpic)
 static inline subpicture_t *decoder_NewSubpictureText(decoder_t *decoder)
 {
     subtext_updater_sys_t *sys = calloc(1, sizeof(*sys));
+
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = SubpictureTextUpdate,
+        .destroy  = SubpictureTextDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = SubpictureTextValidate,
-        .pf_update   = SubpictureTextUpdate,
-        .pf_destroy  = SubpictureTextDestroy,
-        .p_sys       = sys,
+        .sys = sys,
+        .ops = &spu_ops,
     };
+
     SubpictureUpdaterSysRegionInit( &sys->region );
     sys->margin_ratio = 0.04f;
     sys->p_default_style = text_style_Create( STYLE_NO_DEFAULTS );


=====================================
modules/codec/substx3g.c
=====================================
@@ -356,7 +356,7 @@ static int Decode( decoder_t *p_dec, block_t *p_block )
         return VLCDEC_SUCCESS;
     }
 
-    subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+    subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
     const text_style_t *p_root_style = (text_style_t *) p_dec->p_sys;
 
     mp4_box_iterator_t it;


=====================================
modules/codec/textst.c
=====================================
@@ -245,7 +245,7 @@ static int Decode(decoder_t *p_dec, block_t *p_block)
             p_sub->i_start = p_block->i_dts;
         }
 
-        subtext_updater_sys_t *p_spusys = p_sub->updater.p_sys;
+        subtext_updater_sys_t *p_spusys = p_sub->updater.sys;
         textst_FillRegions(p_dec, &p_block->p_buffer[13], p_block->i_buffer - 13,
                            &p_spusys->region);
 


=====================================
modules/codec/ttml/imageupdater.h
=====================================
@@ -73,26 +73,20 @@ static void TTML_ImageSpuAppendRegion(ttml_image_updater_sys_t *p_sys,
     p_sys->pp_append = &p_new->p_next;
 }
 
-static int TTML_ImageSpuValidate(subpicture_t *p_spu,
-                                 bool b_src_changed, const video_format_t *p_fmt_src,
-                                 bool b_dst_changed, const video_format_t *p_fmt_dst,
-                                 vlc_tick_t ts)
-{
-    VLC_UNUSED(p_spu);
-    VLC_UNUSED(b_src_changed); VLC_UNUSED(p_fmt_src);
-    VLC_UNUSED(p_fmt_dst);
-    VLC_UNUSED(ts);
-    return b_dst_changed ? VLC_EGENERIC: VLC_SUCCESS;
-}
-
 static void TTML_ImageSpuUpdate(subpicture_t *p_spu,
-                                const video_format_t *p_fmt_src,
-                                const video_format_t *p_fmt_dst,
+                                bool b_src_changed, const video_format_t *p_fmt_src,
+                                bool b_dst_changed, const video_format_t *p_fmt_dst,
                                 vlc_tick_t i_ts)
 {
     VLC_UNUSED(p_fmt_src);
     VLC_UNUSED(i_ts);
-    ttml_image_updater_sys_t *p_sys = p_spu->updater.p_sys;
+    VLC_UNUSED(b_src_changed);
+    ttml_image_updater_sys_t *p_sys = p_spu->updater.sys;
+
+    if (!b_dst_changed)
+        return;
+
+    vlc_spu_regions_Clear( &p_spu->regions );
 
     /* !WARN: SMPTE-TT image profile requires no scaling, and even it
               would, it does not store the necessary original pic size */
@@ -122,7 +116,7 @@ static void TTML_ImageSpuUpdate(subpicture_t *p_spu,
 
 static void TTML_ImageSpuDestroy(subpicture_t *p_spu)
 {
-    ttml_image_updater_sys_t *p_sys = p_spu->updater.p_sys;
+    ttml_image_updater_sys_t *p_sys = p_spu->updater.sys;
     while(p_sys->p_regions)
     {
         ttml_image_updater_region_t *p_next = p_sys->p_regions->p_next;
@@ -137,11 +131,16 @@ static inline subpicture_t *decoder_NewTTML_ImageSpu(decoder_t *p_dec)
     ttml_image_updater_sys_t *p_sys = calloc(1, sizeof(*p_sys));
     if(!p_sys)
         return NULL;
+
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = TTML_ImageSpuUpdate,
+        .destroy  = TTML_ImageSpuDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = TTML_ImageSpuValidate,
-        .pf_update   = TTML_ImageSpuUpdate,
-        .pf_destroy  = TTML_ImageSpuDestroy,
-        .p_sys       = p_sys,
+        .sys = p_sys,
+        .ops = &spu_ops,
     };
     p_sys->p_regions = NULL;
     p_sys->pp_append = &p_sys->p_regions;


=====================================
modules/codec/ttml/substtml.c
=====================================
@@ -1121,7 +1121,7 @@ static void TTMLRegionsToSpuTextRegions( decoder_t *p_dec, subpicture_t *p_spu,
                                          ttml_region_t *p_regions )
 {
     decoder_sys_t *p_dec_sys = p_dec->p_sys;
-    subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+    subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
     substext_updater_region_t *p_updtregion = NULL;
 
     /* Create region update info from each ttml region */
@@ -1283,7 +1283,7 @@ static void TTMLRegionsToSpuBitmapRegions( decoder_t *p_dec, subpicture_t *p_spu
             r->origin.y = p_region->updt.origin.y;
             r->extent.x = p_region->updt.extent.x;
             r->extent.y = p_region->updt.extent.y;
-            TTML_ImageSpuAppendRegion( p_spu->updater.p_sys, r );
+            TTML_ImageSpuAppendRegion( p_spu->updater.sys, r );
         }
     }
 }


=====================================
modules/codec/webvtt/subsvtt.c
=====================================
@@ -1682,7 +1682,7 @@ static void CreateSpuOrNewUpdaterRegion( decoder_t *p_dec,
         *pp_spu = decoder_NewSubpictureText( p_dec );
         if( *pp_spu )
         {
-            subtext_updater_sys_t *p_spusys = (*pp_spu)->updater.p_sys;
+            subtext_updater_sys_t *p_spusys = (*pp_spu)->updater.sys;
             *pp_updtregion = &p_spusys->region;
         }
     }
@@ -1866,7 +1866,7 @@ static void RenderRegions( decoder_t *p_dec, vlc_tick_t i_nzstart, vlc_tick_t i_
         p_spu->b_ephemer  = true; /* !important */
         p_spu->b_absolute = false; /* can't be absolute as snap to lines can overlap ! */
 
-        subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+        subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
         p_spu_sys->p_default_style->f_font_relsize = WEBVTT_DEFAULT_LINE_HEIGHT_VH /
                                                      WEBVTT_LINE_TO_HEIGHT_RATIO;
         decoder_QueueSub( p_dec, p_spu );


=====================================
modules/codec/zvbi.c
=====================================
@@ -450,7 +450,7 @@ static int Decode( decoder_t *p_dec, block_t *p_block )
         while( offset < i_total && isspace( p_text[offset] ) )
            offset++;
 
-        subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+        subtext_updater_sys_t *p_spu_sys = p_spu->updater.sys;
         p_spu_sys->region.p_segments = text_segment_New( &p_text[offset] );
         if( !p_spu_sys->region.p_segments )
         {


=====================================
modules/spu/subsdelay.c
=====================================
@@ -214,11 +214,8 @@ static bool SubsdelayIsTextEmpty( const subpicture_region_t * );
  * Subpicture functions
  *****************************************************************************/
 
-static int SubpicValidateWrapper( subpicture_t *p_subpic, bool has_src_changed, const video_format_t *p_fmt_src,
-                                  bool has_dst_changed, const video_format_t *p_fmt_dst, vlc_tick_t i_ts );
-
-static void SubpicUpdateWrapper( subpicture_t *p_subpic, const video_format_t *p_fmt_src,
-                                  const video_format_t *p_fmt_dst, vlc_tick_t i_ts );
+static void SubpicUpdateWrapper( subpicture_t *p_subpic, bool has_src_changed, const video_format_t *p_fmt_src,
+                                 bool has_dst_changed, const video_format_t *p_fmt_dst, vlc_tick_t i_ts );
 
 static void SubpicDestroyWrapper( subpicture_t *p_subpic );
 
@@ -659,8 +656,6 @@ static subsdelay_heap_entry_t * SubsdelayEntryCreate( subpicture_t *p_source, fi
 
     subpicture_t *p_new_subpic;
 
-    subpicture_updater_t updater;
-
     /* allocate structure */
 
     p_entry = (subsdelay_heap_entry_t *) malloc( sizeof( subsdelay_heap_entry_t ) );
@@ -671,11 +666,17 @@ static subsdelay_heap_entry_t * SubsdelayEntryCreate( subpicture_t *p_source, fi
     }
 
     /* initialize local updater */
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = SubpicUpdateWrapper,
+        .destroy  = SubpicDestroyWrapper,
+    };
 
-    updater.p_sys = p_entry;
-    updater.pf_validate = SubpicValidateWrapper;
-    updater.pf_update = SubpicUpdateWrapper;
-    updater.pf_destroy = SubpicDestroyWrapper;
+    subpicture_updater_t updater =
+    {
+        .sys = p_entry,
+        .ops = &spu_ops,
+    };
 
     /* create new subpic */
 
@@ -911,33 +912,20 @@ static void SubsdelayRecalculateDelays( filter_t *p_filter )
 }
 
 /*****************************************************************************
- * SubpicValidateWrapper: Subpicture validate callback wrapper
+ * SubpicUpdateWrapper: Subpicture update callback wrapper
  *****************************************************************************/
-static int SubpicValidateWrapper( subpicture_t *p_subpic, bool has_src_changed, const video_format_t *p_fmt_src,
-                                  bool has_dst_changed, const video_format_t *p_fmt_dst, vlc_tick_t i_ts )
+static void SubpicUpdateWrapper( subpicture_t *p_subpic, bool has_src_changed, const video_format_t *p_fmt_src,
+                                 bool has_dst_changed, const video_format_t *p_fmt_dst, vlc_tick_t i_ts )
 {
     subsdelay_heap_entry_t *p_entry;
     vlc_tick_t i_new_ts;
-    int i_result = VLC_SUCCESS;
 
-    p_entry = p_subpic->updater.p_sys;
+    p_entry = p_subpic->updater.sys;
     if( !p_entry )
     {
-        return VLC_SUCCESS;
-    }
-
-    /* call source validate */
-    if( p_entry->p_source->updater.pf_validate )
-    {
-        i_new_ts = p_entry->p_source->i_start +
-                   ( (double)( p_entry->p_source->i_stop - p_entry->p_source->i_start ) * ( i_ts - p_entry->p_source->i_start ) ) /
-                   ( p_entry->i_new_stop - p_entry->p_source->i_start );
-
-        i_result = p_entry->p_source->updater.pf_validate( p_entry->p_source, has_src_changed, p_fmt_src,
-                                                        has_dst_changed, p_fmt_dst, i_new_ts );
+        return;
     }
 
-
     p_entry->b_last_region_saved = false;
 
     subpicture_region_t *p_region =
@@ -952,43 +940,21 @@ static int SubpicValidateWrapper( subpicture_t *p_subpic, bool has_src_changed,
         p_entry->b_last_region_saved = true;
     }
 
-    if( !i_result )
-    {
-        /* subpic update isn't necessary, so local update should be called here */
-        SubpicLocalUpdate( p_subpic, i_ts );
-    }
-
-    return i_result;
-}
-
-/*****************************************************************************
- * SubpicUpdateWrapper: Subpicture update callback wrapper
- *****************************************************************************/
-static void SubpicUpdateWrapper( subpicture_t *p_subpic, const video_format_t *p_fmt_src,
-                                  const video_format_t *p_fmt_dst, vlc_tick_t i_ts )
-{
-    subsdelay_heap_entry_t *p_entry;
-    vlc_tick_t i_new_ts;
-
-    p_entry = p_subpic->updater.p_sys;
-    if( !p_entry )
-    {
-        return;
-    }
+    vlc_spu_regions_Clear( &p_subpic->regions );
 
     /* call source update */
-    if( p_entry->p_source->updater.pf_update )
-    {
-        i_new_ts = p_entry->p_source->i_start +
-                   ( (double)( p_entry->p_source->i_stop - p_entry->p_source->i_start ) * ( i_ts - p_entry->p_source->i_start ) ) /
-                   ( p_entry->i_new_stop - p_entry->p_source->i_start );
+    i_new_ts = p_entry->p_source->i_start +
+                ( (double)( p_entry->p_source->i_stop - p_entry->p_source->i_start ) * ( i_ts - p_entry->p_source->i_start ) ) /
+                ( p_entry->i_new_stop - p_entry->p_source->i_start );
 
-        p_entry->p_source->regions = p_entry->p_subpic->regions;
+    p_entry->p_source->regions = p_entry->p_subpic->regions;
 
-        p_entry->p_source->updater.pf_update( p_entry->p_source, p_fmt_src, p_fmt_dst, i_new_ts );
+    subpicture_updater_t *updater = &p_entry->p_source->updater;
+    updater->ops->update( p_entry->p_source,
+                          has_src_changed, p_fmt_src,
+                          has_dst_changed, p_fmt_dst, i_new_ts );
 
-        p_entry->p_subpic->regions = p_entry->p_source->regions;
-    }
+    p_entry->p_subpic->regions = p_entry->p_source->regions;
 
     SubpicLocalUpdate( p_subpic, i_ts );
 }
@@ -1001,7 +967,7 @@ static void SubpicDestroyWrapper( subpicture_t *p_subpic )
     subsdelay_heap_entry_t *p_entry;
     subsdelay_heap_t *p_heap;
 
-    p_entry = p_subpic->updater.p_sys;
+    p_entry = p_subpic->updater.sys;
 
     if( !p_entry )
     {
@@ -1032,7 +998,7 @@ static void SubpicLocalUpdate( subpicture_t* p_subpic, vlc_tick_t i_ts )
 
     int i_overlapping;
 
-    p_entry = p_subpic->updater.p_sys;
+    p_entry = p_subpic->updater.sys;
     if( !p_entry || !p_entry->p_filter )
     {
         return;


=====================================
src/misc/subpicture.c
=====================================
@@ -70,11 +70,8 @@ subpicture_t *subpicture_New( const subpicture_updater_t *p_upd )
     else
     {
         p_subpic->p_private = NULL;
-
-        p_subpic->updater.pf_validate = NULL;
-        p_subpic->updater.pf_update   = NULL;
-        p_subpic->updater.pf_destroy  = NULL;
-        p_subpic->updater.p_sys       = NULL;
+        p_subpic->updater.ops = NULL;
+        p_subpic->updater.sys = NULL;
     }
     return p_subpic;
 }
@@ -83,8 +80,11 @@ void subpicture_Delete( subpicture_t *p_subpic )
 {
     vlc_spu_regions_Clear( &p_subpic->regions );
 
-    if( p_subpic->updater.pf_destroy )
-        p_subpic->updater.pf_destroy( p_subpic );
+    if (p_subpic->updater.ops != NULL &&
+        p_subpic->updater.ops->destroy != NULL)
+    {
+        p_subpic->updater.ops->destroy(p_subpic);
+    }
 
     if( p_subpic->p_private )
     {
@@ -171,19 +171,15 @@ void subpicture_Update( subpicture_t *p_subpicture,
     subpicture_updater_t *p_upd = &p_subpicture->updater;
     subpicture_private_t *p_private = p_subpicture->p_private;
 
-    if( !p_upd->pf_validate )
+    if (p_upd->ops == NULL)
         return;
-    if( !p_upd->pf_validate( p_subpicture,
-                          !video_format_IsSimilar( p_fmt_src,
-                                                   &p_private->src ), p_fmt_src,
-                          !video_format_IsSimilar( p_fmt_dst,
-                                                   &p_private->dst ), p_fmt_dst,
-                          i_ts ) )
-        return;
-
-    vlc_spu_regions_Clear( &p_subpicture->regions );
 
-    p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts );
+    p_upd->ops->update(p_subpicture,
+                       !video_format_IsSimilar( &p_private->src,
+                                                p_fmt_src ), p_fmt_src,
+                       !video_format_IsSimilar( &p_private->dst,
+                                                p_fmt_dst ), p_fmt_dst,
+                       i_ts);
 
     video_format_Clean( &p_private->src );
     video_format_Clean( &p_private->dst );


=====================================
src/video_output/video_epg.c
=====================================
@@ -494,27 +494,19 @@ static void vout_BuildOSDEpg(epg_spu_updater_sys_t *p_sys,
                          regions );
 }
 
-static int OSDEpgValidate(subpicture_t *subpic,
-                          bool has_src_changed, const video_format_t *fmt_src,
-                          bool has_dst_changed, const video_format_t *fmt_dst,
-                          vlc_tick_t ts)
-{
-    VLC_UNUSED(subpic); VLC_UNUSED(ts);
-    VLC_UNUSED(fmt_src); VLC_UNUSED(has_src_changed);
-    VLC_UNUSED(fmt_dst);
-
-    if (!has_dst_changed)
-        return VLC_SUCCESS;
-    return VLC_EGENERIC;
-}
-
 static void OSDEpgUpdate(subpicture_t *subpic,
-                         const video_format_t *fmt_src,
-                         const video_format_t *fmt_dst,
+                         bool has_src_changed, const video_format_t *fmt_src,
+                         bool has_dst_changed, const video_format_t *fmt_dst,
                          vlc_tick_t ts)
 {
-    epg_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    epg_spu_updater_sys_t *sys = subpic->updater.sys;
     VLC_UNUSED(fmt_src); VLC_UNUSED(ts);
+    VLC_UNUSED(has_src_changed);
+
+    if (!has_dst_changed)
+        return;
+
+    vlc_spu_regions_Clear( &subpic->regions );
 
     video_format_t fmt = *fmt_dst;
     fmt.i_width         = fmt.i_width         * fmt.i_sar_num / fmt.i_sar_den;
@@ -533,7 +525,7 @@ static void OSDEpgUpdate(subpicture_t *subpic,
 
 static void OSDEpgDestroy(subpicture_t *subpic)
 {
-    epg_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    epg_spu_updater_sys_t *sys = subpic->updater.sys;
     if( sys->epg )
         vlc_epg_Delete(sys->epg);
     free( sys->art );
@@ -621,11 +613,15 @@ int vout_OSDEpg(vout_thread_t *vout, input_item_t *input)
     if( !sys->art )
         sys->art = GetDefaultArtUri();
 
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = OSDEpgUpdate,
+        .destroy  = OSDEpgDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = OSDEpgValidate,
-        .pf_update   = OSDEpgUpdate,
-        .pf_destroy  = OSDEpgDestroy,
-        .p_sys       = sys
+        .sys = sys,
+        .ops = &spu_ops,
     };
 
     const vlc_tick_t now = vlc_tick_now();


=====================================
src/video_output/video_text.c
=====================================
@@ -37,27 +37,19 @@ typedef struct {
     char *text;
 } osd_spu_updater_sys_t;
 
-static int OSDTextValidate(subpicture_t *subpic,
-                           bool has_src_changed, const video_format_t *fmt_src,
-                           bool has_dst_changed, const video_format_t *fmt_dst,
-                           vlc_tick_t ts)
-{
-    VLC_UNUSED(subpic); VLC_UNUSED(ts);
-    VLC_UNUSED(fmt_src); VLC_UNUSED(has_src_changed);
-    VLC_UNUSED(fmt_dst);
-
-    if( !has_dst_changed )
-        return VLC_SUCCESS;
-    return VLC_EGENERIC;
-}
-
 static void OSDTextUpdate(subpicture_t *subpic,
-                          const video_format_t *fmt_src,
-                          const video_format_t *fmt_dst,
+                          bool has_src_changed, const video_format_t *fmt_src,
+                          bool has_dst_changed, const video_format_t *fmt_dst,
                           vlc_tick_t ts)
 {
-    osd_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    osd_spu_updater_sys_t *sys = subpic->updater.sys;
     VLC_UNUSED(fmt_src); VLC_UNUSED(ts);
+    VLC_UNUSED(has_src_changed);
+
+    if (!has_dst_changed)
+        return;
+
+    vlc_spu_regions_Clear( &subpic->regions );
 
     if( fmt_dst->i_sar_num <= 0 || fmt_dst->i_sar_den <= 0 )
         return;
@@ -96,7 +88,7 @@ static void OSDTextUpdate(subpicture_t *subpic,
 
 static void OSDTextDestroy(subpicture_t *subpic)
 {
-    osd_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    osd_spu_updater_sys_t *sys = subpic->updater.sys;
 
     free(sys->text);
     free(sys);
@@ -115,11 +107,15 @@ void vout_OSDText(vout_thread_t *vout, int channel,
     sys->position = position;
     sys->text     = strdup(text);
 
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = OSDTextUpdate,
+        .destroy  = OSDTextDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = OSDTextValidate,
-        .pf_update   = OSDTextUpdate,
-        .pf_destroy  = OSDTextDestroy,
-        .p_sys       = sys,
+        .sys = sys,
+        .ops = &spu_ops,
     };
     subpicture_t *subpic = subpicture_New(&updater);
     if (!subpic) {


=====================================
src/video_output/video_widgets.c
=====================================
@@ -253,28 +253,20 @@ typedef struct {
     int position;
 } osdwidget_spu_updater_sys_t;
 
-static int OSDWidgetValidate(subpicture_t *subpic,
-                           bool has_src_changed, const video_format_t *fmt_src,
-                           bool has_dst_changed, const video_format_t *fmt_dst,
-                           vlc_tick_t ts)
-{
-    VLC_UNUSED(subpic); VLC_UNUSED(ts);
-    VLC_UNUSED(fmt_src); VLC_UNUSED(has_src_changed);
-    VLC_UNUSED(fmt_dst);
-
-    if (!has_dst_changed)
-        return VLC_SUCCESS;
-    return VLC_EGENERIC;
-}
-
 static void OSDWidgetUpdate(subpicture_t *subpic,
-                          const video_format_t *fmt_src,
-                          const video_format_t *fmt_dst,
-                          vlc_tick_t ts)
+                            bool has_src_changed, const video_format_t *fmt_src,
+                            bool has_dst_changed, const video_format_t *fmt_dst,
+                            vlc_tick_t ts)
 {
-    osdwidget_spu_updater_sys_t *sys = subpic->updater.p_sys;
+    osdwidget_spu_updater_sys_t *sys = subpic->updater.sys;
     subpicture_region_t *p_region;
     VLC_UNUSED(fmt_src); VLC_UNUSED(ts);
+    VLC_UNUSED(has_src_changed);
+
+    if (!has_dst_changed)
+        return;
+
+    vlc_spu_regions_Clear( &subpic->regions );
 
     video_format_t fmt = *fmt_dst;
     fmt.i_width         = fmt.i_width         * fmt.i_sar_num / fmt.i_sar_den;
@@ -295,7 +287,7 @@ static void OSDWidgetUpdate(subpicture_t *subpic,
 
 static void OSDWidgetDestroy(subpicture_t *subpic)
 {
-    free(subpic->updater.p_sys);
+    free(subpic->updater.sys);
 }
 
 static void OSDWidget(vout_thread_t *vout, int channel, int type, int position)
@@ -311,11 +303,15 @@ static void OSDWidget(vout_thread_t *vout, int channel, int type, int position)
     sys->type     = type;
     sys->position = position;
 
+    static const struct vlc_spu_updater_ops spu_ops =
+    {
+        .update   = OSDWidgetUpdate,
+        .destroy  = OSDWidgetDestroy,
+    };
+
     subpicture_updater_t updater = {
-        .pf_validate = OSDWidgetValidate,
-        .pf_update   = OSDWidgetUpdate,
-        .pf_destroy  = OSDWidgetDestroy,
-        .p_sys       = sys,
+        .sys = sys,
+        .ops = &spu_ops,
     };
     subpicture_t *subpic = subpicture_New(&updater);
     if (!subpic) {


=====================================
src/video_output/vout_subpictures.c
=====================================
@@ -2046,9 +2046,6 @@ vlc_render_subpicture *spu_Render(spu_t *spu,
         entry->subpic->i_start = entry->start;
         entry->subpic->i_stop = entry->stop;
 
-        if (!subpic->updater.pf_validate)
-            continue;
-
         subpicture_Update(subpic,
                           fmt_src, fmt_dst,
                           subpic->b_subtitle ? render_subtitle_date : system_now);



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/31f396f1561688d0dc687521ba2a38a13076e6e3...c1a15d6e3b2bbf436da913b4247c1720bccde71b

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/31f396f1561688d0dc687521ba2a38a13076e6e3...c1a15d6e3b2bbf436da913b4247c1720bccde71b
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list