{
MP3Context *mp3 = s->priv_data;
AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec;
- int bitrate_idx;
- int best_bitrate_idx = -1;
- int best_bitrate_error= INT_MAX;
- int xing_offset;
- int32_t header, mask;
- MPADecodeHeader c;
- int srate_idx, ver = 0, i, channels;
- int needed;
- const char *vendor = (codec->flags & CODEC_FLAG_BITEXACT) ? "Lavf" : LIBAVFORMAT_IDENT;
- int32_t header;
++ int32_t header;
+ 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 ver = 0;
- int lsf, bytes_needed;
++ int bytes_needed, lsf;
++ const char *vendor = (codec->flags & CODEC_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];
}
/* dummy MPEG audio header */
- header = 0xff << 24; // sync
+ header = 0xffU << 24; // sync
header |= (0x7 << 5 | ver << 3 | 0x1 << 1 | 0x1) << 16; // sync/audio-version/layer 3/no crc*/
- header |= (srate_idx << 2) << 8;
+ header |= (srate_idx << 2) << 8;
header |= channels << 6;
- for (bitrate_idx=1; bitrate_idx<15; bitrate_idx++) {
- int error;
- avpriv_mpegaudio_decode_header(&c, header | (bitrate_idx << (4+8)));
- error= FFABS(c.bit_rate - codec->bit_rate);
- if(error < best_bitrate_error){
- best_bitrate_error= error;
- best_bitrate_idx = bitrate_idx;
- lsf = !((header & (1 << 20) && header & (1 << 19)));
-
- xing_offset = xing_offtbl[ver != 3][channels == 1];
- bytes_needed = 4 // header
- + xing_offset
- + 4 // xing tag
- + 4 // frames/size/toc flags
- + 4 // frames
- + 4 // size
- + XING_TOC_SIZE; // toc
-
+ for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) {
+ int bit_rate = 1000 * avpriv_mpa_bitrate_tab[lsf][3 - 1][bitrate_idx];
+ int error = FFABS(bit_rate - codec->bit_rate);
+
- if (error < best_bitrate_error){
++ if (error < best_bitrate_error) {
+ best_bitrate_error = error;
+ best_bitrate_idx = bitrate_idx;
}
}
+ av_assert0(best_bitrate_idx >= 0);
- for (bitrate_idx= best_bitrate_idx;; bitrate_idx++) {
- for (bitrate_idx = best_bitrate_idx; bitrate_idx < 15; bitrate_idx++) {
++ for (bitrate_idx = best_bitrate_idx; ; bitrate_idx++) {
+ int32_t mask = bitrate_idx << (4 + 8);
+ if (15 == bitrate_idx)
+ return -1;
- mask = bitrate_idx << (4+8);
header |= mask;
- avpriv_mpegaudio_decode_header(&c, header);
- xing_offset=xing_offtbl[c.lsf == 1][c.nb_channels == 1];
- needed = 4 // header
+
+ 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
+ ;
- if (needed <= c.frame_size)
+ if (bytes_needed <= mpah.frame_size)
break;
+
header &= ~mask;
}
ffio_wfourcc(s->pb, "Xing");
avio_wb32(s->pb, 0x01 | 0x02 | 0x04); // frames / size / TOC
- mp3->size = c.frame_size;
+ 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
- // TOC
- for (i = 0; i < XING_TOC_SIZE; i++)
- avio_w8(s->pb, 255 * i / XING_TOC_SIZE);
+ // toc
+ for (i = 0; i < XING_TOC_SIZE; ++i)
+ avio_w8(s->pb, (uint8_t)(255 * i / XING_TOC_SIZE));
+
+ 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->delay - 528 - 1, 0)<<12);
- ffio_fill(s->pb, 0, c.frame_size - needed);
+ ffio_fill(s->pb, 0, mpah.frame_size - bytes_needed);
+
+ return 0;
}
/*
{
MP3Context *mp3 = s->priv_data;
- if (mp3->xing_offset && pkt->size >= 4) {
- MPADecodeHeader c;
+ if (pkt->data && pkt->size >= 4) {
- MPADecodeHeader c;
++ MPADecodeHeader mpah;
+ int av_unused base;
+ uint32_t head = AV_RB32(pkt->data);
- avpriv_mpegaudio_decode_header(&c, AV_RB32(pkt->data));
+ if (ff_mpa_check_header(head) < 0) {
+ av_log(s, AV_LOG_WARNING, "Audio packet of size %d (starting with %08X...) "
+ "is invalid, writing it anyway.\n", pkt->size, head);
+ return ff_raw_write_packet(s, pkt);
+ }
- avpriv_mpegaudio_decode_header(&c, head);
++ avpriv_mpegaudio_decode_header(&mpah, head);
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;
- mp3_xing_add_frame(mp3, pkt);
+#ifdef FILTER_VBR_HEADERS
+ /* filter out XING and INFO headers. */
- base = 4 + xing_offtbl[c.lsf == 1][c.nb_channels == 1];
++ 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)
+ mp3_xing_add_frame(mp3, pkt);
}
return ff_raw_write_packet(s, pkt);