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)
33 /* Which channel are present */
40 * byte[x+0]: field (0/1)
41 * byte[x+1]: cc data 1
42 * byte[x+2]: cc data 2
45 uint8_t p_data
[CC_MAX_DATA_SIZE
];
48 static inline void cc_Init( cc_data_t
*c
)
52 for( i
= 0; i
< 4; i
++ )
53 c
-> pb_present
[i
] = false;
57 static inline void cc_Exit( cc_data_t
*c
)
62 static inline void cc_Flush( cc_data_t
*c
)
67 static inline void cc_AppendData( cc_data_t
*c
, int i_field
, const uint8_t cc
[2] )
69 if( i_field
== 0 || i_field
== 1 )
71 c
->pb_present
[2*i_field
+0] =
72 c
->pb_present
[2*i_field
+1] = true;
75 c
->p_data
[c
->i_data
++] = i_field
;
76 c
->p_data
[c
->i_data
++] = cc
[0];
77 c
->p_data
[c
->i_data
++] = cc
[1];
80 static inline void cc_Extract( cc_data_t
*c
, bool b_top_field_first
, const uint8_t *p_src
, int i_src
)
82 static const uint8_t p_cc_ga94
[4] = { 0x47, 0x41, 0x39, 0x34 };
83 static const uint8_t p_cc_dvd
[4] = { 0x43, 0x43, 0x01, 0xf8 };
84 static const uint8_t p_cc_replaytv4a
[2] = { 0xbb, 0x02 };
85 static const uint8_t p_cc_replaytv4b
[2] = { 0xcc, 0x02 };
86 static const uint8_t p_cc_replaytv5a
[2] = { 0x99, 0x02 };
87 static const uint8_t p_cc_replaytv5b
[2] = { 0xaa, 0x02 };
88 static const uint8_t p_cc_scte20
[2] = { 0x03, 0x81 };
89 static const uint8_t p_cc_scte20_old
[2] = { 0x03, 0x01 };
90 //static const uint8_t p_afd_start[4] = { 0x44, 0x54, 0x47, 0x31 };
95 if( !memcmp( p_cc_ga94
, p_src
, 4 ) && i_src
>= 5+1+1+1 && p_src
[4] == 0x03 )
97 /* Extract CC from DVB/ATSC TS */
100 * u1 process_cc_data_flag
101 * u1 additional_data_flag
103 * u8 reserved(1111 1111)
105 * u5 marker bit(1111 1)
110 * u8 marker bit(1111 1111)
111 * if additional_data_flag
118 const uint8_t *cc
= &p_src
[5];
119 const int i_count_cc
= cc
[0]&0x1f;
122 if( !(cc
[0]&0x40) ) // process flag
124 if( i_src
< 5 + 1+1 + i_count_cc
*3 + 1) // broken packet
126 if( i_count_cc
<= 0 ) // no cc present
128 if( cc
[2+i_count_cc
* 3] != 0xff ) // marker absent
132 for( i
= 0; i
< i_count_cc
; i
++, cc
+= 3 )
134 int i_field
= cc
[0] & 0x03;
135 if( ( cc
[0] & 0xfc ) != 0xfc )
137 if( i_field
!= 0 && i_field
!= 1 )
139 if( c
->i_data
+ 3 > CC_MAX_DATA_SIZE
)
142 cc_AppendData( c
, i_field
, &cc
[1] );
146 else if( !memcmp( p_cc_dvd
, p_src
, 4 ) && i_src
> 4+1 )
149 const int b_truncate
= p_src
[4] & 0x01;
150 const int i_field_first
= (p_src
[4] & 0x80) ? 0 : 1;
151 const int i_count_cc2
= (p_src
[4] >> 1) & 0xf;
152 const uint8_t *cc
= &p_src
[5];
155 if( i_src
< 4+1+6*i_count_cc2
- ( b_truncate
? 3 : 0) )
157 for( i
= 0; i
< i_count_cc2
; i
++ )
160 for( j
= 0; j
< 2; j
++, cc
+= 3 )
162 const int i_field
= j
== i_field_first
? 0 : 1;
164 if( b_truncate
&& i
== i_count_cc2
- 1 && j
== 1 )
166 if( cc
[0] != 0xff && cc
[0] != 0xfe )
168 if( c
->i_data
+ 3 > CC_MAX_DATA_SIZE
)
171 cc_AppendData( c
, i_field
, &cc
[1] );
174 c
->b_reorder
= false;
176 else if( i_src
>= 2+2 + 2+2 &&
177 ( ( !memcmp( p_cc_replaytv4a
, &p_src
[0], 2 ) && !memcmp( p_cc_replaytv4b
, &p_src
[4], 2 ) ) ||
178 ( !memcmp( p_cc_replaytv5a
, &p_src
[0], 2 ) && !memcmp( p_cc_replaytv5b
, &p_src
[4], 2 ) ) ) )
181 const uint8_t *cc
= &p_src
[0];
183 if( c
->i_data
+ 2*3 > CC_MAX_DATA_SIZE
)
186 for( i
= 0; i
< 2; i
++, cc
+= 4 )
188 const int i_field
= i
== 0 ? 1 : 0;
190 cc_AppendData( c
, i_field
, &cc
[2] );
192 c
->b_reorder
= false;
194 else if( ( !memcmp( p_cc_scte20
, p_src
, 2 ) ||
195 !memcmp( p_cc_scte20_old
, p_src
, 2 ) ) && i_src
> 2 )
199 bs_init( &s
, &p_src
[2], i_src
- 2 );
200 const int i_cc_count
= bs_read( &s
, 5 );
201 for( int i
= 0; i
< i_cc_count
; i
++ )
204 const int i_field_idx
= bs_read( &s
, 2 );
207 for( int j
= 0; j
< 2; j
++ )
210 for( int k
= 0; k
< 8; k
++ )
211 cc
[j
] |= bs_read( &s
, 1 ) << k
;
215 if( i_field_idx
== 0 )
217 if( c
->i_data
+ 2*3 > CC_MAX_DATA_SIZE
)
220 /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */
221 int i_field
= ((i_field_idx
- 1) & 1);
222 if (!b_top_field_first
)
225 cc_AppendData( c
, i_field
, &cc
[0] );
232 #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x )
233 fprintf( stderr
, "-------------- unknown user data " );
234 for( int i
= 0; i
< i_src
; i
++ )
235 fprintf( stderr
, "%2.2x ", p_src
[i
] );
236 for( int i
= 0; i
< i_src
; i
++ )
237 fprintf( stderr
, "%c ", V(p_src
[i
]) );
238 fprintf( stderr
, "\n" );
241 /* TODO DVD CC, ... */