/src/vlc/modules/codec/cc.h
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * cc.h |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2007 Laurent Aimar |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * |
8 | | * This program is free software; you can redistribute it and/or modify it |
9 | | * under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation; either version 2.1 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program; if not, write to the Free Software Foundation, |
20 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
21 | | *****************************************************************************/ |
22 | | |
23 | | #ifndef VLC_CC_H_ |
24 | | #define VLC_CC_H_ |
25 | | |
26 | | #include <vlc_bits.h> |
27 | | |
28 | 15.9k | #define CC_PKT_BYTE0(field) (0xFC | (0x03 & field)) |
29 | | |
30 | | /* CC have a maximum rate of 9600 bit/s (per field?) */ |
31 | | #define CC_MAX_DATA_SIZE (2 * 3*600) |
32 | | enum cc_payload_type_e |
33 | | { |
34 | | CC_PAYLOAD_NONE, |
35 | | CC_PAYLOAD_RAW, |
36 | | CC_PAYLOAD_GA94, |
37 | | CC_PAYLOAD_DVD, |
38 | | CC_PAYLOAD_REPLAYTV, |
39 | | CC_PAYLOAD_SCTE20, |
40 | | CC_PAYLOAD_CDP, |
41 | | }; |
42 | | typedef struct |
43 | | { |
44 | | /* Which channel are present */ |
45 | | uint64_t i_708channels; |
46 | | uint8_t i_608channels; |
47 | | |
48 | | /* */ |
49 | | bool b_reorder; |
50 | | struct |
51 | | { |
52 | | uint8_t pktsize; |
53 | | uint8_t seq; |
54 | | uint8_t sid_bs; |
55 | | enum |
56 | | { |
57 | | CEA708_PKT_END, |
58 | | CEA708_PKT_WAIT_BLOCK_HEADER, |
59 | | CEA708_PKT_WAIT_EXT_BLOCK_HEADER, |
60 | | CEA708_PKT_IN_BLOCK, |
61 | | } state; |
62 | | } cea708; |
63 | | |
64 | | /* */ |
65 | | enum cc_payload_type_e i_payload_type; |
66 | | int i_payload_other_count; |
67 | | |
68 | | /* CC data per field |
69 | | * byte[x+0]: field (0/1) |
70 | | * byte[x+1]: cc data 1 |
71 | | * byte[x+2]: cc data 2 |
72 | | */ |
73 | | size_t i_data; |
74 | | uint8_t p_data[CC_MAX_DATA_SIZE]; |
75 | | } cc_data_t; |
76 | | |
77 | | static inline void cc_Init( cc_data_t *c ) |
78 | 61.4k | { |
79 | 61.4k | c->i_608channels = 0; |
80 | 61.4k | c->i_708channels = 0; |
81 | 61.4k | c->i_data = 0; |
82 | 61.4k | c->b_reorder = false; |
83 | 61.4k | c->cea708.pktsize = 0; |
84 | 61.4k | c->cea708.seq = 0; |
85 | 61.4k | c->cea708.sid_bs = 0; |
86 | 61.4k | c->cea708.state = CEA708_PKT_END; |
87 | 61.4k | c->i_payload_type = CC_PAYLOAD_NONE; |
88 | 61.4k | c->i_payload_other_count = 0; |
89 | 61.4k | } Unexecuted instantiation: mp4.c:cc_Init Line | Count | Source | 78 | 366 | { | 79 | 366 | c->i_608channels = 0; | 80 | 366 | c->i_708channels = 0; | 81 | 366 | c->i_data = 0; | 82 | | c->b_reorder = false; | 83 | 366 | c->cea708.pktsize = 0; | 84 | 366 | c->cea708.seq = 0; | 85 | 366 | c->cea708.sid_bs = 0; | 86 | 366 | c->cea708.state = CEA708_PKT_END; | 87 | 366 | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 366 | c->i_payload_other_count = 0; | 89 | 366 | } |
Line | Count | Source | 78 | 55.7k | { | 79 | 55.7k | c->i_608channels = 0; | 80 | 55.7k | c->i_708channels = 0; | 81 | 55.7k | c->i_data = 0; | 82 | | c->b_reorder = false; | 83 | 55.7k | c->cea708.pktsize = 0; | 84 | 55.7k | c->cea708.seq = 0; | 85 | 55.7k | c->cea708.sid_bs = 0; | 86 | 55.7k | c->cea708.state = CEA708_PKT_END; | 87 | 55.7k | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 55.7k | c->i_payload_other_count = 0; | 89 | 55.7k | } |
Line | Count | Source | 78 | 3.84k | { | 79 | 3.84k | c->i_608channels = 0; | 80 | 3.84k | c->i_708channels = 0; | 81 | 3.84k | c->i_data = 0; | 82 | | c->b_reorder = false; | 83 | 3.84k | c->cea708.pktsize = 0; | 84 | 3.84k | c->cea708.seq = 0; | 85 | 3.84k | c->cea708.sid_bs = 0; | 86 | 3.84k | c->cea708.state = CEA708_PKT_END; | 87 | 3.84k | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 3.84k | c->i_payload_other_count = 0; | 89 | 3.84k | } |
Line | Count | Source | 78 | 1.55k | { | 79 | 1.55k | c->i_608channels = 0; | 80 | 1.55k | c->i_708channels = 0; | 81 | 1.55k | c->i_data = 0; | 82 | | c->b_reorder = false; | 83 | 1.55k | c->cea708.pktsize = 0; | 84 | 1.55k | c->cea708.seq = 0; | 85 | 1.55k | c->cea708.sid_bs = 0; | 86 | 1.55k | c->cea708.state = CEA708_PKT_END; | 87 | 1.55k | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 1.55k | c->i_payload_other_count = 0; | 89 | 1.55k | } |
|
90 | | static inline void cc_Exit( cc_data_t *c ) |
91 | 57.6k | { |
92 | 57.6k | VLC_UNUSED(c); |
93 | 57.6k | return; |
94 | 57.6k | } Unexecuted instantiation: mp4.c:cc_Exit Line | Count | Source | 91 | 366 | { | 92 | 366 | VLC_UNUSED(c); | 93 | 366 | return; | 94 | 366 | } |
Line | Count | Source | 91 | 55.7k | { | 92 | 55.7k | VLC_UNUSED(c); | 93 | 55.7k | return; | 94 | 55.7k | } |
Unexecuted instantiation: mpegvideo.c:cc_Exit Line | Count | Source | 91 | 1.55k | { | 92 | 1.55k | VLC_UNUSED(c); | 93 | 1.55k | return; | 94 | 1.55k | } |
|
95 | | static inline void cc_Flush( cc_data_t *c ) |
96 | 1.00M | { |
97 | 1.00M | c->i_data = 0; |
98 | 1.00M | c->cea708.state = CEA708_PKT_END; |
99 | 1.00M | } Unexecuted instantiation: mp4.c:cc_Flush Line | Count | Source | 96 | 1.02k | { | 97 | 1.02k | c->i_data = 0; | 98 | 1.02k | c->cea708.state = CEA708_PKT_END; | 99 | 1.02k | } |
Line | Count | Source | 96 | 1.00M | { | 97 | 1.00M | c->i_data = 0; | 98 | 1.00M | c->cea708.state = CEA708_PKT_END; | 99 | 1.00M | } |
Unexecuted instantiation: mpegvideo.c:cc_Flush Line | Count | Source | 96 | 1.28k | { | 97 | 1.28k | c->i_data = 0; | 98 | 1.28k | c->cea708.state = CEA708_PKT_END; | 99 | 1.28k | } |
|
100 | | |
101 | | static inline void cc_ProbeCEA708OneByte( cc_data_t *c, bool b_start, const uint8_t cc ) |
102 | 125k | { |
103 | 125k | if( b_start ) |
104 | 31.2k | { |
105 | 31.2k | const uint8_t i_pkt_sequence = cc >> 6; |
106 | 31.2k | if( i_pkt_sequence > 0 && ((c->cea708.seq + 1) % 4) != i_pkt_sequence ) |
107 | 16.2k | { |
108 | 16.2k | c->cea708.pktsize = 0; |
109 | 16.2k | c->cea708.seq = i_pkt_sequence; |
110 | 16.2k | c->cea708.state = CEA708_PKT_END; |
111 | 16.2k | } |
112 | 15.0k | else |
113 | 15.0k | { |
114 | 15.0k | c->cea708.seq = i_pkt_sequence; |
115 | 15.0k | c->cea708.pktsize = cc & 63; |
116 | 15.0k | if( c->cea708.pktsize == 0 ) |
117 | 5.86k | c->cea708.pktsize = 127; |
118 | 9.15k | else |
119 | 9.15k | c->cea708.pktsize = c->cea708.pktsize * 2 - 1; |
120 | 15.0k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; |
121 | 15.0k | } |
122 | 31.2k | } |
123 | 94.1k | else if( c->cea708.pktsize == 0 ) /* empty pkt reading service blocks */ |
124 | 46.2k | { |
125 | 46.2k | c->cea708.state = CEA708_PKT_END; |
126 | 46.2k | } |
127 | 47.9k | else if( c->cea708.state != CEA708_PKT_END ) |
128 | 41.3k | { |
129 | 41.3k | switch( c->cea708.state ) |
130 | 41.3k | { |
131 | 17.8k | case CEA708_PKT_WAIT_BLOCK_HEADER: /* Byte is service block header */ |
132 | 17.8k | { |
133 | 17.8k | uint8_t i_sid = cc >> 5; |
134 | 17.8k | c->cea708.sid_bs = cc & 0x1F; |
135 | 17.8k | if( i_sid != 0x00 && c->cea708.sid_bs != 0 ) |
136 | 12.5k | { |
137 | 12.5k | if( i_sid != 0x07 ) |
138 | 7.57k | { |
139 | 7.57k | const uint8_t mask = (1 << --i_sid); |
140 | 7.57k | c->i_708channels |= (mask + (mask - 1)); |
141 | 7.57k | c->cea708.state = CEA708_PKT_IN_BLOCK; |
142 | 7.57k | } |
143 | 4.98k | else if( c->cea708.sid_bs < 2 ) |
144 | 594 | { |
145 | 594 | c->cea708.state = CEA708_PKT_END; |
146 | 594 | } |
147 | 4.38k | else |
148 | 4.38k | { |
149 | | /* need to look up next byte in next pkt */ |
150 | 4.38k | c->cea708.state = CEA708_PKT_WAIT_EXT_BLOCK_HEADER; |
151 | 4.38k | } |
152 | 12.5k | } |
153 | 5.33k | else c->cea708.state = CEA708_PKT_END; |
154 | 17.8k | } break; |
155 | | |
156 | 2.31k | case CEA708_PKT_WAIT_EXT_BLOCK_HEADER: |
157 | 2.31k | { |
158 | 2.31k | uint8_t i_extsid = cc & 0x3F; |
159 | 2.31k | if( i_extsid >= 0x07 ) |
160 | 1.00k | { |
161 | 1.00k | const uint64_t mask = (INT64_C(1) << --i_extsid); |
162 | 1.00k | c->i_708channels |= (mask + (mask - 1)); |
163 | 1.00k | } |
164 | 2.31k | if( c->cea708.sid_bs == 0 ) |
165 | 0 | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; |
166 | 2.31k | else |
167 | 2.31k | c->cea708.state = CEA708_PKT_IN_BLOCK; |
168 | 2.31k | } break; |
169 | | |
170 | 21.1k | case CEA708_PKT_IN_BLOCK: |
171 | 21.1k | { |
172 | 21.1k | c->cea708.sid_bs--; |
173 | 21.1k | if( c->cea708.sid_bs == 0 ) |
174 | 4.01k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; |
175 | 21.1k | } break; |
176 | | |
177 | 0 | default: |
178 | 0 | vlc_assert_unreachable(); |
179 | 0 | break; |
180 | 41.3k | } |
181 | 41.3k | c->cea708.pktsize--; |
182 | | |
183 | 41.3k | if(c->cea708.pktsize == 0) |
184 | 852 | c->cea708.state = CEA708_PKT_END; |
185 | 41.3k | } |
186 | 125k | } Unexecuted instantiation: mp4.c:cc_ProbeCEA708OneByte Unexecuted instantiation: ty.c:cc_ProbeCEA708OneByte hxxx_common.c:cc_ProbeCEA708OneByte Line | Count | Source | 102 | 125k | { | 103 | 125k | if( b_start ) | 104 | 31.2k | { | 105 | 31.2k | const uint8_t i_pkt_sequence = cc >> 6; | 106 | 31.2k | if( i_pkt_sequence > 0 && ((c->cea708.seq + 1) % 4) != i_pkt_sequence ) | 107 | 16.2k | { | 108 | 16.2k | c->cea708.pktsize = 0; | 109 | 16.2k | c->cea708.seq = i_pkt_sequence; | 110 | 16.2k | c->cea708.state = CEA708_PKT_END; | 111 | 16.2k | } | 112 | 15.0k | else | 113 | 15.0k | { | 114 | 15.0k | c->cea708.seq = i_pkt_sequence; | 115 | 15.0k | c->cea708.pktsize = cc & 63; | 116 | 15.0k | if( c->cea708.pktsize == 0 ) | 117 | 5.86k | c->cea708.pktsize = 127; | 118 | 9.15k | else | 119 | 9.15k | c->cea708.pktsize = c->cea708.pktsize * 2 - 1; | 120 | 15.0k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; | 121 | 15.0k | } | 122 | 31.2k | } | 123 | 94.1k | else if( c->cea708.pktsize == 0 ) /* empty pkt reading service blocks */ | 124 | 46.2k | { | 125 | 46.2k | c->cea708.state = CEA708_PKT_END; | 126 | 46.2k | } | 127 | 47.9k | else if( c->cea708.state != CEA708_PKT_END ) | 128 | 41.3k | { | 129 | 41.3k | switch( c->cea708.state ) | 130 | 41.3k | { | 131 | 17.8k | case CEA708_PKT_WAIT_BLOCK_HEADER: /* Byte is service block header */ | 132 | 17.8k | { | 133 | 17.8k | uint8_t i_sid = cc >> 5; | 134 | 17.8k | c->cea708.sid_bs = cc & 0x1F; | 135 | 17.8k | if( i_sid != 0x00 && c->cea708.sid_bs != 0 ) | 136 | 12.5k | { | 137 | 12.5k | if( i_sid != 0x07 ) | 138 | 7.57k | { | 139 | 7.57k | const uint8_t mask = (1 << --i_sid); | 140 | 7.57k | c->i_708channels |= (mask + (mask - 1)); | 141 | 7.57k | c->cea708.state = CEA708_PKT_IN_BLOCK; | 142 | 7.57k | } | 143 | 4.98k | else if( c->cea708.sid_bs < 2 ) | 144 | 594 | { | 145 | 594 | c->cea708.state = CEA708_PKT_END; | 146 | 594 | } | 147 | 4.38k | else | 148 | 4.38k | { | 149 | | /* need to look up next byte in next pkt */ | 150 | 4.38k | c->cea708.state = CEA708_PKT_WAIT_EXT_BLOCK_HEADER; | 151 | 4.38k | } | 152 | 12.5k | } | 153 | 5.33k | else c->cea708.state = CEA708_PKT_END; | 154 | 17.8k | } break; | 155 | | | 156 | 2.31k | case CEA708_PKT_WAIT_EXT_BLOCK_HEADER: | 157 | 2.31k | { | 158 | 2.31k | uint8_t i_extsid = cc & 0x3F; | 159 | 2.31k | if( i_extsid >= 0x07 ) | 160 | 1.00k | { | 161 | 1.00k | const uint64_t mask = (INT64_C(1) << --i_extsid); | 162 | 1.00k | c->i_708channels |= (mask + (mask - 1)); | 163 | 1.00k | } | 164 | 2.31k | if( c->cea708.sid_bs == 0 ) | 165 | 0 | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; | 166 | 2.31k | else | 167 | 2.31k | c->cea708.state = CEA708_PKT_IN_BLOCK; | 168 | 2.31k | } break; | 169 | | | 170 | 21.1k | case CEA708_PKT_IN_BLOCK: | 171 | 21.1k | { | 172 | 21.1k | c->cea708.sid_bs--; | 173 | 21.1k | if( c->cea708.sid_bs == 0 ) | 174 | 4.01k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; | 175 | 21.1k | } break; | 176 | | | 177 | 0 | default: | 178 | 0 | vlc_assert_unreachable(); | 179 | 0 | break; | 180 | 41.3k | } | 181 | 41.3k | c->cea708.pktsize--; | 182 | | | 183 | 41.3k | if(c->cea708.pktsize == 0) | 184 | 852 | c->cea708.state = CEA708_PKT_END; | 185 | 41.3k | } | 186 | 125k | } |
Unexecuted instantiation: mpegvideo.c:cc_ProbeCEA708OneByte Unexecuted instantiation: vc1.c:cc_ProbeCEA708OneByte |
187 | | |
188 | | static inline void cc_ProbeCEA708( cc_data_t *c, uint8_t i_field, const uint8_t cc[2] ) |
189 | 62.7k | { |
190 | 62.7k | if( i_field == 3 ) /* DTVCC_PACKET_START */ |
191 | 31.2k | cc_ProbeCEA708OneByte( c, true, cc[0] ); |
192 | 31.4k | else /* DTVCC_PACKET_DATA */ |
193 | 31.4k | cc_ProbeCEA708OneByte( c, false, cc[0] ); |
194 | 62.7k | cc_ProbeCEA708OneByte( c, false, cc[1] ); |
195 | 62.7k | } Unexecuted instantiation: mp4.c:cc_ProbeCEA708 Unexecuted instantiation: ty.c:cc_ProbeCEA708 hxxx_common.c:cc_ProbeCEA708 Line | Count | Source | 189 | 62.7k | { | 190 | 62.7k | if( i_field == 3 ) /* DTVCC_PACKET_START */ | 191 | 31.2k | cc_ProbeCEA708OneByte( c, true, cc[0] ); | 192 | 31.4k | else /* DTVCC_PACKET_DATA */ | 193 | 31.4k | cc_ProbeCEA708OneByte( c, false, cc[0] ); | 194 | | cc_ProbeCEA708OneByte( c, false, cc[1] ); | 195 | 62.7k | } |
Unexecuted instantiation: mpegvideo.c:cc_ProbeCEA708 Unexecuted instantiation: vc1.c:cc_ProbeCEA708 |
196 | | |
197 | | static inline bool cc_AppendData( cc_data_t *c, uint8_t cc_preamble, const uint8_t cc[2] ) |
198 | 91.5k | { |
199 | 91.5k | if (c->i_data + 3 > ARRAY_SIZE(c->p_data)) |
200 | 916 | return false; |
201 | | |
202 | 90.6k | const uint8_t i_field = cc_preamble & 0x03; |
203 | 90.6k | if( i_field == 0 || i_field == 1 ) /* NTSC_CC_FIELD_1 NTSC_CC_FIELD_2 */ |
204 | 27.9k | { |
205 | 27.9k | c->i_608channels |= (3 << (2 * i_field)); |
206 | 27.9k | } |
207 | 62.7k | else |
208 | 62.7k | { |
209 | 62.7k | cc_ProbeCEA708( c, i_field, cc ); |
210 | | /* By default enable at least channel 1 */ |
211 | 62.7k | c->i_708channels |= 1; |
212 | 62.7k | } |
213 | | |
214 | 90.6k | c->p_data[c->i_data++] = cc_preamble; |
215 | 90.6k | c->p_data[c->i_data++] = cc[0]; |
216 | 90.6k | c->p_data[c->i_data++] = cc[1]; |
217 | 90.6k | return true; |
218 | 91.5k | } Unexecuted instantiation: mp4.c:cc_AppendData Line | Count | Source | 198 | 15.9k | { | 199 | 15.9k | if (c->i_data + 3 > ARRAY_SIZE(c->p_data)) | 200 | 0 | return false; | 201 | | | 202 | 15.9k | const uint8_t i_field = cc_preamble & 0x03; | 203 | 15.9k | if( i_field == 0 || i_field == 1 ) /* NTSC_CC_FIELD_1 NTSC_CC_FIELD_2 */ | 204 | 15.9k | { | 205 | 15.9k | c->i_608channels |= (3 << (2 * i_field)); | 206 | 15.9k | } | 207 | 0 | else | 208 | 0 | { | 209 | 0 | cc_ProbeCEA708( c, i_field, cc ); | 210 | | /* By default enable at least channel 1 */ | 211 | 0 | c->i_708channels |= 1; | 212 | 0 | } | 213 | | | 214 | 15.9k | c->p_data[c->i_data++] = cc_preamble; | 215 | 15.9k | c->p_data[c->i_data++] = cc[0]; | 216 | 15.9k | c->p_data[c->i_data++] = cc[1]; | 217 | | return true; | 218 | 15.9k | } |
hxxx_common.c:cc_AppendData Line | Count | Source | 198 | 75.5k | { | 199 | 75.5k | if (c->i_data + 3 > ARRAY_SIZE(c->p_data)) | 200 | 916 | return false; | 201 | | | 202 | 74.6k | const uint8_t i_field = cc_preamble & 0x03; | 203 | 74.6k | if( i_field == 0 || i_field == 1 ) /* NTSC_CC_FIELD_1 NTSC_CC_FIELD_2 */ | 204 | 11.9k | { | 205 | 11.9k | c->i_608channels |= (3 << (2 * i_field)); | 206 | 11.9k | } | 207 | 62.7k | else | 208 | 62.7k | { | 209 | 62.7k | cc_ProbeCEA708( c, i_field, cc ); | 210 | | /* By default enable at least channel 1 */ | 211 | 62.7k | c->i_708channels |= 1; | 212 | 62.7k | } | 213 | | | 214 | 74.6k | c->p_data[c->i_data++] = cc_preamble; | 215 | 74.6k | c->p_data[c->i_data++] = cc[0]; | 216 | 74.6k | c->p_data[c->i_data++] = cc[1]; | 217 | | return true; | 218 | 75.5k | } |
Unexecuted instantiation: mpegvideo.c:cc_AppendData Unexecuted instantiation: vc1.c:cc_AppendData |
219 | | |
220 | | static inline void cc_Extract( cc_data_t *c, enum cc_payload_type_e i_payload_type, |
221 | | bool b_top_field_first, const uint8_t *p_src, int i_src ) |
222 | 29.6k | { |
223 | 29.6k | if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type ) |
224 | 0 | { |
225 | 0 | c->i_payload_other_count++; |
226 | 0 | if( c->i_payload_other_count < 50 ) |
227 | 0 | return; |
228 | 0 | } |
229 | 29.6k | c->i_payload_type = i_payload_type; |
230 | 29.6k | c->i_payload_other_count = 0; |
231 | | |
232 | 29.6k | if( i_payload_type == CC_PAYLOAD_RAW ) |
233 | 0 | { |
234 | 0 | for( int i = 0; i + 2 < i_src; i += 3 ) |
235 | 0 | { |
236 | 0 | const uint8_t *cc = &p_src[i]; |
237 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) |
238 | 0 | break; |
239 | 0 | } |
240 | 0 | c->b_reorder = true; |
241 | 0 | } |
242 | 29.6k | else if( i_payload_type == CC_PAYLOAD_GA94 ) |
243 | 29.6k | { |
244 | | /* cc_data() |
245 | | * u1 reserved(1) |
246 | | * u1 process_cc_data_flag |
247 | | * u1 additional_data_flag |
248 | | * u5 cc_count |
249 | | * u8 reserved(1111 1111) |
250 | | * for cc_count |
251 | | * u5 marker bit(1111 1) |
252 | | * u1 cc_valid |
253 | | * u2 cc_type |
254 | | * u8 cc_data_1 |
255 | | * u8 cc_data_2 |
256 | | * u8 marker bit(1111 1111) |
257 | | * if additional_data_flag |
258 | | * unknown |
259 | | */ |
260 | | /* cc_type: |
261 | | * 0x00: field 1 |
262 | | * 0x01: field 2 |
263 | | */ |
264 | 29.6k | if(i_src < 1) |
265 | 693 | return; |
266 | 28.9k | const uint8_t *cc = &p_src[0]; |
267 | 28.9k | const int i_count_cc = cc[0]&0x1f; |
268 | 28.9k | int i; |
269 | | |
270 | 28.9k | if( !(cc[0]&0x40) ) // process flag |
271 | 1.28k | return; |
272 | 27.6k | if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet |
273 | 991 | return; |
274 | 26.7k | if( i_count_cc <= 0 ) // no cc present |
275 | 487 | return; |
276 | 26.2k | if( cc[2+i_count_cc * 3] != 0xff ) // marker absent |
277 | 1.84k | return; |
278 | 24.3k | cc += 2; |
279 | | |
280 | 99.0k | for( i = 0; i < i_count_cc; i++, cc += 3 ) |
281 | 75.5k | { |
282 | 75.5k | if (!cc_AppendData( c, cc[0], &cc[1] )) |
283 | 916 | break; |
284 | 75.5k | } |
285 | 24.3k | c->b_reorder = true; |
286 | 24.3k | } |
287 | 0 | else if( i_payload_type == CC_PAYLOAD_DVD ) |
288 | 0 | { |
289 | | /* user_data |
290 | | * (u32 stripped earlier) |
291 | | * u32 (0x43 0x43 0x01 0xf8) |
292 | | * u1 caption_odd_field_first (CC1/CC2) |
293 | | * u1 caption_filler |
294 | | * u5 cc_block_count (== cc_count / 2) |
295 | | * u1 caption_extra_field_added (because odd cc_count) |
296 | | * for cc_block_count * 2 + caption_extra_field_added |
297 | | * u7 cc_filler_1 |
298 | | * u1 cc_field_is_odd |
299 | | * u8 cc_data_1 |
300 | | * u8 cc_data_2 |
301 | | */ |
302 | 0 | if(i_src < 6) |
303 | 0 | return; |
304 | 0 | const int b_truncate = p_src[4] & 0x01; |
305 | 0 | const int i_count_cc2 = ((p_src[4] >> 1) & 0x1f); |
306 | 0 | const uint8_t *cc = &p_src[5]; |
307 | 0 | i_src -= 5; |
308 | 0 | int i; |
309 | |
|
310 | 0 | #define CC_ALIGNMENT_TEST (0x7f) |
311 | |
|
312 | 0 | for( i = 0; i < 2*i_count_cc2 + b_truncate && i_src >= 3; i++, cc+=3 ) |
313 | 0 | { |
314 | 0 | if( (cc[0] >> 1) == CC_ALIGNMENT_TEST ) |
315 | 0 | { |
316 | 0 | const bool even_field = (cc[0] & 0x01) ? 0 : 1; |
317 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(even_field), &cc[1] )) |
318 | 0 | break; |
319 | 0 | } |
320 | 0 | i_src -= 3; |
321 | 0 | } |
322 | 0 | c->b_reorder = false; |
323 | 0 | } |
324 | 0 | else if( i_payload_type == CC_PAYLOAD_REPLAYTV ) |
325 | 0 | { |
326 | 0 | if(i_src < 1) |
327 | 0 | return; |
328 | 0 | const uint8_t *cc = &p_src[0]; |
329 | 0 | for( int i_cc_count = i_src >> 2; i_cc_count > 0; |
330 | 0 | i_cc_count--, cc += 4 ) |
331 | 0 | { |
332 | 0 | uint8_t i_field = (cc[0] & 0x02) >> 1; |
333 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] )) |
334 | 0 | return; |
335 | 0 | } |
336 | 0 | c->b_reorder = false; |
337 | 0 | } |
338 | 0 | else if( i_payload_type == CC_PAYLOAD_SCTE20 ) |
339 | 0 | { |
340 | | /* user_data(2) |
341 | | * (u32 stripped earlier) |
342 | | * u16 p_cc_scte20 |
343 | | * u5 cc_count |
344 | | * for cc_count |
345 | | * u2 cc_priority |
346 | | * u2 cc_field_num |
347 | | * u5 cc_line_offset |
348 | | * u8 cc_data_1[1:8] |
349 | | * u8 cc_data_2[1:8] |
350 | | * u1 marker bit |
351 | | * un additional_realtimevideodata |
352 | | * un reserved |
353 | | */ |
354 | 0 | if(i_src < 2) |
355 | 0 | return; |
356 | 0 | bs_t s; |
357 | 0 | bs_init( &s, &p_src[2], i_src - 2 ); |
358 | 0 | const int i_cc_count = bs_read( &s, 5 ); |
359 | 0 | for( int i = 0; i < i_cc_count; i++ ) |
360 | 0 | { |
361 | 0 | bs_skip( &s, 2 ); |
362 | 0 | const int i_field_idx = bs_read( &s, 2 ); |
363 | 0 | bs_skip( &s, 5 ); |
364 | 0 | uint8_t cc[2]; |
365 | 0 | for( int j = 0; j < 2; j++ ) |
366 | 0 | { |
367 | 0 | cc[j] = 0; |
368 | 0 | for( int k = 0; k < 8; k++ ) |
369 | 0 | cc[j] |= bs_read( &s, 1 ) << k; |
370 | 0 | } |
371 | 0 | bs_skip( &s, 1 ); |
372 | |
|
373 | 0 | if( i_field_idx == 0 ) |
374 | 0 | continue; |
375 | | |
376 | | /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */ |
377 | 0 | int i_field = ((i_field_idx - 1) & 1); |
378 | 0 | if (!b_top_field_first) |
379 | 0 | i_field ^= 1; |
380 | |
|
381 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] )) |
382 | 0 | continue; |
383 | 0 | } |
384 | 0 | c->b_reorder = true; |
385 | 0 | } |
386 | 0 | else // CC_PAYLOAD_CDP |
387 | 0 | { |
388 | 0 | # define CDP_FLAG_TIME_CODE_PRESENT (1<<7) |
389 | 0 | # define CDP_FLAG_CC_DATA_PRESENT (1<<6) |
390 | 0 | # define CDP_FLAG_SVC_INFO_PRESENT (1<<5) |
391 | 0 | # define CDP_FLAG_SVC_INFO_START (1<<4) |
392 | 0 | # define CDP_FLAG_SVC_INFO_CHANGE (1<<3) |
393 | 0 | # define CDP_FLAG_SVC_INFO_COMPLETE (1<<2) |
394 | 0 | # define CDP_FLAG_CAPTION_SVC_ACTIVE (1<<1) |
395 | |
|
396 | 0 | if(i_src < 7) |
397 | 0 | return; |
398 | | |
399 | | /* ST334-2 5.2 cdp_header() */ |
400 | 0 | uint8_t cdp_length = p_src[2]; |
401 | 0 | if(cdp_length < 8 || cdp_length > i_src) |
402 | 0 | return; |
403 | 0 | uint8_t cdp_flags = p_src[4]; |
404 | | |
405 | | /* skip header */ |
406 | 0 | p_src += 7; i_src -= 7; |
407 | | |
408 | | /* 5.3 time_code_section() */ |
409 | 0 | if( cdp_flags & CDP_FLAG_TIME_CODE_PRESENT ) |
410 | 0 | { |
411 | 0 | if( i_src < 5 ) // Shall be 5 bytes |
412 | 0 | return; |
413 | 0 | p_src += 5; i_src += 5; |
414 | 0 | } |
415 | | /* 5.4 ccdata_section */ |
416 | 0 | if( cdp_flags & CDP_FLAG_CC_DATA_PRESENT ) |
417 | 0 | { |
418 | | /* ccdata_section() |
419 | | * u8 0x72 |
420 | | * u3 marker bits(111) |
421 | | * u5 cc_count |
422 | | * for cc_count |
423 | | * u5 marker bits(1111 1) |
424 | | * u1 cc_valid |
425 | | * u2 cc_type |
426 | | * u8 cc_data_1 |
427 | | * u8 cc_data_2 |
428 | | */ |
429 | 0 | if( i_src < 2 || p_src[0] != 0x72 ) // marker |
430 | 0 | return; |
431 | | |
432 | 0 | const uint8_t *cc = &p_src[1]; |
433 | 0 | const int i_count_cc = cc[0]&0x1f; |
434 | |
|
435 | 0 | if( i_src - 2 < i_count_cc*3 ) // broken packet |
436 | 0 | return; |
437 | 0 | cc += 1; |
438 | 0 | for( int i = 0; i < i_count_cc; i++, cc += 3 ) |
439 | 0 | { |
440 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) |
441 | 0 | break; |
442 | 0 | } |
443 | 0 | } |
444 | | /* remaining data */ |
445 | 0 | c->b_reorder = false; |
446 | 0 | } |
447 | 29.6k | } Unexecuted instantiation: mp4.c:cc_Extract Unexecuted instantiation: ty.c:cc_Extract Line | Count | Source | 222 | 29.6k | { | 223 | 29.6k | if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type ) | 224 | 0 | { | 225 | 0 | c->i_payload_other_count++; | 226 | 0 | if( c->i_payload_other_count < 50 ) | 227 | 0 | return; | 228 | 0 | } | 229 | 29.6k | c->i_payload_type = i_payload_type; | 230 | 29.6k | c->i_payload_other_count = 0; | 231 | | | 232 | 29.6k | if( i_payload_type == CC_PAYLOAD_RAW ) | 233 | 0 | { | 234 | 0 | for( int i = 0; i + 2 < i_src; i += 3 ) | 235 | 0 | { | 236 | 0 | const uint8_t *cc = &p_src[i]; | 237 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 238 | 0 | break; | 239 | 0 | } | 240 | 0 | c->b_reorder = true; | 241 | 0 | } | 242 | 29.6k | else if( i_payload_type == CC_PAYLOAD_GA94 ) | 243 | 29.6k | { | 244 | | /* cc_data() | 245 | | * u1 reserved(1) | 246 | | * u1 process_cc_data_flag | 247 | | * u1 additional_data_flag | 248 | | * u5 cc_count | 249 | | * u8 reserved(1111 1111) | 250 | | * for cc_count | 251 | | * u5 marker bit(1111 1) | 252 | | * u1 cc_valid | 253 | | * u2 cc_type | 254 | | * u8 cc_data_1 | 255 | | * u8 cc_data_2 | 256 | | * u8 marker bit(1111 1111) | 257 | | * if additional_data_flag | 258 | | * unknown | 259 | | */ | 260 | | /* cc_type: | 261 | | * 0x00: field 1 | 262 | | * 0x01: field 2 | 263 | | */ | 264 | 29.6k | if(i_src < 1) | 265 | 693 | return; | 266 | 28.9k | const uint8_t *cc = &p_src[0]; | 267 | 28.9k | const int i_count_cc = cc[0]&0x1f; | 268 | 28.9k | int i; | 269 | | | 270 | 28.9k | if( !(cc[0]&0x40) ) // process flag | 271 | 1.26k | return; | 272 | 27.6k | if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet | 273 | 991 | return; | 274 | 26.7k | if( i_count_cc <= 0 ) // no cc present | 275 | 487 | return; | 276 | 26.2k | if( cc[2+i_count_cc * 3] != 0xff ) // marker absent | 277 | 1.83k | return; | 278 | 24.3k | cc += 2; | 279 | | | 280 | 99.0k | for( i = 0; i < i_count_cc; i++, cc += 3 ) | 281 | 75.5k | { | 282 | 75.5k | if (!cc_AppendData( c, cc[0], &cc[1] )) | 283 | 916 | break; | 284 | 75.5k | } | 285 | 24.3k | c->b_reorder = true; | 286 | 24.3k | } | 287 | 0 | else if( i_payload_type == CC_PAYLOAD_DVD ) | 288 | 0 | { | 289 | | /* user_data | 290 | | * (u32 stripped earlier) | 291 | | * u32 (0x43 0x43 0x01 0xf8) | 292 | | * u1 caption_odd_field_first (CC1/CC2) | 293 | | * u1 caption_filler | 294 | | * u5 cc_block_count (== cc_count / 2) | 295 | | * u1 caption_extra_field_added (because odd cc_count) | 296 | | * for cc_block_count * 2 + caption_extra_field_added | 297 | | * u7 cc_filler_1 | 298 | | * u1 cc_field_is_odd | 299 | | * u8 cc_data_1 | 300 | | * u8 cc_data_2 | 301 | | */ | 302 | 0 | if(i_src < 6) | 303 | 0 | return; | 304 | 0 | const int b_truncate = p_src[4] & 0x01; | 305 | 0 | const int i_count_cc2 = ((p_src[4] >> 1) & 0x1f); | 306 | 0 | const uint8_t *cc = &p_src[5]; | 307 | 0 | i_src -= 5; | 308 | 0 | int i; | 309 | |
| 310 | 0 | #define CC_ALIGNMENT_TEST (0x7f) | 311 | |
| 312 | 0 | for( i = 0; i < 2*i_count_cc2 + b_truncate && i_src >= 3; i++, cc+=3 ) | 313 | 0 | { | 314 | 0 | if( (cc[0] >> 1) == CC_ALIGNMENT_TEST ) | 315 | 0 | { | 316 | 0 | const bool even_field = (cc[0] & 0x01) ? 0 : 1; | 317 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(even_field), &cc[1] )) | 318 | 0 | break; | 319 | 0 | } | 320 | 0 | i_src -= 3; | 321 | 0 | } | 322 | 0 | c->b_reorder = false; | 323 | 0 | } | 324 | 0 | else if( i_payload_type == CC_PAYLOAD_REPLAYTV ) | 325 | 0 | { | 326 | 0 | if(i_src < 1) | 327 | 0 | return; | 328 | 0 | const uint8_t *cc = &p_src[0]; | 329 | 0 | for( int i_cc_count = i_src >> 2; i_cc_count > 0; | 330 | 0 | i_cc_count--, cc += 4 ) | 331 | 0 | { | 332 | 0 | uint8_t i_field = (cc[0] & 0x02) >> 1; | 333 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] )) | 334 | 0 | return; | 335 | 0 | } | 336 | 0 | c->b_reorder = false; | 337 | 0 | } | 338 | 0 | else if( i_payload_type == CC_PAYLOAD_SCTE20 ) | 339 | 0 | { | 340 | | /* user_data(2) | 341 | | * (u32 stripped earlier) | 342 | | * u16 p_cc_scte20 | 343 | | * u5 cc_count | 344 | | * for cc_count | 345 | | * u2 cc_priority | 346 | | * u2 cc_field_num | 347 | | * u5 cc_line_offset | 348 | | * u8 cc_data_1[1:8] | 349 | | * u8 cc_data_2[1:8] | 350 | | * u1 marker bit | 351 | | * un additional_realtimevideodata | 352 | | * un reserved | 353 | | */ | 354 | 0 | if(i_src < 2) | 355 | 0 | return; | 356 | 0 | bs_t s; | 357 | 0 | bs_init( &s, &p_src[2], i_src - 2 ); | 358 | 0 | const int i_cc_count = bs_read( &s, 5 ); | 359 | 0 | for( int i = 0; i < i_cc_count; i++ ) | 360 | 0 | { | 361 | 0 | bs_skip( &s, 2 ); | 362 | 0 | const int i_field_idx = bs_read( &s, 2 ); | 363 | 0 | bs_skip( &s, 5 ); | 364 | 0 | uint8_t cc[2]; | 365 | 0 | for( int j = 0; j < 2; j++ ) | 366 | 0 | { | 367 | 0 | cc[j] = 0; | 368 | 0 | for( int k = 0; k < 8; k++ ) | 369 | 0 | cc[j] |= bs_read( &s, 1 ) << k; | 370 | 0 | } | 371 | 0 | bs_skip( &s, 1 ); | 372 | |
| 373 | 0 | if( i_field_idx == 0 ) | 374 | 0 | continue; | 375 | | | 376 | | /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */ | 377 | 0 | int i_field = ((i_field_idx - 1) & 1); | 378 | 0 | if (!b_top_field_first) | 379 | 0 | i_field ^= 1; | 380 | |
| 381 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] )) | 382 | 0 | continue; | 383 | 0 | } | 384 | 0 | c->b_reorder = true; | 385 | 0 | } | 386 | 0 | else // CC_PAYLOAD_CDP | 387 | 0 | { | 388 | 0 | # define CDP_FLAG_TIME_CODE_PRESENT (1<<7) | 389 | 0 | # define CDP_FLAG_CC_DATA_PRESENT (1<<6) | 390 | 0 | # define CDP_FLAG_SVC_INFO_PRESENT (1<<5) | 391 | 0 | # define CDP_FLAG_SVC_INFO_START (1<<4) | 392 | 0 | # define CDP_FLAG_SVC_INFO_CHANGE (1<<3) | 393 | 0 | # define CDP_FLAG_SVC_INFO_COMPLETE (1<<2) | 394 | 0 | # define CDP_FLAG_CAPTION_SVC_ACTIVE (1<<1) | 395 | |
| 396 | 0 | if(i_src < 7) | 397 | 0 | return; | 398 | | | 399 | | /* ST334-2 5.2 cdp_header() */ | 400 | 0 | uint8_t cdp_length = p_src[2]; | 401 | 0 | if(cdp_length < 8 || cdp_length > i_src) | 402 | 0 | return; | 403 | 0 | uint8_t cdp_flags = p_src[4]; | 404 | | | 405 | | /* skip header */ | 406 | 0 | p_src += 7; i_src -= 7; | 407 | | | 408 | | /* 5.3 time_code_section() */ | 409 | 0 | if( cdp_flags & CDP_FLAG_TIME_CODE_PRESENT ) | 410 | 0 | { | 411 | 0 | if( i_src < 5 ) // Shall be 5 bytes | 412 | 0 | return; | 413 | 0 | p_src += 5; i_src += 5; | 414 | 0 | } | 415 | | /* 5.4 ccdata_section */ | 416 | 0 | if( cdp_flags & CDP_FLAG_CC_DATA_PRESENT ) | 417 | 0 | { | 418 | | /* ccdata_section() | 419 | | * u8 0x72 | 420 | | * u3 marker bits(111) | 421 | | * u5 cc_count | 422 | | * for cc_count | 423 | | * u5 marker bits(1111 1) | 424 | | * u1 cc_valid | 425 | | * u2 cc_type | 426 | | * u8 cc_data_1 | 427 | | * u8 cc_data_2 | 428 | | */ | 429 | 0 | if( i_src < 2 || p_src[0] != 0x72 ) // marker | 430 | 0 | return; | 431 | | | 432 | 0 | const uint8_t *cc = &p_src[1]; | 433 | 0 | const int i_count_cc = cc[0]&0x1f; | 434 | |
| 435 | 0 | if( i_src - 2 < i_count_cc*3 ) // broken packet | 436 | 0 | return; | 437 | 0 | cc += 1; | 438 | 0 | for( int i = 0; i < i_count_cc; i++, cc += 3 ) | 439 | 0 | { | 440 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 441 | 0 | break; | 442 | 0 | } | 443 | 0 | } | 444 | | /* remaining data */ | 445 | 0 | c->b_reorder = false; | 446 | 0 | } | 447 | 29.6k | } |
Unexecuted instantiation: mpegvideo.c:cc_Extract Line | Count | Source | 222 | 21 | { | 223 | 21 | if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type ) | 224 | 0 | { | 225 | 0 | c->i_payload_other_count++; | 226 | 0 | if( c->i_payload_other_count < 50 ) | 227 | 0 | return; | 228 | 0 | } | 229 | 21 | c->i_payload_type = i_payload_type; | 230 | 21 | c->i_payload_other_count = 0; | 231 | | | 232 | 21 | if( i_payload_type == CC_PAYLOAD_RAW ) | 233 | 0 | { | 234 | 0 | for( int i = 0; i + 2 < i_src; i += 3 ) | 235 | 0 | { | 236 | 0 | const uint8_t *cc = &p_src[i]; | 237 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 238 | 0 | break; | 239 | 0 | } | 240 | 0 | c->b_reorder = true; | 241 | 0 | } | 242 | 21 | else if( i_payload_type == CC_PAYLOAD_GA94 ) | 243 | 21 | { | 244 | | /* cc_data() | 245 | | * u1 reserved(1) | 246 | | * u1 process_cc_data_flag | 247 | | * u1 additional_data_flag | 248 | | * u5 cc_count | 249 | | * u8 reserved(1111 1111) | 250 | | * for cc_count | 251 | | * u5 marker bit(1111 1) | 252 | | * u1 cc_valid | 253 | | * u2 cc_type | 254 | | * u8 cc_data_1 | 255 | | * u8 cc_data_2 | 256 | | * u8 marker bit(1111 1111) | 257 | | * if additional_data_flag | 258 | | * unknown | 259 | | */ | 260 | | /* cc_type: | 261 | | * 0x00: field 1 | 262 | | * 0x01: field 2 | 263 | | */ | 264 | 21 | if(i_src < 1) | 265 | 0 | return; | 266 | 21 | const uint8_t *cc = &p_src[0]; | 267 | 21 | const int i_count_cc = cc[0]&0x1f; | 268 | 21 | int i; | 269 | | | 270 | 21 | if( !(cc[0]&0x40) ) // process flag | 271 | 20 | return; | 272 | 1 | if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet | 273 | 0 | return; | 274 | 1 | if( i_count_cc <= 0 ) // no cc present | 275 | 0 | return; | 276 | 1 | if( cc[2+i_count_cc * 3] != 0xff ) // marker absent | 277 | 1 | return; | 278 | 0 | cc += 2; | 279 | |
| 280 | 0 | for( i = 0; i < i_count_cc; i++, cc += 3 ) | 281 | 0 | { | 282 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 283 | 0 | break; | 284 | 0 | } | 285 | 0 | c->b_reorder = true; | 286 | 0 | } | 287 | 0 | else if( i_payload_type == CC_PAYLOAD_DVD ) | 288 | 0 | { | 289 | | /* user_data | 290 | | * (u32 stripped earlier) | 291 | | * u32 (0x43 0x43 0x01 0xf8) | 292 | | * u1 caption_odd_field_first (CC1/CC2) | 293 | | * u1 caption_filler | 294 | | * u5 cc_block_count (== cc_count / 2) | 295 | | * u1 caption_extra_field_added (because odd cc_count) | 296 | | * for cc_block_count * 2 + caption_extra_field_added | 297 | | * u7 cc_filler_1 | 298 | | * u1 cc_field_is_odd | 299 | | * u8 cc_data_1 | 300 | | * u8 cc_data_2 | 301 | | */ | 302 | 0 | if(i_src < 6) | 303 | 0 | return; | 304 | 0 | const int b_truncate = p_src[4] & 0x01; | 305 | 0 | const int i_count_cc2 = ((p_src[4] >> 1) & 0x1f); | 306 | 0 | const uint8_t *cc = &p_src[5]; | 307 | 0 | i_src -= 5; | 308 | 0 | int i; | 309 | |
| 310 | 0 | #define CC_ALIGNMENT_TEST (0x7f) | 311 | |
| 312 | 0 | for( i = 0; i < 2*i_count_cc2 + b_truncate && i_src >= 3; i++, cc+=3 ) | 313 | 0 | { | 314 | 0 | if( (cc[0] >> 1) == CC_ALIGNMENT_TEST ) | 315 | 0 | { | 316 | 0 | const bool even_field = (cc[0] & 0x01) ? 0 : 1; | 317 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(even_field), &cc[1] )) | 318 | 0 | break; | 319 | 0 | } | 320 | 0 | i_src -= 3; | 321 | 0 | } | 322 | 0 | c->b_reorder = false; | 323 | 0 | } | 324 | 0 | else if( i_payload_type == CC_PAYLOAD_REPLAYTV ) | 325 | 0 | { | 326 | 0 | if(i_src < 1) | 327 | 0 | return; | 328 | 0 | const uint8_t *cc = &p_src[0]; | 329 | 0 | for( int i_cc_count = i_src >> 2; i_cc_count > 0; | 330 | 0 | i_cc_count--, cc += 4 ) | 331 | 0 | { | 332 | 0 | uint8_t i_field = (cc[0] & 0x02) >> 1; | 333 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] )) | 334 | 0 | return; | 335 | 0 | } | 336 | 0 | c->b_reorder = false; | 337 | 0 | } | 338 | 0 | else if( i_payload_type == CC_PAYLOAD_SCTE20 ) | 339 | 0 | { | 340 | | /* user_data(2) | 341 | | * (u32 stripped earlier) | 342 | | * u16 p_cc_scte20 | 343 | | * u5 cc_count | 344 | | * for cc_count | 345 | | * u2 cc_priority | 346 | | * u2 cc_field_num | 347 | | * u5 cc_line_offset | 348 | | * u8 cc_data_1[1:8] | 349 | | * u8 cc_data_2[1:8] | 350 | | * u1 marker bit | 351 | | * un additional_realtimevideodata | 352 | | * un reserved | 353 | | */ | 354 | 0 | if(i_src < 2) | 355 | 0 | return; | 356 | 0 | bs_t s; | 357 | 0 | bs_init( &s, &p_src[2], i_src - 2 ); | 358 | 0 | const int i_cc_count = bs_read( &s, 5 ); | 359 | 0 | for( int i = 0; i < i_cc_count; i++ ) | 360 | 0 | { | 361 | 0 | bs_skip( &s, 2 ); | 362 | 0 | const int i_field_idx = bs_read( &s, 2 ); | 363 | 0 | bs_skip( &s, 5 ); | 364 | 0 | uint8_t cc[2]; | 365 | 0 | for( int j = 0; j < 2; j++ ) | 366 | 0 | { | 367 | 0 | cc[j] = 0; | 368 | 0 | for( int k = 0; k < 8; k++ ) | 369 | 0 | cc[j] |= bs_read( &s, 1 ) << k; | 370 | 0 | } | 371 | 0 | bs_skip( &s, 1 ); | 372 | |
| 373 | 0 | if( i_field_idx == 0 ) | 374 | 0 | continue; | 375 | | | 376 | | /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */ | 377 | 0 | int i_field = ((i_field_idx - 1) & 1); | 378 | 0 | if (!b_top_field_first) | 379 | 0 | i_field ^= 1; | 380 | |
| 381 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] )) | 382 | 0 | continue; | 383 | 0 | } | 384 | 0 | c->b_reorder = true; | 385 | 0 | } | 386 | 0 | else // CC_PAYLOAD_CDP | 387 | 0 | { | 388 | 0 | # define CDP_FLAG_TIME_CODE_PRESENT (1<<7) | 389 | 0 | # define CDP_FLAG_CC_DATA_PRESENT (1<<6) | 390 | 0 | # define CDP_FLAG_SVC_INFO_PRESENT (1<<5) | 391 | 0 | # define CDP_FLAG_SVC_INFO_START (1<<4) | 392 | 0 | # define CDP_FLAG_SVC_INFO_CHANGE (1<<3) | 393 | 0 | # define CDP_FLAG_SVC_INFO_COMPLETE (1<<2) | 394 | 0 | # define CDP_FLAG_CAPTION_SVC_ACTIVE (1<<1) | 395 | |
| 396 | 0 | if(i_src < 7) | 397 | 0 | return; | 398 | | | 399 | | /* ST334-2 5.2 cdp_header() */ | 400 | 0 | uint8_t cdp_length = p_src[2]; | 401 | 0 | if(cdp_length < 8 || cdp_length > i_src) | 402 | 0 | return; | 403 | 0 | uint8_t cdp_flags = p_src[4]; | 404 | | | 405 | | /* skip header */ | 406 | 0 | p_src += 7; i_src -= 7; | 407 | | | 408 | | /* 5.3 time_code_section() */ | 409 | 0 | if( cdp_flags & CDP_FLAG_TIME_CODE_PRESENT ) | 410 | 0 | { | 411 | 0 | if( i_src < 5 ) // Shall be 5 bytes | 412 | 0 | return; | 413 | 0 | p_src += 5; i_src += 5; | 414 | 0 | } | 415 | | /* 5.4 ccdata_section */ | 416 | 0 | if( cdp_flags & CDP_FLAG_CC_DATA_PRESENT ) | 417 | 0 | { | 418 | | /* ccdata_section() | 419 | | * u8 0x72 | 420 | | * u3 marker bits(111) | 421 | | * u5 cc_count | 422 | | * for cc_count | 423 | | * u5 marker bits(1111 1) | 424 | | * u1 cc_valid | 425 | | * u2 cc_type | 426 | | * u8 cc_data_1 | 427 | | * u8 cc_data_2 | 428 | | */ | 429 | 0 | if( i_src < 2 || p_src[0] != 0x72 ) // marker | 430 | 0 | return; | 431 | | | 432 | 0 | const uint8_t *cc = &p_src[1]; | 433 | 0 | const int i_count_cc = cc[0]&0x1f; | 434 | |
| 435 | 0 | if( i_src - 2 < i_count_cc*3 ) // broken packet | 436 | 0 | return; | 437 | 0 | cc += 1; | 438 | 0 | for( int i = 0; i < i_count_cc; i++, cc += 3 ) | 439 | 0 | { | 440 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 441 | 0 | break; | 442 | 0 | } | 443 | 0 | } | 444 | | /* remaining data */ | 445 | 0 | c->b_reorder = false; | 446 | 0 | } | 447 | 21 | } |
|
448 | | |
449 | | |
450 | | static inline void cc_ProbeAndExtract( cc_data_t *c, bool b_top_field_first, const uint8_t *p_src, int i_src ) |
451 | 80 | { |
452 | 80 | static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 }; |
453 | 80 | static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 }; /* ascii 'CC', type_code, cc_block_size */ |
454 | 80 | static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };/* RTV4K, BB02xxxxCC02 */ |
455 | 80 | static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };/* see DVR-ClosedCaption in samples */ |
456 | 80 | static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };/* RTV5K, 9902xxxxAA02 */ |
457 | 80 | static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };/* see DVR-ClosedCaption in samples */ |
458 | 80 | static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 }; /* user_data_type_code, SCTE 20 */ |
459 | 80 | static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };/* user_data_type_code, old, Note 1 */ |
460 | | |
461 | 80 | if( i_src < 4 ) |
462 | 0 | return; |
463 | | |
464 | 80 | enum cc_payload_type_e i_payload_type; |
465 | 80 | if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 ) |
466 | 21 | { |
467 | | /* CC from DVB/ATSC TS */ |
468 | 21 | i_payload_type = CC_PAYLOAD_GA94; |
469 | 21 | i_src -= 5; |
470 | 21 | p_src += 5; |
471 | 21 | } |
472 | 59 | else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 ) |
473 | 0 | { |
474 | 0 | i_payload_type = CC_PAYLOAD_DVD; |
475 | 0 | } |
476 | 59 | else if( i_src >= 2+2 + 2+2 && |
477 | 40 | ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) || |
478 | 40 | ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) ) |
479 | 0 | { |
480 | 0 | i_payload_type = CC_PAYLOAD_REPLAYTV; |
481 | 0 | } |
482 | 59 | else if( ( !memcmp( p_cc_scte20, p_src, 2 ) || |
483 | 59 | !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 ) |
484 | 0 | { |
485 | 0 | i_payload_type = CC_PAYLOAD_SCTE20; |
486 | 0 | } |
487 | 59 | else if (p_src[0] == 0x03 && p_src[1] == i_src - 2) /* DIRECTV */ |
488 | 0 | { |
489 | 0 | i_payload_type = CC_PAYLOAD_GA94; |
490 | 0 | i_src -= 2; |
491 | 0 | p_src += 2; |
492 | 0 | } |
493 | 59 | else if (p_src[0] == 0x96 && p_src[1] == 0x69) /* CDP */ |
494 | 0 | { |
495 | 0 | i_payload_type = CC_PAYLOAD_CDP; |
496 | 0 | } |
497 | 59 | else |
498 | 59 | { |
499 | | #if 0 |
500 | | #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x ) |
501 | | fprintf( stderr, "-------------- unknown user data " ); |
502 | | for( int i = 0; i < i_src; i++ ) |
503 | | fprintf( stderr, "%2.2x ", p_src[i] ); |
504 | | for( int i = 0; i < i_src; i++ ) |
505 | | fprintf( stderr, "%c ", V(p_src[i]) ); |
506 | | fprintf( stderr, "\n" ); |
507 | | #undef V |
508 | | #endif |
509 | 59 | return; |
510 | 59 | } |
511 | | |
512 | 21 | cc_Extract( c, i_payload_type, b_top_field_first, p_src, i_src ); |
513 | 21 | } Unexecuted instantiation: mp4.c:cc_ProbeAndExtract Unexecuted instantiation: ty.c:cc_ProbeAndExtract Unexecuted instantiation: hxxx_common.c:cc_ProbeAndExtract Unexecuted instantiation: mpegvideo.c:cc_ProbeAndExtract Line | Count | Source | 451 | 80 | { | 452 | 80 | static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 }; | 453 | 80 | static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 }; /* ascii 'CC', type_code, cc_block_size */ | 454 | 80 | static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };/* RTV4K, BB02xxxxCC02 */ | 455 | 80 | static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };/* see DVR-ClosedCaption in samples */ | 456 | 80 | static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };/* RTV5K, 9902xxxxAA02 */ | 457 | 80 | static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };/* see DVR-ClosedCaption in samples */ | 458 | 80 | static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 }; /* user_data_type_code, SCTE 20 */ | 459 | 80 | static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };/* user_data_type_code, old, Note 1 */ | 460 | | | 461 | 80 | if( i_src < 4 ) | 462 | 0 | return; | 463 | | | 464 | 80 | enum cc_payload_type_e i_payload_type; | 465 | 80 | if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 ) | 466 | 21 | { | 467 | | /* CC from DVB/ATSC TS */ | 468 | 21 | i_payload_type = CC_PAYLOAD_GA94; | 469 | 21 | i_src -= 5; | 470 | 21 | p_src += 5; | 471 | 21 | } | 472 | 59 | else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 ) | 473 | 0 | { | 474 | 0 | i_payload_type = CC_PAYLOAD_DVD; | 475 | 0 | } | 476 | 59 | else if( i_src >= 2+2 + 2+2 && | 477 | 40 | ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) || | 478 | 40 | ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) ) | 479 | 0 | { | 480 | 0 | i_payload_type = CC_PAYLOAD_REPLAYTV; | 481 | 0 | } | 482 | 59 | else if( ( !memcmp( p_cc_scte20, p_src, 2 ) || | 483 | 59 | !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 ) | 484 | 0 | { | 485 | 0 | i_payload_type = CC_PAYLOAD_SCTE20; | 486 | 0 | } | 487 | 59 | else if (p_src[0] == 0x03 && p_src[1] == i_src - 2) /* DIRECTV */ | 488 | 0 | { | 489 | 0 | i_payload_type = CC_PAYLOAD_GA94; | 490 | 0 | i_src -= 2; | 491 | 0 | p_src += 2; | 492 | 0 | } | 493 | 59 | else if (p_src[0] == 0x96 && p_src[1] == 0x69) /* CDP */ | 494 | 0 | { | 495 | 0 | i_payload_type = CC_PAYLOAD_CDP; | 496 | 0 | } | 497 | 59 | else | 498 | 59 | { | 499 | | #if 0 | 500 | | #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x ) | 501 | | fprintf( stderr, "-------------- unknown user data " ); | 502 | | for( int i = 0; i < i_src; i++ ) | 503 | | fprintf( stderr, "%2.2x ", p_src[i] ); | 504 | | for( int i = 0; i < i_src; i++ ) | 505 | | fprintf( stderr, "%c ", V(p_src[i]) ); | 506 | | fprintf( stderr, "\n" ); | 507 | | #undef V | 508 | | #endif | 509 | 59 | return; | 510 | 59 | } | 511 | | | 512 | 21 | cc_Extract( c, i_payload_type, b_top_field_first, p_src, i_src ); | 513 | 21 | } |
|
514 | | |
515 | | #endif /* _CC_H */ |
516 | | |