Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2019-2021
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / FLAC reframer filter
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include <gpac/avparse.h>
27 : #include <gpac/constants.h>
28 : #include <gpac/filters.h>
29 :
30 : typedef struct
31 : {
32 : u64 pos;
33 : Double duration;
34 : } FLACIdx;
35 :
36 : typedef struct
37 : {
38 : u32 block_size;
39 : u32 sample_rate;
40 : } FLACHeader;
41 :
42 : typedef struct
43 : {
44 : //filter args
45 : Double index;
46 :
47 : //only one input pid declared
48 : GF_FilterPid *ipid;
49 : //only one output pid declared
50 : GF_FilterPid *opid;
51 :
52 : GF_BitStream *bs;
53 : u64 file_pos, cts, prev_cts;
54 :
55 : GF_Fraction64 duration;
56 : Double start_range;
57 : Bool in_seek;
58 : u32 timescale;
59 : Bool is_playing;
60 : Bool is_file;
61 : Bool initial_play_done, file_loaded;
62 : Bool in_error;
63 :
64 : Bool initialized;
65 : u32 sample_rate, nb_channels, bits_per_sample, block_size;
66 :
67 : u8 *flac_buffer;
68 : u32 flac_buffer_size, flac_buffer_alloc, resume_from;
69 : u64 byte_offset;
70 :
71 : GF_FilterPacket *src_pck;
72 :
73 : Bool recompute_cts;
74 : FLACIdx *indexes;
75 : u32 index_alloc_size, index_size;
76 : u32 bitrate;
77 : } GF_FLACDmxCtx;
78 :
79 :
80 :
81 :
82 4 : GF_Err flac_dmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
83 : {
84 : const GF_PropertyValue *p;
85 4 : GF_FLACDmxCtx *ctx = gf_filter_get_udta(filter);
86 :
87 4 : if (is_remove) {
88 0 : ctx->ipid = NULL;
89 0 : if (ctx->opid) {
90 0 : gf_filter_pid_remove(ctx->opid);
91 0 : ctx->opid = NULL;
92 : }
93 : return GF_OK;
94 : }
95 4 : if (! gf_filter_pid_check_caps(pid))
96 : return GF_NOT_SUPPORTED;
97 :
98 4 : ctx->ipid = pid;
99 4 : p = gf_filter_pid_get_property(pid, GF_PROP_PID_TIMESCALE);
100 4 : if (p) ctx->timescale = p->value.uint;
101 :
102 4 : p = gf_filter_pid_get_property_str(pid, "nocts");
103 4 : if (p && p->value.boolean) ctx->recompute_cts = GF_TRUE;
104 4 : else ctx->recompute_cts = GF_FALSE;
105 :
106 4 : if (ctx->timescale && !ctx->opid) {
107 0 : ctx->opid = gf_filter_pid_new(filter);
108 0 : gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
109 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL);
110 : }
111 : return GF_OK;
112 : }
113 :
114 13 : static void flac_dmx_check_dur(GF_Filter *filter, GF_FLACDmxCtx *ctx)
115 : {
116 : u64 rate;
117 : FILE *stream;
118 : const GF_PropertyValue *p;
119 13 : if (!ctx->opid || ctx->timescale || ctx->file_loaded) return;
120 :
121 4 : if (ctx->index<=0) {
122 3 : ctx->file_loaded = GF_TRUE;
123 : return;
124 : }
125 :
126 1 : p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
127 1 : if (!p || !p->value.string || !strncmp(p->value.string, "gmem://", 7)) {
128 0 : ctx->is_file = GF_FALSE;
129 0 : ctx->file_loaded = GF_TRUE;
130 : return;
131 : }
132 1 : ctx->is_file = GF_TRUE;
133 :
134 1 : stream = gf_fopen(p->value.string, "rb");
135 1 : if (!stream) return;
136 1 : gf_fseek(stream, 0, SEEK_END);
137 :
138 1 : rate = gf_ftell(stream);
139 1 : gf_fclose(stream);
140 1 : if (ctx->duration.num && !gf_sys_is_test_mode() ) {
141 0 : rate *= 8 * ctx->duration.den;
142 0 : rate /= ctx->duration.num;
143 0 : ctx->bitrate = (u32) rate;
144 : }
145 :
146 1 : p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILE_CACHED);
147 1 : if (p && p->value.boolean) ctx->file_loaded = GF_TRUE;
148 1 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CAN_DATAREF, & PROP_BOOL(GF_TRUE ) );
149 : }
150 :
151 4 : static void flac_dmx_check_pid(GF_Filter *filter, GF_FLACDmxCtx *ctx, u8 *dsi, u32 dsi_size)
152 : {
153 4 : if (!ctx->opid) {
154 4 : ctx->opid = gf_filter_pid_new(filter);
155 4 : flac_dmx_check_dur(filter, ctx);
156 : }
157 : //copy properties at init or reconfig
158 4 : gf_filter_pid_copy_properties(ctx->opid, ctx->ipid);
159 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_STREAM_TYPE, & PROP_UINT( GF_STREAM_AUDIO));
160 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_UNFRAMED, NULL );
161 4 : if (ctx->is_file && ctx->index) {
162 1 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_PLAYBACK_MODE, & PROP_UINT(GF_PLAYBACK_MODE_FASTFORWARD) );
163 : }
164 4 : if (ctx->duration.num)
165 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DURATION, & PROP_FRAC64(ctx->duration));
166 :
167 4 : if (!ctx->timescale) gf_filter_pid_set_name(ctx->opid, "audio");
168 :
169 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_DECODER_CONFIG, & PROP_DATA( dsi, dsi_size ) );
170 :
171 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_CODECID, & PROP_UINT( GF_CODECID_FLAC ) );
172 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_TIMESCALE, & PROP_UINT(ctx->timescale ? ctx->timescale : ctx->sample_rate));
173 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, & PROP_UINT(ctx->sample_rate));
174 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_NUM_CHANNELS, & PROP_UINT(ctx->nb_channels) );
175 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLES_PER_FRAME, & PROP_UINT(ctx->block_size) );
176 :
177 4 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_AUDIO_BPS, & PROP_UINT(ctx->bits_per_sample) );
178 :
179 4 : if (ctx->bitrate) {
180 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_BITRATE, & PROP_UINT(ctx->bitrate));
181 : }
182 :
183 4 : }
184 :
185 412 : static Bool flac_dmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
186 : {
187 : u32 i;
188 : GF_FilterEvent fevt;
189 412 : GF_FLACDmxCtx *ctx = gf_filter_get_udta(filter);
190 :
191 412 : if (evt->base.on_pid != ctx->opid) return GF_TRUE;
192 :
193 6 : switch (evt->base.type) {
194 4 : case GF_FEVT_PLAY:
195 4 : if (!ctx->is_playing) {
196 4 : ctx->is_playing = GF_TRUE;
197 : }
198 4 : if (! ctx->is_file) {
199 3 : if (evt->play.start_range || ctx->initial_play_done) {
200 0 : ctx->flac_buffer_size = 0;
201 0 : ctx->resume_from = 0;
202 : }
203 3 : ctx->initial_play_done = GF_TRUE;
204 3 : return GF_FALSE;
205 : }
206 1 : flac_dmx_check_dur(filter, ctx);
207 :
208 1 : ctx->start_range = evt->play.start_range;
209 1 : ctx->in_seek = GF_TRUE;
210 1 : ctx->file_pos = 0;
211 1 : if (ctx->start_range) {
212 0 : for (i=1; i<ctx->index_size; i++) {
213 0 : if (ctx->indexes[i].duration>ctx->start_range) {
214 0 : ctx->cts = (u64) (ctx->indexes[i-1].duration * ctx->sample_rate);
215 0 : ctx->file_pos = ctx->indexes[i-1].pos;
216 0 : break;
217 : }
218 : }
219 : }
220 1 : if (!ctx->initial_play_done) {
221 1 : ctx->initial_play_done = GF_TRUE;
222 : //seek will not change the current source state, don't send a seek
223 1 : if (!ctx->file_pos)
224 : return GF_TRUE;
225 : }
226 0 : ctx->flac_buffer_size = 0;
227 0 : ctx->resume_from = 0;
228 : //post a seek
229 0 : GF_FEVT_INIT(fevt, GF_FEVT_SOURCE_SEEK, ctx->ipid);
230 0 : fevt.seek.start_offset = ctx->file_pos;
231 0 : gf_filter_pid_send_event(ctx->ipid, &fevt);
232 :
233 : //cancel event
234 0 : return GF_TRUE;
235 :
236 2 : case GF_FEVT_STOP:
237 2 : ctx->is_playing = GF_FALSE;
238 2 : if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
239 2 : ctx->src_pck = NULL;
240 : //don't cancel event
241 2 : return GF_FALSE;
242 :
243 : case GF_FEVT_SET_SPEED:
244 : //cancel event
245 : return GF_TRUE;
246 : default:
247 : break;
248 : }
249 : //by default don't cancel event - to rework once we have downloading in place
250 0 : return GF_FALSE;
251 : }
252 :
253 : static GFINLINE void flac_dmx_update_cts(GF_FLACDmxCtx *ctx, u32 nb_samp)
254 : {
255 154 : if (ctx->timescale) {
256 0 : u64 inc = nb_samp;
257 0 : inc *= ctx->timescale;
258 0 : inc /= ctx->sample_rate;
259 0 : ctx->cts += inc;
260 : } else {
261 154 : ctx->cts += nb_samp;
262 : }
263 : }
264 :
265 :
266 : u8 const flac_dmx_crc8_table[256] = {
267 : 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
268 : 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
269 : 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
270 : 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
271 : 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
272 : 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
273 : 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
274 : 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
275 : 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
276 : 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
277 : 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
278 : 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
279 : 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
280 : 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
281 : 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
282 : 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
283 : 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
284 : 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
285 : 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
286 : 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
287 : 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
288 : 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
289 : 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
290 : 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
291 : 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
292 : 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
293 : 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
294 : 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
295 : 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
296 : 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
297 : 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
298 : 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
299 : };
300 :
301 0 : u8 flac_dmx_crc8(u8 *data, u32 len)
302 : {
303 : u8 crc = 0;
304 2624 : while (len--)
305 2198 : crc = flac_dmx_crc8_table[crc ^ *data++];
306 0 : return crc;
307 : }
308 :
309 : static u32 flac_dmx_block_sizes[] =
310 : {
311 : 0, 192, 576, 1152, 2304, 4608, 0, 0, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
312 : };
313 : static u32 flac_dmx_samplerates[] =
314 : {
315 : 0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000
316 : };
317 :
318 554 : static Bool flac_parse_header(GF_FLACDmxCtx *ctx, char *data, u32 size, FLACHeader *hdr)
319 : {
320 : u32 block_size, sample_rate, res, top, pos, crc, crc_hdr;
321 :
322 554 : gf_bs_reassign_buffer(ctx->bs, data, size);
323 554 : gf_bs_read_int(ctx->bs, 15);
324 554 : /*block_strategy = */gf_bs_read_int(ctx->bs, 1);
325 554 : block_size = gf_bs_read_int(ctx->bs, 4);
326 554 : sample_rate = gf_bs_read_int(ctx->bs, 4);
327 554 : /*u32 channel_layout = */gf_bs_read_int(ctx->bs, 4);
328 554 : /*u32 bps = */gf_bs_read_int(ctx->bs, 3);
329 554 : gf_bs_read_int(ctx->bs, 1);
330 :
331 554 : res = gf_bs_read_u8(ctx->bs);
332 554 : top = (res & 128) >> 1;
333 554 : if ((res & 0xC0) == 0x80 || (res >= 0xFE)) return GF_FALSE;
334 508 : while (res & top) {
335 82 : s32 tmp = gf_bs_read_u8(ctx->bs);
336 82 : tmp -= 128;
337 82 : if(tmp>>6)
338 : return GF_FALSE;
339 36 : res = (res<<6) + tmp;
340 36 : top <<= 5;
341 : }
342 : //res &= (top << 1) - 1;
343 :
344 426 : if (block_size==6) block_size = 1 + gf_bs_read_int(ctx->bs, 8);
345 420 : else if (block_size==7) block_size = 1 + gf_bs_read_int(ctx->bs, 16);
346 : else {
347 410 : block_size = flac_dmx_block_sizes[block_size];
348 : }
349 :
350 : #if 0
351 : if (bps==0) bps = ctx->bits_per_sample;
352 : else if (bps==1) bps = 8;
353 : else if (bps==2) bps = 12;
354 : else if (bps==4) bps = 16;
355 : else if (bps==5) bps = 20;
356 : else if (bps==6) bps = 24;
357 : #endif
358 :
359 426 : if (sample_rate==0) sample_rate = ctx->sample_rate;
360 420 : else if ((sample_rate&0xC)==0xC) {
361 17 : if (sample_rate==0xC) sample_rate = gf_bs_read_u8(ctx->bs);
362 13 : else if (sample_rate==0xD) sample_rate = gf_bs_read_u16(ctx->bs);
363 13 : else if (sample_rate==0xE) sample_rate = 10*gf_bs_read_u16(ctx->bs);
364 : } else {
365 403 : sample_rate = flac_dmx_samplerates[sample_rate];
366 : }
367 :
368 426 : pos = (u32) gf_bs_get_position(ctx->bs);
369 :
370 426 : crc = gf_bs_read_u8(ctx->bs);
371 426 : crc_hdr = flac_dmx_crc8(data, pos);
372 :
373 426 : if (crc != crc_hdr) {
374 : return GF_FALSE;
375 : }
376 310 : hdr->sample_rate = sample_rate;
377 310 : hdr->block_size = block_size;
378 : return GF_TRUE;
379 : }
380 :
381 426 : GF_Err flac_dmx_process(GF_Filter *filter)
382 : {
383 426 : GF_FLACDmxCtx *ctx = gf_filter_get_udta(filter);
384 : GF_FilterPacket *pck, *dst_pck;
385 : u8 *output;
386 : u8 *start;
387 : Bool final_flush=GF_FALSE;
388 : u32 pck_size, remain, prev_pck_size;
389 : u64 cts = GF_FILTER_NO_TS;
390 : FLACHeader hdr;
391 :
392 426 : if (ctx->in_error)
393 : return GF_NON_COMPLIANT_BITSTREAM;
394 :
395 : //always reparse duration
396 426 : if (!ctx->duration.num)
397 8 : flac_dmx_check_dur(filter, ctx);
398 :
399 426 : if (ctx->opid && !ctx->is_playing)
400 : return GF_OK;
401 :
402 410 : pck = gf_filter_pid_get_packet(ctx->ipid);
403 410 : if (!pck) {
404 4 : if (gf_filter_pid_is_eos(ctx->ipid)) {
405 4 : if (!ctx->flac_buffer_size) {
406 2 : if (ctx->opid)
407 2 : gf_filter_pid_set_eos(ctx->opid);
408 2 : if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
409 2 : ctx->src_pck = NULL;
410 2 : return GF_EOS;
411 : }
412 : final_flush = GF_TRUE;
413 : } else {
414 : return GF_OK;
415 : }
416 : }
417 :
418 408 : prev_pck_size = ctx->flac_buffer_size;
419 408 : if (pck && !ctx->resume_from) {
420 406 : u8 *data = (u8 *) gf_filter_pck_get_data(pck, &pck_size);
421 :
422 406 : if (ctx->byte_offset != GF_FILTER_NO_BO) {
423 406 : u64 byte_offset = gf_filter_pck_get_byte_offset(pck);
424 406 : if (!ctx->flac_buffer_size) {
425 4 : ctx->byte_offset = byte_offset;
426 402 : } else if (ctx->byte_offset + ctx->flac_buffer_size != byte_offset) {
427 154 : ctx->byte_offset = GF_FILTER_NO_BO;
428 154 : if ((byte_offset != GF_FILTER_NO_BO) && (byte_offset>ctx->flac_buffer_size) ) {
429 154 : ctx->byte_offset = byte_offset - ctx->flac_buffer_size;
430 : }
431 : }
432 : }
433 :
434 406 : if (ctx->flac_buffer_size + pck_size > ctx->flac_buffer_alloc) {
435 33 : ctx->flac_buffer_alloc = ctx->flac_buffer_size + pck_size;
436 33 : ctx->flac_buffer = gf_realloc(ctx->flac_buffer, ctx->flac_buffer_alloc);
437 : }
438 406 : memcpy(ctx->flac_buffer + ctx->flac_buffer_size, data, pck_size);
439 406 : ctx->flac_buffer_size += pck_size;
440 : }
441 :
442 : //input pid sets some timescale - we flushed pending data , update cts
443 408 : if (ctx->timescale && pck) {
444 0 : cts = gf_filter_pck_get_cts(pck);
445 : }
446 :
447 0 : if (cts == GF_FILTER_NO_TS) {
448 : //avoids updating cts
449 : prev_pck_size = 0;
450 : }
451 :
452 408 : remain = ctx->flac_buffer_size;
453 408 : start = ctx->flac_buffer;
454 :
455 408 : if (ctx->resume_from) {
456 0 : start += ctx->resume_from - 1;
457 0 : remain -= ctx->resume_from - 1;
458 0 : ctx->resume_from = 0;
459 : }
460 :
461 562 : while (remain>2) {
462 : u32 next_frame=0, nb_samp;
463 560 : u32 cur_size = remain-2;
464 560 : u8 *cur_buf = start+2;
465 : u8 *hdr_start = NULL;
466 :
467 560 : if (final_flush) {
468 : next_frame = remain;
469 : } else {
470 15752 : while (cur_size) {
471 : //wait till we have a frame header
472 15750 : hdr_start = memchr(cur_buf, 0xFF, cur_size);
473 15750 : if (!hdr_start) break;
474 15350 : next_frame = (u32) (hdr_start-start);
475 15350 : if (next_frame == remain)
476 : break;
477 :
478 15350 : if ((hdr_start[1]&0xFC) == 0xF8) {
479 400 : if (flac_parse_header(ctx, hdr_start, (u32) remain - next_frame, &hdr))
480 : break;
481 : }
482 15194 : cur_buf = hdr_start+1;
483 15194 : cur_size = (u32) (cur_buf - start);
484 : assert(cur_size<=remain);
485 15194 : cur_size = remain - cur_size;
486 : hdr_start = NULL;
487 : }
488 558 : if (!hdr_start) break;
489 156 : if (next_frame == remain)
490 : break;
491 : }
492 :
493 :
494 158 : if (!ctx->initialized) {
495 : u32 size = next_frame;
496 : u32 dsi_end = 0;
497 : //we have a header
498 4 : gf_bs_reassign_buffer(ctx->bs, ctx->flac_buffer, size);
499 4 : u32 magic = gf_bs_read_u32(ctx->bs);
500 4 : if (magic != GF_4CC('f','L','a','C')) {
501 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[FLACDmx] invalid FLAC magic\n"));
502 0 : ctx->in_error = GF_TRUE;
503 0 : ctx->flac_buffer_size = 0;
504 0 : if (pck)
505 0 : gf_filter_pid_drop_packet(ctx->ipid);
506 : return GF_NON_COMPLIANT_BITSTREAM;
507 : }
508 12 : while (gf_bs_available(ctx->bs)) {
509 12 : Bool last = gf_bs_read_int(ctx->bs, 1);
510 12 : u32 type = gf_bs_read_int(ctx->bs, 7);
511 12 : u32 len = gf_bs_read_int(ctx->bs, 24);
512 :
513 12 : if (type==0) {
514 4 : u16 min_block_size = gf_bs_read_u16(ctx->bs);
515 4 : u16 max_block_size = gf_bs_read_u16(ctx->bs);
516 4 : /*u32 min_frame_size = */gf_bs_read_u24(ctx->bs);
517 4 : /*u32 max_frame_size = */gf_bs_read_u24(ctx->bs);
518 4 : ctx->sample_rate = gf_bs_read_int(ctx->bs, 20);
519 4 : ctx->nb_channels = 1 + gf_bs_read_int(ctx->bs, 3);
520 4 : ctx->bits_per_sample = 1 + gf_bs_read_int(ctx->bs, 5);
521 4 : if (min_block_size==max_block_size) ctx->block_size = min_block_size;
522 0 : else ctx->block_size = 0;
523 :
524 4 : ctx->duration.num = gf_bs_read_long_int(ctx->bs, 36);
525 4 : ctx->duration.den = ctx->sample_rate;
526 : //ignore the rest
527 4 : gf_bs_skip_bytes(ctx->bs, 16);
528 4 : dsi_end = (u32) gf_bs_get_position(ctx->bs);
529 :
530 : } else {
531 : //ignore the rest for now
532 : //TODO: expose metadata, pictures and co
533 8 : gf_bs_skip_bytes(ctx->bs, len);
534 : }
535 12 : if (last) break;
536 : }
537 4 : if (!dsi_end) {
538 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[FLACDmx] invalid FLAC header\n"));
539 0 : ctx->in_error = GF_TRUE;
540 0 : ctx->flac_buffer_size = 0;
541 0 : if (pck)
542 0 : gf_filter_pid_drop_packet(ctx->ipid);
543 : return GF_NON_COMPLIANT_BITSTREAM;
544 : }
545 4 : flac_dmx_check_pid(filter, ctx, ctx->flac_buffer+4, dsi_end-4);
546 4 : remain -= size;
547 4 : start += size;
548 4 : ctx->initialized = GF_TRUE;
549 4 : if (!ctx->is_playing) break;
550 0 : continue;
551 : }
552 :
553 : //we have a next frame, check we are synchronize
554 154 : if ((start[0] != 0xFF) && ((start[1]&0xFC) != 0xF8)) {
555 0 : GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[FLACDmx] invalid frame, dropping %d bytes and resyncing\n", next_frame));
556 0 : start += next_frame;
557 0 : remain -= next_frame;
558 0 : continue;
559 : }
560 :
561 154 : flac_parse_header(ctx,start, next_frame, &hdr);
562 154 : if (hdr.sample_rate != ctx->sample_rate) {
563 0 : ctx->sample_rate = hdr.sample_rate;
564 0 : gf_filter_pid_set_property(ctx->opid, GF_PROP_PID_SAMPLE_RATE, & PROP_UINT(ctx->sample_rate));
565 : }
566 :
567 154 : nb_samp = hdr.block_size;
568 :
569 154 : if (ctx->in_seek) {
570 1 : u64 nb_samples_at_seek = (u64) (ctx->start_range * ctx->sample_rate);
571 1 : if (ctx->cts + nb_samp >= nb_samples_at_seek) {
572 : //u32 samples_to_discard = (ctx->cts + nb_samp ) - nb_samples_at_seek;
573 1 : ctx->in_seek = GF_FALSE;
574 : }
575 : }
576 :
577 154 : if (ctx->timescale && !prev_pck_size && (cts != GF_FILTER_NO_TS) ) {
578 0 : ctx->cts = cts;
579 : cts = GF_FILTER_NO_TS;
580 : }
581 :
582 154 : if (!ctx->in_seek) {
583 154 : dst_pck = gf_filter_pck_new_alloc(ctx->opid, next_frame, &output);
584 154 : if (!dst_pck) return GF_OUT_OF_MEM;
585 154 : memcpy(output, start, next_frame);
586 :
587 154 : gf_filter_pck_set_cts(dst_pck, ctx->cts);
588 154 : if (!ctx->timescale || (ctx->timescale==ctx->sample_rate) )
589 154 : gf_filter_pck_set_duration(dst_pck, nb_samp);
590 : else {
591 0 : gf_filter_pck_set_duration(dst_pck, (nb_samp * ctx->timescale) / ctx->sample_rate);
592 : }
593 154 : gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
594 154 : gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
595 :
596 154 : if (ctx->byte_offset != GF_FILTER_NO_BO) {
597 154 : gf_filter_pck_set_byte_offset(dst_pck, ctx->byte_offset);
598 : }
599 154 : gf_filter_pck_send(dst_pck);
600 : }
601 : flac_dmx_update_cts(ctx, nb_samp);
602 :
603 : assert (start[0] == 0xFF);
604 : assert((start[1]&0xFC) == 0xF8);
605 :
606 154 : start += next_frame;
607 : assert(remain >= next_frame);
608 154 : remain -= next_frame;
609 :
610 : }
611 :
612 408 : if (!pck) {
613 2 : ctx->flac_buffer_size = 0;
614 2 : return flac_dmx_process(filter);
615 : } else {
616 406 : if (remain < ctx->flac_buffer_size) {
617 156 : memmove(ctx->flac_buffer, start, remain);
618 : }
619 406 : ctx->flac_buffer_size = remain;
620 406 : gf_filter_pid_drop_packet(ctx->ipid);
621 : }
622 406 : return GF_OK;
623 : }
624 :
625 4 : static GF_Err flac_dmx_initialize(GF_Filter *filter)
626 : {
627 4 : GF_FLACDmxCtx *ctx = gf_filter_get_udta(filter);
628 4 : ctx->bs = gf_bs_new((u8 *)ctx, 1, GF_BITSTREAM_READ);
629 4 : return GF_OK;
630 : }
631 4 : static void flac_dmx_finalize(GF_Filter *filter)
632 : {
633 4 : GF_FLACDmxCtx *ctx = gf_filter_get_udta(filter);
634 4 : if (ctx->bs) gf_bs_del(ctx->bs);
635 4 : if (ctx->indexes) gf_free(ctx->indexes);
636 4 : if (ctx->flac_buffer) gf_free(ctx->flac_buffer);
637 4 : if (ctx->src_pck) gf_filter_pck_unref(ctx->src_pck);
638 4 : }
639 :
640 :
641 3065 : static const char *flac_dmx_probe_data(const u8 *data, u32 size, GF_FilterProbeScore *score)
642 : {
643 3065 : if ((size>4) && !strncmp(data, "fLaC", 4)) {
644 4 : *score = GF_FPROBE_SUPPORTED;
645 4 : return "audio/flac";
646 : }
647 : return NULL;
648 : }
649 :
650 : static const GF_FilterCapability FLACDmxCaps[] =
651 : {
652 : CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
653 : CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "flac"),
654 : CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "audio/flac"),
655 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
656 : CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_FLAC),
657 : CAP_BOOL(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
658 : {0},
659 : CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
660 : CAP_BOOL(GF_CAPS_INPUT,GF_PROP_PID_UNFRAMED, GF_TRUE),
661 : CAP_UINT(GF_CAPS_INPUT_OUTPUT,GF_PROP_PID_CODECID, GF_CODECID_FLAC),
662 : CAP_BOOL(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
663 : };
664 :
665 :
666 :
667 : #define OFFS(_n) #_n, offsetof(GF_FLACDmxCtx, _n)
668 : static const GF_FilterArgs FLACDmxArgs[] =
669 : {
670 : { OFFS(index), "indexing window length", GF_PROP_DOUBLE, "1.0", NULL, 0},
671 : {0}
672 : };
673 :
674 :
675 : GF_FilterRegister FLACDmxRegister = {
676 : .name = "rfflac",
677 : GF_FS_SET_DESCRIPTION("FLAC reframer")
678 : GF_FS_SET_HELP("This filter parses FLAC files/data and outputs corresponding audio PID and frames.")
679 : .private_size = sizeof(GF_FLACDmxCtx),
680 : .args = FLACDmxArgs,
681 : .finalize = flac_dmx_finalize,
682 : .initialize = flac_dmx_initialize,
683 : SETCAPS(FLACDmxCaps),
684 : .configure_pid = flac_dmx_configure_pid,
685 : .process = flac_dmx_process,
686 : .probe_data = flac_dmx_probe_data,
687 : .process_event = flac_dmx_process_event
688 : };
689 :
690 :
691 2877 : const GF_FilterRegister *flac_dmx_register(GF_FilterSession *session)
692 : {
693 2877 : return &FLACDmxRegister;
694 : }
|