[FFmpeg-devel] [RFC] [PATCH] mp3: keep gapless information on stream-copy

Andreas Cadhalpun andreas.cadhalpun at googlemail.com
Tue Dec 22 23:40:15 CET 2015


Fixes Debian bug #797965, https://bugs.debian.org/797965
---

This can't be used as is, because it requires copying private stream fields
in ffmpeg.c.
Also the duplication between codec->initial_padding and st->start_skip_samples
is less than ideal.
Does someone have a better idea how to fix this?

---
 ffmpeg.c             |  3 +++
 libavformat/mp3enc.c | 23 +++++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index 10d0f25..a2a0bd7 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -3012,6 +3012,9 @@ static int transcode_init(void)
                     enc_ctx->block_align= 0;
                 if(enc_ctx->codec_id == AV_CODEC_ID_AC3)
                     enc_ctx->block_align= 0;
+                ost->st->start_skip_samples   = ist->st->start_skip_samples;
+                ost->st->first_discard_sample = ist->st->first_discard_sample;
+                ost->st->last_discard_sample  = ist->st->last_discard_sample;
                 break;
             case AVMEDIA_TYPE_VIDEO:
                 enc_ctx->pix_fmt            = dec_ctx->pix_fmt;
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index 40f0672..364442e 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -129,8 +129,9 @@ static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}};
 static int mp3_write_xing(AVFormatContext *s)
 {
     MP3Context       *mp3 = s->priv_data;
-    AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec;
-    AVDictionaryEntry *enc = av_dict_get(s->streams[mp3->audio_stream_idx]->metadata, "encoder", NULL, 0);
+    AVStream          *st  = s->streams[mp3->audio_stream_idx];
+    AVCodecContext *codec  = st->codec;
+    AVDictionaryEntry *enc = av_dict_get(st->metadata, "encoder", NULL, 0);
     AVIOContext *dyn_ctx;
     int32_t        header;
     MPADecodeHeader  mpah;
@@ -141,6 +142,7 @@ static int mp3_write_xing(AVFormatContext *s)
     int ret;
     int ver = 0;
     int bytes_needed;
+    int start_pad, end_pad;
 
     if (!s->pb->seekable || !mp3->write_xing)
         return 0;
@@ -248,10 +250,23 @@ static int mp3_write_xing(AVFormatContext *s)
     avio_w8(dyn_ctx, 0);      // unknown abr/minimal bitrate
 
     // encoder delay
-    if (codec->initial_padding - 528 - 1 >= 1 << 12) {
+    if (codec->initial_padding)
+        start_pad = FFMAX(codec->initial_padding - 528 - 1, 0); // from the encoder
+    else
+        start_pad = FFMAX(st->start_skip_samples - 528 - 1, 0); // from the demuxer
+
+    if (start_pad >= 1 << 12) {
         av_log(s, AV_LOG_WARNING, "Too many samples of initial padding.\n");
+        start_pad = (1 << 12) - 1;
+    }
+
+    end_pad = FFMAX(st->last_discard_sample - st->first_discard_sample + 528 + 1, 0);
+    if (end_pad >= 1 << 12) {
+        av_log(s, AV_LOG_WARNING, "Too many samples of final padding.\n");
+        end_pad = (1 << 12) - 1;
     }
-    avio_wb24(dyn_ctx, FFMAX(codec->initial_padding - 528 - 1, 0)<<12);
+
+    avio_wb24(dyn_ctx, start_pad<<12 | end_pad);
 
     avio_w8(dyn_ctx,   0); // misc
     avio_w8(dyn_ctx,   0); // mp3gain
-- 
2.6.2


More information about the ffmpeg-devel mailing list