[vlc-commits] codec: webvtt: convert cues to dom nodes
Francois Cartegnie
git at videolan.org
Fri Oct 27 17:10:25 CEST 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Oct 27 14:02:51 2017 +0200| [e705b77788d81ae47ca61e12a42b55ef58c0f23f] | committer: Francois Cartegnie
codec: webvtt: convert cues to dom nodes
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=e705b77788d81ae47ca61e12a42b55ef58c0f23f
---
modules/codec/webvtt/subsvtt.c | 199 +++++++++++++++++++++--------------------
1 file changed, 100 insertions(+), 99 deletions(-)
diff --git a/modules/codec/webvtt/subsvtt.c b/modules/codec/webvtt/subsvtt.c
index dd8cbbaa3b..39db68562a 100644
--- a/modules/codec/webvtt/subsvtt.c
+++ b/modules/codec/webvtt/subsvtt.c
@@ -77,20 +77,11 @@ typedef struct
enum webvtt_align_e align;
} webvtt_cue_settings_t;
-struct webvtt_dom_cue_t
-{
- char *psz_id;
- mtime_t i_start;
- mtime_t i_stop;
- webvtt_cue_settings_t settings;
- webvtt_dom_node_t *p_nodes;
- unsigned i_lines;
-};
-
enum webvtt_node_type_e
{
NODE_TAG,
- NODE_TEXT
+ NODE_TEXT,
+ NODE_CUE,
};
#define WEBVTT_NODE_BASE_MEMBERS \
@@ -108,10 +99,21 @@ struct webvtt_region_t
float viewport_anchor_x;
float viewport_anchor_y;
bool b_scroll_up;
- webvtt_dom_cue_t *p_cues[WEBVTT_REGION_LINES_COUNT]; /* worst case 1 line == 1 cue */
+ webvtt_dom_node_t *p_child;
webvtt_region_t *p_next;
};
+struct webvtt_dom_cue_t
+{
+ WEBVTT_NODE_BASE_MEMBERS
+ char *psz_id;
+ mtime_t i_start;
+ mtime_t i_stop;
+ webvtt_cue_settings_t settings;
+ unsigned i_lines;
+ webvtt_dom_node_t *p_child;
+};
+
typedef struct
{
WEBVTT_NODE_BASE_MEMBERS
@@ -310,12 +312,18 @@ static void webvtt_domnode_Debug( webvtt_dom_node_t *p_node, int i_depth )
printf("TAG%s (%s)\n", p_tag->psz_tag, p_tag->psz_attrs );
webvtt_domnode_Debug( p_tag->p_child, i_depth + 1 );
}
+ else if( p_node->type == NODE_CUE )
+ {
+ webvtt_dom_cue_t *p_cue = (webvtt_dom_cue_t *)p_node;
+ printf("CUE %s\n", p_cue->psz_id );
+ webvtt_domnode_Debug( p_cue->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_dom_text_Delete( webvtt_dom_text_t *p_node )
{
@@ -341,6 +349,8 @@ static void webvtt_domnode_ChainDelete( webvtt_dom_node_t *p_node )
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 );
+ else if( p_node->type == NODE_CUE )
+ webvtt_dom_cue_Delete( (webvtt_dom_cue_t *) p_node );
p_node = p_next;
}
@@ -427,10 +437,11 @@ static webvtt_dom_cue_t * webvtt_dom_cue_New( mtime_t i_start, mtime_t i_end )
webvtt_dom_cue_t *p_cue = calloc( 1, sizeof(*p_cue) );
if( p_cue )
{
+ p_cue->type = NODE_CUE;
p_cue->psz_id = NULL;
p_cue->i_start = i_start;
p_cue->i_stop = i_end;
- p_cue->p_nodes = NULL;
+ p_cue->p_child = NULL;
p_cue->i_lines = 0;
webvtt_cue_settings_Init( &p_cue->settings );
}
@@ -439,8 +450,8 @@ 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_ChainDelete( p_cue->p_nodes );
- p_cue->p_nodes = NULL;
+ webvtt_domnode_ChainDelete( p_cue->p_child );
+ p_cue->p_child = NULL;
p_cue->i_lines = 0;
}
@@ -452,16 +463,13 @@ static void webvtt_dom_cue_Delete( webvtt_dom_cue_t *p_cue )
free( p_cue );
}
-/* Returns reduced by one line cue or deletes it */
-static webvtt_dom_cue_t * webvtt_dom_cue_Reduced( webvtt_dom_cue_t *p_cue )
+/* reduces by one line */
+static unsigned webvtt_dom_cue_Reduced( webvtt_dom_cue_t *p_cue )
{
- if( p_cue->i_lines <= 1 )
- {
- webvtt_dom_cue_Delete( p_cue );
- return NULL;
- }
+ if( p_cue->i_lines < 1 )
+ return 0;
- for( webvtt_dom_node_t *p_node = p_cue->p_nodes;
+ for( webvtt_dom_node_t *p_node = p_cue->p_child;
p_node; p_node = p_node->p_next )
{
if( p_node->type != NODE_TEXT )
@@ -475,8 +483,7 @@ static webvtt_dom_cue_t * webvtt_dom_cue_Reduced( webvtt_dom_cue_t *p_cue )
char *psz_new = strndup( nl + 1, i_remain );
free( p_textnode->psz_text );
p_textnode->psz_text = psz_new;
- p_cue->i_lines--;
- return p_cue;
+ return --p_cue->i_lines;
}
else
{
@@ -486,9 +493,7 @@ static webvtt_dom_cue_t * webvtt_dom_cue_Reduced( webvtt_dom_cue_t *p_cue )
}
}
- /* should not happen */
- webvtt_dom_cue_Delete( p_cue );
- return NULL;
+ return p_cue->i_lines;
}
/*****************************************************************************
@@ -557,35 +562,44 @@ static void webvtt_region_Parse( webvtt_region_t *p_region, char *psz_line )
static unsigned webvtt_region_CountLines( const webvtt_region_t *p_region )
{
unsigned i_lines = 0;
- for( size_t i=0; i<WEBVTT_REGION_LINES_COUNT; i++ )
- if( p_region->p_cues[i] )
- i_lines += p_region->p_cues[i]->i_lines;
+ for( const webvtt_dom_node_t *p_node = p_region->p_child;
+ p_node; p_node = p_node->p_next )
+ {
+ assert( p_node->type == NODE_CUE );
+ if( p_node->type != NODE_CUE )
+ continue;
+ i_lines += ((const webvtt_dom_cue_t *)p_node)->i_lines;
+ }
return i_lines;
}
static void webvtt_region_ClearCues( webvtt_region_t *p_region )
{
- for( size_t i=0; i<WEBVTT_REGION_LINES_COUNT; i++ )
- {
- if( p_region->p_cues[i] == NULL )
- continue;
- webvtt_dom_cue_Delete( p_region->p_cues[i] );
- p_region->p_cues[i] = NULL;
- }
+ webvtt_domnode_ChainDelete( p_region->p_child );
+ p_region->p_child = NULL;
}
static void webvtt_region_ClearCuesByTime( webvtt_region_t *p_region, mtime_t i_time )
{
- for( size_t i=0; i<WEBVTT_REGION_LINES_COUNT; i++ )
+ webvtt_dom_node_t **pp_node = &p_region->p_child;
+ while( *pp_node )
{
- if( p_region->p_cues[i] == NULL )
- continue;
- if( p_region->p_cues[i]->i_stop <= i_time )
+ webvtt_dom_node_t *p_node = *pp_node;
+ if( p_node )
{
- webvtt_dom_cue_Delete( p_region->p_cues[i] );
- for( size_t j=i; j<WEBVTT_REGION_LINES_COUNT - 1; j++ )
- p_region->p_cues[j] = p_region->p_cues[j] + 1;
- p_region->p_cues[WEBVTT_REGION_LINES_COUNT - 1] = NULL;
+ assert( p_node->type == NODE_CUE );
+ if( p_node->type == NODE_CUE )
+ {
+ 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;
+ p_node->p_next = NULL;
+ webvtt_dom_cue_Delete( p_cue );
+ continue;
+ }
+ }
+ pp_node = &p_node->p_next;
}
}
}
@@ -594,64 +608,48 @@ 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 )
{
- if( p_region->p_cues[0] )
+ if( p_region->p_child )
{
- webvtt_dom_cue_Delete( p_region->p_cues[0] );
- }
- else
- {
- for( int i=0; i<WEBVTT_REGION_LINES_COUNT; i++ )
+ assert( p_region->p_child->type == NODE_CUE );
+ if( p_region->p_child->type != NODE_CUE )
+ return;
+ webvtt_dom_cue_t *p_cue = (webvtt_dom_cue_t *)p_region->p_child;
+ if( p_cue->i_lines == 1 ||
+ webvtt_dom_cue_Reduced( p_cue ) < 1 )
{
- if( p_region->p_cues[i] )
- {
- p_region->p_cues[i] =
- webvtt_dom_cue_Reduced( p_region->p_cues[i] );
- break;
- }
+ p_region->p_child = p_cue->p_next;
+ p_cue->p_next = NULL;
+ webvtt_dom_cue_Delete( p_cue );
}
}
}
-static void webvtt_region_ScrollUp( webvtt_region_t *p_region )
-{
- if( p_region->p_cues[0] )
- webvtt_dom_cue_Delete( p_region->p_cues[0] );
-
- memmove( &p_region->p_cues[0], &p_region->p_cues[1],
- (WEBVTT_REGION_LINES_COUNT - 1) * sizeof(p_region->p_cues[0]) );
- p_region->p_cues[WEBVTT_REGION_LINES_COUNT - 1] = NULL;
-}
-
static void webvtt_region_AddCue( webvtt_region_t *p_region,
webvtt_dom_cue_t *p_cue )
{
- if( p_region->b_scroll_up == false )
- {
- webvtt_region_ClearCues( p_region );
- }
- else
+ webvtt_dom_node_t **pp_add = &p_region->p_child;
+ while( *pp_add )
+ pp_add = &((*pp_add)->p_next);
+ *pp_add = (webvtt_dom_node_t *)p_cue;
+
+ for( ;; )
{
- while( p_cue->i_lines > p_region->i_lines_max_scroll ) /* eh eh */
+ unsigned i_lines = webvtt_region_CountLines( p_region );
+ if( i_lines > 0 &&
+ ( i_lines > WEBVTT_REGION_LINES_COUNT ||
+ (p_region->b_scroll_up && i_lines > p_region->i_lines_max_scroll)) )
{
- p_cue = webvtt_dom_cue_Reduced( p_cue );
- assert( p_cue );
- if( unlikely(!p_cue) )
- return;
+ webvtt_region_Reduce( p_region ); /* scrolls up */
+ assert( webvtt_region_CountLines( p_region ) < i_lines );
}
-
- while( webvtt_region_CountLines( p_region ) + p_cue->i_lines
- > p_region->i_lines_max_scroll )
- webvtt_region_Reduce( p_region );
-
- /* now move everything up */
- webvtt_region_ScrollUp( p_region );
+ else break;
}
- p_region->p_cues[WEBVTT_REGION_LINES_COUNT - 1] = p_cue;
}
static void webvtt_region_Init( webvtt_region_t *p_region )
@@ -665,8 +663,7 @@ static void webvtt_region_Init( webvtt_region_t *p_region )
p_region->viewport_anchor_x = 0;
p_region->viewport_anchor_y = 1.0; /* 100% */
p_region->b_scroll_up = false;
- for( int i=0; i<WEBVTT_REGION_LINES_COUNT; i++ )
- p_region->p_cues[i] = NULL;
+ p_region->p_child = NULL;
}
static void webvtt_region_Delete( webvtt_region_t *p_region )
@@ -803,11 +800,11 @@ static void ProcessCue( decoder_t *p_dec, const char *psz, webvtt_dom_cue_t *p_c
{
VLC_UNUSED(p_dec);
- if( p_cue->p_nodes )
+ if( p_cue->p_child )
return;
- p_cue->p_nodes = CreateDomNodes( psz, &p_cue->i_lines );
+ p_cue->p_child = CreateDomNodes( psz, &p_cue->i_lines );
#ifdef SUBSVTT_DEBUG
- webvtt_domnode_Debug( p_cue->p_nodes, 0 );
+ webvtt_domnode_Debug( (webvtt_dom_node_t *) p_cue, 0 );
#endif
}
@@ -914,7 +911,7 @@ static text_segment_t *ConvertCueToSegments( decoder_t *p_dec,
struct render_variables_s *p_vars,
const webvtt_dom_cue_t *p_cue )
{
- return ConvertNodesToSegments( p_dec, p_vars, p_cue, p_cue->p_nodes );
+ return ConvertNodesToSegments( p_dec, p_vars, p_cue, p_cue->p_child );
}
static void RenderRegions( decoder_t *p_dec, mtime_t i_start, mtime_t i_stop )
@@ -938,15 +935,18 @@ 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( int i=0; i<WEBVTT_REGION_LINES_COUNT; i++ )
+ for( webvtt_dom_node_t *p_node = p_vttregion->p_child;
+ p_node; p_node = p_node->p_next )
{
- if( !p_vttregion->p_cues[i] ||
- p_vttregion->p_cues[i]->i_start > i_start ||
- p_vttregion->p_cues[i]->i_stop <= i_start )
+ 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;
+
+ if( p_cue->i_start > i_start || p_cue->i_stop <= i_start )
continue;
- text_segment_t *p_new = ConvertCueToSegments( p_dec, &v,
- p_vttregion->p_cues[i] );
+ text_segment_t *p_new = ConvertCueToSegments( p_dec, &v, p_cue );
if( p_new )
{
if( p_segments ) /* auto newlines */
@@ -1067,6 +1067,7 @@ static int ProcessISOBMFF( decoder_t *p_dec,
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 );
}
}
return 0;
More information about the vlc-commits
mailing list