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]

Reply via email to