asf: use ES_OUT_SET_ES_FMT
[vlc.git] / modules / packetizer / flac.c
blob1c47c756ed62bf5c6c9eb13f788e392bc9d978ea
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 p_sys->i_state = STATE_GET_DATA;
400 break;
402 else if( pp_block == NULL )
404 p_sys->i_offset = block_BytestreamRemaining( &p_sys->bytestream );
405 p_sys->i_state = STATE_GET_DATA;
407 return NULL;
410 case STATE_GET_DATA:
411 if( p_sys->i_offset < FLAC_FRAME_SIZE_MIN ||
412 ( p_sys->b_stream_info &&
413 p_sys->stream_info.min_framesize > p_sys->i_offset ) )
415 p_sys->i_offset += 1;
416 p_sys->i_state = STATE_NEXT_SYNC;
417 break;
419 else if( p_sys->b_stream_info &&
420 p_sys->stream_info.max_framesize > FLAC_FRAME_SIZE_MIN &&
421 p_sys->stream_info.max_framesize < p_sys->i_offset )
423 /* Something went wrong, truncate stream head and restart */
424 block_SkipBytes( &p_sys->bytestream, FLAC_HEADER_SIZE_MAX + 2 );
425 block_BytestreamFlush( &p_sys->bytestream );
426 p_sys->i_frame_size = 0;
427 p_sys->crc = 0;
428 p_sys->i_offset = 0;
429 p_sys->i_state = STATE_NOSYNC;
430 p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
431 break;
433 else
435 /* Allocate enough for storage */
436 if( p_sys->i_offset > p_sys->i_buf )
438 size_t i_min_alloc = __MAX(p_sys->i_last_frame_size, p_sys->i_offset);
439 uint8_t *p_realloc = realloc( p_sys->p_buf, i_min_alloc );
440 if( p_realloc )
442 p_sys->i_buf = i_min_alloc;
443 p_sys->p_buf = p_realloc;
446 if ( !p_sys->p_buf )
447 return NULL;
450 /* Copy from previous sync point (frame_size) up to to current (offset) */
451 block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_frame_size,
452 &p_sys->p_buf[p_sys->i_frame_size],
453 p_sys->i_offset - p_sys->i_frame_size );
455 /* update crc to include this data chunk */
456 for( size_t i = p_sys->i_frame_size; i < p_sys->i_offset - 2; i++ )
457 p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[i] );
459 p_sys->i_frame_size = p_sys->i_offset;
461 uint16_t stream_crc = GetWBE(&p_sys->p_buf[p_sys->i_offset - 2]);
462 if( stream_crc != p_sys->crc )
464 /* False positive syncpoint as the CRC does not match */
465 /* Add the 2 last bytes which were not the CRC sum, and go for next sync point */
466 p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[p_sys->i_offset - 2] );
467 p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[p_sys->i_offset - 1] );
468 p_sys->i_offset += 1;
469 p_sys->i_state = STATE_NEXT_SYNC;
470 break; /* continue */
473 p_sys->i_state = STATE_SEND_DATA;
475 /* clean */
476 block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
477 block_BytestreamFlush( &p_sys->bytestream );
478 p_sys->i_last_frame_size = p_sys->i_frame_size;
479 p_sys->i_offset = 0;
480 p_sys->crc = 0;
482 break;
484 case STATE_SEND_DATA:
485 p_dec->fmt_out.audio.i_rate = p_sys->headerinfo.i_rate;
486 p_dec->fmt_out.audio.i_channels = p_sys->headerinfo.i_channels;
487 p_dec->fmt_out.audio.i_physical_channels = pi_channels_maps[p_sys->stream_info.channels];
489 if( p_sys->bytestream.p_block->i_pts > date_Get( &p_sys->pts ) &&
490 p_sys->bytestream.p_block->i_pts != VLC_TICK_INVALID )
492 date_Init( &p_sys->pts, p_sys->headerinfo.i_rate, 1 );
493 date_Set( &p_sys->pts, p_sys->bytestream.p_block->i_pts );
494 p_sys->bytestream.p_block->i_pts = VLC_TICK_INVALID;
498 out = block_heap_Alloc( p_sys->p_buf, p_sys->i_frame_size );
499 if( out )
501 out->i_dts = out->i_pts = date_Get( &p_sys->pts );
502 out->i_flags = p_sys->i_next_block_flags;
503 p_sys->i_next_block_flags = 0;
505 else
506 p_sys->p_buf = NULL;
508 date_Increment( &p_sys->pts, p_sys->headerinfo.i_frame_length );
509 if( out )
510 out->i_length = date_Get( &p_sys->pts ) - out->i_pts;
511 else
512 free( p_sys->p_buf );
514 p_sys->i_buf = 0;
515 p_sys->p_buf = NULL;
516 p_sys->i_frame_size = 0;
517 p_sys->i_offset = 0;
518 p_sys->i_state = STATE_NOSYNC;
520 /* So p_block doesn't get re-added several times */
521 if ( pp_block )
522 *pp_block = block_BytestreamPop(&p_sys->bytestream);
524 return out;
527 return NULL;
530 static int Open(vlc_object_t *p_this)
532 decoder_t *p_dec = (decoder_t*)p_this;
533 decoder_sys_t *p_sys;
535 if (p_dec->fmt_in.i_codec != VLC_CODEC_FLAC)
536 return VLC_EGENERIC;
539 /* */
540 p_dec->p_sys = p_sys = malloc(sizeof(*p_sys));
541 if (!p_sys)
542 return VLC_ENOMEM;
544 p_sys->i_state = STATE_NOSYNC;
545 p_sys->i_offset = 0;
546 p_sys->b_stream_info = false;
547 p_sys->i_last_frame_size = FLAC_FRAME_SIZE_MIN;
548 p_sys->i_frame_size = 0;
549 p_sys->headerinfo.i_pts = VLC_TICK_INVALID;
550 p_sys->i_buf = 0;
551 p_sys->p_buf = NULL;
552 p_sys->i_next_block_flags = 0;
553 block_BytestreamInit(&p_sys->bytestream);
554 date_Init( &p_sys->pts, 1, 1 );
556 /* */
557 es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in);
558 p_dec->fmt_out.i_codec = VLC_CODEC_FLAC;
559 p_dec->fmt_out.b_packetized = true;
561 /* */
562 p_dec->pf_packetize = Packetize;
563 p_dec->pf_flush = Flush;
564 p_dec->pf_get_cc = NULL;
566 return VLC_SUCCESS;
569 static void Close(vlc_object_t *p_this)
571 decoder_t *p_dec = (decoder_t *)p_this;
572 decoder_sys_t *p_sys = p_dec->p_sys;
574 block_BytestreamRelease(&p_sys->bytestream);
575 free(p_sys->p_buf);
576 free(p_sys);