/src/vlc/modules/packetizer/flac.c
Line | Count | Source (jump to first uncovered line) |
1 | | /***************************************************************************** |
2 | | * flac.c: flac packetizer module. |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 1999-2017 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Gildas Bazin <gbazin@videolan.org> |
7 | | * Sigmund Augdal Helberg <dnumgis@videolan.org> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | /***************************************************************************** |
25 | | * Preamble |
26 | | *****************************************************************************/ |
27 | | |
28 | | #ifdef HAVE_CONFIG_H |
29 | | # include "config.h" |
30 | | #endif |
31 | | |
32 | | #include <vlc_common.h> |
33 | | #include <vlc_plugin.h> |
34 | | #include <vlc_codec.h> |
35 | | |
36 | | #include <vlc_block_helper.h> |
37 | | #include "packetizer_helper.h" |
38 | | #include "flac.h" |
39 | | |
40 | | /***************************************************************************** |
41 | | * Module descriptor |
42 | | *****************************************************************************/ |
43 | | static int Open (vlc_object_t *); |
44 | | static void Close(vlc_object_t *); |
45 | | |
46 | 104 | vlc_module_begin() |
47 | 52 | set_subcategory(SUBCAT_SOUT_PACKETIZER) |
48 | 52 | set_description(N_("Flac audio packetizer")) |
49 | 52 | set_capability("audio packetizer", 50) |
50 | 104 | set_callbacks(Open, Close) |
51 | 52 | vlc_module_end() |
52 | | |
53 | | /***************************************************************************** |
54 | | * decoder_sys_t : FLAC decoder descriptor |
55 | | *****************************************************************************/ |
56 | | typedef struct |
57 | | { |
58 | | /* |
59 | | * Input properties |
60 | | */ |
61 | | int i_state; |
62 | | |
63 | | block_bytestream_t bytestream; |
64 | | size_t i_offset; |
65 | | |
66 | | /* |
67 | | * FLAC properties |
68 | | */ |
69 | | struct flac_stream_info stream_info; |
70 | | bool b_stream_info; |
71 | | |
72 | | /* |
73 | | * Common properties |
74 | | */ |
75 | | date_t pts; |
76 | | struct flac_header_info headerinfo; |
77 | | |
78 | | size_t i_last_frame_size; |
79 | | uint16_t crc; |
80 | | size_t i_buf_offset; /* in final buffer before crc check / validation / retry */ |
81 | | size_t i_buf; |
82 | | uint8_t *p_buf; |
83 | | |
84 | | int i_next_block_flags; |
85 | | } decoder_sys_t; |
86 | | |
87 | | static const int pi_channels_maps[9] = |
88 | | { |
89 | | 0, |
90 | | AOUT_CHAN_CENTER, |
91 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, |
92 | | AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT, |
93 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT |
94 | | | AOUT_CHAN_REARRIGHT, |
95 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
96 | | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT, |
97 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
98 | | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE, |
99 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
100 | | | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT |
101 | | | AOUT_CHAN_MIDDLERIGHT, |
102 | | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
103 | | | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
104 | | | AOUT_CHAN_LFE |
105 | | }; |
106 | | |
107 | | |
108 | | /***************************************************************************** |
109 | | * ProcessHeader: process Flac header. |
110 | | *****************************************************************************/ |
111 | | static void ProcessHeader(decoder_t *p_dec) |
112 | 41 | { |
113 | 41 | decoder_sys_t *p_sys = p_dec->p_sys; |
114 | | |
115 | 41 | int i_extra = p_dec->fmt_in->i_extra; |
116 | 41 | char *p_extra = p_dec->fmt_in->p_extra; |
117 | | |
118 | 41 | if (i_extra > 8 && !memcmp(p_extra, "fLaC", 4)) { |
119 | 0 | i_extra -= 8; |
120 | 0 | p_extra += 8; |
121 | 0 | } |
122 | | |
123 | 41 | if (i_extra < FLAC_STREAMINFO_SIZE) |
124 | 0 | return; |
125 | | |
126 | 41 | FLAC_ParseStreamInfo( (uint8_t *) p_extra, &p_sys->stream_info ); |
127 | | |
128 | 41 | p_sys->b_stream_info = true; |
129 | | |
130 | 41 | p_dec->fmt_out.i_extra = i_extra; |
131 | 41 | free(p_dec->fmt_out.p_extra); |
132 | 41 | p_dec->fmt_out.p_extra = malloc(i_extra); |
133 | 41 | if (p_dec->fmt_out.p_extra) |
134 | 41 | memcpy(p_dec->fmt_out.p_extra, p_extra, i_extra); |
135 | 0 | else |
136 | 0 | p_dec->fmt_out.i_extra = 0; |
137 | 41 | } |
138 | | |
139 | | /* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */ |
140 | | static const uint8_t flac_crc8_table[256] = { |
141 | | 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, |
142 | | 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D, |
143 | | 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, |
144 | | 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, |
145 | | 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, |
146 | | 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD, |
147 | | 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, |
148 | | 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD, |
149 | | 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, |
150 | | 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, |
151 | | 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, |
152 | | 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A, |
153 | | 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, |
154 | | 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A, |
155 | | 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, |
156 | | 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, |
157 | | 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, |
158 | | 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4, |
159 | | 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, |
160 | | 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4, |
161 | | 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, |
162 | | 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, |
163 | | 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, |
164 | | 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34, |
165 | | 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, |
166 | | 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63, |
167 | | 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, |
168 | | 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, |
169 | | 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, |
170 | | 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83, |
171 | | 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, |
172 | | 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3 |
173 | | }; |
174 | | |
175 | | static uint8_t flac_crc8(const uint8_t *data, size_t len) |
176 | 246k | { |
177 | 246k | uint8_t crc = 0; |
178 | | |
179 | 1.61M | while (len--) |
180 | 1.36M | crc = flac_crc8_table[crc ^ *data++]; |
181 | | |
182 | 246k | return crc; |
183 | 246k | } |
184 | | |
185 | | /* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */ |
186 | | static const uint16_t flac_crc16_table[256] = { |
187 | | 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, |
188 | | 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, |
189 | | 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, |
190 | | 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, |
191 | | 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, |
192 | | 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, |
193 | | 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, |
194 | | 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, |
195 | | 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, |
196 | | 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, |
197 | | 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, |
198 | | 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, |
199 | | 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, |
200 | | 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, |
201 | | 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, |
202 | | 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, |
203 | | 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, |
204 | | 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, |
205 | | 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, |
206 | | 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, |
207 | | 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, |
208 | | 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, |
209 | | 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, |
210 | | 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, |
211 | | 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, |
212 | | 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, |
213 | | 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, |
214 | | 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, |
215 | | 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, |
216 | | 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, |
217 | | 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, |
218 | | 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 |
219 | | }; |
220 | | |
221 | | static uint16_t flac_crc16(uint16_t crc, uint8_t byte) |
222 | 143M | { |
223 | 143M | return (crc << 8) ^ flac_crc16_table[(crc >> 8) ^ byte]; |
224 | 143M | } |
225 | | #if 0 |
226 | | /* Gives the previous CRC value, before hashing last_byte through it */ |
227 | | static uint16_t flac_crc16_undo(uint16_t crc, const uint8_t last_byte) |
228 | | { |
229 | | /* |
230 | | * Given a byte b, gives a position X in flac_crc16_table, such as: |
231 | | * flac_crc16_rev_table[flac_crc16_table[X] & 0xff] == X |
232 | | * This works because flac_crc16_table[i] & 0xff yields 256 unique values. |
233 | | */ |
234 | | static const uint8_t flac_crc16_rev_table[256] = { |
235 | | 0x00, 0x7f, 0xff, 0x80, 0x7e, 0x01, 0x81, 0xfe, |
236 | | 0xfc, 0x83, 0x03, 0x7c, 0x82, 0xfd, 0x7d, 0x02, |
237 | | 0x78, 0x07, 0x87, 0xf8, 0x06, 0x79, 0xf9, 0x86, |
238 | | 0x84, 0xfb, 0x7b, 0x04, 0xfa, 0x85, 0x05, 0x7a, |
239 | | 0xf0, 0x8f, 0x0f, 0x70, 0x8e, 0xf1, 0x71, 0x0e, |
240 | | 0x0c, 0x73, 0xf3, 0x8c, 0x72, 0x0d, 0x8d, 0xf2, |
241 | | 0x88, 0xf7, 0x77, 0x08, 0xf6, 0x89, 0x09, 0x76, |
242 | | 0x74, 0x0b, 0x8b, 0xf4, 0x0a, 0x75, 0xf5, 0x8a, |
243 | | 0x60, 0x1f, 0x9f, 0xe0, 0x1e, 0x61, 0xe1, 0x9e, |
244 | | 0x9c, 0xe3, 0x63, 0x1c, 0xe2, 0x9d, 0x1d, 0x62, |
245 | | 0x18, 0x67, 0xe7, 0x98, 0x66, 0x19, 0x99, 0xe6, |
246 | | 0xe4, 0x9b, 0x1b, 0x64, 0x9a, 0xe5, 0x65, 0x1a, |
247 | | 0x90, 0xef, 0x6f, 0x10, 0xee, 0x91, 0x11, 0x6e, |
248 | | 0x6c, 0x13, 0x93, 0xec, 0x12, 0x6d, 0xed, 0x92, |
249 | | 0xe8, 0x97, 0x17, 0x68, 0x96, 0xe9, 0x69, 0x16, |
250 | | 0x14, 0x6b, 0xeb, 0x94, 0x6a, 0x15, 0x95, 0xea, |
251 | | 0xc0, 0xbf, 0x3f, 0x40, 0xbe, 0xc1, 0x41, 0x3e, |
252 | | 0x3c, 0x43, 0xc3, 0xbc, 0x42, 0x3d, 0xbd, 0xc2, |
253 | | 0xb8, 0xc7, 0x47, 0x38, 0xc6, 0xb9, 0x39, 0x46, |
254 | | 0x44, 0x3b, 0xbb, 0xc4, 0x3a, 0x45, 0xc5, 0xba, |
255 | | 0x30, 0x4f, 0xcf, 0xb0, 0x4e, 0x31, 0xb1, 0xce, |
256 | | 0xcc, 0xb3, 0x33, 0x4c, 0xb2, 0xcd, 0x4d, 0x32, |
257 | | 0x48, 0x37, 0xb7, 0xc8, 0x36, 0x49, 0xc9, 0xb6, |
258 | | 0xb4, 0xcb, 0x4b, 0x34, 0xca, 0xb5, 0x35, 0x4a, |
259 | | 0xa0, 0xdf, 0x5f, 0x20, 0xde, 0xa1, 0x21, 0x5e, |
260 | | 0x5c, 0x23, 0xa3, 0xdc, 0x22, 0x5d, 0xdd, 0xa2, |
261 | | 0xd8, 0xa7, 0x27, 0x58, 0xa6, 0xd9, 0x59, 0x26, |
262 | | 0x24, 0x5b, 0xdb, 0xa4, 0x5a, 0x25, 0xa5, 0xda, |
263 | | 0x50, 0x2f, 0xaf, 0xd0, 0x2e, 0x51, 0xd1, 0xae, |
264 | | 0xac, 0xd3, 0x53, 0x2c, 0xd2, 0xad, 0x2d, 0x52, |
265 | | 0x28, 0x57, 0xd7, 0xa8, 0x56, 0x29, 0xa9, 0xd6, |
266 | | 0xd4, 0xab, 0x2b, 0x54, 0xaa, 0xd5, 0x55, 0x2a, |
267 | | }; |
268 | | uint8_t idx = flac_crc16_rev_table[crc & 0xff]; |
269 | | return ((idx ^ last_byte) << 8) | ((crc ^ flac_crc16_table[idx]) >> 8); |
270 | | } |
271 | | #endif |
272 | | |
273 | | static void Flush(decoder_t *p_dec) |
274 | 0 | { |
275 | 0 | decoder_sys_t *p_sys = p_dec->p_sys; |
276 | |
|
277 | 0 | p_sys->i_state = STATE_NOSYNC; |
278 | 0 | p_sys->i_offset = 0; |
279 | 0 | date_Set( &p_sys->pts, VLC_TICK_INVALID ); |
280 | 0 | block_BytestreamEmpty(&p_sys->bytestream); |
281 | 0 | } |
282 | | |
283 | | static const uint8_t * FLACStartcodeHelper(const uint8_t *p, const uint8_t *end) |
284 | 13.4M | { |
285 | 54.2M | while( p && p < end ) |
286 | 54.2M | { |
287 | 54.2M | if( (p = memchr(p, 0xFF, end - p)) ) |
288 | 54.2M | { |
289 | 54.2M | if( end - p > 1 && (p[1] & 0xFE) == 0xF8 ) |
290 | 13.4M | return p; |
291 | 40.7M | else |
292 | 40.7M | p++; |
293 | 54.2M | } |
294 | 54.2M | } |
295 | 14.4k | return NULL; |
296 | 13.4M | } |
297 | | |
298 | | static bool FLACStartcodeMatcher(uint8_t i, size_t i_pos, const uint8_t *p_startcode) |
299 | 19.2k | { |
300 | 19.2k | VLC_UNUSED(p_startcode); |
301 | 19.2k | return (i_pos == 0) ? i == 0xFF : (i & 0xFE) == 0xF8; |
302 | 19.2k | } |
303 | | |
304 | | /* */ |
305 | | static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) |
306 | 4.11k | { |
307 | 4.11k | decoder_sys_t *p_sys = p_dec->p_sys; |
308 | 4.11k | uint8_t p_header[FLAC_HEADER_SIZE_MAX]; |
309 | 4.11k | block_t *out = NULL, *in = NULL; |
310 | | |
311 | 4.11k | if ( pp_block && *pp_block) |
312 | 4.06k | { |
313 | 4.06k | in = *pp_block; |
314 | 4.06k | *pp_block = NULL; |
315 | 4.06k | if (in->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) { |
316 | 0 | Flush(p_dec); |
317 | 0 | p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY; |
318 | 0 | if (in->i_flags&BLOCK_FLAG_CORRUPTED) { |
319 | 0 | block_Release(in); |
320 | 0 | return NULL; |
321 | 0 | } |
322 | 0 | } |
323 | 4.06k | } |
324 | | |
325 | 4.11k | if (!p_sys->b_stream_info) |
326 | 41 | ProcessHeader(p_dec); |
327 | | |
328 | 4.11k | if (p_sys->stream_info.channels > 8) |
329 | 0 | { |
330 | 0 | if(in) |
331 | 0 | block_Release(in); |
332 | 0 | msg_Err(p_dec, "This stream uses too many audio channels (%d > 8)", |
333 | 0 | p_sys->stream_info.channels); |
334 | 0 | return NULL; |
335 | 0 | } |
336 | | |
337 | 4.11k | if ( in ) |
338 | 4.06k | block_BytestreamPush(&p_sys->bytestream, in); |
339 | | |
340 | 19.5M | while (1) switch (p_sys->i_state) { |
341 | 721k | case STATE_NOSYNC: |
342 | 721k | if(block_FindStartcodeFromOffset(&p_sys->bytestream, &p_sys->i_offset, |
343 | 721k | NULL, 2, |
344 | 721k | FLACStartcodeHelper, |
345 | 721k | FLACStartcodeMatcher) == VLC_SUCCESS) |
346 | 721k | { |
347 | 721k | p_sys->i_state = STATE_SYNC; |
348 | 721k | } |
349 | | |
350 | | /* First Sync is now on bytestream head, offset == 0 */ |
351 | 721k | block_SkipBytes(&p_sys->bytestream, p_sys->i_offset); |
352 | 721k | block_BytestreamFlush(&p_sys->bytestream); |
353 | 721k | p_sys->i_offset = 0; |
354 | | |
355 | 721k | if( p_sys->i_state != STATE_SYNC ) |
356 | 66 | return NULL; /* Need more data */ |
357 | | /* fallthrough */ |
358 | | |
359 | 721k | case STATE_SYNC: |
360 | | /* Sync state is unverified until we have read frame header and checked CRC |
361 | | Once validated, we'll send data from NEXT_SYNC state where we'll |
362 | | compute frame size */ |
363 | 721k | p_sys->i_state = STATE_HEADER; |
364 | | /* fallthrough */ |
365 | | |
366 | 721k | case STATE_HEADER: |
367 | 721k | { |
368 | | /* Get FLAC frame header (MAX_FLAC_HEADER_SIZE bytes) */ |
369 | 721k | if (block_PeekBytes(&p_sys->bytestream, p_header, FLAC_HEADER_SIZE_MAX)) |
370 | 52 | return NULL; /* Need more data */ |
371 | | |
372 | | /* Check if frame is valid and get frame info */ |
373 | 721k | const struct flac_stream_info *streaminfo = |
374 | 721k | p_sys->b_stream_info ? &p_sys->stream_info : NULL; |
375 | 721k | struct flac_header_info headerinfo; |
376 | 721k | int i_ret = FLAC_ParseSyncInfo(p_header, FLAC_HEADER_SIZE_MAX, streaminfo, |
377 | 721k | flac_crc8, &headerinfo); |
378 | 721k | if (!i_ret || !FLAC_CheckFrameInfo(streaminfo, &headerinfo)) { |
379 | 603k | msg_Dbg(p_dec, "emulated sync word"); |
380 | 603k | block_SkipByte(&p_sys->bytestream); |
381 | 603k | p_sys->i_offset = 0; |
382 | 603k | p_sys->i_state = STATE_NOSYNC; |
383 | 603k | break; |
384 | 603k | } |
385 | | |
386 | 118k | p_sys->headerinfo = headerinfo; |
387 | 118k | p_sys->i_state = STATE_NEXT_SYNC; |
388 | 118k | p_sys->i_offset = FLAC_FRAME_SIZE_MIN; |
389 | 118k | p_sys->i_buf_offset = 0; |
390 | 118k | p_sys->crc = 0; |
391 | | |
392 | | /* We have to read until next frame sync code to compute current frame size |
393 | | * from that boundary. |
394 | | * The confusing part below is that sync code needs to be verified in case |
395 | | * it would appear in data, so we also need to check next frame header CRC |
396 | | */ |
397 | 118k | } |
398 | | /* fallthrough */ |
399 | | |
400 | 12.7M | case STATE_NEXT_SYNC: |
401 | 12.7M | { |
402 | | /* First Sync is on bytestream head, offset will be the position |
403 | | * of the next sync code candidate */ |
404 | 12.7M | if(block_FindStartcodeFromOffset(&p_sys->bytestream, &p_sys->i_offset, |
405 | 12.7M | NULL, 2, |
406 | 12.7M | FLACStartcodeHelper, |
407 | 12.7M | FLACStartcodeMatcher) != VLC_SUCCESS) |
408 | 870 | { |
409 | 870 | size_t i_remain = block_BytestreamRemaining( &p_sys->bytestream ); |
410 | 870 | if( pp_block == NULL && i_remain > FLAC_FRAME_SIZE_MIN ) /* EOF/Drain */ |
411 | 39 | { |
412 | | /* There is no other synccode in the bytestream, |
413 | | * we assume the end of our flac frame is end of bytestream */ |
414 | 39 | p_sys->i_offset = i_remain; |
415 | 39 | p_sys->i_state = STATE_GET_DATA; |
416 | 39 | continue; |
417 | 39 | } |
418 | 831 | return NULL; |
419 | 870 | } |
420 | | |
421 | | /* Check next header */ |
422 | 12.7M | uint8_t nextheader[FLAC_HEADER_SIZE_MAX]; |
423 | 12.7M | if (block_PeekOffsetBytes(&p_sys->bytestream, p_sys->i_offset, |
424 | 12.7M | nextheader, FLAC_HEADER_SIZE_MAX)) |
425 | 562 | return NULL; /* Need more data */ |
426 | | |
427 | 12.7M | const struct flac_stream_info *streaminfo = |
428 | 12.7M | p_sys->b_stream_info ? &p_sys->stream_info : NULL; |
429 | 12.7M | struct flac_header_info dummy; |
430 | | /* Check if frame is valid and get frame info */ |
431 | 12.7M | if(!FLAC_ParseSyncInfo(nextheader, FLAC_HEADER_SIZE_MAX, streaminfo, NULL, &dummy)|| |
432 | 12.7M | !FLAC_CheckFrameInfo(streaminfo, &dummy)) |
433 | 6.46M | { |
434 | | /* Keep trying to find next sync point in bytestream */ |
435 | 6.46M | p_sys->i_offset++; |
436 | 6.46M | continue; |
437 | 6.46M | } |
438 | | |
439 | 6.25M | p_sys->i_state = STATE_GET_DATA; |
440 | 6.25M | continue; |
441 | 12.7M | } |
442 | | |
443 | 6.25M | case STATE_GET_DATA: |
444 | | /* i_offset is the next sync point candidate |
445 | | * our frame_size is the offset from the first sync */ |
446 | 6.25M | if( pp_block != NULL && |
447 | 6.25M | p_sys->b_stream_info && |
448 | 6.25M | p_sys->stream_info.min_framesize > p_sys->i_offset ) |
449 | 14.8k | { |
450 | 14.8k | p_sys->i_offset += 1; |
451 | 14.8k | p_sys->i_state = STATE_NEXT_SYNC; |
452 | 14.8k | break; |
453 | 14.8k | } |
454 | 6.24M | else if( p_sys->b_stream_info && |
455 | 6.24M | p_sys->stream_info.max_framesize > FLAC_FRAME_SIZE_MIN && |
456 | 6.24M | p_sys->stream_info.max_framesize < p_sys->i_offset ) |
457 | 111k | { |
458 | | /* Something went wrong, truncate stream head and restart */ |
459 | 111k | msg_Warn(p_dec, "discarding bytes as we're over framesize %u, %zu", |
460 | 111k | p_sys->stream_info.max_framesize, |
461 | 111k | p_sys->i_offset); |
462 | 111k | if( block_SkipBytes( &p_sys->bytestream, |
463 | 111k | FLAC_HEADER_SIZE_MAX + 2 ) != VLC_SUCCESS ) |
464 | 0 | return NULL; |
465 | 111k | block_BytestreamFlush( &p_sys->bytestream ); |
466 | 111k | p_sys->crc = 0; |
467 | 111k | p_sys->i_buf_offset = 0; |
468 | 111k | p_sys->i_offset = 0; |
469 | 111k | p_sys->i_state = STATE_NOSYNC; |
470 | 111k | p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY; |
471 | 111k | break; |
472 | 111k | } |
473 | 6.13M | else |
474 | 6.13M | { |
475 | | /* Allocate enough for storage */ |
476 | 6.13M | if( p_sys->i_offset > p_sys->i_buf ) |
477 | 375k | { |
478 | 375k | size_t i_min_alloc = __MAX(p_sys->i_last_frame_size, p_sys->i_offset); |
479 | 375k | uint8_t *p_realloc = realloc( p_sys->p_buf, i_min_alloc ); |
480 | 375k | if( p_realloc ) |
481 | 375k | { |
482 | 375k | p_sys->i_buf = i_min_alloc; |
483 | 375k | p_sys->p_buf = p_realloc; |
484 | 375k | } |
485 | | |
486 | 375k | if ( !p_sys->p_buf ) |
487 | 0 | return NULL; |
488 | 375k | } |
489 | | |
490 | | /* Copy from previous sync point up to to current (offset) */ |
491 | 6.13M | block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_buf_offset, |
492 | 6.13M | &p_sys->p_buf[p_sys->i_buf_offset], |
493 | 6.13M | p_sys->i_offset - p_sys->i_buf_offset ); |
494 | | |
495 | | /* update crc to include this data chunk */ |
496 | 136M | for( size_t i = p_sys->i_buf_offset; i < p_sys->i_offset - 2; i++ ) |
497 | 130M | p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[i] ); |
498 | | |
499 | 6.13M | uint16_t stream_crc = GetWBE(&p_sys->p_buf[p_sys->i_offset - 2]); |
500 | 6.13M | if( stream_crc != p_sys->crc ) |
501 | 6.13M | { |
502 | | /* False positive syncpoint as the CRC does not match */ |
503 | | /* Add the 2 last bytes which were not the CRC sum, and go for next sync point */ |
504 | 6.13M | p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[p_sys->i_offset - 2] ); |
505 | 6.13M | p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[p_sys->i_offset - 1] ); |
506 | 6.13M | p_sys->i_buf_offset = p_sys->i_offset; |
507 | 6.13M | p_sys->i_offset += 1; |
508 | 6.13M | p_sys->i_state = !pp_block ? STATE_NOSYNC : STATE_NEXT_SYNC; |
509 | 6.13M | break; /* continue */ |
510 | 6.13M | } |
511 | | |
512 | 2.59k | p_sys->i_state = STATE_SEND_DATA; |
513 | | |
514 | | /* frame size between the two sync codes is now known */ |
515 | 2.59k | p_sys->i_last_frame_size = p_sys->i_offset; |
516 | 2.59k | p_sys->i_buf = p_sys->i_offset; |
517 | | |
518 | | /* clean */ |
519 | 2.59k | block_SkipBytes( &p_sys->bytestream, p_sys->i_offset ); |
520 | 2.59k | block_BytestreamFlush( &p_sys->bytestream ); |
521 | 2.59k | p_sys->i_offset = 0; |
522 | 2.59k | p_sys->crc = 0; |
523 | 2.59k | p_sys->i_buf_offset = 0; |
524 | | |
525 | 2.59k | if( block_BytestreamRemaining(&p_sys->bytestream) > 0 || pp_block == NULL /* drain */) |
526 | 2.59k | p_sys->i_state = STATE_SEND_DATA; |
527 | 0 | else |
528 | 0 | p_sys->i_state = STATE_NOSYNC; |
529 | 2.59k | } |
530 | 2.59k | break; |
531 | | |
532 | 2.59k | case STATE_SEND_DATA: |
533 | 2.59k | p_dec->fmt_out.audio.i_rate = p_sys->headerinfo.i_rate; |
534 | 2.59k | p_dec->fmt_out.audio.i_channels = p_sys->headerinfo.i_channels; |
535 | 2.59k | p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_sys->stream_info.channels]; |
536 | | |
537 | 2.59k | if( p_sys->bytestream.p_block && |
538 | 2.59k | p_sys->bytestream.p_block->i_pts > date_Get( &p_sys->pts ) && |
539 | 2.59k | p_sys->bytestream.p_block->i_pts != VLC_TICK_INVALID ) |
540 | 10 | { |
541 | 10 | date_Init( &p_sys->pts, p_sys->headerinfo.i_rate, 1 ); |
542 | 10 | date_Set( &p_sys->pts, p_sys->bytestream.p_block->i_pts ); |
543 | 10 | p_sys->bytestream.p_block->i_pts = VLC_TICK_INVALID; |
544 | 10 | } |
545 | | |
546 | | |
547 | 2.59k | out = block_heap_Alloc( p_sys->p_buf, p_sys->i_buf ); |
548 | 2.59k | if( out ) |
549 | 2.59k | { |
550 | 2.59k | out->i_dts = out->i_pts = date_Get( &p_sys->pts ); |
551 | 2.59k | out->i_flags = p_sys->i_next_block_flags; |
552 | 2.59k | p_sys->i_next_block_flags = 0; |
553 | 2.59k | } |
554 | 0 | else |
555 | 0 | p_sys->p_buf = NULL; |
556 | | |
557 | 2.59k | date_Increment( &p_sys->pts, p_sys->headerinfo.i_frame_length ); |
558 | 2.59k | if( out ) |
559 | 2.59k | out->i_length = date_Get( &p_sys->pts ) - out->i_pts; |
560 | 0 | else |
561 | 0 | free( p_sys->p_buf ); |
562 | | |
563 | 2.59k | p_sys->i_buf_offset = 0; |
564 | 2.59k | p_sys->i_buf = 0; |
565 | 2.59k | p_sys->p_buf = NULL; |
566 | 2.59k | p_sys->i_offset = 0; |
567 | 2.59k | p_sys->i_state = STATE_NOSYNC; |
568 | | |
569 | | /* So p_block doesn't get re-added several times */ |
570 | 2.59k | if ( pp_block ) |
571 | 2.59k | *pp_block = block_BytestreamPop(&p_sys->bytestream); |
572 | | |
573 | 2.59k | return out; |
574 | 19.5M | } |
575 | | |
576 | 0 | return NULL; |
577 | 4.11k | } |
578 | | |
579 | | static int Open(vlc_object_t *p_this) |
580 | | { |
581 | | decoder_t *p_dec = (decoder_t*)p_this; |
582 | | decoder_sys_t *p_sys; |
583 | | |
584 | | if (p_dec->fmt_in->i_codec != VLC_CODEC_FLAC) |
585 | | return VLC_EGENERIC; |
586 | | |
587 | | |
588 | | /* */ |
589 | | p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)); |
590 | | if (!p_sys) |
591 | | return VLC_ENOMEM; |
592 | | |
593 | | p_sys->i_state = STATE_NOSYNC; |
594 | | p_sys->i_offset = 0; |
595 | | p_sys->b_stream_info = false; |
596 | | p_sys->i_last_frame_size = FLAC_FRAME_SIZE_MIN; |
597 | | p_sys->headerinfo.i_pts = VLC_TICK_INVALID; |
598 | | p_sys->i_buf_offset = 0; |
599 | | p_sys->i_buf = 0; |
600 | | p_sys->p_buf = NULL; |
601 | | p_sys->i_next_block_flags = 0; |
602 | | block_BytestreamInit(&p_sys->bytestream); |
603 | | date_Init( &p_sys->pts, 1, 1 ); |
604 | | |
605 | | /* */ |
606 | | es_format_Copy(&p_dec->fmt_out, p_dec->fmt_in); |
607 | | p_dec->fmt_out.i_codec = VLC_CODEC_FLAC; |
608 | | p_dec->fmt_out.b_packetized = true; |
609 | | |
610 | | /* */ |
611 | | p_dec->pf_packetize = Packetize; |
612 | | p_dec->pf_flush = Flush; |
613 | | p_dec->pf_get_cc = NULL; |
614 | | |
615 | | return VLC_SUCCESS; |
616 | | } |
617 | | |
618 | | static void Close(vlc_object_t *p_this) |
619 | | { |
620 | | decoder_t *p_dec = (decoder_t *)p_this; |
621 | | decoder_sys_t *p_sys = p_dec->p_sys; |
622 | | |
623 | | block_BytestreamRelease(&p_sys->bytestream); |
624 | | free(p_sys->p_buf); |
625 | | free(p_sys); |
626 | | } |