1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * mp3.cpp: Pipeline for the media
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
23 // Relevant links to documentation:
24 // http://www.codeproject.com/KB/audio-video/mpegaudioinfo.aspx
25 // http://www.mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm
26 // http://www.compuphase.com/mp3/sta013.htm
33 static int mpeg1_bitrates
[3][15] = {
34 /* version 1, layer 1 */
35 { 0, 32000, 48000, 56000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000 },
36 /* version 1, layer 2 */
37 { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000 },
38 /* version 1, layer 3 */
39 { 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000 },
42 static int mpeg2_bitrates
[3][15] = {
43 /* version 2, layer 1 */
44 { 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000 },
45 /* version 2, layer 2 */
46 { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000 },
47 /* version 2, layer 3 */
48 { 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000 }
52 mpeg_parse_bitrate (MpegFrameHeader
*mpeg
, guint8 byte
)
54 int i
= (byte
& 0xf0) >> 4;
59 if (mpeg
->version
== 1)
60 mpeg
->bit_rate
= mpeg1_bitrates
[mpeg
->layer
- 1][i
];
62 mpeg
->bit_rate
= mpeg2_bitrates
[mpeg
->layer
- 1][i
];
68 mpeg_encode_bitrate (MpegFrameHeader
*mpeg
, int bit_rate
)
72 if (mpeg
->version
== 1) {
73 for (i
= 1; i
< 15; i
++) {
74 if (mpeg1_bitrates
[mpeg
->layer
- 1][i
] == bit_rate
)
78 for (i
= 1; i
< 15; i
++) {
79 if (mpeg2_bitrates
[mpeg
->layer
- 1][i
] == bit_rate
)
87 return ((i
<< 4) & 0xf0);
90 static int mpeg_samplerates
[3][3] = {
91 { 44100, 48000, 32000 }, // version 1
92 { 22050, 24000, 16000 }, // version 2
93 { 11025, 12000, 8000 } // version 2.5
97 mpeg_parse_samplerate (MpegFrameHeader
*mpeg
, guint8 byte
)
99 int i
= (byte
>> 2) & 0x03;
104 mpeg
->sample_rate
= mpeg_samplerates
[mpeg
->version
- 1][i
];
110 mpeg_parse_channels (MpegFrameHeader
*mpeg
, guint8 byte
)
112 int mode
= (byte
>> 6) & 0x03;
118 case 1: /* joint stereo */
121 case 2: /* dual channel (2 mono channels) */
129 mpeg
->intensity
= (byte
& 0x20) ? 1 : 0;
130 mpeg
->ms
= (byte
& 0x10) ? 1 : 0;
136 mpeg_parse_header (MpegFrameHeader
*mpeg
, const guint8
*buffer
)
138 if (!is_mpeg_header (buffer
))
141 // extract the MPEG version
142 switch ((buffer
[1] >> 3) & 0x03) {
143 case 0: /* MPEG Version 2.5 */
146 case 1: /* reserved */
148 case 2: /* MPEG Version 2 */
151 case 3: /* MPEG Version 1 */
156 // extract the MPEG layer
157 switch ((buffer
[1] >> 1) & 0x03) {
172 // protection (via 16bit crc) bit
173 mpeg
->prot
= (buffer
[1] & 0x01) ? 1 : 0;
175 // extract the bit rate
176 if (!mpeg_parse_bitrate (mpeg
, buffer
[2]))
179 // extract the sample rate
180 if (!mpeg_parse_samplerate (mpeg
, buffer
[2]))
183 // check if the frame is padded
184 mpeg
->padded
= (buffer
[2] & 0x02) ? 1 : 0;
186 // extract the channel mode */
187 if (!mpeg_parse_channels (mpeg
, buffer
[3]))
190 mpeg
->copyright
= (buffer
[3] & 0x08) ? 1 : 0;
191 mpeg
->original
= (buffer
[3] & 0x04) ? 1 : 0;
196 static int mpeg_block_sizes
[3][3] = {
197 { 384, 1152, 1152 }, // version 1
198 { 384, 1152, 576 }, // version 2
199 { 384, 1152, 576 } // version 2.5
202 #define mpeg_block_size(mpeg) mpeg_block_sizes[(mpeg)->version - 1][(mpeg)->layer - 1]
205 mpeg_frame_length (MpegFrameHeader
*mpeg
, bool xing
)
209 // calculate the frame length
210 if (mpeg
->layer
== 1)
211 len
= (((12 * mpeg
->bit_rate
) / (double) mpeg
->sample_rate
) + mpeg
->padded
) * 4;
212 else if (mpeg
->version
== 1)
213 len
= ((144 * mpeg
->bit_rate
) / (double) mpeg
->sample_rate
) + mpeg
->padded
;
215 len
= ((72 * mpeg
->bit_rate
) / (double) mpeg
->sample_rate
) + mpeg
->padded
;
220 #define MPEG_FRAME_LENGTH_MAX ((((144 * 160000) / 8000) + 1) + 2)
222 #define mpeg_frame_size(mpeg) (((mpeg)->bit_rate * (mpeg)->channels * mpeg_block_size (mpeg)) / (mpeg)->sample_rate)
225 mpeg_frame_duration (MpegFrameHeader
*mpeg
)
227 guint64 result
= ((guint64
) mpeg_block_size (mpeg
)) * TIMESPANTICKS_IN_SECOND
/ mpeg
->sample_rate
;
233 mpeg_print_info (MpegFrameHeader
*mpeg
)
237 switch (mpeg
->version
) {
249 printf ("MPEG-%s Audio Layer %d; %d Hz, %d ch, %d kbit\n",
250 version
, mpeg
->layer
, mpeg
->sample_rate
, mpeg
->channels
,
251 mpeg
->bit_rate
/ 1000);
253 printf ("\t16bit crc=%s; padded=%s\n", mpeg
->prot
? "true" : "false",
254 mpeg
->padded
? "true" : "false");
256 printf ("\tframe length = %u bytes\n", mpeg_frame_length (mpeg
, false));
261 mpeg_xing_header_offset (MpegFrameHeader
*mpeg
)
263 if (mpeg
->version
== 1)
264 return mpeg
->channels
== 1 ? 21 : 36;
266 return mpeg
->channels
== 1 ? 13 : 21;
269 #define mpeg_vbri_header_offset 36
272 mpeg_check_vbr_headers (MpegFrameHeader
*mpeg
, MpegVBRHeader
*vbr
, IMediaSource
*source
, gint64 pos
)
274 guint32 nframes
= 0, size
= 0;
276 guint8 buffer
[24], *bufptr
;
280 // first, check for a Xing header
281 offset
= mpeg_xing_header_offset (mpeg
);
282 if (!source
->Seek (pos
+ offset
, SEEK_SET
))
285 if (!source
->Peek (buffer
, 16))
288 if (!strncmp ((const char *) buffer
, "Xing", 4)) {
289 if (buffer
[7] & 0x01) {
290 // decode the number of frames
291 nframes
= (buffer
[8] << 24) + (buffer
[9] << 16) + (buffer
[10] << 8) + buffer
[11];
292 } else if (buffer
[7] & 0x02) {
293 size
= (buffer
[8] << 24) + (buffer
[9] << 16) + (buffer
[10] << 8) + buffer
[11];
295 // calculate the frame length
296 len
= mpeg_frame_length (mpeg
, true);
298 // estimate the number of frames
299 nframes
= size
/ len
;
302 vbr
->type
= MpegXingHeader
;
303 vbr
->nframes
= nframes
;
308 // check for a Fraunhofer VBRI header
309 offset
= mpeg_vbri_header_offset
;
310 if (!source
->Seek (pos
+ offset
, SEEK_SET
))
313 if (!source
->Peek (buffer
, 24))
316 if (!strncmp ((const char *) buffer
, "VBRI", 4)) {
317 // decode the number of frames
318 bufptr
= buffer
+ 14;
319 for (i
= 0; i
< 4; i
++)
320 nframes
= (nframes
<< 8) | *bufptr
++;
322 vbr
->type
= MpegVBRIHeader
;
323 vbr
->nframes
= nframes
;
332 #define MPEG_JUMP_TABLE_GROW_SIZE 16
334 Mp3FrameReader::Mp3FrameReader (IMediaSource
*source
, AudioStream
*stream
, gint64 start
, guint32 frame_len
, guint32 frame_duration
, bool xing
)
336 jmptab
= g_new (MpegFrame
, MPEG_JUMP_TABLE_GROW_SIZE
);
337 avail
= MPEG_JUMP_TABLE_GROW_SIZE
;
340 this->frame_dur
= frame_duration
;
341 this->frame_len
= frame_len
;
343 this->sync_lost
= false;
345 stream_start
= start
;
346 this->source
= source
;
347 this->stream
= stream
;
353 Mp3FrameReader::~Mp3FrameReader ()
359 Mp3FrameReader::AddFrameIndex (gint64 offset
, guint64 pts
, guint32 dur
, gint32 bit_rate
)
362 avail
+= MPEG_JUMP_TABLE_GROW_SIZE
;
363 jmptab
= (MpegFrame
*) g_realloc (jmptab
, avail
* sizeof (MpegFrame
));
366 jmptab
[used
].bit_rate
= bit_rate
;
367 jmptab
[used
].offset
= offset
;
368 jmptab
[used
].pts
= pts
;
369 jmptab
[used
].dur
= dur
;
377 * @hi: the high bound
379 * Finds the midpoint between positive integer values, @lo and @hi.
381 * Notes: Typically expressed as '(@lo + @hi) / 2', this is incorrect
382 * when @lo and @hi are sufficiently large enough that combining them
383 * would overflow their integer type. To work around this, we use the
384 * formula, '@lo + ((@hi - @lo) / 2)', thus preventing this problem
387 * Returns the midpoint between @lo and @hi (rounded down).
389 #define MID(lo, hi) (lo + ((hi - lo) >> 1))
392 Mp3FrameReader::MpegFrameSearch (guint64 pts
)
395 guint32 hi
= used
- 1;
400 end
= start
= jmptab
[m
].pts
;
401 end
+= jmptab
[m
].dur
;
405 } else if (pts
< start
) {
409 // pts should be exactly the beginning of the next frame
423 Mp3FrameReader::Seek (guint64 pts
)
425 gint64 offset
= source
->GetPosition ();
426 gint32 bit_rate
= this->bit_rate
;
427 guint64 cur_pts
= this->cur_pts
;
429 MediaResult result
= MEDIA_FAIL
;
432 return MEDIA_SUCCESS
;
435 if (!source
->Seek (stream_start
, SEEK_SET
)) {
436 LOG_MP3 ("Mp3FrameReader::Seek (%" G_GUINT64_FORMAT
"): Seek error (#1)\n", pts
);
443 return MEDIA_SUCCESS
;
446 // if we are seeking to some place we've been, then we can use our jump table
447 if (used
> 0 && pts
< (jmptab
[used
- 1].pts
+ jmptab
[used
- 1].dur
)) {
448 if (pts
>= jmptab
[used
- 1].pts
) {
449 if (!source
->Seek (jmptab
[used
- 1].offset
, SEEK_SET
)) {
450 LOG_MP3 ("Mp3FrameReader::Seek (%" G_GUINT64_FORMAT
"): Seek error (#2)\n", pts
)
454 this->bit_rate
= jmptab
[used
- 1].bit_rate
;
455 this->cur_pts
= jmptab
[used
- 1].pts
;
457 return MEDIA_SUCCESS
;
460 // search for our requested pts
461 frame
= MpegFrameSearch (pts
);
463 if (!source
->Seek (jmptab
[frame
].offset
, SEEK_SET
)) {
464 LOG_MP3 ("Mp3FrameReader::Seek (%" G_GUINT64_FORMAT
"): Seek error (#3)\n", pts
);
468 this->bit_rate
= jmptab
[frame
].bit_rate
;
469 this->cur_pts
= jmptab
[frame
].pts
;
471 return MEDIA_SUCCESS
;
474 // keep skipping frames until we read to (or past) the requested pts
475 while (this->cur_pts
< pts
) {
476 result
= SkipFrame ();
478 if (!MEDIA_SUCCEEDED (result
)) {
479 LOG_MP3 ("Mp3FrameReader::Seek (%" G_GUINT64_FORMAT
"): Error while skipping frame: %i\n", pts
, result
);
484 // pts requested is at the start of the next frame in the source
485 if (this->cur_pts
== pts
)
486 return MEDIA_SUCCESS
;
488 // pts requested was non-key frame, need to seek back to the most recent key frame
489 if (!source
->Seek (jmptab
[used
- 1].offset
, SEEK_SET
)) {
490 LOG_MP3 ("Mp3FrameReader::Seek (%" G_GUINT64_FORMAT
"): Seek error (#4)\n", pts
);
494 this->bit_rate
= jmptab
[used
- 1].bit_rate
;
495 this->cur_pts
= jmptab
[used
- 1].pts
;
497 return MEDIA_SUCCESS
;
501 // restore FrameReader to previous state
502 source
->Seek (offset
, SEEK_SET
);
503 this->bit_rate
= bit_rate
;
504 this->cur_pts
= cur_pts
;
506 LOG_MP3 ("Mp3FrameReader::Seek (%" G_GUINT64_FORMAT
"): Could not find pts\n", pts
);
512 Mp3FrameReader::SkipFrame ()
514 MpegFrameHeader mpeg
;
521 offset
= source
->GetPosition ();
523 if (!source
->IsPositionAvailable (offset
+ 4, &eof
))
524 return eof
? MEDIA_FAIL
: MEDIA_NOT_ENOUGH_DATA
;
526 if (!source
->Peek (buffer
, 4))
529 if (!mpeg_parse_header (&mpeg
, buffer
)) {
534 if (mpeg
.bit_rate
== 0) {
535 // use the most recently specified bit rate
536 mpeg
.bit_rate
= bit_rate
;
539 bit_rate
= mpeg
.bit_rate
;
541 duration
= mpeg_frame_duration (&mpeg
);
543 if (used
== 0 || offset
> jmptab
[used
- 1].offset
)
544 AddFrameIndex (offset
, cur_pts
, duration
, bit_rate
);
546 len
= (guint32
) mpeg_frame_length (&mpeg
, xing
);
548 if (!source
->IsPositionAvailable (offset
+ len
, &eof
))
549 return eof
? MEDIA_FAIL
: MEDIA_NOT_ENOUGH_DATA
;
551 if (!source
->Seek ((gint64
) len
, SEEK_CUR
))
556 stream
->SetLastAvailablePts (cur_pts
);
558 return MEDIA_SUCCESS
;
562 Mp3FrameReader::TryReadFrame (MediaFrame
**f
)
564 MpegFrameHeader mpeg
;
575 result
= FindMpegHeader (&mpeg
, NULL
, source
, source
->GetPosition (), &offset
);
576 if (!MEDIA_SUCCEEDED (result
))
579 if (!source
->IsPositionAvailable (offset
, &eof
))
580 return eof
? MEDIA_NO_MORE_DATA
: MEDIA_NOT_ENOUGH_DATA
;
582 if (!source
->Seek (offset
, SEEK_SET
))
586 offset
= source
->GetPosition ();
589 // Check if there is enough data available
590 if (!source
->IsPositionAvailable (offset
+ 4, &eof
)) {
591 //printf ("Mp3FrameReader::TryReadFrame (): Exit 2: Buffer underflow (last available pos: %lld, offset: %" G_GUINT64_FORMAT ", diff: %" G_GUINT64_FORMAT ", len: %u)\n", source->GetLastAvailablePosition (), offset, source->GetLastAvailablePosition () - offset, len);
592 return eof
? MEDIA_NO_MORE_DATA
: MEDIA_NOT_ENOUGH_DATA
;
595 if (!source
->Peek (buffer
, 4)) {
596 //printf ("Mp3FrameReader::TryReadFrame (): Exit 3\n");
597 return MEDIA_FAIL
; // Now this shouldn't fail, given that we've checked for the previous error conditions
600 if (!mpeg_parse_header (&mpeg
, buffer
)) {
601 //printf ("Mp3FrameReader::TryReadFrame (): Exit 4\n");
603 return MEDIA_DEMUXER_ERROR
;
606 //printf ("Mp3FrameReader::ReadFrame():\n");
607 //mpeg_print_info (&mpeg);
609 if (mpeg
.bit_rate
== 0) {
610 // use the most recently specified bit rate
611 mpeg
.bit_rate
= bit_rate
;
613 // re-encode the bitrate into the header
614 buffer
[2] |= mpeg_encode_bitrate (&mpeg
, bit_rate
);
617 bit_rate
= mpeg
.bit_rate
;
619 duration
= mpeg_frame_duration (&mpeg
);
621 if (used
== 0 || offset
> jmptab
[used
- 1].offset
)
622 AddFrameIndex (offset
, cur_pts
, duration
, bit_rate
);
624 len
= (guint32
) mpeg_frame_length (&mpeg
, xing
);
626 if (!source
->IsPositionAvailable (offset
+ len
, &eof
)) {
627 //printf ("Mp3FrameReader::TryReadFrame (): Exit 6: Buffer underflow (last available pos: %lld, offset: %" G_GUINT64_FORMAT ", diff: %" G_GUINT64_FORMAT ", len: %u)\n", source->GetLastAvailablePosition (), offset, source->GetLastAvailablePosition () - offset, len);
628 return eof
? MEDIA_NO_MORE_DATA
: MEDIA_BUFFER_UNDERFLOW
;
631 frame
= new MediaFrame (stream
);
635 if (mpeg
.layer
!= 1 && !mpeg
.padded
)
636 frame
->buffer
= (guint8
*) g_try_malloc (frame
->buflen
+ 1);
638 frame
->buffer
= (guint8
*) g_try_malloc (frame
->buflen
);
640 if (frame
->buffer
== NULL
)
641 return MEDIA_OUT_OF_MEMORY
;
643 if (mpeg
.layer
!= 1 && !mpeg
.padded
)
644 frame
->buffer
[frame
->buflen
- 1] = 0;
646 if (!source
->ReadAll (frame
->buffer
, len
)) {
647 //printf ("Mp3FrameReader::TryReadFrame (): Exit 7\n");
651 memcpy (frame
->buffer
, buffer
, 4);
653 frame
->pts
= cur_pts
;
654 frame
->duration
= duration
;
656 frame
->AddState (MediaFrameDemuxed
);
660 return MEDIA_SUCCESS
;
668 Mp3Demuxer::Mp3Demuxer (Media
*media
, IMediaSource
*source
) : IMediaDemuxer (Type::MP3DEMUXER
, media
, source
)
674 Mp3Demuxer::~Mp3Demuxer ()
681 Mp3Demuxer::SeekAsyncInternal (guint64 pts
)
683 MediaResult result
= MEDIA_FAIL
;
686 result
= reader
->Seek (pts
);
688 if (MEDIA_SUCCEEDED (result
)) {
689 ReportSeekCompleted (pts
);
690 } else if (result
== MEDIA_NOT_ENOUGH_DATA
) {
693 ReportErrorOccurred (result
);
698 Mp3FrameReader::FindMpegHeader (MpegFrameHeader
*mpeg
, MpegVBRHeader
*vbr
, IMediaSource
*source
, gint64 start
, gint64
*result
)
700 guint8 buf
[4096], hdr
[4], *inbuf
, *inend
;
701 gint64 pos
, offset
= start
;
702 register guint8
*inptr
;
703 MpegFrameHeader next
;
710 if (!source
->Seek (start
, SEEK_SET
))
716 if (!source
->IsPositionAvailable (offset
+ sizeof (buf
) - n
, &eof
)) {
718 return MEDIA_NOT_ENOUGH_DATA
;
720 // If we reached eof we still need to check if this is a valid mpeg header, so don't fail that case
723 if ((n
= source
->ReadSome (inbuf
, sizeof (buf
) - n
)) <= 0)
724 return MEDIA_NO_MORE_DATA
;
729 if ((inend
- inptr
) < 4)
733 /* mpeg audio sync header begins with a 0xff */
734 while (inptr
< inend
&& *inptr
!= 0xff) {
742 /* found a 0xff byte... could be a frame header */
743 if ((inptr
+ 3) < inend
) {
744 if (mpeg_parse_header (mpeg
, inptr
) && mpeg
->bit_rate
) {
745 /* validate that this is really an MPEG frame header by calculating the
746 * position of the next frame header and checking that it looks like a
747 * valid frame header too */
748 len
= (guint32
) mpeg_frame_length (mpeg
, false);
749 pos
= source
->GetPosition ();
751 if (vbr
&& mpeg_check_vbr_headers (mpeg
, vbr
, source
, offset
)) {
752 if (vbr
->type
== MpegXingHeader
)
753 len
= (guint32
) mpeg_frame_length (mpeg
, true);
755 *result
= offset
+ len
;
756 return MEDIA_SUCCESS
;
759 if (!source
->IsPositionAvailable (offset
+ len
+ 4, &eof
)) {
760 return eof
? MEDIA_FAIL
: MEDIA_NOT_ENOUGH_DATA
;
761 } else if (source
->Seek (offset
+ len
, SEEK_SET
) && source
->Peek (hdr
, 4)) {
762 if (mpeg_parse_header (&next
, hdr
)) {
763 /* everything checks out A-OK */
765 return MEDIA_SUCCESS
;
770 if (pos
== -1 || !source
->Seek (pos
, SEEK_SET
))
774 /* not an mpeg audio sync header */
778 /* not enough data to check */
781 } while (inptr
< inend
);
783 if ((n
= (inend
- inptr
)) > 0) {
784 /* save the remaining bytes */
785 memmove (buf
, inptr
, n
);
788 /* if we scan more than 'MPEG_FRAME_LENGTH_MAX' bytes, this is unlikely to be an mpeg audio stream */
789 } while ((offset
- start
) < MPEG_FRAME_LENGTH_MAX
);
795 Mp3Demuxer::OpenDemuxerAsyncInternal ()
799 LOG_MP3 ("Mp3Demuxer::OpenDemuxerAsyncInternal ()\n");
801 result
= ReadHeader ();
803 if (MEDIA_SUCCEEDED (result
)) {
804 ReportOpenDemuxerCompleted ();
806 ReportErrorOccurred (result
);
811 Mp3Demuxer::ReadHeader ()
813 LOG_MP3 ("Mp3Demuxer::ReadHeader ()\n");
816 IMediaStream
**streams
= NULL
;
818 gint64 header_start
= -1;
819 IMediaStream
*stream
;
820 MpegFrameHeader mpeg
;
834 if (!source
->IsPositionAvailable (10, &eof
))
835 return eof
? MEDIA_FAIL
: MEDIA_NOT_ENOUGH_DATA
;
837 if (!source
->Peek (buffer
, 10))
838 return MEDIA_INVALID_MEDIA
;
840 // Check for a leading ID3 tag
841 if (!strncmp ((const char *) buffer
, "ID3", 3)) {
842 for (i
= 0; i
< 4; i
++) {
843 if (buffer
[6 + i
] & 0x80)
844 return MEDIA_INVALID_MEDIA
;
846 size
= (size
<< 7) | buffer
[6 + i
];
849 if ((buffer
[5] & (1 << 4))) {
850 // add additional 10 bytes for footer
855 // MPEG stream data starts at the end of the ID3 tag
856 stream_start
= (gint64
) size
;
861 // There can be an "arbitrary" amount of garbage at the
862 // beginning of an mp3 stream, so we need to find the first
863 // MPEG sync header by scanning.
864 vbr
.type
= MpegNoVBRHeader
;
865 if (!MEDIA_SUCCEEDED (result
= Mp3FrameReader::FindMpegHeader (&mpeg
, &vbr
, source
, stream_start
, &header_start
))) {
866 source
->Seek (0, SEEK_SET
);
870 stream_start
= header_start
;
872 if (!source
->Seek (stream_start
, SEEK_SET
))
873 return MEDIA_INVALID_MEDIA
;
875 if (vbr
.type
== MpegNoVBRHeader
) {
876 // calculate the frame length
877 len
= mpeg_frame_length (&mpeg
, false);
879 if ((end
= source
->GetSize ()) != -1) {
880 // estimate the number of frames
881 nframes
= ((double) end
- (double) stream_start
) / (double) len
;
886 if (vbr
.type
== MpegXingHeader
)
889 // calculate the frame length
890 len
= mpeg_frame_length (&mpeg
, xing
);
891 nframes
= vbr
.nframes
;
894 // calculate the duration of the first frame
895 duration
= mpeg_frame_duration (&mpeg
);
897 media
= GetMediaReffed ();
898 stream
= audio
= new AudioStream (media
);
901 reader
= new Mp3FrameReader (source
, audio
, stream_start
, len
, duration
, xing
);
903 audio
->codec_id
= CODEC_MP3
;
904 audio
->codec
= g_strdup ("mp3");
906 audio
->duration
= duration
* nframes
;
907 audio
->SetBitRate (mpeg
.bit_rate
);
908 audio
->SetChannels (mpeg
.channels
);
909 audio
->SetSampleRate (mpeg
.sample_rate
);
910 audio
->SetBlockAlign (mpeg_block_size (&mpeg
));
911 audio
->SetBitsPerSample (mpeg
.layer
== 1 ? 32 : 8);
912 audio
->SetExtraData (NULL
);
913 audio
->SetExtraDataSize (0);
915 streams
= g_new (IMediaStream
*, 2);
920 SetStreams (streams
, stream_count
);
923 return MEDIA_SUCCESS
;
927 Mp3Demuxer::GetFrameCallback (MediaClosure
*c
)
929 MediaGetFrameClosure
*closure
= (MediaGetFrameClosure
*) c
;
930 ((Mp3Demuxer
*) closure
->GetDemuxer ())->GetFrameAsyncInternal (closure
->GetStream ());
931 return MEDIA_SUCCESS
;
935 Mp3Demuxer::GetFrameAsyncInternal (IMediaStream
*stream
)
937 MediaFrame
*frame
= NULL
;
940 result
= reader
->TryReadFrame (&frame
);
942 if (result
== MEDIA_DEMUXER_ERROR
|| result
== MEDIA_BUFFER_UNDERFLOW
|| result
== MEDIA_DEMUXER_ERROR
|| result
== MEDIA_NOT_ENOUGH_DATA
) {
943 Media
*media
= GetMediaReffed ();
944 g_return_if_fail (media
!= NULL
);
945 MediaGetFrameClosure
*closure
= new MediaGetFrameClosure (media
, GetFrameCallback
, this, stream
);
946 media
->EnqueueWork (closure
, false);
952 if (result
== MEDIA_NO_MORE_DATA
) {
953 ReportGetFrameCompleted (NULL
);
954 } else if (MEDIA_SUCCEEDED (result
)) {
955 ReportGetFrameCompleted (frame
);
957 ReportErrorOccurred (result
);
969 Mp3DemuxerInfo::Supports (IMediaSource
*source
)
972 gint64 stream_start
= 0;
973 gint64 header_start
= 0;
974 MpegFrameHeader mpeg
;
980 // peek at the first 10 bytes which is enough to contain
981 // either the mp3 frame header or an ID3 tag header
982 if (!source
->Peek (buffer
, 10))
985 // Check for a leading ID3 tag
986 if (!strncmp ((const char *) buffer
, "ID3", 3)) {
987 for (i
= 0; i
< 4; i
++) {
988 if (buffer
[6 + i
] & 0x80)
991 size
= (size
<< 7) | buffer
[6 + i
];
994 if ((buffer
[5] & (1 << 4))) {
995 // add additional 10 bytes for footer
1000 // skip over the ID3 tag
1001 stream_start
= (gint64
) size
;
1004 result
= Mp3FrameReader::FindMpegHeader (&mpeg
, &vbr
, source
, stream_start
, &header_start
);
1006 source
->Seek (0, SEEK_SET
);
1008 LOG_MP3 ("Mp3DemuxerInfo::Supports (%p) result: %i\n", source
, result
);
1014 Mp3DemuxerInfo::Create (Media
*media
, IMediaSource
*source
)
1016 return new Mp3Demuxer (media
, source
);