1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2007 Laurent Aimar
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 *****************************************************************************/
29 /* CC have a maximum rate of 9600 bit/s (per field?) */
30 #define CC_MAX_DATA_SIZE (2 * 3*600)
41 /* Which channel are present */
49 int i_payload_other_count
;
52 * byte[x+0]: field (0/1)
53 * byte[x+1]: cc data 1
54 * byte[x+2]: cc data 2
57 uint8_t p_data
[CC_MAX_DATA_SIZE
];
60 static inline void cc_Init( cc_data_t
*c
)
64 for( i
= 0; i
< 4; i
++ )
65 c
-> pb_present
[i
] = 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
)
76 static inline void cc_Flush( cc_data_t
*c
)
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 };
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
;
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" );
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 )
150 c
->i_payload_type
= i_payload_type
;
151 c
->i_payload_other_count
= 0;
153 if( i_payload_type
== CC_PAYLOAD_GA94
)
157 * u1 process_cc_data_flag
158 * u1 additional_data_flag
160 * u8 reserved(1111 1111)
162 * u5 marker bit(1111 1)
167 * u8 marker bit(1111 1111)
168 * if additional_data_flag
175 const uint8_t *cc
= &p_src
[5];
176 const int i_count_cc
= cc
[0]&0x1f;
179 if( !(cc
[0]&0x40) ) // process flag
181 if( i_src
< 5 + 1+1 + i_count_cc
*3 + 1) // broken packet
183 if( i_count_cc
<= 0 ) // no cc present
185 if( cc
[2+i_count_cc
* 3] != 0xff ) // marker absent
189 for( i
= 0; i
< i_count_cc
; i
++, cc
+= 3 )
191 int i_field
= cc
[0] & 0x03;
192 if( ( cc
[0] & 0xfc ) != 0xfc )
194 if( i_field
!= 0 && i_field
!= 1 )
196 if( c
->i_data
+ 3 > CC_MAX_DATA_SIZE
)
199 cc_AppendData( c
, i_field
, &cc
[1] );
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];
211 if( i_src
< 4+1+6*i_count_cc2
- ( b_truncate
? 3 : 0) )
213 for( i
= 0; i
< i_count_cc2
; i
++ )
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 )
222 if( cc
[0] != 0xff && cc
[0] != 0xfe )
224 if( c
->i_data
+ 3 > CC_MAX_DATA_SIZE
)
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];
236 if( c
->i_data
+ 2*3 > CC_MAX_DATA_SIZE
)
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;
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
++ )
255 const int i_field_idx
= bs_read( &s
, 2 );
258 for( int j
= 0; j
< 2; j
++ )
261 for( int k
= 0; k
< 8; k
++ )
262 cc
[j
] |= bs_read( &s
, 1 ) << k
;
266 if( i_field_idx
== 0 )
268 if( c
->i_data
+ 2*3 > CC_MAX_DATA_SIZE
)
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
)
276 cc_AppendData( c
, i_field
, &cc
[0] );