|
|
|
@@ -119,8 +119,11 @@ static void mp3_write_xing(AVFormatContext *s) |
|
|
|
MPADecodeHeader mpah; |
|
|
|
int srate_idx, i, channels; |
|
|
|
int bitrate_idx; |
|
|
|
int best_bitrate_idx; |
|
|
|
int best_bitrate_error = INT_MAX; |
|
|
|
int xing_offset; |
|
|
|
int ver = 0; |
|
|
|
int lsf, bytes_needed; |
|
|
|
|
|
|
|
if (!s->pb->seekable || !mp3->write_xing) |
|
|
|
return; |
|
|
|
@@ -150,21 +153,51 @@ static void mp3_write_xing(AVFormatContext *s) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* 64 kbps frame, should be large enough */ |
|
|
|
bitrate_idx = (ver == 3) ? 5 : 8; |
|
|
|
|
|
|
|
/* dummy MPEG audio header */ |
|
|
|
header = 0xff << 24; // sync |
|
|
|
header |= (0x7 << 5 | ver << 3 | 0x1 << 1 | 0x1) << 16; // sync/audio-version/layer 3/no crc*/ |
|
|
|
header |= (bitrate_idx << 4 | srate_idx << 2) << 8; |
|
|
|
header |= (srate_idx << 2) << 8; |
|
|
|
header |= channels << 6; |
|
|
|
|
|
|
|
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){ |
|
|
|
best_bitrate_error = error; |
|
|
|
best_bitrate_idx = bitrate_idx; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (bitrate_idx = best_bitrate_idx; bitrate_idx < 15; bitrate_idx++) { |
|
|
|
int32_t mask = bitrate_idx << (4 + 8); |
|
|
|
header |= mask; |
|
|
|
|
|
|
|
avpriv_mpegaudio_decode_header(&mpah, header); |
|
|
|
|
|
|
|
if (bytes_needed <= mpah.frame_size) |
|
|
|
break; |
|
|
|
|
|
|
|
header &= ~mask; |
|
|
|
} |
|
|
|
|
|
|
|
avio_wb32(s->pb, header); |
|
|
|
|
|
|
|
avpriv_mpegaudio_decode_header(&mpah, header); |
|
|
|
|
|
|
|
av_assert0(mpah.frame_size >= XING_MAX_SIZE); |
|
|
|
|
|
|
|
xing_offset = xing_offtbl[ver != 3][codec->channels == 1]; |
|
|
|
ffio_fill(s->pb, 0, xing_offset); |
|
|
|
mp3->xing_offset = avio_tell(s->pb); |
|
|
|
ffio_wfourcc(s->pb, "Xing"); |
|
|
|
@@ -180,8 +213,7 @@ static void mp3_write_xing(AVFormatContext *s) |
|
|
|
for (i = 0; i < XING_TOC_SIZE; i++) |
|
|
|
avio_w8(s->pb, 255 * i / XING_TOC_SIZE); |
|
|
|
|
|
|
|
mpah.frame_size -= 4 + xing_offset + 4 + 4 + 4 + 4 + XING_TOC_SIZE; |
|
|
|
ffio_fill(s->pb, 0, mpah.frame_size); |
|
|
|
ffio_fill(s->pb, 0, mpah.frame_size - bytes_needed); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
|