/src/vlc/modules/packetizer/flac.h
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * flac.h: fLAC audio headers |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2001-2018 VLC authors, VideoLabs and VideoLAN |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify it |
7 | | * under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation; either version 2.1 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with this program; if not, write to the Free Software Foundation, |
18 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
19 | | *****************************************************************************/ |
20 | | #include <vlc_common.h> |
21 | | |
22 | 117k | #define FLAC_HEADER_SIZE_MIN 9 |
23 | 57.0M | #define FLAC_HEADER_SIZE_MAX 16 |
24 | 5.69k | #define FLAC_STREAMINFO_SIZE 34 |
25 | 18.3M | #define FLAC_FRAME_SIZE_MIN ((48+(8 + 4 + 1*4)+FLAC_HEADER_SIZE_MAX)/8) |
26 | | |
27 | | struct flac_stream_info |
28 | | { |
29 | | unsigned min_blocksize, max_blocksize; |
30 | | unsigned min_framesize, max_framesize; |
31 | | unsigned sample_rate; |
32 | | unsigned channels; |
33 | | unsigned bits_per_sample; |
34 | | uint64_t total_samples; |
35 | | }; |
36 | | |
37 | | struct flac_header_info |
38 | | { |
39 | | vlc_tick_t i_pts; |
40 | | unsigned i_rate; |
41 | | unsigned i_channels; |
42 | | unsigned i_bits_per_sample; |
43 | | unsigned i_frame_length; |
44 | | }; |
45 | | |
46 | | static inline void FLAC_ParseStreamInfo( const uint8_t *p_buf, |
47 | | struct flac_stream_info *stream_info ) |
48 | 1.37k | { |
49 | 1.37k | stream_info->min_blocksize = GetWBE( &p_buf[0] ); |
50 | 1.37k | stream_info->min_blocksize = VLC_CLIP( stream_info->min_blocksize, 16, 65535 ); |
51 | | |
52 | 1.37k | stream_info->max_blocksize = GetWBE( &p_buf[2] ); |
53 | 1.37k | stream_info->max_blocksize = VLC_CLIP( stream_info->max_blocksize, 16, 65535 ); |
54 | | |
55 | 1.37k | stream_info->min_framesize = GetDWBE( &p_buf[3] ) & 0x00FFFFFF; |
56 | 1.37k | stream_info->min_framesize = __MAX( stream_info->min_framesize, FLAC_FRAME_SIZE_MIN ); |
57 | | |
58 | 1.37k | stream_info->max_framesize = GetDWBE( &p_buf[6] ) & 0x00FFFFFF; |
59 | | |
60 | 1.37k | stream_info->sample_rate = GetDWBE( &p_buf[10] ) >> 12; |
61 | 1.37k | stream_info->channels = ((p_buf[12] >> 1) & 0x07) + 1; |
62 | 1.37k | stream_info->bits_per_sample = (((p_buf[12] & 0x01) << 4) | p_buf[13] >> 4) + 1; |
63 | | |
64 | 1.37k | stream_info->total_samples = GetQWBE(&p_buf[4+6]) & ((INT64_C(1)<<36)-1); |
65 | 1.37k | } |
66 | | |
67 | | /* Will return UINT64_MAX for an invalid utf-8 sequence */ |
68 | | static inline uint64_t read_utf8(const uint8_t *p_buf, unsigned i_buf, int *pi_read) |
69 | 11.6M | { |
70 | | /* Max coding bits is 56 - 8 */ |
71 | | /* Value max precision is 36 bits */ |
72 | 11.6M | uint64_t i_result = 0; |
73 | 11.6M | unsigned i; |
74 | | |
75 | 11.6M | if(i_buf < 1) |
76 | 0 | return UINT64_MAX; |
77 | | |
78 | 11.6M | if (!(p_buf[0] & 0x80)) { /* 0xxxxxxx */ |
79 | 10.5M | i_result = p_buf[0]; |
80 | 10.5M | i = 0; |
81 | 10.5M | } else if (p_buf[0] & 0xC0 && !(p_buf[0] & 0x20)) { /* 110xxxxx */ |
82 | 64.3k | i_result = p_buf[0] & 0x1F; |
83 | 64.3k | i = 1; |
84 | 1.06M | } else if (p_buf[0] & 0xE0 && !(p_buf[0] & 0x10)) { /* 1110xxxx */ |
85 | 154k | i_result = p_buf[0] & 0x0F; |
86 | 154k | i = 2; |
87 | 911k | } else if (p_buf[0] & 0xF0 && !(p_buf[0] & 0x08)) { /* 11110xxx */ |
88 | 139k | i_result = p_buf[0] & 0x07; |
89 | 139k | i = 3; |
90 | 771k | } else if (p_buf[0] & 0xF8 && !(p_buf[0] & 0x04)) { /* 111110xx */ |
91 | 150k | i_result = p_buf[0] & 0x03; |
92 | 150k | i = 4; |
93 | 620k | } else if (p_buf[0] & 0xFC && !(p_buf[0] & 0x02)) { /* 1111110x */ |
94 | 228k | i_result = p_buf[0] & 0x01; |
95 | 228k | i = 5; |
96 | 392k | } else if (p_buf[0] & 0xFE && !(p_buf[0] & 0x01)) { /* 11111110 */ |
97 | 37.3k | i_result = 0; |
98 | 37.3k | i = 6; |
99 | 354k | } else { |
100 | 354k | return UINT64_MAX; |
101 | 354k | } |
102 | | |
103 | 11.3M | if(i_buf < i + 1) |
104 | 0 | return UINT64_MAX; |
105 | | |
106 | 13.4M | for (unsigned j = 1; j <= i; j++) { |
107 | 2.42M | if (!(p_buf[j] & 0x80) || (p_buf[j] & 0x40)) { /* 10xxxxxx */ |
108 | 270k | return UINT64_MAX; |
109 | 270k | } |
110 | 2.14M | i_result <<= 6; |
111 | 2.14M | i_result |= (p_buf[j] & 0x3F); |
112 | 2.14M | } |
113 | | |
114 | 11.0M | *pi_read = i; |
115 | 11.0M | return i_result; |
116 | 11.3M | } |
117 | | |
118 | | static inline int FLAC_CheckFrameInfo(const struct flac_stream_info *stream_info, |
119 | | const struct flac_header_info *h) |
120 | 10.8M | { |
121 | | /* Sanity check using stream info header when possible */ |
122 | 10.8M | if (stream_info) |
123 | 10.8M | { |
124 | 10.8M | if ((stream_info->min_blocksize != stream_info->max_blocksize && |
125 | 2.13M | h->i_frame_length < stream_info->min_blocksize) || |
126 | 10.7M | h->i_frame_length > stream_info->max_blocksize) |
127 | 474k | return 0; |
128 | 10.3M | if(stream_info->max_framesize && |
129 | 10.3M | stream_info->min_framesize > stream_info->max_framesize) |
130 | 51.1k | return 0; |
131 | 10.3M | if (h->i_bits_per_sample != stream_info->bits_per_sample) |
132 | 135k | return 0; |
133 | 10.1M | if (h->i_rate != stream_info->sample_rate) |
134 | 233k | return 0; |
135 | 10.1M | } |
136 | 9.93M | return 1; |
137 | 10.8M | } |
138 | | |
139 | | /***************************************************************************** |
140 | | * FLAC_ParseSyncInfo: parse FLAC sync info |
141 | | * - stream_info can be NULL |
142 | | * - pf_crc8 can be NULL to skip crc check |
143 | | * Returns: 1 on success, 0 on failure, and -1 if could be incorrect |
144 | | *****************************************************************************/ |
145 | | static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, unsigned i_buf, |
146 | | const struct flac_stream_info *stream_info, |
147 | | uint8_t(*pf_crc8)(const uint8_t *, size_t), |
148 | | struct flac_header_info *h) |
149 | 23.8M | { |
150 | 23.8M | bool b_guessing = false; |
151 | | |
152 | 23.8M | if(unlikely(i_buf < FLAC_HEADER_SIZE_MIN)) |
153 | 0 | return 0; |
154 | | |
155 | | /* Check syncword */ |
156 | 23.8M | if (p_buf[0] != 0xFF || (p_buf[1] & 0xFE) != 0xF8) |
157 | 0 | return 0; |
158 | | |
159 | | /* Check there is no emulated sync code in the rest of the header */ |
160 | 23.8M | if (p_buf[2] == 0xff || p_buf[3] == 0xFF) |
161 | 6.31M | return 0; |
162 | | |
163 | | /* Find blocksize (framelength) */ |
164 | 17.5M | int blocksize_hint = 0; |
165 | 17.5M | unsigned blocksize = p_buf[2] >> 4; |
166 | 17.5M | if (blocksize >= 8) { |
167 | 2.16M | blocksize = 256 << (blocksize - 8); |
168 | 15.4M | } else if (blocksize == 0) { /* value 0 is reserved */ |
169 | 10.2M | b_guessing = true; |
170 | 10.2M | if (stream_info && |
171 | 10.2M | stream_info->min_blocksize == stream_info->max_blocksize) |
172 | 9.53M | blocksize = stream_info->min_blocksize; |
173 | 737k | else |
174 | 737k | return 0; /* We can't do anything with this */ |
175 | 10.2M | } else if (blocksize == 1) { |
176 | 57.1k | blocksize = 192; |
177 | 5.08M | } else if (blocksize == 6 || blocksize == 7) { |
178 | 2.40M | blocksize_hint = blocksize; |
179 | 2.40M | blocksize = 0; |
180 | 2.67M | } else /* 2, 3, 4, 5 */ { |
181 | 2.67M | blocksize = 576 << (blocksize - 2); |
182 | 2.67M | } |
183 | | |
184 | 16.8M | if (stream_info && !blocksize_hint) |
185 | 14.4M | if (blocksize < stream_info->min_blocksize || |
186 | 11.9M | blocksize > stream_info->max_blocksize) |
187 | 3.33M | return 0; |
188 | | |
189 | | /* Find samplerate */ |
190 | 13.5M | int samplerate_hint = p_buf[2] & 0xf; |
191 | 13.5M | unsigned int samplerate; |
192 | 13.5M | if (samplerate_hint == 0) { |
193 | 11.8M | if (stream_info) |
194 | 11.8M | samplerate = stream_info->sample_rate; |
195 | 14.9k | else |
196 | 14.9k | return 0; /* We can't do anything with this */ |
197 | 11.8M | } else if (samplerate_hint == 15) { |
198 | 26.2k | return 0; /* invalid */ |
199 | 1.59M | } else if (samplerate_hint < 12) { |
200 | 1.25M | static const int16_t flac_samplerate[12] = { |
201 | 1.25M | 0, 8820, 17640, 19200, |
202 | 1.25M | 800, 1600, 2205, 2400, |
203 | 1.25M | 3200, 4410, 4800, 9600, |
204 | 1.25M | }; |
205 | 1.25M | samplerate = flac_samplerate[samplerate_hint] * 10; |
206 | 1.25M | } else { |
207 | 341k | samplerate = 0; /* at end of header */ |
208 | 341k | } |
209 | | |
210 | | /* Find channels */ |
211 | 13.4M | unsigned channels = p_buf[3] >> 4; |
212 | 13.4M | if (channels >= 8) { |
213 | 466k | if (channels >= 11) /* reserved */ |
214 | 39.7k | return 0; |
215 | 426k | channels = 2; |
216 | 426k | } else |
217 | 13.0M | channels++; |
218 | | |
219 | | |
220 | | /* Find bits per sample */ |
221 | 13.4M | static const int8_t flac_bits_per_sample[8] = { |
222 | 13.4M | 0, 8, 12, -1, 16, 20, 24, 32 |
223 | 13.4M | }; |
224 | 13.4M | int bits_per_sample = flac_bits_per_sample[(p_buf[3] & 0x0e) >> 1]; |
225 | 13.4M | if (bits_per_sample == 0) { |
226 | 9.30M | if (stream_info) |
227 | 9.30M | bits_per_sample = stream_info->bits_per_sample; |
228 | 297 | else |
229 | 297 | return 0; |
230 | 9.30M | } else if (bits_per_sample < 0) |
231 | 8.88k | return 0; |
232 | | |
233 | | |
234 | | /* reserved for future use */ |
235 | 13.4M | if (p_buf[3] & 0x01) |
236 | 1.75M | return 0; |
237 | | |
238 | | /* End of fixed size header */ |
239 | 11.6M | unsigned i_header = 4; |
240 | | |
241 | | /* > FLAC_HEADER_SIZE_MIN checks start here */ |
242 | | |
243 | | /* Check Sample/Frame number */ |
244 | 11.6M | int i_read; |
245 | 11.6M | uint64_t i_fsnumber = read_utf8(&p_buf[i_header++], i_buf - 4, &i_read); |
246 | | |
247 | | /* Invalid UTF-8 */ |
248 | 11.6M | if (i_fsnumber == UINT64_MAX) |
249 | 625k | return 0; |
250 | | |
251 | | /* Invalid Sample/Frame number */ |
252 | 11.0M | if (stream_info && stream_info->total_samples != 0 && i_fsnumber > stream_info->total_samples) |
253 | 39.4k | return 0; |
254 | | |
255 | 10.9M | i_header += i_read; |
256 | | |
257 | | /* Read blocksize */ |
258 | 10.9M | if (blocksize_hint) { |
259 | 1.95M | if(i_header == i_buf) |
260 | 0 | return 0; |
261 | 1.95M | blocksize = p_buf[i_header++]; |
262 | 1.95M | if (blocksize_hint == 7) { |
263 | 1.62M | blocksize <<= 8; |
264 | 1.62M | blocksize |= p_buf[i_header++]; |
265 | 1.62M | } |
266 | 1.95M | blocksize++; |
267 | 1.95M | } |
268 | | |
269 | | /* Read sample rate */ |
270 | 10.9M | if (samplerate == 0) { |
271 | 161k | if(i_header == i_buf) |
272 | 0 | return 0; |
273 | 161k | samplerate = p_buf[i_header++]; |
274 | 161k | if (samplerate_hint != 12) { /* 16 bits */ |
275 | 151k | if(i_header == i_buf) |
276 | 0 | return 0; |
277 | 151k | samplerate <<= 8; |
278 | 151k | samplerate |= p_buf[i_header++]; |
279 | 151k | } |
280 | | |
281 | 161k | if (samplerate_hint == 12) |
282 | 10.6k | samplerate *= 1000; |
283 | 151k | else if (samplerate_hint == 14) |
284 | 130k | samplerate *= 10; |
285 | 161k | } |
286 | | |
287 | 10.9M | if ( !samplerate ) |
288 | 2.11k | return 0; |
289 | | |
290 | 10.9M | if(i_header == i_buf) /* no crc space */ |
291 | 0 | return 0; |
292 | | |
293 | | /* Check the CRC-8 byte */ |
294 | 10.9M | if (pf_crc8 && |
295 | 378k | pf_crc8(p_buf, i_header) != p_buf[i_header]) |
296 | 101k | return 0; |
297 | | |
298 | | /* Compute from frame absolute time */ |
299 | 10.8M | if ( (p_buf[1] & 0x01) == 0 ) /* Fixed blocksize stream / Frames */ |
300 | 4.77M | { |
301 | 4.77M | const unsigned fixedblocksize = stream_info ? stream_info->min_blocksize : blocksize; |
302 | 4.77M | h->i_pts = VLC_TICK_0 + vlc_tick_from_samples(fixedblocksize * i_fsnumber, samplerate); |
303 | 4.77M | } |
304 | 6.11M | else /* Variable blocksize stream / Samples */ |
305 | 6.11M | h->i_pts = VLC_TICK_0 + vlc_tick_from_samples(i_fsnumber, samplerate); |
306 | | |
307 | 10.8M | h->i_bits_per_sample = bits_per_sample; |
308 | 10.8M | h->i_rate = samplerate; |
309 | 10.8M | h->i_channels = channels; |
310 | 10.8M | h->i_frame_length = blocksize; |
311 | | |
312 | 10.8M | return b_guessing ? -1 : 1; |
313 | 10.9M | } |