vlc | branch: master | Francois Cartegnie <[email protected]> | 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; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
