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