[PR] avformat/movenc: drain buffered EAC3 packets (PR #23605)

James Almer via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178248038169.59.5344855179646760861@29965ddac10e>
PR #23605 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23605
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23605.patch

handle_eac3() will buffer a packet if it doesn't reach the desired num_blocks value, but if it was the last one to be passed to the muxer, it will never be written.
Fix this by writing it during mov_write_trailer().


>From 7268d3fbf53b84ee4845e8a3b32634c458c8026a Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Fri, 26 Jun 2026 10:21:56 -0300
Subject: [PATCH 1/2] avformat/movenc: read packet duration at the time it's
 needed

Reading it at the beginning of ff_mov_write_packet() means that any changes to it
that happen afterwards will not be taken into account for the remainer calculation.

Signed-off-by: James Almer <[email protected]>
---
 libavformat/movenc.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index c14f05ecc8..6012b16d67 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -6935,7 +6935,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     AVCodecParameters *par;
     AVProducerReferenceTime *prft;
     unsigned int samples_in_chunk = 0;
-    int64_t duration = pkt->duration;
+    int64_t duration;
     int size = pkt->size, ret = 0, offset = 0;
     size_t prft_size;
     uint8_t *reformatted_data = NULL;
@@ -7309,12 +7309,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     sd = av_packet_side_data_get(pkt->side_data, pkt->side_data_elems, AV_PKT_DATA_SKIP_SAMPLES);
     if (sd && sd->size >= 10 && trk->par->frame_size) {
         duration = FFMAX(av_rescale_q(trk->par->frame_size, (AVRational){ 1, trk->par->sample_rate },
-                                      trk->st->time_base), duration);
+                                      trk->st->time_base), pkt->duration);
         duration -= av_rescale_q(AV_RL32(sd->data + 4), (AVRational){ 1, trk->par->sample_rate },
                                  trk->st->time_base);
         if (duration < 0)
             return AVERROR_INVALIDDATA;
-    }
+    } else
+        duration = pkt->duration;
 
     trk->track_duration = pkt->dts - trk->start_dts + pkt->duration;
     trk->last_sample_is_subtitle_end = 0;
-- 
2.52.0


>From 63b669d46b2a2a7b52751babc385eedaa65fd348 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Fri, 26 Jun 2026 10:23:55 -0300
Subject: [PATCH 2/2] avformat/movenc: drain buffered EAC3 packets

handle_eac3() will buffer a packet if it doesn't reach the desired num_blocks
value, but if it was the last one to be passed to the muxer, it will never be
written.
Fix this by writing it during mov_write_trailer().

Signed-off-by: James Almer <[email protected]>
---
 libavformat/movenc.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 6012b16d67..f907f89acd 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -382,6 +382,7 @@ static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track)
 
 struct eac3_info {
     AVPacket *pkt;
+    uint8_t eof;
     uint8_t ec3_done;
     uint8_t num_blocks;
 
@@ -575,6 +576,11 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
     }
 
 concatenate:
+    if (info->eof) {
+        av_assert1(!info->pkt->size);
+        ret = pkt->size;
+        goto end;
+    }
     if (!info->num_blocks && num_blocks == 6) {
         ret = pkt->size;
         goto end;
@@ -9030,6 +9036,23 @@ static int mov_write_trailer(AVFormatContext *s)
         }
     }
 
+    //Also check for a buffered EAC3 packet
+    for (i = 0; i < mov->nb_tracks; i++) {
+        MOVTrack *trk = &mov->tracks[i];
+        if (trk->par->codec_id != AV_CODEC_ID_EAC3)
+            continue;
+
+        struct eac3_info *info = trk->eac3_priv;
+        if (!info->pkt->size)
+            continue;
+        av_packet_move_ref(mov->pkt, info->pkt);
+        info->eof = 1;
+        res = mov_write_single_packet(s, mov->pkt);
+        if (res < 0)
+            return res;
+        av_packet_unref(mov->pkt);
+    }
+
     // Check if we have any tracks that require squashing.
     // In that case, we'll have to write the packet here.
     if ((res = mov_write_squashed_packets(s)) < 0)
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.