[vlc-commits] codec: ttml: generate multiple subpictures
Francois Cartegnie
git at videolan.org
Mon Jan 23 10:27:36 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Jan 23 10:25:12 2017 +0100| [5b9e7009653f58373c999ea57ee34256f8492110] | committer: Francois Cartegnie
codec: ttml: generate multiple subpictures
'demuxes' the multiple timings
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=5b9e7009653f58373c999ea57ee34256f8492110
---
modules/codec/ttml/substtml.c | 158 +++++++++++++++++++++++++++---------------
1 file changed, 104 insertions(+), 54 deletions(-)
diff --git a/modules/codec/ttml/substtml.c b/modules/codec/ttml/substtml.c
index 984f88d..e50bdc0 100644
--- a/modules/codec/ttml/substtml.c
+++ b/modules/codec/ttml/substtml.c
@@ -75,7 +75,7 @@ enum
UNICODE_BIDI_OVERRIDE = 4,
};
-static ttml_region_t *ParseTTML( decoder_t *, const uint8_t *, size_t );
+static tt_node_t *ParseTTML( decoder_t *, const uint8_t *, size_t );
static void ttml_style_Delete( ttml_style_t* p_ttml_style )
{
@@ -591,8 +591,12 @@ static void AppendTextToRegion( ttml_context_t *p_ctx, const tt_textnode_t *p_tt
}
static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t *p_node,
- ttml_region_t *p_region )
+ ttml_region_t *p_region, int64_t i_playbacktime )
{
+ if( i_playbacktime != -1 &&
+ !tt_timings_Contains( &p_node->timings, i_playbacktime ) )
+ return;
+
const char *psz_regionid = (const char *)
vlc_dictionary_value_for_key( &p_node->attr_dict, "region" );
@@ -620,17 +624,16 @@ static void ConvertNodesToRegionContent( ttml_context_t *p_ctx, const tt_node_t
}
else
{
- ConvertNodesToRegionContent( p_ctx, (const tt_node_t *) p_child, p_region );
+ ConvertNodesToRegionContent( p_ctx, (const tt_node_t *) p_child,
+ p_region, i_playbacktime );
}
}
}
-static ttml_region_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, size_t i_buffer )
+static tt_node_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, size_t i_buffer )
{
- stream_t* p_sub = NULL;
- xml_reader_t* p_xml_reader = NULL;
- ttml_region_t* p_regions = NULL;
- ttml_region_t** pp_region_last = &p_regions;
+ stream_t* p_sub;
+ xml_reader_t* p_xml_reader;
p_sub = vlc_stream_MemoryNew( p_dec, (uint8_t*) p_buffer, i_buffer, true );
if( unlikely( p_sub == NULL ) )
@@ -648,9 +651,20 @@ static ttml_region_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, siz
{
if( p_rootnode )
tt_node_RecursiveDelete( p_rootnode );
- goto end;
+ p_rootnode = NULL;
}
+ xml_ReaderDelete( p_xml_reader );
+ vlc_stream_Delete( p_sub );
+
+ return p_rootnode;
+}
+
+static ttml_region_t *GenerateRegions( tt_node_t *p_rootnode, int64_t i_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" ) )
{
const tt_node_t *p_bodynode = FindNode( p_rootnode, "body", 1, NULL );
@@ -659,7 +673,7 @@ static ttml_region_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, siz
ttml_context_t context;
context.p_rootnode = p_rootnode;
vlc_dictionary_init( &context.regions, 1 );
- ConvertNodesToRegionContent( &context, p_bodynode, NULL );
+ ConvertNodesToRegionContent( &context, p_bodynode, NULL, i_playbacktime );
for( int i = 0; i < context.regions.i_size; ++i )
{
@@ -680,18 +694,22 @@ static ttml_region_t *ParseTTML( decoder_t *p_dec, const uint8_t *p_buffer, siz
/* TODO */
}
- tt_node_RecursiveDelete( p_rootnode );
-
-end:
- xml_ReaderDelete( p_xml_reader );
- vlc_stream_Delete( p_sub );
-
return p_regions;
}
static subpicture_t *ParseBlock( decoder_t *p_dec, const block_t *p_block )
{
- subpicture_t *p_spu = NULL;
+ subpicture_t *p_spus_head = NULL;
+ subpicture_t **pp_spus_tail = &p_spus_head;
+
+ int64_t *p_timings_array = NULL;
+ size_t i_timings_count = 0;
+
+ tt_timings_t temporal_extent;
+ temporal_extent.i_type = TT_TIMINGS_PARALLEL;
+ temporal_extent.i_begin = -1;
+ temporal_extent.i_end = -1;
+ temporal_extent.i_dur = -1;
if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
return NULL;
@@ -703,58 +721,90 @@ static subpicture_t *ParseBlock( decoder_t *p_dec, const block_t *p_block )
return NULL;
}
- ttml_region_t *p_regions = ParseTTML( p_dec, p_block->p_buffer, p_block->i_buffer );
- if( p_regions && ( p_spu = decoder_NewSubpictureText( p_dec ) ) )
- {
- p_spu->i_start = p_block->i_pts;
- p_spu->i_stop = p_block->i_pts + p_block->i_length;
- p_spu->b_ephemer = (p_block->i_length == 0);
- p_spu->b_absolute = false;
+ tt_node_t *p_rootnode = ParseTTML( p_dec, p_block->p_buffer, p_block->i_buffer );
+ if( !p_rootnode )
+ return NULL;
+
+ tt_timings_Resolve( (tt_basenode_t *) p_rootnode, &temporal_extent,
+ &p_timings_array, &i_timings_count );
- subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
- subpicture_updater_sys_region_t *p_updtregion = NULL;
+ for( size_t i=0; i<i_timings_count; i++ )
+ printf("%ld ", p_timings_array[i]);
+ printf("\n");
- /* Create region update info from each ttml region */
- for( ttml_region_t *p_region = p_regions;
- p_region; p_region = (ttml_region_t *) p_region->updt.p_next )
+ for( size_t i=0; i+1 < i_timings_count; i++ )
+ {
+ subpicture_t *p_spu = NULL;
+ ttml_region_t *p_regions = GenerateRegions( p_rootnode, p_timings_array[i] );
+ if( p_regions && ( p_spu = decoder_NewSubpictureText( p_dec ) ) )
{
- if( p_updtregion == NULL )
+ p_spu->i_start = VLC_TS_0 + p_timings_array[i];
+ p_spu->i_stop = VLC_TS_0 + p_timings_array[i+1] - 1;
+ p_spu->b_ephemer = false;
+ p_spu->b_absolute = false;
+
+ mtime_t i_reftime = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;
+ if( p_spu->i_start < i_reftime - VLC_TS_0 ) /* relative timings have been sent */
{
- p_updtregion = &p_spu_sys->region;
+ p_spu->i_start += i_reftime - VLC_TS_0;
+ p_spu->i_stop += i_reftime - VLC_TS_0;
}
- else
+
+ subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
+ subpicture_updater_sys_region_t *p_updtregion = NULL;
+
+ /* Create region update info from each ttml region */
+ for( ttml_region_t *p_region = p_regions;
+ p_region; p_region = (ttml_region_t *) p_region->updt.p_next )
{
- p_updtregion = SubpictureUpdaterSysRegionNew();
if( p_updtregion == NULL )
- break;
- SubpictureUpdaterSysRegionAdd( &p_spu_sys->region, p_updtregion );
- }
+ {
+ p_updtregion = &p_spu_sys->region;
+ }
+ else
+ {
+ p_updtregion = SubpictureUpdaterSysRegionNew();
+ if( p_updtregion == NULL )
+ break;
+ SubpictureUpdaterSysRegionAdd( &p_spu_sys->region, p_updtregion );
+ }
- /* broken legacy align var (can't handle center...) */
- if( p_dec->p_sys->i_align & SUBPICTURE_ALIGN_MASK )
- {
- p_spu_sys->region.align = p_dec->p_sys->i_align & (SUBPICTURE_ALIGN_BOTTOM|SUBPICTURE_ALIGN_TOP);
- p_spu_sys->region.inner_align = p_dec->p_sys->i_align & (SUBPICTURE_ALIGN_LEFT|SUBPICTURE_ALIGN_RIGHT);
+ /* broken legacy align var (can't handle center...) */
+ if( p_dec->p_sys->i_align & SUBPICTURE_ALIGN_MASK )
+ {
+ p_spu_sys->region.align = p_dec->p_sys->i_align & (SUBPICTURE_ALIGN_BOTTOM|SUBPICTURE_ALIGN_TOP);
+ p_spu_sys->region.inner_align = p_dec->p_sys->i_align & (SUBPICTURE_ALIGN_LEFT|SUBPICTURE_ALIGN_RIGHT);
+ }
+
+ /* copy and take ownership of pointeds */
+ *p_updtregion = p_region->updt;
+ p_updtregion->p_next = NULL;
+ p_region->updt.p_region_style = NULL;
+ p_region->updt.p_segments = NULL;
}
- /* copy and take ownership of pointeds */
- *p_updtregion = p_region->updt;
- p_updtregion->p_next = NULL;
- p_region->updt.p_region_style = NULL;
- p_region->updt.p_segments = NULL;
}
- }
+ /* cleanup */
+ while( p_regions )
+ {
+ ttml_region_t *p_nextregion = (ttml_region_t *) p_regions->updt.p_next;
+ ttml_region_Delete( p_regions );
+ p_regions = p_nextregion;
+ }
- /* cleanup */
- while( p_regions )
- {
- ttml_region_t *p_nextregion = (ttml_region_t *) p_regions->updt.p_next;
- ttml_region_Delete( p_regions );
- p_regions = p_nextregion;
+ if( p_spu )
+ {
+ *pp_spus_tail = p_spu;
+ pp_spus_tail = &p_spu->p_next;
+ }
}
- return p_spu;
+ tt_node_RecursiveDelete( p_rootnode );
+
+ free( p_timings_array );
+
+ return p_spus_head;
}
More information about the vlc-commits
mailing list