/src/vlc/modules/codec/ttml/ttmlpes.h
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * ttmlpes.c : TTML subtitles in EN 303 560 payload |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2018 VideoLabs, VLC authors and VideoLAN |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify it |
7 | | * under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation; either version 2.1 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with this program; if not, write to the Free Software Foundation, |
18 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
19 | | *****************************************************************************/ |
20 | | |
21 | | #include <vlc_common.h> |
22 | | #include <vlc_block.h> |
23 | | #include <vlc_stream.h> |
24 | | |
25 | | enum |
26 | | { |
27 | | TTML_UNCOMPRESSED_DOCUMENT = 0x01, |
28 | | TTML_GZIP_COMPRESSED_DOCUMENT = 0x02, |
29 | | }; |
30 | | |
31 | | struct ttml_in_pes_ctx |
32 | | { |
33 | | vlc_tick_t i_offset; /* relative segment offset to apply */ |
34 | | vlc_tick_t i_prev_block_time; /* because blocks are duplicated */ |
35 | | vlc_tick_t i_prev_segment_start_time; /* because content can overlap */ |
36 | | }; |
37 | | |
38 | | static void ttml_in_pes_Init(struct ttml_in_pes_ctx *p) |
39 | 0 | { |
40 | 0 | p->i_offset = 0; |
41 | 0 | p->i_prev_block_time = -1; |
42 | 0 | p->i_prev_segment_start_time = -1; |
43 | 0 | } |
44 | | |
45 | | static inline bool TTML_in_PES(decoder_t *p_dec) |
46 | 0 | { |
47 | 0 | return p_dec->fmt_in->i_codec == VLC_CODEC_TTML_TS; |
48 | 0 | } |
49 | | |
50 | | static block_t * DecompressTTML( decoder_t *p_dec, const uint8_t *p_data, size_t i_data ) |
51 | 0 | { |
52 | 0 | block_t *p_decomp = NULL; |
53 | 0 | block_t **pp_append = &p_decomp; |
54 | |
|
55 | 0 | stream_t *s = vlc_stream_MemoryNew( p_dec, (uint8_t *) p_data, i_data, true ); |
56 | 0 | if( !s ) |
57 | 0 | return NULL; |
58 | 0 | stream_t *p_inflate = vlc_stream_FilterNew( s, "inflate" ); |
59 | 0 | if( p_inflate ) |
60 | 0 | { |
61 | 0 | for( ;; ) |
62 | 0 | { |
63 | 0 | *pp_append = vlc_stream_Block( p_inflate, 64 * 1024 ); |
64 | 0 | if( *pp_append == NULL || |
65 | 0 | (*pp_append)->i_buffer < 64*1024 ) |
66 | 0 | break; |
67 | 0 | pp_append = &((*pp_append)->p_next); |
68 | 0 | } |
69 | 0 | s = p_inflate; |
70 | 0 | } |
71 | 0 | vlc_stream_Delete( s ); |
72 | 0 | return p_decomp ? block_ChainGather( p_decomp ) : NULL; |
73 | 0 | } |
74 | | |
75 | | static int ParsePESEncap( decoder_t *p_dec, |
76 | | struct ttml_in_pes_ctx *p_ctx, |
77 | | int(*pf_decode)(decoder_t *, block_t *), |
78 | | block_t *p_block ) |
79 | 0 | { |
80 | 0 | if( p_block == NULL ) /* No Drain */ |
81 | 0 | return VLCDEC_SUCCESS; |
82 | | |
83 | 0 | if( p_block->i_buffer < 7 ) |
84 | 0 | { |
85 | 0 | block_Release( p_block ); |
86 | 0 | return VLC_EGENERIC; |
87 | 0 | } |
88 | | |
89 | 0 | if( p_block->i_dts == p_ctx->i_prev_block_time ) |
90 | 0 | { |
91 | 0 | block_Release( p_block ); |
92 | 0 | return VLC_SUCCESS; |
93 | 0 | } |
94 | | |
95 | 0 | int64_t i_segment_base = GetDWBE(p_block->p_buffer); |
96 | 0 | i_segment_base = (i_segment_base << 16) | GetWBE(&p_block->p_buffer[4]); |
97 | 0 | i_segment_base *= 100; |
98 | 0 | uint8_t i_num_segments = p_block->p_buffer[6]; |
99 | 0 | size_t i_data = p_block->i_buffer - 7; |
100 | 0 | const uint8_t *p_data = &p_block->p_buffer[7]; |
101 | 0 | p_ctx->i_offset = (p_block->i_dts - VLC_TICK_0) - i_segment_base; |
102 | 0 | for( uint8_t i=0; i<i_num_segments; i++ ) |
103 | 0 | { |
104 | 0 | if( i_data < 3 ) |
105 | 0 | break; |
106 | 0 | uint8_t i_type = p_data[0]; |
107 | 0 | uint16_t i_size = GetWBE(&p_data[1]); |
108 | 0 | if( i_size > i_data - 3 ) |
109 | 0 | break; |
110 | 0 | block_t *p_segment = NULL; |
111 | 0 | if( i_type == TTML_UNCOMPRESSED_DOCUMENT ) |
112 | 0 | { |
113 | 0 | p_segment = block_Alloc( i_size ); |
114 | 0 | if( p_segment ) |
115 | 0 | memcpy( p_segment->p_buffer, &p_data[3], i_size ); |
116 | 0 | } |
117 | 0 | else if( i_type == TTML_GZIP_COMPRESSED_DOCUMENT ) |
118 | 0 | { |
119 | 0 | p_segment = DecompressTTML( p_dec, &p_data[3], i_size ); |
120 | 0 | } |
121 | |
|
122 | 0 | if( p_segment ) |
123 | 0 | { |
124 | 0 | block_CopyProperties( p_segment, p_block ); |
125 | 0 | pf_decode( p_dec, p_segment ); |
126 | 0 | } |
127 | |
|
128 | 0 | p_data += 3 + i_size; |
129 | 0 | i_data -= 3 + i_size; |
130 | 0 | } |
131 | |
|
132 | 0 | p_ctx->i_prev_block_time = p_block->i_dts; |
133 | 0 | block_Release( p_block ); |
134 | 0 | return VLC_SUCCESS; |
135 | 0 | } |