Qt: do not show open options in both normal and advanced UI
[vlc.git] / modules / codec / cc.h
blob500973fa2a6634c6e3454d664035e55689d66a02
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
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifndef _CC_H
25 #define _CC_H 1
27 #include <vlc_bits.h>
29 /* CC have a maximum rate of 9600 bit/s (per field?) */
30 #define CC_MAX_DATA_SIZE (2 * 3*600)
31 enum
33 CC_PAYLOAD_NONE,
34 CC_PAYLOAD_GA94,
35 CC_PAYLOAD_DVD,
36 CC_PAYLOAD_REPLAYTV,
37 CC_PAYLOAD_SCTE20,
39 typedef struct
41 /* Which channel are present */
42 bool pb_present[4];
44 /* */
45 bool b_reorder;
47 /* */
48 int i_payload_type;
49 int i_payload_other_count;
51 /* CC data per field
52 * byte[x+0]: field (0/1)
53 * byte[x+1]: cc data 1
54 * byte[x+2]: cc data 2
56 int i_data;
57 uint8_t p_data[CC_MAX_DATA_SIZE];
58 } cc_data_t;
60 static inline void cc_Init( cc_data_t *c )
62 int i;
64 for( i = 0; i < 4; i++ )
65 c-> pb_present[i] = false;
66 c->i_data = 0;
67 c->b_reorder = false;
68 c->i_payload_type = CC_PAYLOAD_NONE;
69 c->i_payload_other_count = 0;
71 static inline void cc_Exit( cc_data_t *c )
73 VLC_UNUSED(c);
74 return;
76 static inline void cc_Flush( cc_data_t *c )
78 c->i_data = 0;
81 static inline void cc_AppendData( cc_data_t *c, int i_field, const uint8_t cc[2] )
83 if( i_field == 0 || i_field == 1 )
85 c->pb_present[2*i_field+0] =
86 c->pb_present[2*i_field+1] = true;
89 c->p_data[c->i_data++] = i_field;
90 c->p_data[c->i_data++] = cc[0];
91 c->p_data[c->i_data++] = cc[1];
94 static inline void cc_Extract( cc_data_t *c, bool b_top_field_first, const uint8_t *p_src, int i_src )
96 static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 };
97 static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 };
98 static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };
99 static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };
100 static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };
101 static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };
102 static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 };
103 static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };
105 if( i_src < 4 )
106 return;
108 int i_payload_type;
109 if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 )
111 /* CC from DVB/ATSC TS */
112 i_payload_type = CC_PAYLOAD_GA94;
114 else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 )
116 i_payload_type = CC_PAYLOAD_DVD;
118 else if( i_src >= 2+2 + 2+2 &&
119 ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) ||
120 ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) )
122 i_payload_type = CC_PAYLOAD_REPLAYTV;
124 else if( ( !memcmp( p_cc_scte20, p_src, 2 ) ||
125 !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 )
127 i_payload_type = CC_PAYLOAD_SCTE20;
129 else
131 #if 0
132 #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x )
133 fprintf( stderr, "-------------- unknown user data " );
134 for( int i = 0; i < i_src; i++ )
135 fprintf( stderr, "%2.2x ", p_src[i] );
136 for( int i = 0; i < i_src; i++ )
137 fprintf( stderr, "%c ", V(p_src[i]) );
138 fprintf( stderr, "\n" );
139 #undef V
140 #endif
141 return;
144 if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type )
146 c->i_payload_other_count++;
147 if( c->i_payload_other_count < 50 )
148 return;
150 c->i_payload_type = i_payload_type;
151 c->i_payload_other_count = 0;
153 if( i_payload_type == CC_PAYLOAD_GA94 )
155 /* cc_data()
156 * u1 reserved(1)
157 * u1 process_cc_data_flag
158 * u1 additional_data_flag
159 * u5 cc_count
160 * u8 reserved(1111 1111)
161 * for cc_count
162 * u5 marker bit(1111 1)
163 * u1 cc_valid
164 * u2 cc_type
165 * u8 cc_data_1
166 * u8 cc_data_2
167 * u8 marker bit(1111 1111)
168 * if additional_data_flag
169 * unknown
171 /* cc_type:
172 * 0x00: field 1
173 * 0x01: field 2
175 const uint8_t *cc = &p_src[5];
176 const int i_count_cc = cc[0]&0x1f;
177 int i;
179 if( !(cc[0]&0x40) ) // process flag
180 return;
181 if( i_src < 5 + 1+1 + i_count_cc*3 + 1) // broken packet
182 return;
183 if( i_count_cc <= 0 ) // no cc present
184 return;
185 if( cc[2+i_count_cc * 3] != 0xff ) // marker absent
186 return;
187 cc += 2;
189 for( i = 0; i < i_count_cc; i++, cc += 3 )
191 int i_field = cc[0] & 0x03;
192 if( ( cc[0] & 0xfc ) != 0xfc )
193 continue;
194 if( i_field != 0 && i_field != 1 )
195 continue;
196 if( c->i_data + 3 > CC_MAX_DATA_SIZE )
197 continue;
199 cc_AppendData( c, i_field, &cc[1] );
201 c->b_reorder = true;
203 else if( i_payload_type == CC_PAYLOAD_DVD )
205 const int b_truncate = p_src[4] & 0x01;
206 const int i_field_first = (p_src[4] & 0x80) ? 0 : 1;
207 const int i_count_cc2 = (p_src[4] >> 1) & 0xf;
208 const uint8_t *cc = &p_src[5];
209 int i;
211 if( i_src < 4+1+6*i_count_cc2 - ( b_truncate ? 3 : 0) )
212 return;
213 for( i = 0; i < i_count_cc2; i++ )
215 int j;
216 for( j = 0; j < 2; j++, cc += 3 )
218 const int i_field = j == i_field_first ? 0 : 1;
220 if( b_truncate && i == i_count_cc2 - 1 && j == 1 )
221 break;
222 if( cc[0] != 0xff && cc[0] != 0xfe )
223 continue;
224 if( c->i_data + 3 > CC_MAX_DATA_SIZE )
225 continue;
227 cc_AppendData( c, i_field, &cc[1] );
230 c->b_reorder = false;
232 else if( i_payload_type == CC_PAYLOAD_REPLAYTV )
234 const uint8_t *cc = &p_src[0];
235 int i;
236 if( c->i_data + 2*3 > CC_MAX_DATA_SIZE )
237 return;
239 for( i = 0; i < 2; i++, cc += 4 )
241 const int i_field = i == 0 ? 1 : 0;
243 cc_AppendData( c, i_field, &cc[2] );
245 c->b_reorder = false;
247 else
249 bs_t s;
250 bs_init( &s, &p_src[2], i_src - 2 );
251 const int i_cc_count = bs_read( &s, 5 );
252 for( int i = 0; i < i_cc_count; i++ )
254 bs_skip( &s, 2 );
255 const int i_field_idx = bs_read( &s, 2 );
256 bs_skip( &s, 5 );
257 uint8_t cc[2];
258 for( int j = 0; j < 2; j++ )
260 cc[j] = 0;
261 for( int k = 0; k < 8; k++ )
262 cc[j] |= bs_read( &s, 1 ) << k;
264 bs_skip( &s, 1 );
266 if( i_field_idx == 0 )
267 continue;
268 if( c->i_data + 2*3 > CC_MAX_DATA_SIZE )
269 continue;
271 /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */
272 int i_field = ((i_field_idx - 1) & 1);
273 if (!b_top_field_first)
274 i_field ^= 1;
276 cc_AppendData( c, i_field, &cc[0] );
278 c->b_reorder = true;
282 #endif /* _CC_H */