/src/vlc/modules/codec/cc.h
Line | Count | Source (jump to first uncovered line) |
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 | 14.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 | 51.5k | { |
79 | 51.5k | c->i_608channels = 0; |
80 | 51.5k | c->i_708channels = 0; |
81 | 51.5k | c->i_data = 0; |
82 | 51.5k | c->b_reorder = false; |
83 | 51.5k | c->cea708.pktsize = 0; |
84 | 51.5k | c->cea708.seq = 0; |
85 | 51.5k | c->cea708.sid_bs = 0; |
86 | 51.5k | c->cea708.state = CEA708_PKT_END; |
87 | 51.5k | c->i_payload_type = CC_PAYLOAD_NONE; |
88 | 51.5k | c->i_payload_other_count = 0; |
89 | 51.5k | } Unexecuted instantiation: mp4.c:cc_Init Line | Count | Source | 78 | 391 | { | 79 | 391 | c->i_608channels = 0; | 80 | 391 | c->i_708channels = 0; | 81 | 391 | c->i_data = 0; | 82 | 391 | c->b_reorder = false; | 83 | 391 | c->cea708.pktsize = 0; | 84 | 391 | c->cea708.seq = 0; | 85 | 391 | c->cea708.sid_bs = 0; | 86 | 391 | c->cea708.state = CEA708_PKT_END; | 87 | 391 | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 391 | c->i_payload_other_count = 0; | 89 | 391 | } |
Line | Count | Source | 78 | 48.4k | { | 79 | 48.4k | c->i_608channels = 0; | 80 | 48.4k | c->i_708channels = 0; | 81 | 48.4k | c->i_data = 0; | 82 | 48.4k | c->b_reorder = false; | 83 | 48.4k | c->cea708.pktsize = 0; | 84 | 48.4k | c->cea708.seq = 0; | 85 | 48.4k | c->cea708.sid_bs = 0; | 86 | 48.4k | c->cea708.state = CEA708_PKT_END; | 87 | 48.4k | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 48.4k | c->i_payload_other_count = 0; | 89 | 48.4k | } |
Line | Count | Source | 78 | 1.49k | { | 79 | 1.49k | c->i_608channels = 0; | 80 | 1.49k | c->i_708channels = 0; | 81 | 1.49k | c->i_data = 0; | 82 | 1.49k | c->b_reorder = false; | 83 | 1.49k | c->cea708.pktsize = 0; | 84 | 1.49k | c->cea708.seq = 0; | 85 | 1.49k | c->cea708.sid_bs = 0; | 86 | 1.49k | c->cea708.state = CEA708_PKT_END; | 87 | 1.49k | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 1.49k | c->i_payload_other_count = 0; | 89 | 1.49k | } |
Line | Count | Source | 78 | 1.16k | { | 79 | 1.16k | c->i_608channels = 0; | 80 | 1.16k | c->i_708channels = 0; | 81 | 1.16k | c->i_data = 0; | 82 | 1.16k | c->b_reorder = false; | 83 | 1.16k | c->cea708.pktsize = 0; | 84 | 1.16k | c->cea708.seq = 0; | 85 | 1.16k | c->cea708.sid_bs = 0; | 86 | 1.16k | c->cea708.state = CEA708_PKT_END; | 87 | 1.16k | c->i_payload_type = CC_PAYLOAD_NONE; | 88 | 1.16k | c->i_payload_other_count = 0; | 89 | 1.16k | } |
|
90 | | static inline void cc_Exit( cc_data_t *c ) |
91 | 50.0k | { |
92 | 50.0k | VLC_UNUSED(c); |
93 | 50.0k | return; |
94 | 50.0k | } Unexecuted instantiation: mp4.c:cc_Exit Line | Count | Source | 91 | 391 | { | 92 | 391 | VLC_UNUSED(c); | 93 | 391 | return; | 94 | 391 | } |
Line | Count | Source | 91 | 48.4k | { | 92 | 48.4k | VLC_UNUSED(c); | 93 | 48.4k | return; | 94 | 48.4k | } |
Unexecuted instantiation: mpegvideo.c:cc_Exit Line | Count | Source | 91 | 1.16k | { | 92 | 1.16k | VLC_UNUSED(c); | 93 | 1.16k | return; | 94 | 1.16k | } |
|
95 | | static inline void cc_Flush( cc_data_t *c ) |
96 | 661k | { |
97 | 661k | c->i_data = 0; |
98 | 661k | c->cea708.state = CEA708_PKT_END; |
99 | 661k | } Unexecuted instantiation: mp4.c:cc_Flush Line | Count | Source | 96 | 1.17k | { | 97 | 1.17k | c->i_data = 0; | 98 | 1.17k | c->cea708.state = CEA708_PKT_END; | 99 | 1.17k | } |
Line | Count | Source | 96 | 659k | { | 97 | 659k | c->i_data = 0; | 98 | 659k | c->cea708.state = CEA708_PKT_END; | 99 | 659k | } |
Unexecuted instantiation: mpegvideo.c:cc_Flush Line | Count | Source | 96 | 875 | { | 97 | 875 | c->i_data = 0; | 98 | 875 | c->cea708.state = CEA708_PKT_END; | 99 | 875 | } |
|
100 | | |
101 | | static inline void cc_ProbeCEA708OneByte( cc_data_t *c, bool b_start, const uint8_t cc ) |
102 | 56.4k | { |
103 | 56.4k | if( b_start ) |
104 | 18.0k | { |
105 | 18.0k | const uint8_t i_pkt_sequence = cc >> 6; |
106 | 18.0k | if( i_pkt_sequence > 0 && ((c->cea708.seq + 1) % 4) != i_pkt_sequence ) |
107 | 11.1k | { |
108 | 11.1k | c->cea708.pktsize = 0; |
109 | 11.1k | c->cea708.seq = i_pkt_sequence; |
110 | 11.1k | c->cea708.state = CEA708_PKT_END; |
111 | 11.1k | } |
112 | 6.90k | else |
113 | 6.90k | { |
114 | 6.90k | c->cea708.seq = i_pkt_sequence; |
115 | 6.90k | c->cea708.pktsize = cc & 63; |
116 | 6.90k | if( c->cea708.pktsize == 0 ) |
117 | 2.77k | c->cea708.pktsize = 127; |
118 | 4.12k | else |
119 | 4.12k | c->cea708.pktsize = c->cea708.pktsize * 2 - 1; |
120 | 6.90k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; |
121 | 6.90k | } |
122 | 18.0k | } |
123 | 38.3k | else if( c->cea708.pktsize == 0 ) /* empty pkt reading service blocks */ |
124 | 13.9k | { |
125 | 13.9k | c->cea708.state = CEA708_PKT_END; |
126 | 13.9k | } |
127 | 24.3k | else if( c->cea708.state != CEA708_PKT_END ) |
128 | 17.6k | { |
129 | 17.6k | switch( c->cea708.state ) |
130 | 17.6k | { |
131 | 7.80k | case CEA708_PKT_WAIT_BLOCK_HEADER: /* Byte is service block header */ |
132 | 7.80k | { |
133 | 7.80k | uint8_t i_sid = cc >> 5; |
134 | 7.80k | c->cea708.sid_bs = cc & 0x1F; |
135 | 7.80k | if( i_sid != 0x00 && c->cea708.sid_bs != 0 ) |
136 | 5.30k | { |
137 | 5.30k | if( i_sid != 0x07 ) |
138 | 2.82k | { |
139 | 2.82k | const uint8_t mask = (1 << --i_sid); |
140 | 2.82k | c->i_708channels |= (mask + (mask - 1)); |
141 | 2.82k | c->cea708.state = CEA708_PKT_IN_BLOCK; |
142 | 2.82k | } |
143 | 2.47k | else if( c->cea708.sid_bs < 2 ) |
144 | 331 | { |
145 | 331 | c->cea708.state = CEA708_PKT_END; |
146 | 331 | } |
147 | 2.14k | else |
148 | 2.14k | { |
149 | | /* need to look up next byte in next pkt */ |
150 | 2.14k | c->cea708.state = CEA708_PKT_WAIT_EXT_BLOCK_HEADER; |
151 | 2.14k | } |
152 | 5.30k | } |
153 | 2.50k | else c->cea708.state = CEA708_PKT_END; |
154 | 7.80k | } break; |
155 | | |
156 | 938 | case CEA708_PKT_WAIT_EXT_BLOCK_HEADER: |
157 | 938 | { |
158 | 938 | uint8_t i_extsid = cc & 0x3F; |
159 | 938 | if( i_extsid >= 0x07 ) |
160 | 658 | { |
161 | 658 | const uint64_t mask = (INT64_C(1) << --i_extsid); |
162 | 658 | c->i_708channels |= (mask + (mask - 1)); |
163 | 658 | } |
164 | 938 | if( c->cea708.sid_bs == 0 ) |
165 | 0 | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; |
166 | 938 | else |
167 | 938 | c->cea708.state = CEA708_PKT_IN_BLOCK; |
168 | 938 | } break; |
169 | | |
170 | 8.92k | case CEA708_PKT_IN_BLOCK: |
171 | 8.92k | { |
172 | 8.92k | c->cea708.sid_bs--; |
173 | 8.92k | if( c->cea708.sid_bs == 0 ) |
174 | 1.16k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; |
175 | 8.92k | } break; |
176 | | |
177 | 0 | default: |
178 | 0 | vlc_assert_unreachable(); |
179 | 0 | break; |
180 | 17.6k | } |
181 | 17.6k | c->cea708.pktsize--; |
182 | | |
183 | 17.6k | if(c->cea708.pktsize == 0) |
184 | 354 | c->cea708.state = CEA708_PKT_END; |
185 | 17.6k | } |
186 | 56.4k | } Unexecuted instantiation: mp4.c:cc_ProbeCEA708OneByte Unexecuted instantiation: ty.c:cc_ProbeCEA708OneByte hxxx_common.c:cc_ProbeCEA708OneByte Line | Count | Source | 102 | 56.4k | { | 103 | 56.4k | if( b_start ) | 104 | 18.0k | { | 105 | 18.0k | const uint8_t i_pkt_sequence = cc >> 6; | 106 | 18.0k | if( i_pkt_sequence > 0 && ((c->cea708.seq + 1) % 4) != i_pkt_sequence ) | 107 | 11.1k | { | 108 | 11.1k | c->cea708.pktsize = 0; | 109 | 11.1k | c->cea708.seq = i_pkt_sequence; | 110 | 11.1k | c->cea708.state = CEA708_PKT_END; | 111 | 11.1k | } | 112 | 6.90k | else | 113 | 6.90k | { | 114 | 6.90k | c->cea708.seq = i_pkt_sequence; | 115 | 6.90k | c->cea708.pktsize = cc & 63; | 116 | 6.90k | if( c->cea708.pktsize == 0 ) | 117 | 2.77k | c->cea708.pktsize = 127; | 118 | 4.12k | else | 119 | 4.12k | c->cea708.pktsize = c->cea708.pktsize * 2 - 1; | 120 | 6.90k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; | 121 | 6.90k | } | 122 | 18.0k | } | 123 | 38.3k | else if( c->cea708.pktsize == 0 ) /* empty pkt reading service blocks */ | 124 | 13.9k | { | 125 | 13.9k | c->cea708.state = CEA708_PKT_END; | 126 | 13.9k | } | 127 | 24.3k | else if( c->cea708.state != CEA708_PKT_END ) | 128 | 17.6k | { | 129 | 17.6k | switch( c->cea708.state ) | 130 | 17.6k | { | 131 | 7.80k | case CEA708_PKT_WAIT_BLOCK_HEADER: /* Byte is service block header */ | 132 | 7.80k | { | 133 | 7.80k | uint8_t i_sid = cc >> 5; | 134 | 7.80k | c->cea708.sid_bs = cc & 0x1F; | 135 | 7.80k | if( i_sid != 0x00 && c->cea708.sid_bs != 0 ) | 136 | 5.30k | { | 137 | 5.30k | if( i_sid != 0x07 ) | 138 | 2.82k | { | 139 | 2.82k | const uint8_t mask = (1 << --i_sid); | 140 | 2.82k | c->i_708channels |= (mask + (mask - 1)); | 141 | 2.82k | c->cea708.state = CEA708_PKT_IN_BLOCK; | 142 | 2.82k | } | 143 | 2.47k | else if( c->cea708.sid_bs < 2 ) | 144 | 331 | { | 145 | 331 | c->cea708.state = CEA708_PKT_END; | 146 | 331 | } | 147 | 2.14k | else | 148 | 2.14k | { | 149 | | /* need to look up next byte in next pkt */ | 150 | 2.14k | c->cea708.state = CEA708_PKT_WAIT_EXT_BLOCK_HEADER; | 151 | 2.14k | } | 152 | 5.30k | } | 153 | 2.50k | else c->cea708.state = CEA708_PKT_END; | 154 | 7.80k | } break; | 155 | | | 156 | 938 | case CEA708_PKT_WAIT_EXT_BLOCK_HEADER: | 157 | 938 | { | 158 | 938 | uint8_t i_extsid = cc & 0x3F; | 159 | 938 | if( i_extsid >= 0x07 ) | 160 | 658 | { | 161 | 658 | const uint64_t mask = (INT64_C(1) << --i_extsid); | 162 | 658 | c->i_708channels |= (mask + (mask - 1)); | 163 | 658 | } | 164 | 938 | if( c->cea708.sid_bs == 0 ) | 165 | 0 | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; | 166 | 938 | else | 167 | 938 | c->cea708.state = CEA708_PKT_IN_BLOCK; | 168 | 938 | } break; | 169 | | | 170 | 8.92k | case CEA708_PKT_IN_BLOCK: | 171 | 8.92k | { | 172 | 8.92k | c->cea708.sid_bs--; | 173 | 8.92k | if( c->cea708.sid_bs == 0 ) | 174 | 1.16k | c->cea708.state = CEA708_PKT_WAIT_BLOCK_HEADER; | 175 | 8.92k | } break; | 176 | | | 177 | 0 | default: | 178 | 0 | vlc_assert_unreachable(); | 179 | 0 | break; | 180 | 17.6k | } | 181 | 17.6k | c->cea708.pktsize--; | 182 | | | 183 | 17.6k | if(c->cea708.pktsize == 0) | 184 | 354 | c->cea708.state = CEA708_PKT_END; | 185 | 17.6k | } | 186 | 56.4k | } |
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 | 28.2k | { |
190 | 28.2k | if( i_field == 3 ) /* DTVCC_PACKET_START */ |
191 | 18.0k | cc_ProbeCEA708OneByte( c, true, cc[0] ); |
192 | 10.1k | else /* DTVCC_PACKET_DATA */ |
193 | 10.1k | cc_ProbeCEA708OneByte( c, false, cc[0] ); |
194 | 28.2k | cc_ProbeCEA708OneByte( c, false, cc[1] ); |
195 | 28.2k | } Unexecuted instantiation: mp4.c:cc_ProbeCEA708 Unexecuted instantiation: ty.c:cc_ProbeCEA708 hxxx_common.c:cc_ProbeCEA708 Line | Count | Source | 189 | 28.2k | { | 190 | 28.2k | if( i_field == 3 ) /* DTVCC_PACKET_START */ | 191 | 18.0k | cc_ProbeCEA708OneByte( c, true, cc[0] ); | 192 | 10.1k | else /* DTVCC_PACKET_DATA */ | 193 | 10.1k | cc_ProbeCEA708OneByte( c, false, cc[0] ); | 194 | 28.2k | cc_ProbeCEA708OneByte( c, false, cc[1] ); | 195 | 28.2k | } |
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 | 51.5k | { |
199 | 51.5k | if (c->i_data + 3 > ARRAY_SIZE(c->p_data)) |
200 | 239 | return false; |
201 | | |
202 | 51.2k | const uint8_t i_field = cc_preamble & 0x03; |
203 | 51.2k | if( i_field == 0 || i_field == 1 ) /* NTSC_CC_FIELD_1 NTSC_CC_FIELD_2 */ |
204 | 23.0k | { |
205 | 23.0k | c->i_608channels |= (3 << (2 * i_field)); |
206 | 23.0k | } |
207 | 28.2k | else |
208 | 28.2k | { |
209 | 28.2k | cc_ProbeCEA708( c, i_field, cc ); |
210 | | /* By default enable at least channel 1 */ |
211 | 28.2k | c->i_708channels |= 1; |
212 | 28.2k | } |
213 | | |
214 | 51.2k | c->p_data[c->i_data++] = cc_preamble; |
215 | 51.2k | c->p_data[c->i_data++] = cc[0]; |
216 | 51.2k | c->p_data[c->i_data++] = cc[1]; |
217 | 51.2k | return true; |
218 | 51.5k | } Unexecuted instantiation: mp4.c:cc_AppendData Line | Count | Source | 198 | 14.9k | { | 199 | 14.9k | if (c->i_data + 3 > ARRAY_SIZE(c->p_data)) | 200 | 0 | return false; | 201 | | | 202 | 14.9k | const uint8_t i_field = cc_preamble & 0x03; | 203 | 14.9k | if( i_field == 0 || i_field == 1 ) /* NTSC_CC_FIELD_1 NTSC_CC_FIELD_2 */ | 204 | 14.9k | { | 205 | 14.9k | c->i_608channels |= (3 << (2 * i_field)); | 206 | 14.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 | 14.9k | c->p_data[c->i_data++] = cc_preamble; | 215 | 14.9k | c->p_data[c->i_data++] = cc[0]; | 216 | 14.9k | c->p_data[c->i_data++] = cc[1]; | 217 | 14.9k | return true; | 218 | 14.9k | } |
hxxx_common.c:cc_AppendData Line | Count | Source | 198 | 36.5k | { | 199 | 36.5k | if (c->i_data + 3 > ARRAY_SIZE(c->p_data)) | 200 | 239 | return false; | 201 | | | 202 | 36.2k | const uint8_t i_field = cc_preamble & 0x03; | 203 | 36.2k | if( i_field == 0 || i_field == 1 ) /* NTSC_CC_FIELD_1 NTSC_CC_FIELD_2 */ | 204 | 8.07k | { | 205 | 8.07k | c->i_608channels |= (3 << (2 * i_field)); | 206 | 8.07k | } | 207 | 28.2k | else | 208 | 28.2k | { | 209 | 28.2k | cc_ProbeCEA708( c, i_field, cc ); | 210 | | /* By default enable at least channel 1 */ | 211 | 28.2k | c->i_708channels |= 1; | 212 | 28.2k | } | 213 | | | 214 | 36.2k | c->p_data[c->i_data++] = cc_preamble; | 215 | 36.2k | c->p_data[c->i_data++] = cc[0]; | 216 | 36.2k | c->p_data[c->i_data++] = cc[1]; | 217 | 36.2k | return true; | 218 | 36.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 | 14.5k | { |
223 | 14.5k | if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type ) |
224 | 1 | { |
225 | 1 | c->i_payload_other_count++; |
226 | 1 | if( c->i_payload_other_count < 50 ) |
227 | 0 | return; |
228 | 1 | } |
229 | 14.5k | c->i_payload_type = i_payload_type; |
230 | 14.5k | c->i_payload_other_count = 0; |
231 | | |
232 | 14.5k | 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 | 14.5k | else if( i_payload_type == CC_PAYLOAD_GA94 ) |
243 | 14.5k | { |
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 | 14.5k | const uint8_t *cc = &p_src[0]; |
265 | 14.5k | const int i_count_cc = cc[0]&0x1f; |
266 | 14.5k | int i; |
267 | | |
268 | 14.5k | if( !(cc[0]&0x40) ) // process flag |
269 | 1.23k | return; |
270 | 13.3k | if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet |
271 | 725 | return; |
272 | 12.6k | if( i_count_cc <= 0 ) // no cc present |
273 | 477 | return; |
274 | 12.1k | if( cc[2+i_count_cc * 3] != 0xff ) // marker absent |
275 | 1.39k | return; |
276 | 10.7k | cc += 2; |
277 | | |
278 | 47.0k | for( i = 0; i < i_count_cc; i++, cc += 3 ) |
279 | 36.5k | { |
280 | 36.5k | if (!cc_AppendData( c, cc[0], &cc[1] )) |
281 | 239 | break; |
282 | 36.5k | } |
283 | 10.7k | c->b_reorder = true; |
284 | 10.7k | } |
285 | 0 | else if( i_payload_type == CC_PAYLOAD_DVD ) |
286 | 0 | { |
287 | | /* user_data |
288 | | * (u32 stripped earlier) |
289 | | * u32 (0x43 0x43 0x01 0xf8) |
290 | | * u1 caption_odd_field_first (CC1/CC2) |
291 | | * u1 caption_filler |
292 | | * u5 cc_block_count (== cc_count / 2) |
293 | | * u1 caption_extra_field_added (because odd cc_count) |
294 | | * for cc_block_count * 2 + caption_extra_field_added |
295 | | * u7 cc_filler_1 |
296 | | * u1 cc_field_is_odd |
297 | | * u8 cc_data_1 |
298 | | * u8 cc_data_2 |
299 | | */ |
300 | 0 | const int b_truncate = p_src[4] & 0x01; |
301 | 0 | const int i_count_cc2 = ((p_src[4] >> 1) & 0x1f); |
302 | 0 | const uint8_t *cc = &p_src[5]; |
303 | 0 | i_src -= 5; |
304 | 0 | int i; |
305 | |
|
306 | 0 | #define CC_ALIGNMENT_TEST (0x7f) |
307 | |
|
308 | 0 | for( i = 0; i < 2*i_count_cc2 + b_truncate && i_src >= 3; i++, cc+=3 ) |
309 | 0 | { |
310 | 0 | if( (cc[0] >> 1) == CC_ALIGNMENT_TEST ) |
311 | 0 | { |
312 | 0 | const bool even_field = (cc[0] & 0x01) ? 0 : 1; |
313 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(even_field), &cc[1] )) |
314 | 0 | break; |
315 | 0 | } |
316 | 0 | i_src -= 3; |
317 | 0 | } |
318 | 0 | c->b_reorder = false; |
319 | 0 | } |
320 | 0 | else if( i_payload_type == CC_PAYLOAD_REPLAYTV ) |
321 | 0 | { |
322 | 0 | const uint8_t *cc = &p_src[0]; |
323 | 0 | for( int i_cc_count = i_src >> 2; i_cc_count > 0; |
324 | 0 | i_cc_count--, cc += 4 ) |
325 | 0 | { |
326 | 0 | uint8_t i_field = (cc[0] & 0x02) >> 1; |
327 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] )) |
328 | 0 | return; |
329 | 0 | } |
330 | 0 | c->b_reorder = false; |
331 | 0 | } |
332 | 0 | else if( i_payload_type == CC_PAYLOAD_SCTE20 ) |
333 | 0 | { |
334 | | /* user_data(2) |
335 | | * (u32 stripped earlier) |
336 | | * u16 p_cc_scte20 |
337 | | * u5 cc_count |
338 | | * for cc_count |
339 | | * u2 cc_priority |
340 | | * u2 cc_field_num |
341 | | * u5 cc_line_offset |
342 | | * u8 cc_data_1[1:8] |
343 | | * u8 cc_data_2[1:8] |
344 | | * u1 marker bit |
345 | | * un additional_realtimevideodata |
346 | | * un reserved |
347 | | */ |
348 | 0 | bs_t s; |
349 | 0 | bs_init( &s, &p_src[2], i_src - 2 ); |
350 | 0 | const int i_cc_count = bs_read( &s, 5 ); |
351 | 0 | for( int i = 0; i < i_cc_count; i++ ) |
352 | 0 | { |
353 | 0 | bs_skip( &s, 2 ); |
354 | 0 | const int i_field_idx = bs_read( &s, 2 ); |
355 | 0 | bs_skip( &s, 5 ); |
356 | 0 | uint8_t cc[2]; |
357 | 0 | for( int j = 0; j < 2; j++ ) |
358 | 0 | { |
359 | 0 | cc[j] = 0; |
360 | 0 | for( int k = 0; k < 8; k++ ) |
361 | 0 | cc[j] |= bs_read( &s, 1 ) << k; |
362 | 0 | } |
363 | 0 | bs_skip( &s, 1 ); |
364 | |
|
365 | 0 | if( i_field_idx == 0 ) |
366 | 0 | continue; |
367 | | |
368 | | /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */ |
369 | 0 | int i_field = ((i_field_idx - 1) & 1); |
370 | 0 | if (!b_top_field_first) |
371 | 0 | i_field ^= 1; |
372 | |
|
373 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] )) |
374 | 0 | continue; |
375 | 0 | } |
376 | 0 | c->b_reorder = true; |
377 | 0 | } |
378 | 0 | else // CC_PAYLOAD_CDP |
379 | 0 | { |
380 | 0 | # define CDP_FLAG_TIME_CODE_PRESENT (1<<7) |
381 | 0 | # define CDP_FLAG_CC_DATA_PRESENT (1<<6) |
382 | 0 | # define CDP_FLAG_SVC_INFO_PRESENT (1<<5) |
383 | 0 | # define CDP_FLAG_SVC_INFO_START (1<<4) |
384 | 0 | # define CDP_FLAG_SVC_INFO_CHANGE (1<<3) |
385 | 0 | # define CDP_FLAG_SVC_INFO_COMPLETE (1<<2) |
386 | 0 | # define CDP_FLAG_CAPTION_SVC_ACTIVE (1<<1) |
387 | |
|
388 | 0 | if(i_src < 7) |
389 | 0 | return; |
390 | | |
391 | | /* ST334-2 5.2 cdp_header() */ |
392 | 0 | uint8_t cdp_length = p_src[2]; |
393 | 0 | if(cdp_length < 8 || cdp_length > i_src) |
394 | 0 | return; |
395 | 0 | uint8_t cdp_flags = p_src[4]; |
396 | | |
397 | | /* skip header */ |
398 | 0 | p_src += 7; i_src -= 7; |
399 | | |
400 | | /* 5.3 time_code_section() */ |
401 | 0 | if( cdp_flags & CDP_FLAG_TIME_CODE_PRESENT ) |
402 | 0 | { |
403 | 0 | if( i_src < 5 ) // Shall be 5 bytes |
404 | 0 | return; |
405 | 0 | p_src += 5; i_src += 5; |
406 | 0 | } |
407 | | /* 5.4 ccdata_section */ |
408 | 0 | if( cdp_flags & CDP_FLAG_CC_DATA_PRESENT ) |
409 | 0 | { |
410 | | /* ccdata_section() |
411 | | * u8 0x72 |
412 | | * u3 marker bits(111) |
413 | | * u5 cc_count |
414 | | * for cc_count |
415 | | * u5 marker bits(1111 1) |
416 | | * u1 cc_valid |
417 | | * u2 cc_type |
418 | | * u8 cc_data_1 |
419 | | * u8 cc_data_2 |
420 | | */ |
421 | 0 | if( i_src < 2 || p_src[0] != 0x72 ) // marker |
422 | 0 | return; |
423 | | |
424 | 0 | const uint8_t *cc = &p_src[1]; |
425 | 0 | const int i_count_cc = cc[0]&0x1f; |
426 | |
|
427 | 0 | if( i_src - 2 < i_count_cc*3 ) // broken packet |
428 | 0 | return; |
429 | 0 | cc += 1; |
430 | 0 | for( int i = 0; i < i_count_cc; i++, cc += 3 ) |
431 | 0 | { |
432 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) |
433 | 0 | break; |
434 | 0 | } |
435 | 0 | } |
436 | | /* remaining data */ |
437 | 0 | c->b_reorder = false; |
438 | 0 | } |
439 | 14.5k | } Unexecuted instantiation: mp4.c:cc_Extract Unexecuted instantiation: ty.c:cc_Extract Line | Count | Source | 222 | 14.5k | { | 223 | 14.5k | 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 | 14.5k | c->i_payload_type = i_payload_type; | 230 | 14.5k | c->i_payload_other_count = 0; | 231 | | | 232 | 14.5k | 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 | 14.5k | else if( i_payload_type == CC_PAYLOAD_GA94 ) | 243 | 14.5k | { | 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 | 14.5k | const uint8_t *cc = &p_src[0]; | 265 | 14.5k | const int i_count_cc = cc[0]&0x1f; | 266 | 14.5k | int i; | 267 | | | 268 | 14.5k | if( !(cc[0]&0x40) ) // process flag | 269 | 1.21k | return; | 270 | 13.3k | if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet | 271 | 725 | return; | 272 | 12.6k | if( i_count_cc <= 0 ) // no cc present | 273 | 477 | return; | 274 | 12.1k | if( cc[2+i_count_cc * 3] != 0xff ) // marker absent | 275 | 1.39k | return; | 276 | 10.7k | cc += 2; | 277 | | | 278 | 47.0k | for( i = 0; i < i_count_cc; i++, cc += 3 ) | 279 | 36.5k | { | 280 | 36.5k | if (!cc_AppendData( c, cc[0], &cc[1] )) | 281 | 239 | break; | 282 | 36.5k | } | 283 | 10.7k | c->b_reorder = true; | 284 | 10.7k | } | 285 | 0 | else if( i_payload_type == CC_PAYLOAD_DVD ) | 286 | 0 | { | 287 | | /* user_data | 288 | | * (u32 stripped earlier) | 289 | | * u32 (0x43 0x43 0x01 0xf8) | 290 | | * u1 caption_odd_field_first (CC1/CC2) | 291 | | * u1 caption_filler | 292 | | * u5 cc_block_count (== cc_count / 2) | 293 | | * u1 caption_extra_field_added (because odd cc_count) | 294 | | * for cc_block_count * 2 + caption_extra_field_added | 295 | | * u7 cc_filler_1 | 296 | | * u1 cc_field_is_odd | 297 | | * u8 cc_data_1 | 298 | | * u8 cc_data_2 | 299 | | */ | 300 | 0 | const int b_truncate = p_src[4] & 0x01; | 301 | 0 | const int i_count_cc2 = ((p_src[4] >> 1) & 0x1f); | 302 | 0 | const uint8_t *cc = &p_src[5]; | 303 | 0 | i_src -= 5; | 304 | 0 | int i; | 305 | |
| 306 | 0 | #define CC_ALIGNMENT_TEST (0x7f) | 307 | |
| 308 | 0 | for( i = 0; i < 2*i_count_cc2 + b_truncate && i_src >= 3; i++, cc+=3 ) | 309 | 0 | { | 310 | 0 | if( (cc[0] >> 1) == CC_ALIGNMENT_TEST ) | 311 | 0 | { | 312 | 0 | const bool even_field = (cc[0] & 0x01) ? 0 : 1; | 313 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(even_field), &cc[1] )) | 314 | 0 | break; | 315 | 0 | } | 316 | 0 | i_src -= 3; | 317 | 0 | } | 318 | 0 | c->b_reorder = false; | 319 | 0 | } | 320 | 0 | else if( i_payload_type == CC_PAYLOAD_REPLAYTV ) | 321 | 0 | { | 322 | 0 | const uint8_t *cc = &p_src[0]; | 323 | 0 | for( int i_cc_count = i_src >> 2; i_cc_count > 0; | 324 | 0 | i_cc_count--, cc += 4 ) | 325 | 0 | { | 326 | 0 | uint8_t i_field = (cc[0] & 0x02) >> 1; | 327 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] )) | 328 | 0 | return; | 329 | 0 | } | 330 | 0 | c->b_reorder = false; | 331 | 0 | } | 332 | 0 | else if( i_payload_type == CC_PAYLOAD_SCTE20 ) | 333 | 0 | { | 334 | | /* user_data(2) | 335 | | * (u32 stripped earlier) | 336 | | * u16 p_cc_scte20 | 337 | | * u5 cc_count | 338 | | * for cc_count | 339 | | * u2 cc_priority | 340 | | * u2 cc_field_num | 341 | | * u5 cc_line_offset | 342 | | * u8 cc_data_1[1:8] | 343 | | * u8 cc_data_2[1:8] | 344 | | * u1 marker bit | 345 | | * un additional_realtimevideodata | 346 | | * un reserved | 347 | | */ | 348 | 0 | bs_t s; | 349 | 0 | bs_init( &s, &p_src[2], i_src - 2 ); | 350 | 0 | const int i_cc_count = bs_read( &s, 5 ); | 351 | 0 | for( int i = 0; i < i_cc_count; i++ ) | 352 | 0 | { | 353 | 0 | bs_skip( &s, 2 ); | 354 | 0 | const int i_field_idx = bs_read( &s, 2 ); | 355 | 0 | bs_skip( &s, 5 ); | 356 | 0 | uint8_t cc[2]; | 357 | 0 | for( int j = 0; j < 2; j++ ) | 358 | 0 | { | 359 | 0 | cc[j] = 0; | 360 | 0 | for( int k = 0; k < 8; k++ ) | 361 | 0 | cc[j] |= bs_read( &s, 1 ) << k; | 362 | 0 | } | 363 | 0 | bs_skip( &s, 1 ); | 364 | |
| 365 | 0 | if( i_field_idx == 0 ) | 366 | 0 | continue; | 367 | | | 368 | | /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */ | 369 | 0 | int i_field = ((i_field_idx - 1) & 1); | 370 | 0 | if (!b_top_field_first) | 371 | 0 | i_field ^= 1; | 372 | |
| 373 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] )) | 374 | 0 | continue; | 375 | 0 | } | 376 | 0 | c->b_reorder = true; | 377 | 0 | } | 378 | 0 | else // CC_PAYLOAD_CDP | 379 | 0 | { | 380 | 0 | # define CDP_FLAG_TIME_CODE_PRESENT (1<<7) | 381 | 0 | # define CDP_FLAG_CC_DATA_PRESENT (1<<6) | 382 | 0 | # define CDP_FLAG_SVC_INFO_PRESENT (1<<5) | 383 | 0 | # define CDP_FLAG_SVC_INFO_START (1<<4) | 384 | 0 | # define CDP_FLAG_SVC_INFO_CHANGE (1<<3) | 385 | 0 | # define CDP_FLAG_SVC_INFO_COMPLETE (1<<2) | 386 | 0 | # define CDP_FLAG_CAPTION_SVC_ACTIVE (1<<1) | 387 | |
| 388 | 0 | if(i_src < 7) | 389 | 0 | return; | 390 | | | 391 | | /* ST334-2 5.2 cdp_header() */ | 392 | 0 | uint8_t cdp_length = p_src[2]; | 393 | 0 | if(cdp_length < 8 || cdp_length > i_src) | 394 | 0 | return; | 395 | 0 | uint8_t cdp_flags = p_src[4]; | 396 | | | 397 | | /* skip header */ | 398 | 0 | p_src += 7; i_src -= 7; | 399 | | | 400 | | /* 5.3 time_code_section() */ | 401 | 0 | if( cdp_flags & CDP_FLAG_TIME_CODE_PRESENT ) | 402 | 0 | { | 403 | 0 | if( i_src < 5 ) // Shall be 5 bytes | 404 | 0 | return; | 405 | 0 | p_src += 5; i_src += 5; | 406 | 0 | } | 407 | | /* 5.4 ccdata_section */ | 408 | 0 | if( cdp_flags & CDP_FLAG_CC_DATA_PRESENT ) | 409 | 0 | { | 410 | | /* ccdata_section() | 411 | | * u8 0x72 | 412 | | * u3 marker bits(111) | 413 | | * u5 cc_count | 414 | | * for cc_count | 415 | | * u5 marker bits(1111 1) | 416 | | * u1 cc_valid | 417 | | * u2 cc_type | 418 | | * u8 cc_data_1 | 419 | | * u8 cc_data_2 | 420 | | */ | 421 | 0 | if( i_src < 2 || p_src[0] != 0x72 ) // marker | 422 | 0 | return; | 423 | | | 424 | 0 | const uint8_t *cc = &p_src[1]; | 425 | 0 | const int i_count_cc = cc[0]&0x1f; | 426 | |
| 427 | 0 | if( i_src - 2 < i_count_cc*3 ) // broken packet | 428 | 0 | return; | 429 | 0 | cc += 1; | 430 | 0 | for( int i = 0; i < i_count_cc; i++, cc += 3 ) | 431 | 0 | { | 432 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 433 | 0 | break; | 434 | 0 | } | 435 | 0 | } | 436 | | /* remaining data */ | 437 | 0 | c->b_reorder = false; | 438 | 0 | } | 439 | 14.5k | } |
Unexecuted instantiation: mpegvideo.c:cc_Extract Line | Count | Source | 222 | 14 | { | 223 | 14 | if( c->i_payload_type != CC_PAYLOAD_NONE && c->i_payload_type != i_payload_type ) | 224 | 1 | { | 225 | 1 | c->i_payload_other_count++; | 226 | 1 | if( c->i_payload_other_count < 50 ) | 227 | 0 | return; | 228 | 1 | } | 229 | 14 | c->i_payload_type = i_payload_type; | 230 | 14 | c->i_payload_other_count = 0; | 231 | | | 232 | 14 | 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 | 14 | else if( i_payload_type == CC_PAYLOAD_GA94 ) | 243 | 14 | { | 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 | 14 | const uint8_t *cc = &p_src[0]; | 265 | 14 | const int i_count_cc = cc[0]&0x1f; | 266 | 14 | int i; | 267 | | | 268 | 14 | if( !(cc[0]&0x40) ) // process flag | 269 | 14 | return; | 270 | 0 | if( i_src < 1+1 + i_count_cc*3 + 1) // broken packet | 271 | 0 | return; | 272 | 0 | if( i_count_cc <= 0 ) // no cc present | 273 | 0 | return; | 274 | 0 | if( cc[2+i_count_cc * 3] != 0xff ) // marker absent | 275 | 0 | return; | 276 | 0 | cc += 2; | 277 | |
| 278 | 0 | for( i = 0; i < i_count_cc; i++, cc += 3 ) | 279 | 0 | { | 280 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 281 | 0 | break; | 282 | 0 | } | 283 | 0 | c->b_reorder = true; | 284 | 0 | } | 285 | 0 | else if( i_payload_type == CC_PAYLOAD_DVD ) | 286 | 0 | { | 287 | | /* user_data | 288 | | * (u32 stripped earlier) | 289 | | * u32 (0x43 0x43 0x01 0xf8) | 290 | | * u1 caption_odd_field_first (CC1/CC2) | 291 | | * u1 caption_filler | 292 | | * u5 cc_block_count (== cc_count / 2) | 293 | | * u1 caption_extra_field_added (because odd cc_count) | 294 | | * for cc_block_count * 2 + caption_extra_field_added | 295 | | * u7 cc_filler_1 | 296 | | * u1 cc_field_is_odd | 297 | | * u8 cc_data_1 | 298 | | * u8 cc_data_2 | 299 | | */ | 300 | 0 | const int b_truncate = p_src[4] & 0x01; | 301 | 0 | const int i_count_cc2 = ((p_src[4] >> 1) & 0x1f); | 302 | 0 | const uint8_t *cc = &p_src[5]; | 303 | 0 | i_src -= 5; | 304 | 0 | int i; | 305 | |
| 306 | 0 | #define CC_ALIGNMENT_TEST (0x7f) | 307 | |
| 308 | 0 | for( i = 0; i < 2*i_count_cc2 + b_truncate && i_src >= 3; i++, cc+=3 ) | 309 | 0 | { | 310 | 0 | if( (cc[0] >> 1) == CC_ALIGNMENT_TEST ) | 311 | 0 | { | 312 | 0 | const bool even_field = (cc[0] & 0x01) ? 0 : 1; | 313 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(even_field), &cc[1] )) | 314 | 0 | break; | 315 | 0 | } | 316 | 0 | i_src -= 3; | 317 | 0 | } | 318 | 0 | c->b_reorder = false; | 319 | 0 | } | 320 | 0 | else if( i_payload_type == CC_PAYLOAD_REPLAYTV ) | 321 | 0 | { | 322 | 0 | const uint8_t *cc = &p_src[0]; | 323 | 0 | for( int i_cc_count = i_src >> 2; i_cc_count > 0; | 324 | 0 | i_cc_count--, cc += 4 ) | 325 | 0 | { | 326 | 0 | uint8_t i_field = (cc[0] & 0x02) >> 1; | 327 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[2] )) | 328 | 0 | return; | 329 | 0 | } | 330 | 0 | c->b_reorder = false; | 331 | 0 | } | 332 | 0 | else if( i_payload_type == CC_PAYLOAD_SCTE20 ) | 333 | 0 | { | 334 | | /* user_data(2) | 335 | | * (u32 stripped earlier) | 336 | | * u16 p_cc_scte20 | 337 | | * u5 cc_count | 338 | | * for cc_count | 339 | | * u2 cc_priority | 340 | | * u2 cc_field_num | 341 | | * u5 cc_line_offset | 342 | | * u8 cc_data_1[1:8] | 343 | | * u8 cc_data_2[1:8] | 344 | | * u1 marker bit | 345 | | * un additional_realtimevideodata | 346 | | * un reserved | 347 | | */ | 348 | 0 | bs_t s; | 349 | 0 | bs_init( &s, &p_src[2], i_src - 2 ); | 350 | 0 | const int i_cc_count = bs_read( &s, 5 ); | 351 | 0 | for( int i = 0; i < i_cc_count; i++ ) | 352 | 0 | { | 353 | 0 | bs_skip( &s, 2 ); | 354 | 0 | const int i_field_idx = bs_read( &s, 2 ); | 355 | 0 | bs_skip( &s, 5 ); | 356 | 0 | uint8_t cc[2]; | 357 | 0 | for( int j = 0; j < 2; j++ ) | 358 | 0 | { | 359 | 0 | cc[j] = 0; | 360 | 0 | for( int k = 0; k < 8; k++ ) | 361 | 0 | cc[j] |= bs_read( &s, 1 ) << k; | 362 | 0 | } | 363 | 0 | bs_skip( &s, 1 ); | 364 | |
| 365 | 0 | if( i_field_idx == 0 ) | 366 | 0 | continue; | 367 | | | 368 | | /* 1,2,3 -> 0,1,0. I.E. repeated field 3 is merged with field 1 */ | 369 | 0 | int i_field = ((i_field_idx - 1) & 1); | 370 | 0 | if (!b_top_field_first) | 371 | 0 | i_field ^= 1; | 372 | |
| 373 | 0 | if (!cc_AppendData( c, CC_PKT_BYTE0(i_field), &cc[0] )) | 374 | 0 | continue; | 375 | 0 | } | 376 | 0 | c->b_reorder = true; | 377 | 0 | } | 378 | 0 | else // CC_PAYLOAD_CDP | 379 | 0 | { | 380 | 0 | # define CDP_FLAG_TIME_CODE_PRESENT (1<<7) | 381 | 0 | # define CDP_FLAG_CC_DATA_PRESENT (1<<6) | 382 | 0 | # define CDP_FLAG_SVC_INFO_PRESENT (1<<5) | 383 | 0 | # define CDP_FLAG_SVC_INFO_START (1<<4) | 384 | 0 | # define CDP_FLAG_SVC_INFO_CHANGE (1<<3) | 385 | 0 | # define CDP_FLAG_SVC_INFO_COMPLETE (1<<2) | 386 | 0 | # define CDP_FLAG_CAPTION_SVC_ACTIVE (1<<1) | 387 | |
| 388 | 0 | if(i_src < 7) | 389 | 0 | return; | 390 | | | 391 | | /* ST334-2 5.2 cdp_header() */ | 392 | 0 | uint8_t cdp_length = p_src[2]; | 393 | 0 | if(cdp_length < 8 || cdp_length > i_src) | 394 | 0 | return; | 395 | 0 | uint8_t cdp_flags = p_src[4]; | 396 | | | 397 | | /* skip header */ | 398 | 0 | p_src += 7; i_src -= 7; | 399 | | | 400 | | /* 5.3 time_code_section() */ | 401 | 0 | if( cdp_flags & CDP_FLAG_TIME_CODE_PRESENT ) | 402 | 0 | { | 403 | 0 | if( i_src < 5 ) // Shall be 5 bytes | 404 | 0 | return; | 405 | 0 | p_src += 5; i_src += 5; | 406 | 0 | } | 407 | | /* 5.4 ccdata_section */ | 408 | 0 | if( cdp_flags & CDP_FLAG_CC_DATA_PRESENT ) | 409 | 0 | { | 410 | | /* ccdata_section() | 411 | | * u8 0x72 | 412 | | * u3 marker bits(111) | 413 | | * u5 cc_count | 414 | | * for cc_count | 415 | | * u5 marker bits(1111 1) | 416 | | * u1 cc_valid | 417 | | * u2 cc_type | 418 | | * u8 cc_data_1 | 419 | | * u8 cc_data_2 | 420 | | */ | 421 | 0 | if( i_src < 2 || p_src[0] != 0x72 ) // marker | 422 | 0 | return; | 423 | | | 424 | 0 | const uint8_t *cc = &p_src[1]; | 425 | 0 | const int i_count_cc = cc[0]&0x1f; | 426 | |
| 427 | 0 | if( i_src - 2 < i_count_cc*3 ) // broken packet | 428 | 0 | return; | 429 | 0 | cc += 1; | 430 | 0 | for( int i = 0; i < i_count_cc; i++, cc += 3 ) | 431 | 0 | { | 432 | 0 | if (!cc_AppendData( c, cc[0], &cc[1] )) | 433 | 0 | break; | 434 | 0 | } | 435 | 0 | } | 436 | | /* remaining data */ | 437 | 0 | c->b_reorder = false; | 438 | 0 | } | 439 | 14 | } |
|
440 | | |
441 | | |
442 | | static inline void cc_ProbeAndExtract( cc_data_t *c, bool b_top_field_first, const uint8_t *p_src, int i_src ) |
443 | 52 | { |
444 | 52 | static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 }; |
445 | 52 | static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 }; /* ascii 'CC', type_code, cc_block_size */ |
446 | 52 | static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };/* RTV4K, BB02xxxxCC02 */ |
447 | 52 | static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };/* see DVR-ClosedCaption in samples */ |
448 | 52 | static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };/* RTV5K, 9902xxxxAA02 */ |
449 | 52 | static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };/* see DVR-ClosedCaption in samples */ |
450 | 52 | static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 }; /* user_data_type_code, SCTE 20 */ |
451 | 52 | static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };/* user_data_type_code, old, Note 1 */ |
452 | | |
453 | 52 | if( i_src < 4 ) |
454 | 0 | return; |
455 | | |
456 | 52 | enum cc_payload_type_e i_payload_type; |
457 | 52 | if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 ) |
458 | 14 | { |
459 | | /* CC from DVB/ATSC TS */ |
460 | 14 | i_payload_type = CC_PAYLOAD_GA94; |
461 | 14 | i_src -= 5; |
462 | 14 | p_src += 5; |
463 | 14 | } |
464 | 38 | else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 ) |
465 | 0 | { |
466 | 0 | i_payload_type = CC_PAYLOAD_DVD; |
467 | 0 | } |
468 | 38 | else if( i_src >= 2+2 + 2+2 && |
469 | 38 | ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) || |
470 | 20 | ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) ) |
471 | 0 | { |
472 | 0 | i_payload_type = CC_PAYLOAD_REPLAYTV; |
473 | 0 | } |
474 | 38 | else if( ( !memcmp( p_cc_scte20, p_src, 2 ) || |
475 | 38 | !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 ) |
476 | 0 | { |
477 | 0 | i_payload_type = CC_PAYLOAD_SCTE20; |
478 | 0 | } |
479 | 38 | else if (p_src[0] == 0x03 && p_src[1] == i_src - 2) /* DIRECTV */ |
480 | 0 | { |
481 | 0 | i_payload_type = CC_PAYLOAD_GA94; |
482 | 0 | i_src -= 2; |
483 | 0 | p_src += 2; |
484 | 0 | } |
485 | 38 | else if (p_src[0] == 0x96 && p_src[1] == 0x69) /* CDP */ |
486 | 0 | { |
487 | 0 | i_payload_type = CC_PAYLOAD_CDP; |
488 | 0 | } |
489 | 38 | else |
490 | 38 | { |
491 | | #if 0 |
492 | | #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x ) |
493 | | fprintf( stderr, "-------------- unknown user data " ); |
494 | | for( int i = 0; i < i_src; i++ ) |
495 | | fprintf( stderr, "%2.2x ", p_src[i] ); |
496 | | for( int i = 0; i < i_src; i++ ) |
497 | | fprintf( stderr, "%c ", V(p_src[i]) ); |
498 | | fprintf( stderr, "\n" ); |
499 | | #undef V |
500 | | #endif |
501 | 38 | return; |
502 | 38 | } |
503 | | |
504 | 14 | cc_Extract( c, i_payload_type, b_top_field_first, p_src, i_src ); |
505 | 14 | } 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 | 443 | 52 | { | 444 | 52 | static const uint8_t p_cc_ga94[4] = { 0x47, 0x41, 0x39, 0x34 }; | 445 | 52 | static const uint8_t p_cc_dvd[4] = { 0x43, 0x43, 0x01, 0xf8 }; /* ascii 'CC', type_code, cc_block_size */ | 446 | 52 | static const uint8_t p_cc_replaytv4a[2] = { 0xbb, 0x02 };/* RTV4K, BB02xxxxCC02 */ | 447 | 52 | static const uint8_t p_cc_replaytv4b[2] = { 0xcc, 0x02 };/* see DVR-ClosedCaption in samples */ | 448 | 52 | static const uint8_t p_cc_replaytv5a[2] = { 0x99, 0x02 };/* RTV5K, 9902xxxxAA02 */ | 449 | 52 | static const uint8_t p_cc_replaytv5b[2] = { 0xaa, 0x02 };/* see DVR-ClosedCaption in samples */ | 450 | 52 | static const uint8_t p_cc_scte20[2] = { 0x03, 0x81 }; /* user_data_type_code, SCTE 20 */ | 451 | 52 | static const uint8_t p_cc_scte20_old[2] = { 0x03, 0x01 };/* user_data_type_code, old, Note 1 */ | 452 | | | 453 | 52 | if( i_src < 4 ) | 454 | 0 | return; | 455 | | | 456 | 52 | enum cc_payload_type_e i_payload_type; | 457 | 52 | if( !memcmp( p_cc_ga94, p_src, 4 ) && i_src >= 5+1+1+1 && p_src[4] == 0x03 ) | 458 | 14 | { | 459 | | /* CC from DVB/ATSC TS */ | 460 | 14 | i_payload_type = CC_PAYLOAD_GA94; | 461 | 14 | i_src -= 5; | 462 | 14 | p_src += 5; | 463 | 14 | } | 464 | 38 | else if( !memcmp( p_cc_dvd, p_src, 4 ) && i_src > 4+1 ) | 465 | 0 | { | 466 | 0 | i_payload_type = CC_PAYLOAD_DVD; | 467 | 0 | } | 468 | 38 | else if( i_src >= 2+2 + 2+2 && | 469 | 38 | ( ( !memcmp( p_cc_replaytv4a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv4b, &p_src[4], 2 ) ) || | 470 | 20 | ( !memcmp( p_cc_replaytv5a, &p_src[0], 2 ) && !memcmp( p_cc_replaytv5b, &p_src[4], 2 ) ) ) ) | 471 | 0 | { | 472 | 0 | i_payload_type = CC_PAYLOAD_REPLAYTV; | 473 | 0 | } | 474 | 38 | else if( ( !memcmp( p_cc_scte20, p_src, 2 ) || | 475 | 38 | !memcmp( p_cc_scte20_old, p_src, 2 ) ) && i_src > 2 ) | 476 | 0 | { | 477 | 0 | i_payload_type = CC_PAYLOAD_SCTE20; | 478 | 0 | } | 479 | 38 | else if (p_src[0] == 0x03 && p_src[1] == i_src - 2) /* DIRECTV */ | 480 | 0 | { | 481 | 0 | i_payload_type = CC_PAYLOAD_GA94; | 482 | 0 | i_src -= 2; | 483 | 0 | p_src += 2; | 484 | 0 | } | 485 | 38 | else if (p_src[0] == 0x96 && p_src[1] == 0x69) /* CDP */ | 486 | 0 | { | 487 | 0 | i_payload_type = CC_PAYLOAD_CDP; | 488 | 0 | } | 489 | 38 | else | 490 | 38 | { | 491 | | #if 0 | 492 | | #define V(x) ( ( x < 0x20 || x >= 0x7f ) ? '?' : x ) | 493 | | fprintf( stderr, "-------------- unknown user data " ); | 494 | | for( int i = 0; i < i_src; i++ ) | 495 | | fprintf( stderr, "%2.2x ", p_src[i] ); | 496 | | for( int i = 0; i < i_src; i++ ) | 497 | | fprintf( stderr, "%c ", V(p_src[i]) ); | 498 | | fprintf( stderr, "\n" ); | 499 | | #undef V | 500 | | #endif | 501 | 38 | return; | 502 | 38 | } | 503 | | | 504 | 14 | cc_Extract( c, i_payload_type, b_top_field_first, p_src, i_src ); | 505 | 14 | } |
|
506 | | |
507 | | #endif /* _CC_H */ |
508 | | |