summaryrefslogtreecommitdiff
path: root/libavformat/mp3.c
diff options
context:
space:
mode:
authorAndreas Öman <andreas@lonelycoder.com>2007-10-23 13:35:20 +0000
committerAndreas Öman <andreas@lonelycoder.com>2007-10-23 13:35:20 +0000
commitca851a3a082f3678c5f0e7e8dc24480a5f483ec6 (patch)
tree163d764c0b83d529644f22494b33bd2ef93086e6 /libavformat/mp3.c
parent71fa13e8757700d817ae3058fac3c5c55eaed839 (diff)
add support for reading duration from Xing-tag in mp3 files
Originally committed as revision 10845 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/mp3.c')
-rw-r--r--libavformat/mp3.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/libavformat/mp3.c b/libavformat/mp3.c
index 6173be225e..b2bc89587a 100644
--- a/libavformat/mp3.c
+++ b/libavformat/mp3.c
@@ -21,6 +21,7 @@
#include "avformat.h"
#include "mpegaudio.h"
#include "avstring.h"
+#include "mpegaudiodecheader.h"
#define ID3v2_HEADER_SIZE 10
#define ID3v1_TAG_SIZE 128
@@ -424,12 +425,40 @@ static int mp3_read_probe(AVProbeData *p)
else return 0;
}
+/**
+ * Try to extract a xing tag from the stream and if found, decode it
+ */
+static void mp3_parse_xing(AVFormatContext *s, AVStream *st)
+{
+ uint32_t v, frames, spf;
+ const offset_t offtbl[2][2] = {{32, 17}, {17,9}};
+ MPADecodeContext c;
+
+ ff_mpegaudio_decode_header(&c, get_be32(&s->pb));
+ url_fseek(&s->pb, offtbl[c.lsf == 1][c.nb_channels == 1], SEEK_CUR);
+ v = get_be32(&s->pb);
+ if(c.layer != 3 ||
+ (v != MKBETAG('X', 'i', 'n', 'g') &&
+ v != MKBETAG('I', 'n', 'f', 'o')))
+ return;
+
+ v = get_be32(&s->pb);
+ if(v & 0x1) {
+ frames = get_be32(&s->pb); /* Total number of frames in file */
+ spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */
+
+ st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate},
+ st->time_base);
+ }
+}
+
static int mp3_read_header(AVFormatContext *s,
AVFormatParameters *ap)
{
AVStream *st;
uint8_t buf[ID3v1_TAG_SIZE];
int len, ret, filesize;
+ offset_t off;
st = av_new_stream(s, 0);
if (!st)
@@ -469,6 +498,10 @@ static int mp3_read_header(AVFormatContext *s,
url_fseek(&s->pb, 0, SEEK_SET);
}
+ off = url_ftell(&s->pb);
+ mp3_parse_xing(s, st);
+ url_fseek(&s->pb, off, SEEK_SET);
+
/* the parameters will be extracted from the compressed bitstream */
return 0;
}