]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mp3.c
vorbiscomment: convert metadata before computing the header's length
[ffmpeg] / libavformat / mp3.c
index e2f230acad08928a1f4caed84bd93a00745c12fc..ceba2ce50640c3a225335a0a00a70ca1ae94a282 100644 (file)
@@ -42,13 +42,12 @@ static int mp3_read_probe(AVProbeData *p)
     AVCodecContext avctx;
 
     buf0 = p->buf;
-    if(ff_id3v2_match(buf0)) {
-        buf0 += ff_id3v2_tag_len(buf0);
-    }
+    end = p->buf + p->buf_size - sizeof(uint32_t);
+    while(buf0 < end && !*buf0)
+        buf0++;
 
     max_frames = 0;
     buf = buf0;
-    end = p->buf + p->buf_size - sizeof(uint32_t);
 
     for(; buf < end; buf= buf2+1) {
         buf2 = buf;
@@ -81,7 +80,8 @@ static int mp3_read_probe(AVProbeData *p)
 static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
 {
     uint32_t v, spf;
-    int frames = -1; /* Total number of frames in file */
+    unsigned frames = 0; /* Total number of frames in file */
+    unsigned size = 0; /* Total number of bytes in the stream */
     const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
     MPADecodeHeader c;
     int vbrtag_size = 0;
@@ -102,6 +102,8 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
         v = get_be32(s->pb);
         if(v & 0x1)
             frames = get_be32(s->pb);
+        if(v & 0x2)
+            size = get_be32(s->pb);
     }
 
     /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */
@@ -110,21 +112,26 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
     if(v == MKBETAG('V', 'B', 'R', 'I')) {
         /* Check tag version */
         if(get_be16(s->pb) == 1) {
-            /* skip delay, quality and total bytes */
-            url_fseek(s->pb, 8, SEEK_CUR);
+            /* skip delay and quality */
+            url_fseek(s->pb, 4, SEEK_CUR);
             frames = get_be32(s->pb);
+            size = get_be32(s->pb);
         }
     }
 
-    if(frames < 0)
+    if(!frames && !size)
         return -1;
 
     /* Skip the vbr tag frame */
     url_fseek(s->pb, base + vbrtag_size, SEEK_SET);
 
     spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */
-    st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate},
-                                st->time_base);
+    if(frames)
+        st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate},
+                                    st->time_base);
+    if(size)
+        st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf);
+
     return 0;
 }
 
@@ -138,7 +145,7 @@ static int mp3_read_header(AVFormatContext *s,
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = CODEC_TYPE_AUDIO;
+    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
     st->codec->codec_id = CODEC_ID_MP3;
     st->need_parsing = AVSTREAM_PARSE_FULL;
     st->start_time = 0;
@@ -146,7 +153,6 @@ static int mp3_read_header(AVFormatContext *s,
     // lcm of all mp3 sample rates
     av_set_pts_info(st, 64, 1, 14112000);
 
-    ff_id3v2_read(s);
     off = url_ftell(s->pb);
 
     if (!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX))
@@ -189,7 +195,6 @@ AVInputFormat mp3_demuxer = {
     mp3_read_packet,
     .flags= AVFMT_GENERIC_INDEX,
     .extensions = "mp2,mp3,m2a", /* XXX: use probe */
-    .metadata_conv = ff_id3v2_metadata_conv,
 };
 #endif
 
@@ -212,18 +217,18 @@ static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
     buf[0] = 'T';
     buf[1] = 'A';
     buf[2] = 'G';
-    count += id3v1_set_string(s, "title",   buf +  3, 30);
-    count += id3v1_set_string(s, "author",  buf + 33, 30);
-    count += id3v1_set_string(s, "album",   buf + 63, 30);
-    count += id3v1_set_string(s, "date",    buf + 93,  4);
+    count += id3v1_set_string(s, "TIT2",    buf +  3, 30);       //title
+    count += id3v1_set_string(s, "TPE1",    buf + 33, 30);       //author|artist
+    count += id3v1_set_string(s, "TALB",    buf + 63, 30);       //album
+    count += id3v1_set_string(s, "TDRL",    buf + 93,  4);       //date
     count += id3v1_set_string(s, "comment", buf + 97, 30);
-    if ((tag = av_metadata_get(s->metadata, "track", NULL, 0))) {
+    if ((tag = av_metadata_get(s->metadata, "TRCK", NULL, 0))) { //track
         buf[125] = 0;
         buf[126] = atoi(tag->value);
         count++;
     }
     buf[127] = 0xFF; /* default to unknown genre */
-    if ((tag = av_metadata_get(s->metadata, "genre", NULL, 0))) {
+    if ((tag = av_metadata_get(s->metadata, "TCON", NULL, 0))) { //genre
         for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
             if (!strcasecmp(tag->value, ff_id3v1_genre_str[i])) {
                 buf[127] = i;
@@ -310,10 +315,11 @@ static int mp3_write_header(struct AVFormatContext *s)
     size_pos = url_ftell(s->pb);
     put_be32(s->pb, 0);
 
+    ff_metadata_conv(&s->metadata, ff_id3v2_metadata_conv, NULL);
     while ((t = av_metadata_get(s->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) {
         uint32_t tag = 0;
 
-        if (t->key[0] == 'T' && strcmp(t->key, "TSSE")) {
+        if (t->key[0] == 'T' && strlen(t->key) == 4) {
             int i;
             for (i = 0; *ff_id3v2_tags[i]; i++)
                 if (AV_RB32(t->key) == AV_RB32(ff_id3v2_tags[i])) {
@@ -338,11 +344,6 @@ static int mp3_write_header(struct AVFormatContext *s)
             av_free(buf);
         }
     }
-    if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) {
-        totlen += strlen(LIBAVFORMAT_IDENT) + ID3v2_HEADER_SIZE + 2;
-        id3v2_put_ttag(s, LIBAVFORMAT_IDENT, strlen(LIBAVFORMAT_IDENT) + 1,
-                       MKBETAG('T', 'S', 'S', 'E'));
-    }
 
     cur_pos = url_ftell(s->pb);
     url_fseek(s->pb, size_pos, SEEK_SET);
@@ -363,6 +364,6 @@ AVOutputFormat mp3_muxer = {
     mp3_write_header,
     mp3_write_packet,
     mp3_write_trailer,
-    .metadata_conv = ff_id3v2_metadata_conv,
+    AVFMT_NOTIMESTAMPS,
 };
 #endif