mirror of https://code.videolan.org/videolan/vlc
codec/demux: ttml: handle non-default namespaces
This commit is contained in:
parent
a55c9e9a6b
commit
44879313ba
|
@ -124,7 +124,8 @@ enum
|
|||
* Then we convert attributes, merging with style by id or region
|
||||
* style, and sets from parent node.
|
||||
*/
|
||||
static tt_node_t *ParseTTML( decoder_t *, const uint8_t *, size_t );
|
||||
static tt_node_t *ParseTTML( decoder_t *, tt_namespaces_t *,
|
||||
const uint8_t *, size_t );
|
||||
|
||||
static void ttml_style_Delete( ttml_style_t* p_ttml_style )
|
||||
{
|
||||
|
@ -280,16 +281,17 @@ static bool ttml_read_coords( const char *value, ttml_length_t *h, ttml_length_t
|
|||
return false;
|
||||
}
|
||||
|
||||
static tt_node_t * FindNode( tt_node_t *p_node, const char *psz_nodename,
|
||||
static tt_node_t * FindNode( tt_namespaces_t *p_nss, tt_node_t *p_node,
|
||||
const char *psz_nodename, const char *psz_namespace,
|
||||
size_t i_maxdepth, const char *psz_id )
|
||||
{
|
||||
if( !tt_node_NameCompare( p_node->psz_node_name, psz_nodename ) )
|
||||
if( tt_node_Match( p_node, psz_nodename, psz_namespace ) )
|
||||
{
|
||||
if( psz_id != NULL )
|
||||
{
|
||||
char *psz = vlc_dictionary_value_for_key( &p_node->attr_dict, "xml:id" );
|
||||
const char *psz = tt_node_GetAttribute( p_nss, p_node, "id", TT_NS_XML );
|
||||
if( !psz ) /* People can't do xml properly */
|
||||
psz = vlc_dictionary_value_for_key( &p_node->attr_dict, "id" );
|
||||
psz = tt_node_GetAttribute( p_nss, p_node, "id", NULL );
|
||||
if( psz && !strcmp( psz, psz_id ) )
|
||||
return p_node;
|
||||
}
|
||||
|
@ -305,7 +307,9 @@ static tt_node_t * FindNode( tt_node_t *p_node, const char *psz_nodename,
|
|||
if( p_child->i_type == TT_NODE_TYPE_TEXT )
|
||||
continue;
|
||||
|
||||
p_node = FindNode( (tt_node_t *) p_child, psz_nodename, i_maxdepth - 1, psz_id );
|
||||
p_node = FindNode( p_nss, (tt_node_t *) p_child,
|
||||
psz_nodename, psz_namespace,
|
||||
i_maxdepth - 1, psz_id );
|
||||
if( p_node )
|
||||
return p_node;
|
||||
}
|
||||
|
@ -316,25 +320,25 @@ static tt_node_t * FindNode( tt_node_t *p_node, const char *psz_nodename,
|
|||
static void FillTextStyle( const char *psz_attr, const char *psz_val,
|
||||
text_style_t *p_text_style )
|
||||
{
|
||||
if( !strcasecmp ( "tts:fontFamily", psz_attr ) )
|
||||
if( !strcasecmp ( "fontFamily", psz_attr ) )
|
||||
{
|
||||
free( p_text_style->psz_fontname );
|
||||
p_text_style->psz_fontname = strdup( psz_val );
|
||||
}
|
||||
else if( !strcasecmp( "tts:opacity", psz_attr ) )
|
||||
else if( !strcasecmp( "opacity", psz_attr ) )
|
||||
{
|
||||
p_text_style->i_background_alpha = atoi( psz_val );
|
||||
p_text_style->i_font_alpha = atoi( psz_val );
|
||||
p_text_style->i_features |= STYLE_HAS_BACKGROUND_ALPHA | STYLE_HAS_FONT_ALPHA;
|
||||
}
|
||||
else if( !strcasecmp( "tts:color", psz_attr ) )
|
||||
else if( !strcasecmp( "color", psz_attr ) )
|
||||
{
|
||||
unsigned int i_color = vlc_html_color( psz_val, NULL );
|
||||
p_text_style->i_font_color = (i_color & 0xffffff);
|
||||
p_text_style->i_font_alpha = (i_color & 0xFF000000) >> 24;
|
||||
p_text_style->i_features |= STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA;
|
||||
}
|
||||
else if( !strcasecmp( "tts:backgroundColor", psz_attr ) )
|
||||
else if( !strcasecmp( "backgroundColor", psz_attr ) )
|
||||
{
|
||||
unsigned int i_color = vlc_html_color( psz_val, NULL );
|
||||
p_text_style->i_background_color = i_color & 0xFFFFFF;
|
||||
|
@ -343,7 +347,7 @@ static void FillTextStyle( const char *psz_attr, const char *psz_val,
|
|||
| STYLE_HAS_BACKGROUND_ALPHA;
|
||||
p_text_style->i_style_flags |= STYLE_BACKGROUND;
|
||||
}
|
||||
else if( !strcasecmp( "tts:fontStyle", psz_attr ) )
|
||||
else if( !strcasecmp( "fontStyle", psz_attr ) )
|
||||
{
|
||||
if( !strcasecmp ( "italic", psz_val ) || !strcasecmp ( "oblique", psz_val ) )
|
||||
p_text_style->i_style_flags |= STYLE_ITALIC;
|
||||
|
@ -351,7 +355,7 @@ static void FillTextStyle( const char *psz_attr, const char *psz_val,
|
|||
p_text_style->i_style_flags &= ~STYLE_ITALIC;
|
||||
p_text_style->i_features |= STYLE_HAS_FLAGS;
|
||||
}
|
||||
else if( !strcasecmp ( "tts:fontWeight", psz_attr ) )
|
||||
else if( !strcasecmp ( "fontWeight", psz_attr ) )
|
||||
{
|
||||
if( !strcasecmp ( "bold", psz_val ) )
|
||||
p_text_style->i_style_flags |= STYLE_BOLD;
|
||||
|
@ -359,7 +363,7 @@ static void FillTextStyle( const char *psz_attr, const char *psz_val,
|
|||
p_text_style->i_style_flags &= ~STYLE_BOLD;
|
||||
p_text_style->i_features |= STYLE_HAS_FLAGS;
|
||||
}
|
||||
else if( !strcasecmp ( "tts:textDecoration", psz_attr ) )
|
||||
else if( !strcasecmp ( "textDecoration", psz_attr ) )
|
||||
{
|
||||
if( !strcasecmp ( "underline", psz_val ) )
|
||||
p_text_style->i_style_flags |= STYLE_UNDERLINE;
|
||||
|
@ -371,7 +375,7 @@ static void FillTextStyle( const char *psz_attr, const char *psz_val,
|
|||
p_text_style->i_style_flags &= ~STYLE_STRIKEOUT;
|
||||
p_text_style->i_features |= STYLE_HAS_FLAGS;
|
||||
}
|
||||
else if( !strcasecmp( "tts:textOutline", psz_attr ) )
|
||||
else if( !strcasecmp( "textOutline", psz_attr ) )
|
||||
{
|
||||
char *value = strdup( psz_val );
|
||||
char* psz_saveptr = NULL;
|
||||
|
@ -433,10 +437,13 @@ static void FillUpdaterCoords( ttml_context_t *p_ctx, ttml_length_t h, ttml_leng
|
|||
}
|
||||
|
||||
static void FillRegionStyle( ttml_context_t *p_ctx,
|
||||
const char *psz_attr, const char *psz_val,
|
||||
ttml_region_t *p_region )
|
||||
const char *psz_attr, const char *psz_namespace,
|
||||
const char *psz_val, ttml_region_t *p_region )
|
||||
{
|
||||
if( !strcasecmp( "tts:displayAlign", psz_attr ) )
|
||||
if( strcmp( psz_namespace, TT_NS_STYLING ) )
|
||||
return;
|
||||
|
||||
if( !strcasecmp( "displayAlign", psz_attr ) )
|
||||
{
|
||||
p_region->updt.inner_align &= ~(SUBPICTURE_ALIGN_TOP|SUBPICTURE_ALIGN_BOTTOM);
|
||||
if( !strcasecmp( "after", psz_val ) )
|
||||
|
@ -445,12 +452,12 @@ static void FillRegionStyle( ttml_context_t *p_ctx,
|
|||
/* "before" */
|
||||
p_region->updt.inner_align |= SUBPICTURE_ALIGN_TOP;
|
||||
}
|
||||
else if( !strcasecmp ( "tts:origin", psz_attr ) ||
|
||||
!strcasecmp ( "tts:extent", psz_attr ) )
|
||||
else if( !strcasecmp ( "origin", psz_attr ) ||
|
||||
!strcasecmp ( "extent", psz_attr ) )
|
||||
{
|
||||
ttml_length_t x, y;
|
||||
if( ttml_read_coords( psz_val, &x, &y ) )
|
||||
FillUpdaterCoords( p_ctx, x, y, (psz_attr[4] == 'o'), &p_region->updt );
|
||||
FillUpdaterCoords( p_ctx, x, y, (psz_attr[0] == 'o'), &p_region->updt );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,20 +490,30 @@ static void ComputeTTMLStyles( ttml_context_t *p_ctx, const vlc_dictionary_t *p_
|
|||
p_text_style->i_font_size = len.i_value;
|
||||
}
|
||||
|
||||
static void FillTTMLStyle( const char *psz_attr, const char *psz_val,
|
||||
ttml_style_t *p_ttml_style )
|
||||
static void FillTTMLStyle( const char *psz_attr, const char *psz_namespace,
|
||||
const char *psz_val, ttml_style_t *p_ttml_style )
|
||||
{
|
||||
if( !strcasecmp( "tts:extent", psz_attr ) )
|
||||
if( !strcmp( psz_namespace, TT_NS_XML ) )
|
||||
{
|
||||
if( !strcasecmp( "space", psz_attr ) )
|
||||
p_ttml_style->b_preserve_space = !strcmp( "preserve", psz_val );
|
||||
return;
|
||||
}
|
||||
|
||||
if( strcmp( psz_namespace, TT_NS_STYLING ) )
|
||||
return;
|
||||
|
||||
if( !strcasecmp( "extent", psz_attr ) )
|
||||
{
|
||||
ttml_read_coords( psz_val, &p_ttml_style->extent_h,
|
||||
&p_ttml_style->extent_v );
|
||||
}
|
||||
else if( !strcasecmp( "tts:origin", psz_attr ) )
|
||||
else if( !strcasecmp( "origin", psz_attr ) )
|
||||
{
|
||||
ttml_read_coords( psz_val, &p_ttml_style->origin_h,
|
||||
&p_ttml_style->origin_v );
|
||||
}
|
||||
else if( !strcasecmp( "tts:textAlign", psz_attr ) )
|
||||
else if( !strcasecmp( "textAlign", psz_attr ) )
|
||||
{
|
||||
p_ttml_style->i_text_align &= ~(SUBPICTURE_ALIGN_LEFT|SUBPICTURE_ALIGN_RIGHT);
|
||||
if( !strcasecmp ( "left", psz_val ) )
|
||||
|
@ -513,13 +530,13 @@ static void FillTTMLStyle( const char *psz_attr, const char *psz_val,
|
|||
printf("**%s %x\n", psz_val, p_ttml_style->i_text_align);
|
||||
#endif
|
||||
}
|
||||
else if( !strcasecmp( "tts:fontSize", psz_attr ) )
|
||||
else if( !strcasecmp( "fontSize", psz_attr ) )
|
||||
{
|
||||
ttml_length_t len = ttml_read_length( psz_val );
|
||||
if( len.unit != TTML_UNIT_UNKNOWN && len.i_value > 0.0 )
|
||||
p_ttml_style->font_size = len;
|
||||
}
|
||||
else if( !strcasecmp( "tts:direction", psz_attr ) )
|
||||
else if( !strcasecmp( "direction", psz_attr ) )
|
||||
{
|
||||
if( !strcasecmp( "rtl", psz_val ) )
|
||||
{
|
||||
|
@ -532,14 +549,14 @@ static void FillTTMLStyle( const char *psz_attr, const char *psz_val,
|
|||
p_ttml_style->b_direction_set = true;
|
||||
}
|
||||
}
|
||||
else if( !strcasecmp( "tts:unicodeBidi", psz_attr ) )
|
||||
else if( !strcasecmp( "unicodeBidi", psz_attr ) )
|
||||
{
|
||||
if( !strcasecmp( "bidiOverride", psz_val ) )
|
||||
p_ttml_style->i_direction |= UNICODE_BIDI_OVERRIDE & ~UNICODE_BIDI_EMBEDDED;
|
||||
else if( !strcasecmp( "embed", psz_val ) )
|
||||
p_ttml_style->i_direction |= UNICODE_BIDI_EMBEDDED & ~UNICODE_BIDI_OVERRIDE;
|
||||
}
|
||||
else if( !strcasecmp( "tts:writingMode", psz_attr ) )
|
||||
else if( !strcasecmp( "writingMode", psz_attr ) )
|
||||
{
|
||||
if( !strcasecmp( "rl", psz_val ) || !strcasecmp( "rltb", psz_val ) )
|
||||
{
|
||||
|
@ -554,17 +571,13 @@ static void FillTTMLStyle( const char *psz_attr, const char *psz_val,
|
|||
p_ttml_style->b_direction_set = true;
|
||||
}
|
||||
}
|
||||
else if( !strcmp( "tts:display", psz_attr ) )
|
||||
else if( !strcmp( "display", psz_attr ) )
|
||||
{
|
||||
if( !strcmp( "none", psz_val ) )
|
||||
p_ttml_style->display = TTML_DISPLAY_NONE;
|
||||
else
|
||||
p_ttml_style->display = TTML_DISPLAY_AUTO;
|
||||
}
|
||||
else if( !strcasecmp( "xml:space", psz_attr ) )
|
||||
{
|
||||
p_ttml_style->b_preserve_space = !strcmp( "preserve", psz_val );
|
||||
}
|
||||
else FillTextStyle( psz_attr, psz_val, p_ttml_style->font_style );
|
||||
}
|
||||
|
||||
|
@ -576,27 +589,22 @@ static void DictionaryMerge( const vlc_dictionary_t *p_src, vlc_dictionary_t *p_
|
|||
for ( const vlc_dictionary_entry_t* p_entry = p_src->p_entries[i];
|
||||
p_entry != NULL; p_entry = p_entry->p_next )
|
||||
{
|
||||
if( !strncmp( "tts:", p_entry->psz_key, 4 ) ||
|
||||
!strncmp( "ttp:", p_entry->psz_key, 4 ) ||
|
||||
!strcmp( "xml:space", p_entry->psz_key ) )
|
||||
if( vlc_dictionary_has_key( p_dst, p_entry->psz_key ) )
|
||||
{
|
||||
if( vlc_dictionary_has_key( p_dst, p_entry->psz_key ) )
|
||||
if( b_override )
|
||||
{
|
||||
if( b_override )
|
||||
{
|
||||
vlc_dictionary_remove_value_for_key( p_dst, p_entry->psz_key, NULL, NULL );
|
||||
vlc_dictionary_insert( p_dst, p_entry->psz_key, p_entry->p_value );
|
||||
}
|
||||
}
|
||||
else
|
||||
vlc_dictionary_remove_value_for_key( p_dst, p_entry->psz_key, NULL, NULL );
|
||||
vlc_dictionary_insert( p_dst, p_entry->psz_key, p_entry->p_value );
|
||||
}
|
||||
}
|
||||
else
|
||||
vlc_dictionary_insert( p_dst, p_entry->psz_key, p_entry->p_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DictMergeWithStyleID( ttml_context_t *p_ctx, const char *psz_styles,
|
||||
vlc_dictionary_t *p_dst )
|
||||
static void DictMergeWithStyleID( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const char *psz_styles, vlc_dictionary_t *p_dst )
|
||||
{
|
||||
assert(p_ctx->p_rootnode);
|
||||
char *psz_dup;
|
||||
|
@ -612,8 +620,10 @@ static void DictMergeWithStyleID( ttml_context_t *p_ctx, const char *psz_styles,
|
|||
while( psz_id )
|
||||
{
|
||||
/* Lookup referenced style ID */
|
||||
const tt_node_t *p_node = FindNode( p_ctx->p_rootnode,
|
||||
"style", -1, psz_id );
|
||||
const tt_node_t *p_node = FindNode( p_nss,
|
||||
p_ctx->p_rootnode,
|
||||
"style", TT_NS,
|
||||
-1, psz_id );
|
||||
if( p_node )
|
||||
DictionaryMerge( &p_node->attr_dict, &tempdict, true );
|
||||
|
||||
|
@ -628,23 +638,25 @@ static void DictMergeWithStyleID( ttml_context_t *p_ctx, const char *psz_styles,
|
|||
}
|
||||
}
|
||||
|
||||
static void DictMergeWithRegionID( ttml_context_t *p_ctx, const char *psz_id,
|
||||
vlc_dictionary_t *p_dst )
|
||||
static void DictMergeWithRegionID( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const char *psz_id, vlc_dictionary_t *p_dst )
|
||||
{
|
||||
assert(p_ctx->p_rootnode);
|
||||
if( psz_id && p_ctx->p_rootnode )
|
||||
{
|
||||
const tt_node_t *p_regionnode = FindNode( p_ctx->p_rootnode,
|
||||
"region", -1, psz_id );
|
||||
const tt_node_t *p_regionnode = FindNode( p_nss,
|
||||
p_ctx->p_rootnode,
|
||||
"region", TT_NS,
|
||||
-1, psz_id );
|
||||
if( !p_regionnode )
|
||||
return;
|
||||
|
||||
DictionaryMerge( &p_regionnode->attr_dict, p_dst, false );
|
||||
|
||||
const char *psz_styleid = (const char *)
|
||||
vlc_dictionary_value_for_key( &p_regionnode->attr_dict, "style" );
|
||||
const char *psz_styleid =
|
||||
tt_node_GetAttribute( p_nss, p_regionnode, "style", NULL );
|
||||
if( psz_styleid )
|
||||
DictMergeWithStyleID( p_ctx, psz_styleid, p_dst );
|
||||
DictMergeWithStyleID( p_ctx, p_nss, psz_styleid, p_dst );
|
||||
|
||||
for( const tt_basenode_t *p_child = p_regionnode->p_child;
|
||||
p_child; p_child = p_child->p_next )
|
||||
|
@ -653,7 +665,7 @@ static void DictMergeWithRegionID( ttml_context_t *p_ctx, const char *psz_id,
|
|||
continue;
|
||||
|
||||
const tt_node_t *p_node = (const tt_node_t *) p_child;
|
||||
if( !tt_node_NameCompare( p_node->psz_node_name, "style" ) )
|
||||
if( tt_node_Match( p_node, "style", TT_NS ) )
|
||||
{
|
||||
DictionaryMerge( &p_node->attr_dict, p_dst, false );
|
||||
}
|
||||
|
@ -661,7 +673,8 @@ static void DictMergeWithRegionID( ttml_context_t *p_ctx, const char *psz_id,
|
|||
}
|
||||
}
|
||||
|
||||
static void DictToTTMLStyle( ttml_context_t *p_ctx, const vlc_dictionary_t *p_dict,
|
||||
static void DictToTTMLStyle( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const vlc_dictionary_t *p_dict,
|
||||
ttml_style_t *p_ttml_style )
|
||||
{
|
||||
for( int i = 0; i < p_dict->i_size; ++i )
|
||||
|
@ -669,13 +682,18 @@ static void DictToTTMLStyle( ttml_context_t *p_ctx, const vlc_dictionary_t *p_di
|
|||
for ( vlc_dictionary_entry_t* p_entry = p_dict->p_entries[i];
|
||||
p_entry != NULL; p_entry = p_entry->p_next )
|
||||
{
|
||||
FillTTMLStyle( p_entry->psz_key, p_entry->p_value, p_ttml_style );
|
||||
const char *psz_namespace = tt_namespaces_GetURI( p_nss, p_entry->psz_key );
|
||||
if( !psz_namespace )
|
||||
continue;
|
||||
const char *psz_name = tt_LocalName( p_entry->psz_key );
|
||||
FillTTMLStyle( psz_name, psz_namespace, p_entry->p_value, p_ttml_style );
|
||||
}
|
||||
}
|
||||
ComputeTTMLStyles( p_ctx, p_dict, p_ttml_style );
|
||||
}
|
||||
|
||||
static ttml_style_t * InheritTTMLStyles( ttml_context_t *p_ctx, tt_node_t *p_node )
|
||||
static ttml_style_t * InheritTTMLStyles( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
tt_node_t *p_node )
|
||||
{
|
||||
assert( p_node );
|
||||
ttml_style_t *p_ttml_style = NULL;
|
||||
|
@ -687,20 +705,18 @@ static ttml_style_t * InheritTTMLStyles( ttml_context_t *p_ctx, tt_node_t *p_nod
|
|||
{
|
||||
DictionaryMerge( &p_node->attr_dict, &merged, false );
|
||||
|
||||
const char *psz_styleid = (const char *)
|
||||
vlc_dictionary_value_for_key( &p_node->attr_dict, "style" );
|
||||
const char *psz_styleid = tt_node_GetAttribute( p_nss, p_node, "style", NULL );
|
||||
if( psz_styleid )
|
||||
DictMergeWithStyleID( p_ctx, psz_styleid, &merged );
|
||||
DictMergeWithStyleID( p_ctx, p_nss, psz_styleid, &merged );
|
||||
|
||||
const char *psz_regionid = (const char *)
|
||||
vlc_dictionary_value_for_key( &p_node->attr_dict, "region" );
|
||||
const char *psz_regionid = tt_node_GetAttribute( p_nss, p_node, "region", NULL );
|
||||
if( psz_regionid )
|
||||
DictMergeWithRegionID( p_ctx, psz_regionid, &merged );
|
||||
DictMergeWithRegionID( p_ctx, p_nss, psz_regionid, &merged );
|
||||
}
|
||||
|
||||
if( !vlc_dictionary_is_empty( &merged ) && (p_ttml_style = ttml_style_New()) )
|
||||
{
|
||||
DictToTTMLStyle( p_ctx, &merged, p_ttml_style );
|
||||
DictToTTMLStyle( p_ctx, p_nss, &merged, p_ttml_style );
|
||||
}
|
||||
|
||||
vlc_dictionary_clear( &merged, NULL, NULL );
|
||||
|
@ -708,14 +724,15 @@ static ttml_style_t * InheritTTMLStyles( ttml_context_t *p_ctx, tt_node_t *p_nod
|
|||
return p_ttml_style;
|
||||
}
|
||||
|
||||
static int ParseTTMLChunk( xml_reader_t *p_reader, tt_node_t **pp_rootnode )
|
||||
static int ParseTTMLChunk( xml_reader_t *p_reader, tt_namespaces_t *p_nss,
|
||||
tt_node_t **pp_rootnode )
|
||||
{
|
||||
const char *psz_node_name, *psz_node_namespace;
|
||||
|
||||
do
|
||||
{
|
||||
int i_type = xml_ReaderNextNodeNS( p_reader, &psz_node_name, &psz_node_namespace );
|
||||
fprintf(stderr, "Parse %s %s \n", psz_node_name, psz_node_namespace);
|
||||
|
||||
if( i_type <= XML_READER_NONE )
|
||||
break;
|
||||
|
||||
|
@ -725,20 +742,20 @@ static int ParseTTMLChunk( xml_reader_t *p_reader, tt_node_t **pp_rootnode )
|
|||
break;
|
||||
|
||||
case XML_READER_STARTELEM:
|
||||
if( tt_node_NameCompare( psz_node_name, "tt" ) ||
|
||||
if( strcmp( psz_node_namespace, TT_NS ) ||
|
||||
strcmp( tt_LocalName( psz_node_name ), "tt" ) ||
|
||||
*pp_rootnode != NULL )
|
||||
return VLC_EGENERIC;
|
||||
|
||||
*pp_rootnode = tt_node_NewRead( p_reader, NULL, psz_node_name,
|
||||
psz_node_namespace );
|
||||
*pp_rootnode = tt_node_NewRead( p_reader, p_nss, NULL,
|
||||
psz_node_name, psz_node_namespace );
|
||||
if( !*pp_rootnode ||
|
||||
tt_nodes_Read( p_reader, *pp_rootnode ) != VLC_SUCCESS )
|
||||
tt_nodes_Read( p_reader, p_nss, *pp_rootnode ) != VLC_SUCCESS )
|
||||
return VLC_EGENERIC;
|
||||
break;
|
||||
|
||||
case XML_READER_ENDELEM:
|
||||
if( !*pp_rootnode ||
|
||||
tt_node_NameCompare( psz_node_name, (*pp_rootnode)->psz_node_name ) )
|
||||
strcmp( psz_node_name, (*pp_rootnode)->psz_node_name ) )
|
||||
return VLC_EGENERIC;
|
||||
break;
|
||||
}
|
||||
|
@ -792,7 +809,8 @@ static void StripSpacing( text_segment_t *p_segment )
|
|||
*p = ' ';
|
||||
}
|
||||
|
||||
static ttml_region_t *GetTTMLRegion( ttml_context_t *p_ctx, const char *psz_region_id )
|
||||
static ttml_region_t *GetTTMLRegion( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const char *psz_region_id )
|
||||
{
|
||||
ttml_region_t *p_region = ( ttml_region_t * )
|
||||
vlc_dictionary_value_for_key( &p_ctx->regions, psz_region_id ? psz_region_id : "" );
|
||||
|
@ -805,7 +823,7 @@ static ttml_region_t *GetTTMLRegion( ttml_context_t *p_ctx, const char *psz_regi
|
|||
vlc_dictionary_t merged;
|
||||
vlc_dictionary_init( &merged, 0 );
|
||||
/* Get all attributes, including region > style */
|
||||
DictMergeWithRegionID( p_ctx, psz_region_id, &merged );
|
||||
DictMergeWithRegionID( p_ctx, p_nss, psz_region_id, &merged );
|
||||
if( (p_region = ttml_region_New( false )) )
|
||||
{
|
||||
/* Fill from its own attributes */
|
||||
|
@ -814,8 +832,12 @@ static ttml_region_t *GetTTMLRegion( ttml_context_t *p_ctx, const char *psz_regi
|
|||
for ( vlc_dictionary_entry_t* p_entry = merged.p_entries[i];
|
||||
p_entry != NULL; p_entry = p_entry->p_next )
|
||||
{
|
||||
FillRegionStyle( p_ctx, p_entry->psz_key, p_entry->p_value,
|
||||
p_region );
|
||||
const char *psz_namespace = tt_namespaces_GetURI( p_nss, p_entry->psz_key );
|
||||
if( !psz_namespace )
|
||||
continue;
|
||||
const char *psz_name = tt_LocalName( p_entry->psz_key );
|
||||
FillRegionStyle( p_ctx, psz_name, psz_namespace,
|
||||
p_entry->p_value, p_region );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -841,7 +863,8 @@ static void AppendLineBreakToRegion( ttml_region_t *p_region )
|
|||
}
|
||||
}
|
||||
|
||||
static void AppendTextToRegion( ttml_context_t *p_ctx, const tt_textnode_t *p_ttnode,
|
||||
static void AppendTextToRegion( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const tt_textnode_t *p_ttnode,
|
||||
const ttml_style_t *p_set_styles, ttml_region_t *p_region )
|
||||
{
|
||||
text_segment_t *p_segment;
|
||||
|
@ -853,7 +876,7 @@ static void AppendTextToRegion( ttml_context_t *p_ctx, const tt_textnode_t *p_tt
|
|||
if( p_segment )
|
||||
{
|
||||
bool b_preserve_space = false;
|
||||
ttml_style_t *s = InheritTTMLStyles( p_ctx, p_ttnode->p_parent );
|
||||
ttml_style_t *s = InheritTTMLStyles( p_ctx, p_nss, p_ttnode->p_parent );
|
||||
if( s )
|
||||
{
|
||||
if( p_set_styles )
|
||||
|
@ -900,12 +923,13 @@ static void AppendTextToRegion( ttml_context_t *p_ctx, const tt_textnode_t *p_tt
|
|||
p_region->pp_last_segment = &p_segment->p_next;
|
||||
}
|
||||
|
||||
static const char * GetSMPTEImage( ttml_context_t *p_ctx, const char *psz_id )
|
||||
static const char * GetSMPTEImage( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const char *psz_id )
|
||||
{
|
||||
if( !p_ctx->p_rootnode )
|
||||
return NULL;
|
||||
|
||||
tt_node_t *p_head = FindNode( p_ctx->p_rootnode, "head", 1, NULL );
|
||||
tt_node_t *p_head = FindNode( p_nss, p_ctx->p_rootnode, "head", TT_NS, 1, NULL );
|
||||
if( !p_head )
|
||||
return NULL;
|
||||
|
||||
|
@ -916,10 +940,11 @@ static const char * GetSMPTEImage( ttml_context_t *p_ctx, const char *psz_id )
|
|||
continue;
|
||||
|
||||
tt_node_t *p_node = (tt_node_t *) p_child;
|
||||
if( tt_node_NameCompare( p_node->psz_node_name, "metadata" ) )
|
||||
if( !tt_node_Match( p_node, "metadata", TT_NS ) )
|
||||
continue;
|
||||
|
||||
tt_node_t *p_imagenode = FindNode( p_node, "smpte:image", 1, psz_id );
|
||||
tt_node_t *p_imagenode = FindNode( p_nss, p_node, "image", TT_NS_SMPTE_TT_EXT,
|
||||
1, psz_id );
|
||||
if( !p_imagenode )
|
||||
continue;
|
||||
|
||||
|
@ -936,7 +961,8 @@ static const char * GetSMPTEImage( ttml_context_t *p_ctx, const char *psz_id )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t *p_node,
|
||||
static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, tt_namespaces_t *p_nss,
|
||||
const tt_node_t *p_node,
|
||||
ttml_region_t *p_region,
|
||||
const ttml_style_t *p_upper_set_styles,
|
||||
tt_time_t playbacktime )
|
||||
|
@ -945,34 +971,29 @@ static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t
|
|||
!tt_timings_Contains( &p_node->timings, &playbacktime ) )
|
||||
return;
|
||||
|
||||
const char *psz_regionid = (const char *)
|
||||
vlc_dictionary_value_for_key( &p_node->attr_dict, "region" );
|
||||
const char *psz_regionid = tt_node_GetAttribute( p_nss, p_node, "region", NULL );
|
||||
|
||||
/* Region isn't set or is changing */
|
||||
if( psz_regionid || p_region == NULL )
|
||||
p_region = GetTTMLRegion( p_ctx, psz_regionid );
|
||||
p_region = GetTTMLRegion( p_ctx, p_nss, psz_regionid );
|
||||
|
||||
/* Check for bitmap profile defined by ST2052 / SMPTE-TT */
|
||||
if( !tt_node_NameCompare( p_node->psz_node_name, "div" ) &&
|
||||
vlc_dictionary_has_key( &p_node->attr_dict, "smpte:backgroundImage" ) )
|
||||
if( tt_node_Match( p_node, "div", TT_NS ) )
|
||||
{
|
||||
if( !p_region->bgbitmap.p_bytes )
|
||||
const char *psz_id = tt_node_GetAttribute( p_nss, p_node, "backgroundImage",
|
||||
TT_NS_SMPTE_TT_EXT );
|
||||
if( !p_region->bgbitmap.p_bytes && psz_id && *psz_id == '#' )
|
||||
{
|
||||
const char *psz_id = vlc_dictionary_value_for_key( &p_node->attr_dict,
|
||||
"smpte:backgroundImage" );
|
||||
/* Seems SMPTE can't make diff between html and xml.. */
|
||||
if( psz_id && *psz_id == '#' )
|
||||
{
|
||||
const char *psz_base64 = GetSMPTEImage( p_ctx, &psz_id[1] );
|
||||
if( psz_base64 )
|
||||
p_region->bgbitmap.i_bytes =
|
||||
vlc_b64_decode_binary( &p_region->bgbitmap.p_bytes, psz_base64 );
|
||||
}
|
||||
const char *psz_base64 = GetSMPTEImage( p_ctx, p_nss, &psz_id[1] );
|
||||
if( psz_base64 )
|
||||
p_region->bgbitmap.i_bytes =
|
||||
vlc_b64_decode_binary( &p_region->bgbitmap.p_bytes, psz_base64 );
|
||||
}
|
||||
}
|
||||
|
||||
/* awkward paragraph handling */
|
||||
if( !tt_node_NameCompare( p_node->psz_node_name, "p" ) &&
|
||||
if( tt_node_Match( p_node, "p", TT_NS ) &&
|
||||
p_region->updt.p_segments )
|
||||
{
|
||||
AppendLineBreakToRegion( p_region );
|
||||
|
@ -988,10 +1009,10 @@ static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t
|
|||
{
|
||||
if( p_child->i_type == TT_NODE_TYPE_TEXT )
|
||||
{
|
||||
AppendTextToRegion( p_ctx, (const tt_textnode_t *) p_child,
|
||||
AppendTextToRegion( p_ctx, p_nss, (const tt_textnode_t *) p_child,
|
||||
p_set_styles, p_region );
|
||||
}
|
||||
else if( !tt_node_NameCompare( ((const tt_node_t *)p_child)->psz_node_name, "set" ) )
|
||||
else if( tt_node_Match( (const tt_node_t *)p_child, "set", TT_NS ) )
|
||||
{
|
||||
const tt_node_t *p_set = (const tt_node_t *)p_child;
|
||||
if( !tt_time_Valid( &playbacktime ) ||
|
||||
|
@ -1000,17 +1021,17 @@ static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t
|
|||
if( p_set_styles != NULL || (p_set_styles = ttml_style_New()) )
|
||||
{
|
||||
/* Merge with or create a local set of styles to apply to following childs */
|
||||
DictToTTMLStyle( p_ctx, &p_set->attr_dict, p_set_styles );
|
||||
DictToTTMLStyle( p_ctx, p_nss, &p_set->attr_dict, p_set_styles );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( !tt_node_NameCompare( ((const tt_node_t *)p_child)->psz_node_name, "br" ) )
|
||||
else if( tt_node_Match( (const tt_node_t *)p_child, "br", TT_NS ) )
|
||||
{
|
||||
AppendLineBreakToRegion( p_region );
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertNodesToRegionContent( p_ctx, (const tt_node_t *) p_child,
|
||||
ConvertNodesToRegionContent( p_ctx, p_nss, (const tt_node_t *) p_child,
|
||||
p_region, p_set_styles, playbacktime );
|
||||
}
|
||||
}
|
||||
|
@ -1019,7 +1040,8 @@ static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t
|
|||
ttml_style_Delete( p_set_styles );
|
||||
}
|
||||
|
||||
static tt_node_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, size_t i_buffer )
|
||||
static tt_node_t *ParseTTML( decoder_t *p_dec, tt_namespaces_t *p_nss,
|
||||
const uint8_t *p_buffer, size_t i_buffer )
|
||||
{
|
||||
stream_t* p_sub;
|
||||
xml_reader_t* p_xml_reader;
|
||||
|
@ -1036,7 +1058,7 @@ static tt_node_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, size_t i
|
|||
}
|
||||
|
||||
tt_node_t *p_rootnode = NULL;
|
||||
if( ParseTTMLChunk( p_xml_reader, &p_rootnode ) != VLC_SUCCESS )
|
||||
if( ParseTTMLChunk( p_xml_reader, p_nss, &p_rootnode ) != VLC_SUCCESS )
|
||||
{
|
||||
if( p_rootnode )
|
||||
tt_node_RecursiveDelete( p_rootnode );
|
||||
|
@ -1049,7 +1071,8 @@ static tt_node_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, size_t i
|
|||
return p_rootnode;
|
||||
}
|
||||
|
||||
static void InitTTMLContext( tt_node_t *p_rootnode, ttml_context_t *p_ctx )
|
||||
static void InitTTMLContext( tt_namespaces_t *p_nss, tt_node_t *p_rootnode,
|
||||
ttml_context_t *p_ctx )
|
||||
{
|
||||
p_ctx->p_rootnode = p_rootnode;
|
||||
/* set defaults required for size/cells computation */
|
||||
|
@ -1060,16 +1083,14 @@ static void InitTTMLContext( tt_node_t *p_rootnode, ttml_context_t *p_ctx )
|
|||
p_ctx->i_cell_resolution_v = TTML_DEFAULT_CELL_RESOLUTION_V;
|
||||
p_ctx->i_cell_resolution_h = TTML_DEFAULT_CELL_RESOLUTION_H;
|
||||
/* and override them */
|
||||
const char *value = vlc_dictionary_value_for_key( &p_rootnode->attr_dict,
|
||||
"tts:extent" );
|
||||
if( value != kVLCDictionaryNotFound )
|
||||
const char *value = tt_node_GetAttribute( p_nss, p_rootnode, "extent", TT_NS_STYLING );
|
||||
if( value )
|
||||
{
|
||||
ttml_read_coords( value, &p_ctx->root_extent_h,
|
||||
&p_ctx->root_extent_v );
|
||||
}
|
||||
value = vlc_dictionary_value_for_key( &p_rootnode->attr_dict,
|
||||
"ttp:cellResolution" );
|
||||
if( value != kVLCDictionaryNotFound )
|
||||
value = tt_node_GetAttribute( p_nss, p_rootnode, "cellResolution", TT_NS_PARAMETER );
|
||||
if( value )
|
||||
{
|
||||
unsigned w, h;
|
||||
if( sscanf( value, "%u %u", &w, &h) == 2 && w && h )
|
||||
|
@ -1080,22 +1101,23 @@ static void InitTTMLContext( tt_node_t *p_rootnode, ttml_context_t *p_ctx )
|
|||
}
|
||||
}
|
||||
|
||||
static ttml_region_t *GenerateRegions( tt_node_t *p_rootnode, tt_time_t playbacktime )
|
||||
static ttml_region_t *GenerateRegions( tt_namespaces_t *p_nss, tt_node_t *p_rootnode,
|
||||
tt_time_t playbacktime )
|
||||
{
|
||||
ttml_region_t* p_regions = NULL;
|
||||
ttml_region_t** pp_region_last = &p_regions;
|
||||
|
||||
if( !tt_node_NameCompare( p_rootnode->psz_node_name, "tt" ) )
|
||||
if( tt_node_Match( p_rootnode, "tt", TT_NS ) )
|
||||
{
|
||||
const tt_node_t *p_bodynode = FindNode( p_rootnode, "body", 1, NULL );
|
||||
const tt_node_t *p_bodynode = FindNode( p_nss, p_rootnode, "body", TT_NS, 1, NULL );
|
||||
if( p_bodynode )
|
||||
{
|
||||
ttml_context_t context;
|
||||
InitTTMLContext( p_rootnode, &context );
|
||||
InitTTMLContext( p_nss, p_rootnode, &context );
|
||||
context.p_rootnode = p_rootnode;
|
||||
|
||||
vlc_dictionary_init( &context.regions, 1 );
|
||||
ConvertNodesToRegionContent( &context, p_bodynode, NULL, NULL, playbacktime );
|
||||
ConvertNodesToRegionContent( &context, p_nss, p_bodynode, NULL, NULL, playbacktime );
|
||||
|
||||
for( int i = 0; i < context.regions.i_size; ++i )
|
||||
{
|
||||
|
@ -1110,8 +1132,8 @@ static ttml_region_t *GenerateRegions( tt_node_t *p_rootnode, tt_time_t playback
|
|||
vlc_dictionary_clear( &context.regions, NULL, NULL );
|
||||
}
|
||||
}
|
||||
else if ( !tt_node_NameCompare( p_rootnode->psz_node_name, "div" ) ||
|
||||
!tt_node_NameCompare( p_rootnode->psz_node_name, "p" ) )
|
||||
else if ( tt_node_Match( p_rootnode, "div", TT_NS ) ||
|
||||
tt_node_Match( p_rootnode, "p", TT_NS ) )
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
@ -1315,9 +1337,14 @@ static int ParseBlock( decoder_t *p_dec, const block_t *p_block )
|
|||
return VLCDEC_SUCCESS;
|
||||
}
|
||||
|
||||
tt_node_t *p_rootnode = ParseTTML( p_dec, p_block->p_buffer, p_block->i_buffer );
|
||||
tt_namespaces_t namespaces;
|
||||
tt_namespaces_Init( &namespaces );
|
||||
tt_node_t *p_rootnode = ParseTTML( p_dec, &namespaces, p_block->p_buffer, p_block->i_buffer );
|
||||
if( !p_rootnode )
|
||||
{
|
||||
tt_namespaces_Clean( &namespaces );
|
||||
return VLCDEC_SUCCESS;
|
||||
}
|
||||
|
||||
tt_timings_Resolve( (tt_basenode_t *) p_rootnode, &temporal_extent,
|
||||
&p_timings_array, &i_timings_count );
|
||||
|
@ -1347,7 +1374,7 @@ static int ParseBlock( decoder_t *p_dec, const block_t *p_block )
|
|||
|
||||
bool b_bitmap_regions = false;
|
||||
subpicture_t *p_spu = NULL;
|
||||
ttml_region_t *p_regions = GenerateRegions( p_rootnode, p_timings_array[i] );
|
||||
ttml_region_t *p_regions = GenerateRegions( &namespaces, p_rootnode, p_timings_array[i] );
|
||||
if( p_regions )
|
||||
{
|
||||
if( p_regions->bgbitmap.i_bytes > 0 && p_regions->updt.p_segments == NULL )
|
||||
|
@ -1389,6 +1416,7 @@ static int ParseBlock( decoder_t *p_dec, const block_t *p_block )
|
|||
}
|
||||
|
||||
tt_node_RecursiveDelete( p_rootnode );
|
||||
tt_namespaces_Clean( &namespaces );
|
||||
|
||||
free( p_timings_array );
|
||||
|
||||
|
|
|
@ -177,11 +177,22 @@ bool tt_node_Match( const tt_node_t *p_node, const char *psz_name, const char *p
|
|||
return !!psz_namespace == !!psz_nodens;
|
||||
}
|
||||
|
||||
int tt_node_NameCompare( const char* psz_tagname, const char* psz_pattern )
|
||||
const char * tt_node_GetAttribute( tt_namespaces_t *p_nss, const tt_node_t *p_node,
|
||||
const char *psz_name, const char *psz_namespace )
|
||||
{
|
||||
if( !strncasecmp( "tt:", psz_tagname, 3 ) )
|
||||
psz_tagname += 3;
|
||||
return strcasecmp( psz_tagname, psz_pattern );
|
||||
const void *value;
|
||||
char *alloc = NULL;
|
||||
if( psz_namespace )
|
||||
{
|
||||
const char *psz_prefix = tt_namespaces_GetPrefix( p_nss, psz_namespace );
|
||||
if( psz_prefix == NULL ||
|
||||
asprintf( &alloc, "%s:%s", psz_prefix, psz_name ) < 1 )
|
||||
return NULL;
|
||||
psz_name = alloc;
|
||||
}
|
||||
value = vlc_dictionary_value_for_key( &p_node->attr_dict, psz_name );
|
||||
free( alloc );
|
||||
return value != kVLCDictionaryNotFound ? (const char *)value : NULL;
|
||||
}
|
||||
|
||||
bool tt_node_HasChild( const tt_node_t *p_node )
|
||||
|
@ -385,7 +396,8 @@ tt_node_t * tt_node_New( tt_node_t* p_parent,
|
|||
return p_node;
|
||||
}
|
||||
|
||||
tt_node_t * tt_node_NewRead( xml_reader_t* reader, tt_node_t* p_parent,
|
||||
tt_node_t * tt_node_NewRead( xml_reader_t* reader,
|
||||
tt_namespaces_t *p_nss, tt_node_t* p_parent,
|
||||
const char* psz_node_name, const char *psz_namespace )
|
||||
{
|
||||
tt_node_t *p_node = tt_node_New( p_parent, psz_node_name, psz_namespace );
|
||||
|
@ -397,7 +409,8 @@ tt_node_t * tt_node_NewRead( xml_reader_t* reader, tt_node_t* p_parent,
|
|||
psz_key != NULL;
|
||||
psz_key = xml_ReaderNextAttrNS( reader, &psz_value, &psz_ns ) )
|
||||
{
|
||||
fprintf(stderr,"ATTR %s %s %s\n", psz_key, psz_value, psz_ns);
|
||||
if( psz_ns && psz_key )
|
||||
tt_namespaces_Register( p_nss, psz_key, psz_ns );
|
||||
char *psz_val = strdup( psz_value );
|
||||
if( psz_val )
|
||||
{
|
||||
|
@ -474,7 +487,7 @@ static int tt_node_Skip( xml_reader_t *p_reader, const char *psz_skipped )
|
|||
return VLC_EGENERIC;
|
||||
}
|
||||
#endif
|
||||
int tt_nodes_Read( xml_reader_t *p_reader, tt_node_t *p_root_node )
|
||||
int tt_nodes_Read( xml_reader_t *p_reader, tt_namespaces_t *p_nss, tt_node_t *p_root_node )
|
||||
{
|
||||
size_t i_depth = 0;
|
||||
tt_node_t *p_node = p_root_node;
|
||||
|
@ -496,7 +509,9 @@ int tt_nodes_Read( xml_reader_t *p_reader, tt_node_t *p_root_node )
|
|||
|
||||
case XML_READER_STARTELEM:
|
||||
{
|
||||
tt_node_t *p_newnode = tt_node_NewRead( p_reader, p_node, psz_node_name,
|
||||
tt_namespaces_Register( p_nss, psz_node_name, psz_node_namespace );
|
||||
tt_node_t *p_newnode = tt_node_NewRead( p_reader, p_nss, p_node,
|
||||
psz_node_name,
|
||||
psz_node_namespace );
|
||||
if( !p_newnode )
|
||||
return VLC_EGENERIC;
|
||||
|
@ -517,7 +532,7 @@ int tt_nodes_Read( xml_reader_t *p_reader, tt_node_t *p_root_node )
|
|||
|
||||
case XML_READER_ENDELEM:
|
||||
{
|
||||
if( strcmp( psz_node_name, p_node->psz_node_name ) )
|
||||
if( !tt_node_Match( p_node, psz_node_name, psz_node_namespace ) )
|
||||
return VLC_EGENERIC;
|
||||
|
||||
if( i_depth == 0 )
|
||||
|
|
|
@ -129,16 +129,17 @@ static inline const char *tt_LocalName( const char *psz_qname )
|
|||
tt_textnode_t *tt_textnode_New( tt_node_t *p_parent, const char *psz_text );
|
||||
tt_textnode_t *tt_subtextnode_New( tt_node_t *p_parent, const char *psz_text, size_t );
|
||||
tt_node_t * tt_node_New( tt_node_t* p_parent, const char* psz_node_name, const char *psz_namespace );
|
||||
tt_node_t * tt_node_NewRead( xml_reader_t* reader, tt_node_t* p_parent, const char* psz_node_name,
|
||||
const char *psz_namespace );
|
||||
tt_node_t * tt_node_NewRead( xml_reader_t* reader, tt_namespaces_t *, tt_node_t* p_parent,
|
||||
const char* psz_node_name, const char *psz_namespace );
|
||||
void tt_node_RecursiveDelete( tt_node_t *p_node );
|
||||
bool tt_node_Match( const tt_node_t *p_node, const char* psz_name, const char* psz_namespace );
|
||||
int tt_node_NameCompare( const char* psz_tagname, const char* psz_pattern );
|
||||
const char * tt_node_GetAttribute( tt_namespaces_t *, const tt_node_t *p_node,
|
||||
const char *psz_name, const char *psz_namespace );
|
||||
bool tt_node_HasChild( const tt_node_t *p_node );
|
||||
int tt_node_AddAttribute( tt_node_t *p_node, const char *key, const char *value );
|
||||
void tt_node_RemoveAttribute( tt_node_t *p_node, const char *key );
|
||||
|
||||
int tt_nodes_Read( xml_reader_t *p_reader, tt_node_t *p_root_node );
|
||||
int tt_nodes_Read( xml_reader_t *p_reader, tt_namespaces_t *, tt_node_t *p_root_node );
|
||||
|
||||
void tt_timings_Resolve( tt_basenode_t *p_child, const tt_timings_t *p_container_timings,
|
||||
tt_time_t **pp_array, size_t *pi_count );
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef struct
|
|||
bool b_first_time;
|
||||
|
||||
tt_node_t *p_rootnode;
|
||||
tt_namespaces_t namespaces;
|
||||
|
||||
tt_timings_t temporal_extent;
|
||||
|
||||
|
@ -157,11 +158,11 @@ static int Control( demux_t* p_demux, int i_query, va_list args )
|
|||
static int ReadTTML( demux_t* p_demux )
|
||||
{
|
||||
demux_sys_t* p_sys = p_demux->p_sys;
|
||||
const char* psz_node_name, *psz_namespace;
|
||||
const char* psz_node_name, *psz_node_namespace;
|
||||
|
||||
do
|
||||
{
|
||||
int i_type = xml_ReaderNextNodeNS( p_sys->p_reader, &psz_node_name, &psz_namespace );
|
||||
int i_type = xml_ReaderNextNodeNS( p_sys->p_reader, &psz_node_name, &psz_node_namespace );
|
||||
bool b_empty = xml_ReaderIsEmptyElement( p_sys->p_reader );
|
||||
|
||||
if( i_type <= XML_READER_NONE )
|
||||
|
@ -173,22 +174,25 @@ static int ReadTTML( demux_t* p_demux )
|
|||
break;
|
||||
|
||||
case XML_READER_STARTELEM:
|
||||
if( tt_node_NameCompare( psz_node_name, "tt" ) ||
|
||||
if( strcmp( psz_node_namespace, TT_NS ) ||
|
||||
strcmp( tt_LocalName( psz_node_name ), "tt" ) ||
|
||||
p_sys->p_rootnode != NULL )
|
||||
return VLC_EGENERIC;
|
||||
|
||||
p_sys->p_rootnode = tt_node_NewRead( p_sys->p_reader, NULL, psz_node_name,
|
||||
psz_namespace );
|
||||
p_sys->p_rootnode = tt_node_NewRead( p_sys->p_reader, &p_sys->namespaces, NULL,
|
||||
psz_node_name,
|
||||
psz_node_namespace );
|
||||
if( b_empty )
|
||||
break;
|
||||
if( !p_sys->p_rootnode ||
|
||||
tt_nodes_Read( p_sys->p_reader, p_sys->p_rootnode ) != VLC_SUCCESS )
|
||||
tt_nodes_Read( p_sys->p_reader,
|
||||
&p_sys->namespaces, p_sys->p_rootnode ) != VLC_SUCCESS )
|
||||
return VLC_EGENERIC;
|
||||
break;
|
||||
|
||||
case XML_READER_ENDELEM:
|
||||
if( !p_sys->p_rootnode ||
|
||||
tt_node_NameCompare( psz_node_name, p_sys->p_rootnode->psz_node_name ) )
|
||||
strcmp( psz_node_name, p_sys->p_rootnode->psz_node_name ) )
|
||||
return VLC_EGENERIC;
|
||||
break;
|
||||
}
|
||||
|
@ -342,6 +346,7 @@ int tt_OpenDemux( vlc_object_t* p_this )
|
|||
tt_time_Init( &p_sys->temporal_extent.end );
|
||||
tt_time_Init( &p_sys->temporal_extent.dur );
|
||||
p_sys->temporal_extent.begin.base = 0;
|
||||
tt_namespaces_Init( &p_sys->namespaces );
|
||||
|
||||
p_sys->p_xml = xml_Create( p_demux );
|
||||
if( !p_sys->p_xml )
|
||||
|
@ -419,6 +424,8 @@ void tt_CloseDemux( vlc_object_t* p_this )
|
|||
if( p_sys->p_xml )
|
||||
xml_Delete( p_sys->p_xml );
|
||||
|
||||
tt_namespaces_Clean( &p_sys->namespaces );
|
||||
|
||||
free( p_sys->times.p_array );
|
||||
|
||||
free( p_sys );
|
||||
|
|
Loading…
Reference in New Issue