1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#include <stdlib.h>
28#include <string.h>
29
30#define CONTAINER_IS_BIG_ENDIAN
31//#define ENABLE_CONTAINERS_LOG_FORMAT
32//#define ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE
33#define CONTAINER_HELPER_LOG_INDENT(a) 0
34#include "containers/core/containers_private.h"
35#include "containers/core/containers_io_helpers.h"
36#include "containers/core/containers_utils.h"
37#include "containers/core/containers_logging.h"
38#include "mpga_common.h"
39
40/******************************************************************************
41Defines and constants.
42******************************************************************************/
43#define MPGA_XING_HAS_FRAMES 0x00000001
44#define MPGA_XING_HAS_BYTES 0x00000002
45#define MPGA_XING_HAS_TOC 0x00000004
46#define MPGA_XING_HAS_QUALITY 0x00000008
47
48#define MPGA_MAX_BAD_FRAMES 4096 /*< Maximum number of failed byte-wise syncs,
49 should be at least 2881+4 to cover the largest
50 frame size (MPEG2.5 Layer 2, 160kbit/s 8kHz)
51 + next frame header */
52
53static const unsigned int mpga_sample_rate_adts[16] =
54{96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350};
55
56static const GUID_T asf_guid_header =
57{0x75B22630, 0x668E, 0x11CF, {0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C}};
58
59/******************************************************************************
60Type definitions
61******************************************************************************/
62typedef struct VC_CONTAINER_MODULE_T
63{
64 VC_CONTAINER_TRACK_T *track;
65 uint64_t data_offset;
66 uint64_t data_size;
67 uint64_t num_frames; /**< Total number of frames (if known) */
68 unsigned int frame_size_samples; /**< Frame size in samples */
69 unsigned int bitrate; /**< Bitrate (might change on a per-frame basis if VBR) */
70 unsigned int sample_rate;
71 unsigned int channels;
72
73 /* MPEG audio header information */
74 unsigned int version; /**< 1 for MPEG1, 2 for MPEG2, etc. */
75 unsigned int layer;
76
77 /* VBR header information */
78 uint8_t xing_toc[100];
79 int xing_toc_valid;
80
81 /* Per-frame state (updated upon a read or a seek) */
82 unsigned int frame_size;
83 unsigned int frame_data_left;
84 uint64_t frame_index;
85 int64_t frame_offset;
86 int64_t frame_time_pos; /**< pts of current frame */
87 unsigned int frame_bitrate; /**< bitrate of current frame */
88
89 VC_CONTAINER_STATUS_T (*pf_parse_header)( uint8_t frame_header[MPGA_HEADER_SIZE],
90 uint32_t *p_frame_size, unsigned int *p_frame_bitrate, unsigned int *p_version,
91 unsigned int *p_layer, unsigned int *p_sample_rate, unsigned int *p_channels,
92 unsigned int *p_frame_size_samples, unsigned int *p_offset);
93
94 uint8_t extradata[2]; /**< codec extra data for aac */
95
96} VC_CONTAINER_MODULE_T;
97
98/******************************************************************************
99Function prototypes
100******************************************************************************/
101VC_CONTAINER_STATUS_T mpga_reader_open( VC_CONTAINER_T * );
102
103/******************************************************************************
104Local Functions
105******************************************************************************/
106static uint32_t PEEK_BYTES_AT( VC_CONTAINER_T *p_ctx, int64_t offset, uint8_t *buffer, int size )
107{
108 int ret;
109 int64_t current_position = STREAM_POSITION(p_ctx);
110 SEEK(p_ctx, current_position + offset);
111 ret = PEEK_BYTES(p_ctx, buffer, size);
112 SEEK(p_ctx, current_position);
113 return ret;
114}
115
116/*****************************************************************************/
117static VC_CONTAINER_STATUS_T mpga_check_frame_header( VC_CONTAINER_T *p_ctx,
118 VC_CONTAINER_MODULE_T *module, uint8_t frame_header[MPGA_HEADER_SIZE] )
119{
120 VC_CONTAINER_PARAM_UNUSED(p_ctx);
121 return module->pf_parse_header(frame_header, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
122}
123
124/*****************************************************************************/
125static VC_CONTAINER_STATUS_T mpga_sync( VC_CONTAINER_T *p_ctx )
126{
127 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
128 VC_CONTAINER_STATUS_T status;
129 uint8_t frame_header[MPGA_HEADER_SIZE];
130 uint32_t frame_size;
131 unsigned int frame_bitrate, version, layer, sample_rate, channels;
132 unsigned int frame_size_samples, offset;
133 int sync_count = 0;
134
135 /* If we can't see a full frame header, we treat this as EOS although it
136 could be a bad stream as well, the caller should distinct between
137 these two cases */
138 if (PEEK_BYTES(p_ctx, (uint8_t*)frame_header, MPGA_HEADER_SIZE) != MPGA_HEADER_SIZE)
139 return VC_CONTAINER_ERROR_EOS;
140
141 while (sync_count++ < MPGA_MAX_BAD_FRAMES)
142 {
143 status = module->pf_parse_header(frame_header, &frame_size, &frame_bitrate,
144 &version, &layer, &sample_rate, &channels,
145 &frame_size_samples, &offset);
146 if (status == VC_CONTAINER_SUCCESS &&
147 frame_size /* We do not support free format streams */)
148 {
149 LOG_DEBUG(p_ctx, "MPEGv%d, layer %d, %d bps, %d Hz",
150 version, layer, frame_bitrate, sample_rate);
151 if (PEEK_BYTES_AT(p_ctx, (int64_t)frame_size, frame_header, MPGA_HEADER_SIZE) != MPGA_HEADER_SIZE ||
152 mpga_check_frame_header(p_ctx, module, frame_header) == VC_CONTAINER_SUCCESS)
153 break;
154
155 /* If we've reached an ID3 tag then the frame is valid as well */
156 if((frame_header[0] == 'I' && frame_header[1] == 'D' && frame_header[2] == '3') ||
157 (frame_header[0] == 'T' && frame_header[1] == 'A' && frame_header[2] == 'G'))
158 break;
159 }
160 else if (status == VC_CONTAINER_SUCCESS)
161 {
162 LOG_DEBUG(p_ctx, "free format not supported");
163 }
164
165 if (SKIP_BYTES(p_ctx, 1) != 1 || PEEK_BYTES(p_ctx, (uint8_t*)frame_header, MPGA_HEADER_SIZE) != MPGA_HEADER_SIZE)
166 return VC_CONTAINER_ERROR_EOS;
167 }
168
169 if(sync_count > MPGA_MAX_BAD_FRAMES) /* We didn't find a valid frame */
170 return VC_CONTAINER_ERROR_FORMAT_INVALID;
171
172 if (module->version)
173 {
174 /* FIXME: we don't currently care whether or not the number of channels changes mid-stream */
175 if (version != module->version || layer != module->layer)
176 {
177 LOG_DEBUG(p_ctx, "version or layer not allowed to change mid-stream");
178 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
179 }
180 }
181 else
182 {
183 module->version = version;
184 module->layer = layer;
185 module->sample_rate = sample_rate;
186 module->channels = channels;
187 module->frame_size_samples = frame_size_samples;
188 }
189
190 if(offset) SKIP_BYTES(p_ctx, offset);
191 module->frame_data_left = module->frame_size = frame_size - offset;
192 module->frame_bitrate = frame_bitrate;
193
194 return VC_CONTAINER_SUCCESS;
195}
196
197/*****************************************************************************/
198static int64_t mpga_calculate_frame_time( VC_CONTAINER_T *p_ctx )
199{
200 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
201 int64_t time;
202 time = INT64_C(1000000) * module->frame_index *
203 module->frame_size_samples / module->sample_rate;
204 return time;
205}
206
207/*****************************************************************************/
208static VC_CONTAINER_STATUS_T mpga_read_vbr_headers( VC_CONTAINER_T *p_ctx )
209{
210 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
211 VC_CONTAINER_TRACK_T *track = p_ctx->tracks[0];
212 VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_NOT_FOUND;
213 uint32_t peek_buf[1];
214 int64_t offset, start = STREAM_POSITION(p_ctx);
215
216 /* Look for XING header (immediately after layer 3 side information) */
217 offset = (module->version == 1) ? ((module->channels == 1) ? INT64_C(21) : INT64_C(36)) :
218 ((module->channels == 1) ? INT64_C(13) : INT64_C(21));
219
220 if (PEEK_BYTES_AT(p_ctx, offset, (uint8_t*)peek_buf, 4) != 4)
221 return VC_CONTAINER_ERROR_FORMAT_INVALID; /* File would be way too small */
222
223 if (peek_buf[0] == VC_FOURCC('X','i','n','g') || peek_buf[0] == VC_FOURCC('I','n','f','o'))
224 {
225 uint32_t flags = 0, num_frames = 0, data_size = 0;
226
227 /* If the first frame has a XING header then we know it's a valid (but empty) audio
228 frame so we safely parse the header whilst skipping to the next frame */
229 SKIP_BYTES(p_ctx, offset); /* FIXME: we don't care about layer 3 side information? */
230
231 SKIP_FOURCC(p_ctx, "XING");
232 flags = READ_U32(p_ctx, "XING flags");
233
234 if (flags & MPGA_XING_HAS_FRAMES)
235 num_frames = READ_U32(p_ctx, "XING frames");
236
237 if (flags & MPGA_XING_HAS_BYTES)
238 data_size = READ_U32(p_ctx, "XING bytes");
239
240 if (flags & MPGA_XING_HAS_TOC)
241 {
242 READ_BYTES(p_ctx, module->xing_toc, sizeof(module->xing_toc));
243 /* TOC is useful only if we know the number of frames */
244 if (num_frames) module->xing_toc_valid = 1;
245 /* Ensure time zero points to first frame even if TOC is broken */
246 module->xing_toc[0] = 0;
247 }
248
249 if (flags & MPGA_XING_HAS_QUALITY)
250 SKIP_U32(p_ctx, "XING quality");
251
252 module->data_size = data_size;
253 module->num_frames = num_frames;
254
255 if (module->num_frames && module->data_size)
256 {
257 /* We can calculate average bitrate */
258 module->bitrate =
259 module->data_size * module->sample_rate * 8 / (module->num_frames * module->frame_size_samples);
260 }
261
262 p_ctx->duration = (module->num_frames * module->frame_size_samples * 1000000LL) / module->sample_rate;
263
264 /* Look for additional LAME header (follows XING) */
265 if (PEEK_BYTES(p_ctx, (uint8_t*)peek_buf, 4) != 4)
266 return VC_CONTAINER_ERROR_FORMAT_INVALID; /* File would still be way too small */
267
268 if (peek_buf[0] == VC_FOURCC('L','A','M','E'))
269 {
270 uint32_t encoder_delay;
271
272 SKIP_FOURCC(p_ctx, "LAME");
273 SKIP_STRING(p_ctx, 5, "LAME encoder version");
274 SKIP_U8(p_ctx, "LAME tag revision/VBR method");
275 SKIP_U8(p_ctx, "LAME LP filter value");
276 SKIP_U32(p_ctx, "LAME peak signal amplitude");
277 SKIP_U16(p_ctx, "LAME radio replay gain");
278 SKIP_U16(p_ctx, "LAME audiophile replay gain");
279 SKIP_U8(p_ctx, "LAME encoder flags");
280 SKIP_U8(p_ctx, "LAME ABR/minimal bitrate");
281 encoder_delay = READ_U24(p_ctx, "LAME encoder delay/padding");
282 SKIP_U8(p_ctx, "LAME misc");
283 SKIP_U8(p_ctx, "LAME MP3 gain");
284 SKIP_U16(p_ctx, "LAME presets and surround info");
285 SKIP_U32(p_ctx, "LAME music length");
286 SKIP_U16(p_ctx, "LAME music CRC");
287 SKIP_U16(p_ctx, "LAME tag CRC");
288 track->format->type->audio.gap_delay = (encoder_delay >> 12) + module->frame_size_samples;
289 track->format->type->audio.gap_padding = encoder_delay & 0xfff;
290 }
291
292 SEEK(p_ctx, start);
293 status = VC_CONTAINER_SUCCESS;
294 }
295
296 /* FIXME: if not success, try to read 'VBRI' header */
297
298 return status;
299}
300
301/*****************************************************************************
302Functions exported as part of the Container Module API
303 *****************************************************************************/
304static VC_CONTAINER_STATUS_T mpga_reader_read( VC_CONTAINER_T *p_ctx,
305 VC_CONTAINER_PACKET_T *p_packet, uint32_t flags )
306{
307 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
308 VC_CONTAINER_TRACK_T *track = p_ctx->tracks[0];
309 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
310
311 if (module->frame_data_left == 0)
312 {
313 status = mpga_sync(p_ctx);
314 if (status != VC_CONTAINER_SUCCESS) goto error;
315 }
316
317 if (module->bitrate)
318 {
319 /* Simple moving average over bitrate values seen so far */
320 module->bitrate = (module->bitrate * 31 + module->frame_bitrate) >> 5;
321 }
322 else
323 {
324 module->bitrate = module->frame_bitrate;
325 }
326
327 /* Check if we can skip the frame straight-away */
328 if (!track->is_enabled ||
329 ((flags & VC_CONTAINER_READ_FLAG_SKIP) && !(flags & VC_CONTAINER_READ_FLAG_INFO)))
330 {
331 /* Just skip the frame */
332 SKIP_BYTES(p_ctx, module->frame_size);
333 module->frame_data_left = 0;
334 if(!track->is_enabled)
335 status = VC_CONTAINER_ERROR_CONTINUE;
336 goto end;
337 }
338
339 /* Fill in packet information */
340 p_packet->flags = p_packet->track = 0;
341 if (module->frame_data_left == module->frame_size)
342 p_packet->flags |= VC_CONTAINER_PACKET_FLAG_FRAME;
343 else
344 p_packet->flags |= VC_CONTAINER_PACKET_FLAG_FRAME_END;
345
346 p_packet->size = module->frame_data_left;
347
348 p_packet->pts = module->frame_time_pos;
349 p_packet->dts = VC_CONTAINER_TIME_UNKNOWN;
350
351 if ((flags & VC_CONTAINER_READ_FLAG_SKIP))
352 {
353 SKIP_BYTES(p_ctx, module->frame_size);
354 module->frame_data_left = 0;
355 goto end;
356 }
357
358 if (flags & VC_CONTAINER_READ_FLAG_INFO)
359 return VC_CONTAINER_SUCCESS;
360
361 p_packet->size = MIN(p_packet->buffer_size, module->frame_data_left);
362 p_packet->size = READ_BYTES(p_ctx, p_packet->data, p_packet->size);
363 module->frame_data_left -= p_packet->size;
364
365 end:
366 if (module->frame_data_left == 0)
367 {
368 module->frame_index++;
369 module->frame_offset += module->frame_size;
370 module->frame_time_pos = mpga_calculate_frame_time(p_ctx);
371
372#if 0 /* FIXME: is this useful e.g. progressive download? */
373 module->num_frames = MAX(module->num_frames, module->frame_index);
374 module->data_size = MAX(module->data_size, module->frame_offset);
375 p_ctx->duration = MAX(p_ctx->duration, mpga_calculate_frame_time(p_ctx));
376#endif
377 }
378
379 return status == VC_CONTAINER_SUCCESS ? STREAM_STATUS(p_ctx) : status;
380
381error:
382 return status;
383}
384
385/*****************************************************************************/
386static VC_CONTAINER_STATUS_T mpga_reader_seek( VC_CONTAINER_T *p_ctx,
387 int64_t *p_offset,
388 VC_CONTAINER_SEEK_MODE_T mode,
389 VC_CONTAINER_SEEK_FLAGS_T flags)
390{
391 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
392 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
393 uint64_t seekpos, position = STREAM_POSITION(p_ctx);
394 VC_CONTAINER_PARAM_UNUSED(flags);
395
396 if (mode != VC_CONTAINER_SEEK_MODE_TIME || !STREAM_SEEKABLE(p_ctx))
397 return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
398
399 if (*p_offset != INT64_C(0))
400 {
401 if (!p_ctx->duration)
402 return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION;
403
404 if (module->xing_toc_valid)
405 {
406 int64_t ppm;
407 int percent, lower, upper, delta;
408
409 ppm = (*p_offset * module->sample_rate) / (module->num_frames * module->frame_size_samples);
410 ppm = MIN(ppm, INT64_C(999999));
411
412 percent = ppm / 10000;
413 delta = ppm % 10000;
414
415 lower = module->xing_toc[percent];
416 upper = percent < 99 ? module->xing_toc[percent + 1] : 256;
417
418 seekpos = module->data_offset +
419 (((module->data_size * lower) + (module->data_size * (upper - lower) * delta) / 10000) >> 8);
420 }
421 else
422 {
423 /* The following will be accurate for CBR only */
424 seekpos = module->data_offset + (*p_offset * module->data_size) / p_ctx->duration;
425 }
426 }
427 else
428 {
429 seekpos = module->data_offset;
430 }
431
432 SEEK(p_ctx, seekpos);
433 status = mpga_sync(p_ctx);
434 if (status && status != VC_CONTAINER_ERROR_EOS)
435 goto error;
436
437 module->frame_index = (*p_offset * module->num_frames + (p_ctx->duration >> 1)) / p_ctx->duration;
438 module->frame_offset = STREAM_POSITION(p_ctx) - module->data_offset;
439
440 *p_offset = module->frame_time_pos = mpga_calculate_frame_time(p_ctx);
441
442 return STREAM_STATUS(p_ctx);
443
444error:
445 SEEK(p_ctx, position);
446 return status;
447}
448
449/*****************************************************************************/
450static VC_CONTAINER_STATUS_T mpga_reader_close( VC_CONTAINER_T *p_ctx )
451{
452 VC_CONTAINER_MODULE_T *module = p_ctx->priv->module;
453
454 if (p_ctx->tracks_num != 0)
455 vc_container_free_track(p_ctx, p_ctx->tracks[0]);
456 p_ctx->tracks = NULL;
457 p_ctx->tracks_num = 0;
458 free(module);
459 p_ctx->priv->module = 0;
460 return VC_CONTAINER_SUCCESS;
461}
462
463/*****************************************************************************/
464VC_CONTAINER_STATUS_T mpga_reader_open( VC_CONTAINER_T *p_ctx )
465{
466 const char *extension = vc_uri_path_extension(p_ctx->priv->uri);
467 VC_CONTAINER_MODULE_T *module = 0;
468 VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS;
469 VC_CONTAINER_TRACK_T *track = NULL;
470 unsigned int i;
471 GUID_T guid;
472
473 /* Check if the user has specified a container */
474 vc_uri_find_query(p_ctx->priv->uri, 0, "container", &extension);
475
476 /* Since mpeg audio is difficult to auto-detect, we use the extension as
477 part of the autodetection */
478 if(!extension)
479 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
480 if(strcasecmp(extension, "mp3") && strcasecmp(extension, "mp2") &&
481 strcasecmp(extension, "aac") && strcasecmp(extension, "adts"))
482 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
483
484 /* Check we're not in fact dealing with an ASF file */
485 if(PEEK_BYTES(p_ctx, (uint8_t *)&guid, sizeof(guid)) == sizeof(guid) &&
486 !memcmp(&guid, &asf_guid_header, sizeof(guid)))
487 return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
488
489 LOG_DEBUG(p_ctx, "using mpga reader");
490
491 /* Allocate our context */
492 if ((module = malloc(sizeof(*module))) == NULL)
493 {
494 status = VC_CONTAINER_ERROR_OUT_OF_MEMORY;
495 goto error;
496 }
497
498 memset(module, 0, sizeof(*module));
499 p_ctx->priv->module = module;
500 p_ctx->tracks = &module->track;
501
502 p_ctx->tracks[0] = vc_container_allocate_track(p_ctx, 0);
503 if(!p_ctx->tracks[0])
504 {
505 status = VC_CONTAINER_ERROR_OUT_OF_MEMORY;
506 goto error;
507 }
508 p_ctx->tracks_num = 1;
509
510 module->pf_parse_header = mpga_read_header;
511 if(!strcasecmp(extension, "aac") || !strcasecmp(extension, "adts"))
512 module->pf_parse_header = adts_read_header;
513
514 if ((status = mpga_sync(p_ctx)) != VC_CONTAINER_SUCCESS)
515 {
516 /* An error here probably means it's not an mpga file at all */
517 if(status == VC_CONTAINER_ERROR_FORMAT_INVALID)
518 status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
519 goto error;
520 }
521
522 /* If we got this far, we're probably dealing with an mpeg audio file */
523 track = p_ctx->tracks[0];
524 track->format->es_type = VC_CONTAINER_ES_TYPE_AUDIO;
525 track->format->codec = VC_CONTAINER_CODEC_MPGA;
526 if(module->pf_parse_header == adts_read_header)
527 {
528 uint8_t *extra = track->format->extradata = module->extradata;
529 unsigned int sr_id;
530 for( sr_id = 0; sr_id < 13; sr_id++ )
531 if( mpga_sample_rate_adts[sr_id] == module->sample_rate ) break;
532 extra[0] = (module->version << 3) | ((sr_id & 0xe) >> 1);
533 extra[1] = ((sr_id & 0x1) << 7) | (module->channels << 3);
534 track->format->extradata_size = 2;
535 track->format->codec = VC_CONTAINER_CODEC_MP4A;
536 }
537 track->format->flags |= VC_CONTAINER_ES_FORMAT_FLAG_FRAMED;
538 track->is_enabled = true;
539 track->format->type->audio.channels = module->channels;
540 track->format->type->audio.sample_rate = module->sample_rate;
541 track->format->type->audio.bits_per_sample = 0;
542 track->format->type->audio.block_align = 1;
543
544 module->data_offset = STREAM_POSITION(p_ctx);
545
546 /* Look for VBR headers within the first frame */
547 status = mpga_read_vbr_headers(p_ctx);
548 if (status && status != VC_CONTAINER_ERROR_NOT_FOUND) goto error;
549
550 /* If we couldn't get this information from VBR headers, try to determine
551 file size, bitrate, number of frames and duration */
552 if (!module->data_size)
553 module->data_size = MAX(p_ctx->priv->io->size - module->data_offset, INT64_C(0));
554
555 if (!module->bitrate)
556 {
557 if (STREAM_SEEKABLE(p_ctx))
558 {
559 /* Scan past a few hundred frames (audio will often have
560 silence in the beginning so we need to see more than
561 just a few frames) and estimate bitrate */
562 for (i = 0; i < 256; ++i)
563 if (mpga_reader_read(p_ctx, NULL, VC_CONTAINER_READ_FLAG_SKIP)) break;
564 /* Seek back to start of data */
565 SEEK(p_ctx, module->data_offset);
566 module->frame_index = 0;
567 module->frame_offset = INT64_C(0);
568 module->frame_time_pos = mpga_calculate_frame_time(p_ctx);
569 }
570 else
571 {
572 /* Bitrate will be correct for CBR only */
573 module->bitrate = module->frame_bitrate;
574 }
575 }
576
577 track->format->bitrate = module->bitrate;
578
579 if (!module->num_frames)
580 {
581 module->num_frames = (module->data_size * module->sample_rate * 8LL) /
582 (module->bitrate * module->frame_size_samples);
583 }
584
585 if (!p_ctx->duration && module->bitrate)
586 {
587 p_ctx->duration = (INT64_C(8000000) * module->data_size) / module->bitrate;
588 }
589
590 p_ctx->priv->pf_close = mpga_reader_close;
591 p_ctx->priv->pf_read = mpga_reader_read;
592 p_ctx->priv->pf_seek = mpga_reader_seek;
593
594 if(STREAM_SEEKABLE(p_ctx)) p_ctx->capabilities |= VC_CONTAINER_CAPS_CAN_SEEK;
595
596 if(STREAM_STATUS(p_ctx) != VC_CONTAINER_SUCCESS) goto error;
597 return VC_CONTAINER_SUCCESS;
598
599error:
600 if(status == VC_CONTAINER_SUCCESS || status == VC_CONTAINER_ERROR_EOS)
601 status = VC_CONTAINER_ERROR_FORMAT_INVALID;
602 LOG_DEBUG(p_ctx, "error opening stream (%i)", status);
603 if (p_ctx->tracks_num != 0)
604 vc_container_free_track(p_ctx, p_ctx->tracks[0]);
605 p_ctx->tracks = NULL;
606 p_ctx->tracks_num = 0;
607 if (module) free(module);
608 p_ctx->priv->module = NULL;
609 return status;
610}
611
612/********************************************************************************
613 Entrypoint function
614 ********************************************************************************/
615
616#if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__)
617# pragma weak reader_open mpga_reader_open
618#endif
619