[vlc-commits] codec: webvtt: split nodes by type

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


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Oct 27 12:31:07 2017 +0200| [bef3b60598aebe39910b1a4695ea3deb127719f7] | committer: Francois Cartegnie

codec: webvtt: split nodes by type

so we can convert regions to nodes.

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

 modules/codec/webvtt/subsvtt.c | 188 ++++++++++++++++++++++++++++-------------
 1 file changed, 130 insertions(+), 58 deletions(-)

diff --git a/modules/codec/webvtt/subsvtt.c b/modules/codec/webvtt/subsvtt.c
index 75328a0de8..dd8cbbaa3b 100644
--- a/modules/codec/webvtt/subsvtt.c
+++ b/modules/codec/webvtt/subsvtt.c
@@ -47,7 +47,7 @@
  *****************************************************************************/
 
 typedef struct webvtt_region_t webvtt_region_t;
-typedef struct webvtt_domnode_t webvtt_domnode_t;
+typedef struct webvtt_dom_node_t webvtt_dom_node_t;
 typedef struct webvtt_dom_cue_t webvtt_dom_cue_t;
 
 #define WEBVTT_REGION_LINES_COUNT          18
@@ -83,10 +83,21 @@ struct webvtt_dom_cue_t
     mtime_t i_start;
     mtime_t i_stop;
     webvtt_cue_settings_t settings;
-    webvtt_domnode_t *p_nodes;
+    webvtt_dom_node_t *p_nodes;
     unsigned i_lines;
 };
 
+enum webvtt_node_type_e
+{
+    NODE_TAG,
+    NODE_TEXT
+};
+
+#define WEBVTT_NODE_BASE_MEMBERS \
+    enum webvtt_node_type_e type;\
+    webvtt_dom_node_t *p_parent;\
+    webvtt_dom_node_t *p_next;
+
 struct webvtt_region_t
 {
     char *psz_id;
@@ -101,15 +112,23 @@ struct webvtt_region_t
     webvtt_region_t *p_next;
 };
 
-struct webvtt_domnode_t
+typedef struct
+{
+    WEBVTT_NODE_BASE_MEMBERS
+    char *psz_text;
+} webvtt_dom_text_t;
+
+typedef struct
 {
+    WEBVTT_NODE_BASE_MEMBERS
     char *psz_tag;
     char *psz_attrs;
-    char *psz_text;
+    webvtt_dom_node_t *p_child;
+} webvtt_dom_tag_t;
 
-    webvtt_domnode_t *p_parent;
-    webvtt_domnode_t *p_next;
-    webvtt_domnode_t *p_child;
+struct webvtt_dom_node_t
+{
+    WEBVTT_NODE_BASE_MEMBERS
 };
 
 struct decoder_sys_t
@@ -276,51 +295,90 @@ static void webvtt_cue_settings_Init( webvtt_cue_settings_t *p_settings )
  *
  *****************************************************************************/
 #ifdef SUBSVTT_DEBUG
-static void webvtt_domnode_Debug( webvtt_domnode_t *p_node, int i_depth )
+static void webvtt_domnode_Debug( webvtt_dom_node_t *p_node, int i_depth )
 {
     for( ; p_node ; p_node = p_node->p_next )
     {
         for( int i=0; i<i_depth; i++) printf(" ");
-        if( p_node->psz_text )
-            printf("TEXT %s\n", p_node->psz_text );
-        else
-            printf("TAG%s (%s)\n", p_node->psz_tag, p_node->psz_attrs );
-        webvtt_domnode_Debug( p_node->p_child, i_depth + 1 );
+        if( p_node->type == NODE_TEXT )
+        {
+            printf("TEXT %s\n", ((webvtt_dom_text_t *)p_node)->psz_text );
+        }
+        else if( p_node->type == NODE_TAG )
+        {
+            webvtt_dom_tag_t *p_tag = (webvtt_dom_tag_t *)p_node;
+            printf("TAG%s (%s)\n", p_tag->psz_tag, p_tag->psz_attrs );
+            webvtt_domnode_Debug( p_tag->p_child, i_depth + 1 );
+        }
     }
 }
 #endif
-static void webvtt_domnode_RecursiveDelete( webvtt_domnode_t *p_node )
+
+static void webvtt_domnode_ChainDelete( webvtt_dom_node_t *p_node );
+
+
+static void webvtt_dom_text_Delete( webvtt_dom_text_t *p_node )
+{
+    free( p_node->psz_text );
+    free( p_node );
+}
+
+static void webvtt_dom_tag_Delete( webvtt_dom_tag_t *p_node )
+{
+    free( p_node->psz_attrs );
+    free( p_node->psz_tag );
+    webvtt_domnode_ChainDelete( p_node->p_child );
+    free( p_node );
+}
+
+static void webvtt_domnode_ChainDelete( webvtt_dom_node_t *p_node )
 {
     while( p_node )
     {
-        assert( p_node->psz_text == NULL || p_node->p_child == NULL );
-        webvtt_domnode_t *p_next = p_node->p_next;
+        webvtt_dom_node_t *p_next = p_node->p_next;
 
-        webvtt_domnode_RecursiveDelete( p_node->p_child );
-        free( p_node->psz_tag );
-        free( p_node->psz_attrs );
-        free( p_node->psz_text );
-        free( p_node );
+        if( p_node->type == NODE_TAG )
+            webvtt_dom_tag_Delete( (webvtt_dom_tag_t *) p_node );
+        else if( p_node->type == NODE_TEXT )
+            webvtt_dom_text_Delete( (webvtt_dom_text_t *) p_node );
 
         p_node = p_next;
     }
 }
 
-static webvtt_domnode_t * webvtt_domnode_New( webvtt_domnode_t *p_parent )
+static webvtt_dom_text_t * webvtt_dom_text_New( webvtt_dom_node_t *p_parent )
+{
+    webvtt_dom_text_t *p_node = calloc( 1, sizeof(*p_node) );
+    if( p_node )
+    {
+        p_node->type = NODE_TEXT;
+        p_node->p_parent = p_parent;
+    }
+    return p_node;
+}
+
+static webvtt_dom_tag_t * webvtt_dom_tag_New( webvtt_dom_node_t *p_parent )
 {
-    webvtt_domnode_t *p_node = calloc( 1, sizeof(*p_node) );
+    webvtt_dom_tag_t *p_node = calloc( 1, sizeof(*p_node) );
     if( p_node )
+    {
+        p_node->type = NODE_TAG;
         p_node->p_parent = p_parent;
+    }
     return p_node;
 }
 
-static webvtt_domnode_t * webvtt_domnode_getParentByTag( webvtt_domnode_t *p_parent,
+static webvtt_dom_node_t * webvtt_domnode_getParentByTag( webvtt_dom_node_t *p_parent,
                                                          const char *psz_tag )
 {
     for( ; p_parent ; p_parent = p_parent->p_parent )
     {
-        if( p_parent->psz_tag && psz_tag && !strcmp( p_parent->psz_tag, psz_tag ) )
-            break;
+        if( p_parent->type == NODE_TAG )
+        {
+            webvtt_dom_tag_t *p_node = (webvtt_dom_tag_t *) p_parent;
+            if( p_node->psz_tag && psz_tag && !strcmp( p_node->psz_tag, psz_tag ) )
+                break;
+        }
     }
     return p_parent;
 }
@@ -381,7 +439,7 @@ static webvtt_dom_cue_t * webvtt_dom_cue_New( mtime_t i_start, mtime_t i_end )
 
 static void webvtt_dom_cue_ClearText( webvtt_dom_cue_t *p_cue )
 {
-    webvtt_domnode_RecursiveDelete( p_cue->p_nodes );
+    webvtt_domnode_ChainDelete( p_cue->p_nodes );
     p_cue->p_nodes = NULL;
     p_cue->i_lines = 0;
 }
@@ -403,26 +461,27 @@ static webvtt_dom_cue_t * webvtt_dom_cue_Reduced( webvtt_dom_cue_t *p_cue )
         return NULL;
     }
 
-    for( webvtt_domnode_t *p_node = p_cue->p_nodes;
+    for( webvtt_dom_node_t *p_node = p_cue->p_nodes;
                            p_node; p_node = p_node->p_next )
     {
-        if( !p_node->psz_text )
+        if( p_node->type != NODE_TEXT )
             continue;
-        const char *nl = strchr( p_node->psz_text, '\n' );
+        webvtt_dom_text_t *p_textnode = (webvtt_dom_text_t *) p_node;
+        const char *nl = strchr( p_textnode->psz_text, '\n' );
         if( nl )
         {
-            size_t i_len = strlen( p_node->psz_text );
-            size_t i_remain = i_len - (nl - p_node->psz_text);
+            size_t i_len = strlen( p_textnode->psz_text );
+            size_t i_remain = i_len - (nl - p_textnode->psz_text);
             char *psz_new = strndup( nl + 1, i_remain );
-            free( p_node->psz_text );
-            p_node->psz_text = psz_new;
+            free( p_textnode->psz_text );
+            p_textnode->psz_text = psz_new;
             p_cue->i_lines--;
             return p_cue;
         }
         else
         {
-            free( p_node->psz_text );
-            p_node->psz_text = NULL;
+            free( p_textnode->psz_text );
+            p_textnode->psz_text = NULL;
             /* FIXME: probably can do a local nodes cleanup */
         }
     }
@@ -651,11 +710,11 @@ static unsigned CountNewLines( const char *psz )
     return i;
 }
 
-static webvtt_domnode_t * CreateDomNodes( const char *psz_text, unsigned *pi_lines )
+static webvtt_dom_node_t * CreateDomNodes( const char *psz_text, unsigned *pi_lines )
 {
-    webvtt_domnode_t *p_head = NULL;
-    webvtt_domnode_t **pp_append = &p_head;
-    webvtt_domnode_t *p_parent = p_head;
+    webvtt_dom_node_t *p_head = NULL;
+    webvtt_dom_node_t **pp_append = &p_head;
+    webvtt_dom_node_t *p_parent = p_head;
     *pi_lines = 0;
 
     while( *psz_text )
@@ -666,19 +725,19 @@ static webvtt_domnode_t * CreateDomNodes( const char *psz_text, unsigned *pi_lin
         {
             if( psz_tag - psz_text > 0 )
             {
-                webvtt_domnode_t *p_node = webvtt_domnode_New( p_parent );
+                webvtt_dom_text_t *p_node = webvtt_dom_text_New( p_parent );
                 if( p_node )
                 {
                     p_node->psz_text = strndup( psz_text, psz_tag - psz_text );
                     *pi_lines += ((*pi_lines == 0) ? 1 : 0) + CountNewLines( p_node->psz_text );
-                    *pp_append = p_node;
+                    *pp_append = (webvtt_dom_node_t *) p_node;
                     pp_append = &p_node->p_next;
                 }
             }
 
             if( ! IsEndTag( psz_tag ) )
             {
-                webvtt_domnode_t *p_node = webvtt_domnode_New( p_parent );
+                webvtt_dom_tag_t *p_node = webvtt_dom_tag_New( p_parent );
                 if( p_node )
                 {
                     const char *psz_attrs = NULL;
@@ -686,8 +745,8 @@ static webvtt_domnode_t * CreateDomNodes( const char *psz_text, unsigned *pi_lin
                     p_node->psz_tag = strndup( psz_name, psz_attrs - psz_name );
                     if( psz_attrs != psz_taglast )
                         p_node->psz_attrs = strndup( psz_attrs, psz_taglast - psz_attrs );
-                    *pp_append = p_node;
-                    p_parent = p_node;
+                    *pp_append = (webvtt_dom_node_t *) p_node;
+                    p_parent = (webvtt_dom_node_t *) p_node;
                     pp_append = &p_node->p_child;
                 }
             }
@@ -717,12 +776,12 @@ static webvtt_domnode_t * CreateDomNodes( const char *psz_text, unsigned *pi_lin
         }
         else /* Special case: end */
         {
-            webvtt_domnode_t *p_node = webvtt_domnode_New( p_parent );
+            webvtt_dom_text_t *p_node = webvtt_dom_text_New( p_parent );
             if( p_node )
             {
                 p_node->psz_text = strdup( psz_text );
                 *pi_lines += ((*pi_lines == 0) ? 1 : 0) + CountNewLines( p_node->psz_text );
-                *pp_append = p_node;
+                *pp_append = (webvtt_dom_node_t *) p_node;
             }
             break;
         }
@@ -752,16 +811,21 @@ static void ProcessCue( decoder_t *p_dec, const char *psz, webvtt_dom_cue_t *p_c
 #endif
 }
 
-static text_style_t * InheritStyles( decoder_t *p_dec, const webvtt_domnode_t *p_node )
+static text_style_t * InheritStyles( decoder_t *p_dec, const webvtt_dom_node_t *p_node )
 {
     VLC_UNUSED(p_dec);
 
     text_style_t *p_style = NULL;
     for( ; p_node; p_node = p_node->p_parent )
     {
-        if( p_node->psz_tag )
+        if( p_node->type == NODE_TAG )
         {
-            if ( !strcmp( p_node->psz_tag, "b" ) )
+            const webvtt_dom_tag_t *p_tagnode = (const webvtt_dom_tag_t *)p_node;
+            if ( p_tagnode->psz_tag == NULL )
+            {
+                continue;
+            }
+            else if ( !strcmp( p_tagnode->psz_tag, "b" ) )
             {
                 if( p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS )) )
                 {
@@ -769,7 +833,7 @@ static text_style_t * InheritStyles( decoder_t *p_dec, const webvtt_domnode_t *p
                     p_style->i_features |= STYLE_HAS_FLAGS;
                 }
             }
-            else if ( !strcmp( p_node->psz_tag, "i" ) )
+            else if ( !strcmp( p_tagnode->psz_tag, "i" ) )
             {
                 if( p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS )) )
                 {
@@ -777,7 +841,7 @@ static text_style_t * InheritStyles( decoder_t *p_dec, const webvtt_domnode_t *p
                     p_style->i_features |= STYLE_HAS_FLAGS;
                 }
             }
-            else if ( !strcmp( p_node->psz_tag, "u" ) )
+            else if ( !strcmp( p_tagnode->psz_tag, "u" ) )
             {
                 if( p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS )) )
                 {
@@ -785,12 +849,12 @@ static text_style_t * InheritStyles( decoder_t *p_dec, const webvtt_domnode_t *p
                     p_style->i_features |= STYLE_HAS_FLAGS;
                 }
             }
-            else if ( !strcmp( p_node->psz_tag, "v" ) && p_node->psz_attrs )
+            else if ( !strcmp( p_tagnode->psz_tag, "v" ) && p_tagnode->psz_attrs )
             {
                 if( p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS )) )
                 {
                     unsigned a = 0;
-                    for( char *p = p_node->psz_attrs; *p; p++ )
+                    for( char *p = p_tagnode->psz_attrs; *p; p++ )
                         a = (a << 3) ^ *p;
                     p_style->i_font_color = (0x7F7F7F | a) & 0xFFFFFF;
                     p_style->i_features |= STYLE_HAS_FONT_COLOR;
@@ -813,15 +877,19 @@ struct render_variables_s
 static text_segment_t *ConvertNodesToSegments( decoder_t *p_dec,
                                                struct render_variables_s *p_vars,
                                                const webvtt_dom_cue_t *p_cue,
-                                               const webvtt_domnode_t *p_node )
+                                               const webvtt_dom_node_t *p_node )
 {
     text_segment_t *p_head = NULL;
     text_segment_t **pp_append = &p_head;
     for( ; p_node ; p_node = p_node->p_next )
     {
-        if( p_node->psz_text )
+        if( p_node->type == NODE_TEXT )
         {
-            *pp_append = text_segment_New( p_node->psz_text );
+            const webvtt_dom_text_t *p_textnode = (const webvtt_dom_text_t *) p_node;
+            if( p_textnode->psz_text == NULL )
+                continue;
+
+            *pp_append = text_segment_New( p_textnode->psz_text );
             if( *pp_append )
             {
                 if( (*pp_append)->psz_text )
@@ -830,8 +898,12 @@ static text_segment_t *ConvertNodesToSegments( decoder_t *p_dec,
                 pp_append = &((*pp_append)->p_next);
             }
         }
+        else if( p_node->type == NODE_TAG )
+        {
+            *pp_append = ConvertNodesToSegments( p_dec, p_vars, p_cue,
+                                                 ((const webvtt_dom_tag_t *)p_node)->p_child );
+        }
 
-        *pp_append = ConvertNodesToSegments( p_dec, p_vars, p_cue, p_node->p_child );
         while( *pp_append )
             pp_append = &((*pp_append)->p_next);
     }



More information about the vlc-commits mailing list