[vlc-commits] codec: webvtt: convert regions to dom nodes and drop default one

Francois Cartegnie git at videolan.org
Fri Oct 27 17:10:29 CEST 2017


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Oct 27 16:19:11 2017 +0200| [86f4b1aef9da20fe832b3911b0d57a44b46712fe] | committer: Francois Cartegnie

codec: webvtt: convert regions to dom nodes and drop default one

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=86f4b1aef9da20fe832b3911b0d57a44b46712fe
---

 modules/codec/webvtt/subsvtt.c | 296 +++++++++++++++++++++++------------------
 1 file changed, 169 insertions(+), 127 deletions(-)

diff --git a/modules/codec/webvtt/subsvtt.c b/modules/codec/webvtt/subsvtt.c
index 39db68562a..d490e6bfde 100644
--- a/modules/codec/webvtt/subsvtt.c
+++ b/modules/codec/webvtt/subsvtt.c
@@ -82,6 +82,7 @@ enum webvtt_node_type_e
     NODE_TAG,
     NODE_TEXT,
     NODE_CUE,
+    NODE_REGION,
 };
 
 #define WEBVTT_NODE_BASE_MEMBERS \
@@ -91,6 +92,7 @@ enum webvtt_node_type_e
 
 struct webvtt_region_t
 {
+    WEBVTT_NODE_BASE_MEMBERS
     char *psz_id;
     float f_width;
     unsigned i_lines_max_scroll;
@@ -100,7 +102,6 @@ struct webvtt_region_t
     float viewport_anchor_y;
     bool b_scroll_up;
     webvtt_dom_node_t *p_child;
-    webvtt_region_t *p_next;
 };
 
 struct webvtt_dom_cue_t
@@ -135,8 +136,8 @@ struct webvtt_dom_node_t
 
 struct decoder_sys_t
 {
-    webvtt_region_t regions;
-    webvtt_region_t **pp_region_append;
+    webvtt_region_t *p_regions;
+    webvtt_dom_cue_t *p_regionless_cues;
 };
 
 #define ATOM_iden VLC_FOURCC('i', 'd', 'e', 'n')
@@ -318,12 +319,19 @@ static void webvtt_domnode_Debug( webvtt_dom_node_t *p_node, int i_depth )
             printf("CUE %s\n", p_cue->psz_id );
             webvtt_domnode_Debug( p_cue->p_child, i_depth + 1 );
         }
+        else if( p_node->type == NODE_REGION )
+        {
+            webvtt_region_t *p_region = (webvtt_region_t *)p_node;
+            printf("REGION %s\n", p_region->psz_id );
+            webvtt_domnode_Debug( p_region->p_child, i_depth + 1 );
+        }
     }
 }
 #endif
 
 static void webvtt_domnode_ChainDelete( webvtt_dom_node_t *p_node );
 static void webvtt_dom_cue_Delete( webvtt_dom_cue_t *p_cue );
+static void webvtt_region_Delete( webvtt_region_t *p_region );
 
 static void webvtt_dom_text_Delete( webvtt_dom_text_t *p_node )
 {
@@ -339,6 +347,17 @@ static void webvtt_dom_tag_Delete( webvtt_dom_tag_t *p_node )
     free( p_node );
 }
 
+static void webvtt_domnode_AppendLast( webvtt_dom_node_t **pp_append,
+                                       webvtt_dom_node_t *p_node )
+{
+    while( *pp_append )
+        pp_append = &((*pp_append)->p_next);
+    *pp_append = p_node;
+}
+
+#define webvtt_domnode_AppendLast( a, b ) \
+    webvtt_domnode_AppendLast( (webvtt_dom_node_t **) a, (webvtt_dom_node_t *) b )
+
 static void webvtt_domnode_ChainDelete( webvtt_dom_node_t *p_node )
 {
     while( p_node )
@@ -351,6 +370,8 @@ static void webvtt_domnode_ChainDelete( webvtt_dom_node_t *p_node )
             webvtt_dom_text_Delete( (webvtt_dom_text_t *) p_node );
         else if( p_node->type == NODE_CUE )
             webvtt_dom_cue_Delete( (webvtt_dom_cue_t *) p_node );
+        else if( p_node->type == NODE_REGION )
+            webvtt_region_Delete( (webvtt_region_t *) p_node );
 
         p_node = p_next;
     }
@@ -579,12 +600,11 @@ static void webvtt_region_ClearCues( webvtt_region_t *p_region )
     p_region->p_child = NULL;
 }
 
-static void webvtt_region_ClearCuesByTime( webvtt_region_t *p_region, mtime_t i_time )
+static void ClearCuesByTime( webvtt_dom_node_t **pp_next, mtime_t i_time )
 {
-    webvtt_dom_node_t **pp_node = &p_region->p_child;
-    while( *pp_node )
+    while( *pp_next )
     {
-        webvtt_dom_node_t *p_node = *pp_node;
+        webvtt_dom_node_t *p_node = *pp_next;
         if( p_node )
         {
             assert( p_node->type == NODE_CUE );
@@ -593,24 +613,17 @@ static void webvtt_region_ClearCuesByTime( webvtt_region_t *p_region, mtime_t i_
                 webvtt_dom_cue_t *p_cue = (webvtt_dom_cue_t *)p_node;
                 if( p_cue->i_stop <= i_time )
                 {
-                    *pp_node = p_node->p_next;
+                    *pp_next = p_node->p_next;
                     p_node->p_next = NULL;
                     webvtt_dom_cue_Delete( p_cue );
                     continue;
                 }
             }
-            pp_node = &p_node->p_next;
+            pp_next = &p_node->p_next;
         }
     }
 }
 
-static void webvtt_region_Clean( webvtt_region_t *p_region )
-{
-    webvtt_region_ClearCues( p_region );
-    free( p_region->psz_id );
-    p_region->psz_id = NULL;
-}
-
 /* Remove top most line/cue for bottom insert */
 static void webvtt_region_Reduce( webvtt_region_t *p_region )
 {
@@ -652,23 +665,10 @@ static void webvtt_region_AddCue( webvtt_region_t *p_region,
     }
 }
 
-static void webvtt_region_Init( webvtt_region_t *p_region )
-{
-    p_region->psz_id = NULL;
-    p_region->p_next = NULL;
-    p_region->f_width = 1.0; /* 100% */
-    p_region->anchor_x = 0;
-    p_region->anchor_y = 1.0; /* 100% */
-    p_region->i_lines_max_scroll = 3;
-    p_region->viewport_anchor_x = 0;
-    p_region->viewport_anchor_y = 1.0; /* 100% */
-    p_region->b_scroll_up = false;
-    p_region->p_child = NULL;
-}
-
 static void webvtt_region_Delete( webvtt_region_t *p_region )
 {
-    webvtt_region_Clean( p_region );
+    webvtt_region_ClearCues( p_region );
+    free( p_region->psz_id );
     free( p_region );
 }
 
@@ -676,24 +676,32 @@ static webvtt_region_t * webvtt_region_New( void )
 {
     webvtt_region_t *p_region = malloc(sizeof(*p_region));
     if( p_region )
-        webvtt_region_Init( p_region );
+    {
+        p_region->type = NODE_REGION;
+        p_region->psz_id = NULL;
+        p_region->p_next = NULL;
+        p_region->f_width = 1.0; /* 100% */
+        p_region->anchor_x = 0;
+        p_region->anchor_y = 1.0; /* 100% */
+        p_region->i_lines_max_scroll = 3;
+        p_region->viewport_anchor_x = 0;
+        p_region->viewport_anchor_y = 1.0; /* 100% */
+        p_region->b_scroll_up = false;
+        p_region->p_child = NULL;
+    }
     return p_region;
 }
 
 static webvtt_region_t * webvtt_region_GetByID( decoder_sys_t *p_sys,
                                                 const char *psz_id )
 {
-    webvtt_region_t *p_region = &p_sys->regions;
-    if( psz_id != NULL )
+    for( webvtt_region_t *p_region = p_sys->p_regions; p_region && psz_id;
+                          p_region = (webvtt_region_t *) p_region->p_next )
     {
-        for( p_region = p_sys->regions.p_next;
-             p_region; p_region = p_region->p_next )
-        {
-            if( !strcmp( psz_id, p_region->psz_id ) )
-                return p_region;
-        }
+        if( !strcmp( psz_id, p_region->psz_id ) )
+            return p_region;
     }
-    return p_region;
+    return NULL;
 }
 
 /*****************************************************************************
@@ -789,11 +797,15 @@ static webvtt_dom_node_t * CreateDomNodes( const char *psz_text, unsigned *pi_li
 
 static void ExpireCues( decoder_t *p_dec, mtime_t i_time )
 {
-    for( webvtt_region_t *p_vttregion = &p_dec->p_sys->regions;
-                          p_vttregion; p_vttregion = p_vttregion->p_next )
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    for( webvtt_region_t *p_vttregion = p_sys->p_regions; p_vttregion;
+                          p_vttregion = (webvtt_region_t *) p_vttregion->p_next )
     {
-        webvtt_region_ClearCuesByTime( p_vttregion, i_time );
+        assert( p_vttregion->type == NODE_REGION );
+        ClearCuesByTime( &p_vttregion->p_child, i_time );
     }
+
+    ClearCuesByTime( (webvtt_dom_node_t **) &p_sys->p_regionless_cues, i_time );
 }
 
 static void ProcessCue( decoder_t *p_dec, const char *psz, webvtt_dom_cue_t *p_cue )
@@ -880,6 +892,9 @@ static text_segment_t *ConvertNodesToSegments( decoder_t *p_dec,
     text_segment_t **pp_append = &p_head;
     for( ; p_node ; p_node = p_node->p_next )
     {
+        while( *pp_append )
+            pp_append = &((*pp_append)->p_next);
+
         if( p_node->type == NODE_TEXT )
         {
             const webvtt_dom_text_t *p_textnode = (const webvtt_dom_text_t *) p_node;
@@ -892,7 +907,6 @@ static text_segment_t *ConvertNodesToSegments( decoder_t *p_dec,
                 if( (*pp_append)->psz_text )
                     vlc_xml_decode( (*pp_append)->psz_text );
                 (*pp_append)->style = InheritStyles( p_dec, p_node );
-                pp_append = &((*pp_append)->p_next);
             }
         }
         else if( p_node->type == NODE_TAG )
@@ -900,9 +914,6 @@ static text_segment_t *ConvertNodesToSegments( decoder_t *p_dec,
             *pp_append = ConvertNodesToSegments( p_dec, p_vars, p_cue,
                                                  ((const webvtt_dom_tag_t *)p_node)->p_child );
         }
-
-        while( *pp_append )
-            pp_append = &((*pp_append)->p_next);
     }
     return p_head;
 }
@@ -914,17 +925,72 @@ static text_segment_t *ConvertCueToSegments( decoder_t *p_dec,
     return ConvertNodesToSegments( p_dec, p_vars, p_cue, p_cue->p_child );
 }
 
+static text_segment_t * ConvertCuesToSegments( decoder_t *p_dec, mtime_t i_start, mtime_t i_stop,
+                                               struct render_variables_s *p_vars,
+                                               const webvtt_dom_cue_t *p_cue )
+{
+    text_segment_t *p_segments = NULL;
+    text_segment_t **pp_append = &p_segments;
+    VLC_UNUSED(i_stop);
+
+    for( ; p_cue; p_cue = (const webvtt_dom_cue_t *) p_cue->p_next )
+    {
+        assert( p_cue->type == NODE_CUE );
+        if( p_cue->type != NODE_CUE )
+            continue;
+
+        if( p_cue->i_start > i_start || p_cue->i_stop <= i_start )
+            continue;
+
+        text_segment_t *p_new = ConvertCueToSegments( p_dec, p_vars, p_cue );
+        if( p_new )
+        {
+            while( *pp_append )
+                pp_append = &((*pp_append)->p_next);
+
+            if( p_segments ) /* auto newlines */
+            {
+                *pp_append = text_segment_New( "\n" );
+                if( *pp_append )
+                    pp_append = &((*pp_append)->p_next);
+            }
+
+            *pp_append = p_new;
+        }
+    }
+    return p_segments;
+}
+
+static void CreateSpuOrNewUpdaterRegion( decoder_t *p_dec,
+                                         subpicture_t **pp_spu,
+                                         subpicture_updater_sys_region_t **pp_updtregion )
+{
+    if( *pp_spu == NULL )
+    {
+        *pp_spu = decoder_NewSubpictureText( p_dec );
+        if( *pp_spu )
+            *pp_updtregion = &(*pp_spu)->updater.p_sys->region;
+    }
+    else
+    {
+        subpicture_updater_sys_region_t *p_new =
+                                SubpictureUpdaterSysRegionNew( );
+        if( p_new )
+        {
+            SubpictureUpdaterSysRegionAdd( *pp_updtregion, p_new );
+            *pp_updtregion = p_new;
+        }
+    }
+}
+
 static void RenderRegions( decoder_t *p_dec, mtime_t i_start, mtime_t i_stop )
 {
     subpicture_t *p_spu = NULL;
     subpicture_updater_sys_region_t *p_updtregion = NULL;
 
-    for( webvtt_region_t *p_vttregion = &p_dec->p_sys->regions;
-                          p_vttregion; p_vttregion = p_vttregion->p_next )
+    for( const webvtt_region_t *p_vttregion = p_dec->p_sys->p_regions; p_vttregion;
+                                p_vttregion = (const webvtt_region_t *) p_vttregion->p_next )
     {
-        text_segment_t *p_segments = NULL;
-        text_segment_t **pp_append = &p_segments;
-
         /* Variables */
         struct render_variables_s v;
         v.p_region = p_vttregion;
@@ -935,81 +1001,60 @@ static void RenderRegions( decoder_t *p_dec, mtime_t i_start, mtime_t i_stop )
         v.i_top = p_vttregion->viewport_anchor_y - v.i_top_offset;
         /* !Variables */
 
-        for( webvtt_dom_node_t *p_node = p_vttregion->p_child;
-                                p_node; p_node = p_node->p_next )
+        text_segment_t *p_segments =
+                ConvertCuesToSegments( p_dec, i_start, i_stop, &v,
+                                      (const webvtt_dom_cue_t *)p_vttregion->p_child );
+        if( !p_segments )
+            continue;
+
+        CreateSpuOrNewUpdaterRegion( p_dec, &p_spu, &p_updtregion );
+        if( !p_spu || !p_updtregion )
         {
-            assert( p_node->type == NODE_CUE );
-            if( p_node->type != NODE_CUE )
-                continue;
-            webvtt_dom_cue_t *p_cue = (webvtt_dom_cue_t *) p_node;
+            text_segment_ChainDelete( p_segments );
+            continue;
+        }
 
-            if( p_cue->i_start > i_start || p_cue->i_stop <= i_start )
-                continue;
+        p_updtregion->align = SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_LEFT;
+        p_updtregion->origin.x = v.i_left;
+        p_updtregion->origin.y = v.i_top;
+        p_updtregion->extent.x = p_vttregion->f_width;
 
-            text_segment_t *p_new = ConvertCueToSegments( p_dec, &v, p_cue );
-            if( p_new )
-            {
-                if( p_segments ) /* auto newlines */
-                {
-                    *pp_append = text_segment_New( "\n" );
-                    if( *pp_append )
-                        pp_append = &((*pp_append)->p_next);
-                }
+        p_updtregion->flags = UPDT_REGION_ORIGIN_X_IS_RATIO|UPDT_REGION_ORIGIN_Y_IS_RATIO
+                            | UPDT_REGION_EXTENT_X_IS_RATIO;
+        p_updtregion->p_segments = p_segments;
+    }
 
-                *pp_append = p_new;
-                while( *pp_append )
-                    pp_append = &((*pp_append)->p_next);
-            }
-        }
+    for( const webvtt_dom_cue_t *p_cue = p_dec->p_sys->p_regionless_cues; p_cue;
+                                 p_cue = (const webvtt_dom_cue_t *) p_cue->p_next )
+    {
+        /* Variables */
+        struct render_variables_s v;
+        v.p_region = NULL;
+        v.i_left_offset = 0.0;
+        v.i_left = 0.0;
+        v.i_top_offset = 0.0;
+        v.i_top = 0.0;
+        /* !Variables */
+
+        text_segment_t *p_segments = ConvertCuesToSegments( p_dec, i_start, i_stop, &v, p_cue );
         if( !p_segments )
             continue;
 
-        if( p_spu == NULL )
-        {
-            p_spu = decoder_NewSubpictureText( p_dec );
-            if( p_spu )
-            {
-                p_updtregion = &p_spu->updater.p_sys->region;
-                p_spu->i_start = i_start;
-                p_spu->i_stop  = i_stop;
-            }
-        }
-        else
-        {
-            subpicture_updater_sys_region_t *p_new =
-                                    SubpictureUpdaterSysRegionNew( );
-            if( p_new )
-            {
-                SubpictureUpdaterSysRegionAdd( p_updtregion, p_new );
-                p_updtregion = p_new;
-            }
-        }
-
+        CreateSpuOrNewUpdaterRegion( p_dec, &p_spu, &p_updtregion );
         if( !p_spu || !p_updtregion )
         {
             text_segment_ChainDelete( p_segments );
             continue;
         }
 
-
-        if( p_vttregion == &p_dec->p_sys->regions )
-        {
-            p_updtregion->align = SUBPICTURE_ALIGN_BOTTOM;
-        }
-        else
-        {
-            p_updtregion->align = SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_LEFT;
-            p_updtregion->origin.x = v.i_left;
-            p_updtregion->origin.y = v.i_top;
-            p_updtregion->extent.x = p_vttregion->f_width;
-        }
-        p_updtregion->flags = UPDT_REGION_ORIGIN_X_IS_RATIO|UPDT_REGION_ORIGIN_Y_IS_RATIO
-                            | UPDT_REGION_EXTENT_X_IS_RATIO;
+        p_updtregion->align = SUBPICTURE_ALIGN_BOTTOM;
         p_updtregion->p_segments = p_segments;
     }
 
     if( p_spu )
     {
+        p_spu->i_start = i_start;
+        p_spu->i_stop = i_stop;
         p_spu->b_ephemer  = true; /* !important */
         p_spu->b_absolute = false;
 
@@ -1063,11 +1108,15 @@ static int ProcessISOBMFF( decoder_t *p_dec,
 
             webvtt_region_t *p_region = webvtt_region_GetByID( p_dec->p_sys,
                                                                p_cue->settings.psz_region );
-            if( p_region == NULL )
-                p_region = webvtt_region_GetByID( p_dec->p_sys, NULL /*defaut region*/ );
-            assert( p_region );
-            webvtt_region_AddCue( p_region, p_cue );
-            assert( p_region->p_child );
+            if( p_region )
+            {
+                webvtt_region_AddCue( p_region, p_cue );
+                assert( p_region->p_child );
+            }
+            else
+            {
+                webvtt_domnode_AppendLast( &p_dec->p_sys->p_regionless_cues, p_cue );
+            }
         }
     }
     return 0;
@@ -1092,9 +1141,8 @@ static void ParserHeaderHandler( void *priv, enum webvtt_header_line_e s,
         {
             if( ctx->p_region->psz_id )
             {
+                webvtt_domnode_AppendLast( &p_sys->p_regions, ctx->p_region );
                 msg_Dbg( p_dec, "added new region %s", ctx->p_region->psz_id );
-                *p_sys->pp_region_append = ctx->p_region;
-                p_sys->pp_region_append = &ctx->p_region->p_next;
             }
             /* incomplete region decl (no id at least) */
             else webvtt_region_Delete( ctx->p_region );
@@ -1170,14 +1218,8 @@ void CloseDecoder( vlc_object_t *p_this )
     decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    while( p_sys->regions.p_next )
-    {
-        webvtt_region_t *p_next = p_sys->regions.p_next->p_next;
-        webvtt_region_Clean( p_sys->regions.p_next );
-        free( p_sys->regions.p_next );
-        p_sys->regions.p_next = p_next;
-    }
-    webvtt_region_Clean( &p_sys->regions );
+    webvtt_domnode_ChainDelete( (webvtt_dom_node_t *) p_sys->p_regions );
+    webvtt_domnode_ChainDelete( (webvtt_dom_node_t *) p_sys->p_regionless_cues );
 
     free( p_sys );
 }
@@ -1198,8 +1240,8 @@ int OpenDecoder( vlc_object_t *p_this )
     if( unlikely( p_sys == NULL ) )
         return VLC_ENOMEM;
 
-    webvtt_region_Init( &p_sys->regions );
-    p_sys->pp_region_append = &p_sys->regions.p_next;
+    p_sys->p_regions = NULL;
+    p_sys->p_regionless_cues = NULL;
 
     p_dec->pf_decode = DecodeBlock;
 



More information about the vlc-commits mailing list