Merge commit 'ef363ebd596da18f889a7d4845023a23dfac84c9'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 24 Oct 2014 12:48:12 +0000 (14:48 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 24 Oct 2014 13:30:12 +0000 (15:30 +0200)
* commit 'ef363ebd596da18f889a7d4845023a23dfac84c9':
  mp3enc: write full LAME frame

Conflicts:
libavformat/mp3enc.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
doc/muxers.texi
libavformat/mp3enc.c
tests/ref/lavf-fate/mp3

diff --cc doc/muxers.texi
Simple merge
@@@ -120,15 -135,14 +136,14 @@@ static int mp3_write_xing(AVFormatConte
      MPADecodeHeader  mpah;
      int srate_idx, i, channels;
      int bitrate_idx;
 -    int best_bitrate_idx;
 +    int best_bitrate_idx = -1;
      int best_bitrate_error = INT_MAX;
-     int xing_offset;
+     int ret;
      int ver = 0;
 -    int lsf, bytes_needed;
 +    int bytes_needed;
-     const char *vendor = (s->flags & AVFMT_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT;
  
      if (!s->pb->seekable || !mp3->write_xing)
 -        return;
 +        return 0;
  
      for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) {
          const uint16_t base_freq = avpriv_mpa_freq_tab[i];
          header |= mask;
  
          avpriv_mpegaudio_decode_header(&mpah, header);
-         xing_offset=xing_offtbl[mpah.lsf == 1][mpah.nb_channels == 1];
-         bytes_needed = 4              // header
-                + xing_offset
-                + 4              // xing tag
-                + 4              // frames/size/toc flags
-                + 4              // frames
-                + 4              // size
-                + XING_TOC_SIZE   // toc
-                + 24
-                ;
++        mp3->xing_offset = xing_offtbl[mpah.lsf == 1][mpah.nb_channels == 1] + 4;
++        bytes_needed     = mp3->xing_offset + XING_SIZE;
  
          if (bytes_needed <= mpah.frame_size)
              break;
          header &= ~mask;
      }
  
-     avio_wb32(s->pb, header);
+     ret = avio_open_dyn_buf(&dyn_ctx);
+     if (ret < 0)
 -        return;
++        return ret;
+     avio_wb32(dyn_ctx, header);
  
-     ffio_fill(s->pb, 0, xing_offset);
-     mp3->xing_offset = avio_tell(s->pb);
-     ffio_wfourcc(s->pb, "Xing");
-     avio_wb32(s->pb, 0x01 | 0x02 | 0x04);  // frames / size / TOC
 -    avpriv_mpegaudio_decode_header(&mpah, header);
 -
 -    av_assert0(mpah.frame_size >= bytes_needed);
 -
+     ffio_fill(dyn_ctx, 0, mp3->xing_offset - 4);
+     ffio_wfourcc(dyn_ctx, "Xing");
+     avio_wb32(dyn_ctx, 0x01 | 0x02 | 0x04 | 0x08);  // frames / size / TOC / vbr scale
  
      mp3->size = mpah.frame_size;
 -    mp3->want = 1;
 +    mp3->want=1;
 +    mp3->seen=0;
 +    mp3->pos=0;
  
-     avio_wb32(s->pb, 0);  // frames
-     avio_wb32(s->pb, 0);  // size
+     avio_wb32(dyn_ctx, 0);  // frames
+     avio_wb32(dyn_ctx, 0);  // size
+     // TOC
+     for (i = 0; i < XING_TOC_SIZE; i++)
 -        avio_w8(dyn_ctx, 255 * i / XING_TOC_SIZE);
++        avio_w8(dyn_ctx, (uint8_t)(255 * i / XING_TOC_SIZE));
+     // vbr quality
+     // we write it, because some (broken) tools always expect it to be present
+     avio_wb32(dyn_ctx, 0);
+     // encoder short version string
+     if (enc) {
+         uint8_t encoder_str[9] = { 0 };
+         memcpy(encoder_str, enc->value, FFMIN(strlen(enc->value), sizeof(encoder_str)));
+         avio_write(dyn_ctx, encoder_str, sizeof(encoder_str));
+     } else
 -        ffio_fill(dyn_ctx, 0, 9);
++        avio_write(dyn_ctx, "Lavf\0\0\0\0\0", 9);
+     avio_w8(dyn_ctx, 0);      // tag revision 0 / unknown vbr method
+     avio_w8(dyn_ctx, 0);      // unknown lowpass filter value
+     ffio_fill(dyn_ctx, 0, 8); // empty replaygain fields
+     avio_w8(dyn_ctx, 0);      // unknown encoding flags
+     avio_w8(dyn_ctx, 0);      // unknown abr/minimal bitrate
+     // encoder delay
 -    if (codec->initial_padding >= 1 << 12) {
++    if (codec->initial_padding - 528 - 1 >= 1 << 12) {
+         av_log(s, AV_LOG_WARNING, "Too many samples of initial padding.\n");
 -        avio_wb24(dyn_ctx, 0);
 -    } else {
 -        avio_wb24(dyn_ctx, codec->initial_padding << 12);
+     }
++    avio_wb24(dyn_ctx, FFMAX(codec->initial_padding - 528 - 1, 0)<<12);
+     avio_w8(dyn_ctx,   0); // misc
+     avio_w8(dyn_ctx,   0); // mp3gain
+     avio_wb16(dyn_ctx, 0); // preset
+     // audio length and CRCs (will be updated later)
+     avio_wb32(dyn_ctx, 0); // music length
+     avio_wb16(dyn_ctx, 0); // music crc
+     avio_wb16(dyn_ctx, 0); // tag crc
  
-     // toc
-     for (i = 0; i < XING_TOC_SIZE; ++i)
-         avio_w8(s->pb, (uint8_t)(255 * i / XING_TOC_SIZE));
+     ffio_fill(dyn_ctx, 0, mpah.frame_size - bytes_needed);
  
-     for (i = 0; i < strlen(vendor); ++i)
-         avio_w8(s->pb, vendor[i]);
-     for (; i < 21; ++i)
-         avio_w8(s->pb, 0);
-     avio_wb24(s->pb, FFMAX(codec->initial_padding - 528 - 1, 0)<<12);
+     mp3->xing_frame_size   = avio_close_dyn_buf(dyn_ctx, &mp3->xing_frame);
+     mp3->xing_frame_offset = avio_tell(s->pb);
+     avio_write(s->pb, mp3->xing_frame, mp3->xing_frame_size);
  
-     ffio_fill(s->pb, 0, mpah.frame_size - bytes_needed);
+     mp3->audio_size = mp3->xing_frame_size;
 +
 +    return 0;
  }
  
  /*
@@@ -266,36 -310,20 +309,40 @@@ static int mp3_write_audio_packet(AVFor
  
          h = AV_RB32(pkt->data);
          if (ff_mpa_check_header(h) == 0) {
 -            avpriv_mpegaudio_decode_header(&c, h);
 +            avpriv_mpegaudio_decode_header(&mpah, h);
              if (!mp3->initial_bitrate)
 -                mp3->initial_bitrate = c.bit_rate;
 -            if ((c.bit_rate == 0) || (mp3->initial_bitrate != c.bit_rate))
 +                mp3->initial_bitrate = mpah.bit_rate;
 +            if ((mpah.bit_rate == 0) || (mp3->initial_bitrate != mpah.bit_rate))
                  mp3->has_variable_bitrate = 1;
 +        } else {
 +            av_log(s, AV_LOG_WARNING, "Audio packet of size %d (starting with %08X...) "
 +                   "is invalid, writing it anyway.\n", pkt->size, h);
          }
  
 -        mp3_xing_add_frame(mp3, pkt);
 +#ifdef FILTER_VBR_HEADERS
 +        /* filter out XING and INFO headers. */
 +        base = 4 + xing_offtbl[mpah.lsf == 1][mpah.nb_channels == 1];
 +
 +        if (base + 4 <= pkt->size) {
 +            uint32_t v = AV_RB32(pkt->data + base);
 +
 +            if (MKBETAG('X','i','n','g') == v || MKBETAG('I','n','f','o') == v)
 +                return 0;
 +        }
 +
 +        /* filter out VBRI headers. */
 +        base = 4 + 32;
 +
 +        if (base + 4 <= pkt->size && MKBETAG('V','B','R','I') == AV_RB32(pkt->data + base))
 +            return 0;
 +#endif
  
-         if (mp3->xing_offset)
+         if (mp3->xing_offset) {
 +            mp3_xing_add_frame(mp3, pkt);
+             mp3->audio_size += pkt->size;
+             mp3->audio_crc   = av_crc(av_crc_get_table(AV_CRC_16_ANSI_LE),
+                                       mp3->audio_crc, pkt->data, pkt->size);
+         }
      }
  
      return ff_raw_write_packet(s, pkt);
index ec66652,0000000..b559538
mode 100644,000000..100644
--- /dev/null
@@@ -1,3 -1,0 +1,3 @@@
- 8facd3cc6158b611cb312920a426cbd7 *./tests/data/lavf-fate/lavf.mp3
++f231c5316357fd747573cbcb02f889c5 *./tests/data/lavf-fate/lavf.mp3
 +96016 ./tests/data/lavf-fate/lavf.mp3
 +./tests/data/lavf-fate/lavf.mp3 CRC=0x6c9850fe