/*****************************************************************************
* ttmlpes.c : TTML subtitles in EN 303 560 payload
*****************************************************************************
* Copyright (C) 2018 VideoLabs, VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <vlc_common.h>
#include <vlc_block.h>
#include <vlc_stream.h>
enum
{
TTML_UNCOMPRESSED_DOCUMENT = 0x01,
TTML_GZIP_COMPRESSED_DOCUMENT = 0x02,
};
struct ttml_in_pes_ctx
{
vlc_tick_t i_offset; /* relative segment offset to apply */
vlc_tick_t i_prev_block_time; /* because blocks are duplicated */
vlc_tick_t i_prev_segment_start_time; /* because content can overlap */
};
static void ttml_in_pes_Init(struct ttml_in_pes_ctx *p)
{
p->i_offset = 0;
p->i_prev_block_time = -1;
p->i_prev_segment_start_time = -1;
}
static inline bool TTML_in_PES(decoder_t *p_dec)
{
return p_dec->fmt_in->i_codec == VLC_CODEC_TTML_TS;
}
static block_t * DecompressTTML( decoder_t *p_dec, const uint8_t *p_data, size_t i_data )
{
block_t *p_decomp = NULL;
block_t **pp_append = &p_decomp;
stream_t *s = vlc_stream_MemoryNew( p_dec, (uint8_t *) p_data, i_data, true );
if( !s )
return NULL;
stream_t *p_inflate = vlc_stream_FilterNew( s, "inflate" );
if( p_inflate )
{
for( ;; )
{
*pp_append = vlc_stream_Block( p_inflate, 64 * 1024 );
if( *pp_append == NULL ||
(*pp_append)->i_buffer < 64*1024 )
break;
pp_append = &((*pp_append)->p_next);
}
s = p_inflate;
}
vlc_stream_Delete( s );
return p_decomp ? block_ChainGather( p_decomp ) : NULL;
}
static int ParsePESEncap( decoder_t *p_dec,
struct ttml_in_pes_ctx *p_ctx,
int(*pf_decode)(decoder_t *, block_t *),
block_t *p_block )
{
if( p_block == NULL ) /* No Drain */
return VLCDEC_SUCCESS;
if( p_block->i_buffer < 7 )
{
block_Release( p_block );
return VLC_EGENERIC;
}
if( p_block->i_dts == p_ctx->i_prev_block_time )
{
block_Release( p_block );
return VLC_SUCCESS;
}
int64_t i_segment_base = GetDWBE(p_block->p_buffer);
i_segment_base = (i_segment_base << 16) | GetWBE(&p_block->p_buffer[4]);
i_segment_base *= 100;
uint8_t i_num_segments = p_block->p_buffer[6];
size_t i_data = p_block->i_buffer - 7;
const uint8_t *p_data = &p_block->p_buffer[7];
p_ctx->i_offset = (p_block->i_dts - VLC_TICK_0) - i_segment_base;
for( uint8_t i=0; i<i_num_segments; i++ )
{
if( i_data < 3 )
break;
uint8_t i_type = p_data[0];
uint16_t i_size = GetWBE(&p_data[1]);
if( i_size > i_data - 3 )
break;
block_t *p_segment = NULL;
if( i_type == TTML_UNCOMPRESSED_DOCUMENT )
{
p_segment = block_Alloc( i_size );
if( p_segment )
memcpy( p_segment->p_buffer, &p_data[3], i_size );
}
else if( i_type == TTML_GZIP_COMPRESSED_DOCUMENT )
{
p_segment = DecompressTTML( p_dec, &p_data[3], i_size );
}
if( p_segment )
{
block_CopyProperties( p_segment, p_block );
pf_decode( p_dec, p_segment );
}
p_data += 3 + i_size;
i_data -= 3 + i_size;
}
p_ctx->i_prev_block_time = p_block->i_dts;
block_Release( p_block );
return VLC_SUCCESS;
}
¤ Dauer der Verarbeitung: 0.3 Sekunden
¤
*© Formatika GbR, Deutschland