codec: ass: Don't force fonts that aren't shipped anymore in the winstore app
[vlc.git] / modules / codec / cc.h
blob6f8b6c48cab7357ecbce31f085e18281da565ad6
1 /*****************************************************************************
2 * cc.h
3 *****************************************************************************
4 * Copyright (C) 2007 Laurent Aimar
5 * $Id$
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifndef VLC_CC_H_
25 #define VLC_CC_H_
27 #include <vlc_bits.h>
29 #define BLOCK_FLAG_ORDERED_CAPTIONS (0x01 << BLOCK_FLAG_PRIVATE_SHIFT)
31 #define CC_PKT_BYTE0(field) (0xFC | (0x03 & field))
33 /* CC have a maximum rate of 9600 bit/s (per field?) */
34 #define CC_MAX_DATA_SIZE (2 * 3*600)
35 enum cc_payload_type_e
37 CC_PAYLOAD_NONE,
38 CC_PAYLOAD_GA94,
39 CC_PAYLOAD_DVD,
40 CC_PAYLOAD_REPLAYTV,
41 CC_PAYLOAD_SCTE20,
43 typedef struct
45 /* Which channel are present */
46 bool pb_present[4];
48 /* */
49 bool b_reorder;
51 /* */
52 enum cc_payload_type_e i_payload_type;
53 int i_payload_other_count;
55 /* CC data per field
56 * byte[x+0]: field (0/1)
57 * byte[x+1]: cc data 1
58 * byte[x+2]: cc data 2
60 int i_data;
61 uint8_t p_data[CC_MAX_DATA_SIZE];
62 } cc_data_t;
64 static inline void cc_Init( cc_data_t *c )
66 int i;
68 for( i = 0; i < 4; i++ )
69 c-> pb_present[i] = false;
70 c->i_data = 0;
71 c->b_reorder = false;
72 c->i_payload_type = CC_PAYLOAD_NONE;
73 c->i_payload_other_count = 0;
75 static inline void cc_Exit( cc_data_t *c )
77 VLC_UNUSED(c);
78 return;
80 static inline void cc_Flush( cc_data_t *c )
82 c->i_data = 0;
85 static inline void cc_AppendData( cc_data_t *c, uint8_t cc_preamble, const uint8_t cc[2] )
87 uint8_t i_field = cc_preamble & 0x03;
88 if( i_field == 0 || i_field == 1 )
90 c->pb_present[2*i_field+0] =
91 c->pb_present[2*i_field+1] = true;
94 c->p_data[c->i_data++] = cc_preamble;
95 c->p_data[c->i_data++] = cc[0];
96 c->p_data[c->i_data++] = cc[1];
99 static inline void cc_Extract( cc_data_t *c, enum cc_payload_type_e i_payload_type,
100 bool b_top_field_first, const uint8_t *p_src, int i_src )
102 if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type )
104 c->i_payload_other_count++;
105 if( c->i_payload_other_count < 50 )
106 return;
108 c->i_payload_type = i_payload_type;
109 c->i_payload_other_count = 0;
111 if( i_payload_type == CC_PAYLOAD_GA94 )
113 /* cc_data()
114 * u1 reserved(1)
115 * u1 process_cc_data_flag
116 * u1 additional_data_flag
117 * u5 cc_count
118 * u8 reserved(1111 1111)
119 * for cc_count
120 * u5 marker bit(1111 1)
121 * u1 cc_valid
122 * u2 cc_type
123 * u8 cc_data_1
124 * u8 cc_data_2
125 * u8 marker bit(1111 1111)
126 * if additional_data_flag
127 * unknown
129 /* cc_type:
130 * 0x00: field 1
131 * 0x01: field 2
133 const uint8_t *cc = &p_src[0];
134 const int i_count_cc = cc[0]&0x1f;
135 int i;
137 if( !(cc[0]&0x40) ) // process flag
138 return;
139 if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet
140 return;
141 if( i_count_cc <= 0 ) // no cc present
142 return;
143 if( cc[2+i_count_cc * 3] != 0xff ) // marker absent
144 return;
145 cc += 2;
147 for( i = 0; i < i_count_cc; i++, cc += 3 )
149 if( c->i_data + 3 > CC_MAX_DATA_SIZE )
150 break;
152 cc_AppendData( c, cc[0], &cc[1] );
154 c->b_reorder = true;
156 else if( i_payload_type == CC_PAYLOAD_DVD )
158 /* user_data
159 * (u32 stripped earlier)
160 * u32 (0x43 0x43 0x01 0xf8)
161 * u1 caption_odd_field_first (CC1/CC2)
162 * u1 caption_filler
163 * u5 cc_block_count (== cc_count / 2)
164 * u1 caption_extra_field_added (because odd cc_count)
165 * for cc_block_count * 2 + caption_extra_field_added
166 * u7 cc_filler_1
167 * u1 cc_field_is_odd
168 * u8 cc_data_1
169 * u8 cc_data_2
171 const int b_truncate = p_src[4] & 0x01;
172 const int i_field_first = (p_src[4] & 0x80) ? 0 : 1;
173 const int i_count_cc2 = (p_src[4] >> 1) & 0xf;
174 const uint8_t *cc = &p_src[5];
175 int i;
177 if( i_src < 4+1+6*i_count_cc2 - ( b_truncate ? 3 : 0) )
178 return;
179 for( i = 0; i < i_count_cc2; i++ )
181 int j;
182 for( j = 0; j < 2; j++, cc += 3 )
184 const int i_field = j == i_field_first ? 0 : 1;
186 if( b_truncate && i == i_count_cc2 - 1 && j == 1 )
187 break;
188 if( (cc[0] & 0xfe) != 0xfe )
189 continue;
190 if( c->i_data + 3 > CC_MAX_DATA_SIZE )
191 continue;
193 cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[1] );
196 c->b_reorder = false;
198 else if( i_payload_type == CC_PAYLOAD_REPLAYTV )
200 const uint8_t *cc = &p_src[0];
201 for( int i_cc_count = i_src >> 2; i_cc_count > 0;
202 i_cc_count--, cc += 4 )
204 if( c->i_data + 3 > CC_MAX_DATA_SIZE )
205 return;
206 uint8_t i_field = (cc[0] & 0x02) >> 1;
207 cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] );
209 c->b_reorder = false;
211 else /* CC_PAYLOAD_SCTE20 */
213 /* user_data(2)
214 * (u32 stripped earlier)
215 * u16 p_cc_scte20
216 * u5 cc_count
217 * for cc_count
218 * u2 cc_priority
219 * u2 cc_field_num
220 * u5 cc_line_offset
221 * u8 cc_data_1[1:8]
222 * u8 cc_data_2[1:8]
223 * u1 marker bit
224 * un additional_realtimevideodata
225 * un reserved
227 bs_t s;
228 bs_init( &s, &p_src[2], i_src - 2 );
229 const int i_cc_count = bs_read( &s, 5 );
230 for( int i = 0; i < i_cc_count; i++ )
232 bs_skip( &s, 2 );
233 const int i_field_idx = bs_read( &s, 2 );
234 bs_skip( &s, 5 );
235 uint8_t cc[2];
236 for( int j = 0; j < 2; j++ )
238 cc[j] = 0;
239 for( int k = 0; k < 8; k++ )
240 cc[j] |= bs_read( &s, 1 ) << k;
242 bs_skip( &s, 1 );
244 if( i_field_idx == 0 )
245 continue;
246 if( c->i_data + 2*3 > CC_MAX_DATA_SIZE )
247 continue;
249 /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */
250 int i_field = ((i_field_idx - 1) & 1);
251 if (!b_top_field_first)
252 i_field ^= 1;
254 cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] );
256 c->b_reorder = true;
261 static inline void cc_ProbeAndExtract( cc_data_t *c, bool b_top_field_first, const uint8_t *p_src, int i_src )
263 static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 };
264 static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 }; /* ascii 'CC', type_code, cc_block_size */
265 static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };/* RTV4K, BB02xxxxCC02 */
266 static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };/* see DVR-ClosedCaption in samples */
267 static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };/* RTV5K, 9902xxxxAA02 */
268 static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };/* see DVR-ClosedCaption in samples */
269 static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 }; /* user_data_type_code, SCTE 20 */
270 static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };/* user_data_type_code, old, Note 1 */
272 if( i_src < 4 )
273 return;
275 enum cc_payload_type_e i_payload_type;
276 if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 )
278 /* CC from DVB/ATSC TS */
279 i_payload_type = CC_PAYLOAD_GA94;
280 i_src -= 5;
281 p_src += 5;
283 else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 )
285 i_payload_type = CC_PAYLOAD_DVD;
287 else if( i_src >= 2+2 + 2+2 &&
288 ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) ||
289 ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) )
291 i_payload_type = CC_PAYLOAD_REPLAYTV;
293 else if( ( !memcmp( p_cc_scte20, p_src, 2 ) ||
294 !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 )
296 i_payload_type = CC_PAYLOAD_SCTE20;
298 else if (p_src[0] == 0x03 && p_src[1] == i_src - 2) /* DIRECTV */
300 i_payload_type = CC_PAYLOAD_GA94;
301 i_src -= 2;
302 p_src += 2;
304 else
306 #if 0
307 #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x )
308 fprintf( stderr, "-------------- unknown user data " );
309 for( int i = 0; i < i_src; i++ )
310 fprintf( stderr, "%2.2x ", p_src[i] );
311 for( int i = 0; i < i_src; i++ )
312 fprintf( stderr, "%c ", V(p_src[i]) );
313 fprintf( stderr, "\n" );
314 #undef V
315 #endif
316 return;
319 cc_Extract( c, i_payload_type, b_top_field_first, p_src, i_src );
322 #endif /* _CC_H */