This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 3ab8b976c186f68b43dc2cae081453d69a7e8c55
Author:     James Almer <[email protected]>
AuthorDate: Mon Feb 2 22:56:49 2026 -0300
Commit:     James Almer <[email protected]>
CommitDate: Thu Feb 5 23:21:49 2026 -0300

    avformat/matroskaenc: parse Opus packets to write proper durations
    
    Before this patch, the last packet in the affected fate test would be 
written
    without a BlockDuration element despite the packet's duration being shorter
    than the Opus frame size.
    
    Signed-off-by: James Almer <[email protected]>
---
 libavformat/matroskaenc.c              | 36 ++++++++++++++++++++++++++++++++--
 tests/ref/fate/matroska-ogg-opus-remux |  6 +++---
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 50188c396c..ceecb5f2ca 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -69,6 +69,7 @@
 #include "libavcodec/itut35.h"
 #include "libavcodec/xiph.h"
 #include "libavcodec/mpeg4audio.h"
+#include "libavcodec/opus/parse.h"
 
 /* Level 1 elements we create a SeekHead entry for:
  * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */
@@ -209,6 +210,10 @@ typedef struct mkv_track {
      * The callback shall not return an error on the second call. */
     int             (*reformat)(struct MatroskaMuxContext *, AVIOContext *,
                                 const AVPacket *, int *size);
+
+    // Opus specific
+    OpusParseContext *opus;
+    OpusPacket *opus_pkt;
 } mkv_track;
 
 typedef struct MatroskaMuxContext {
@@ -859,6 +864,14 @@ static void mkv_deinit(AVFormatContext *s)
 
     av_freep(&mkv->cur_block.h2645_nalu_list.nalus);
     av_freep(&mkv->cues.entries);
+
+    for (int i = 0; i < s->nb_streams; i++) {
+        mkv_track *track = &mkv->tracks[i];
+        if (track->opus)
+            avpriv_opus_parse_uninit_context(track->opus);
+        av_freep(&track->opus);
+        av_freep(&track->opus_pkt);
+    }
     av_freep(&mkv->tracks);
 }
 
@@ -2799,11 +2812,12 @@ static void mkv_write_blockadditional(EbmlWriter 
*writer, const uint8_t *buf,
 }
 
 static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv,
-                           AVIOContext *pb, const AVCodecParameters *par,
+                           AVIOContext *pb, const AVStream *st,
                            mkv_track *track, const AVPacket *pkt,
                            int keyframe, int64_t ts, uint64_t duration,
                            int force_blockgroup, int64_t relative_packet_pos)
 {
+    const AVCodecParameters *par  = st->codecpar;
     uint8_t t35_buf[6 + AV_HDR_PLUS_MAX_PAYLOAD_SIZE];
     uint8_t *side_data;
     size_t side_data_size;
@@ -2829,6 +2843,19 @@ static int mkv_write_block(void *logctx, 
MatroskaMuxContext *mkv,
         duration != track->default_duration_high &&
         duration != track->default_duration_low))
         ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration);
+    else if (track->opus) {
+        ret = avpriv_opus_parse_packet(&track->opus_pkt, pkt->data, pkt->size,
+                                       track->opus->nb_streams > 1, logctx);
+        if (!ret) {
+            /* If the packet's duration is inconsistent with the coded 
duration,
+             * add an explicit duration element. */
+            uint64_t parsed_duration = 
av_rescale_q(track->opus_pkt->frame_count * track->opus_pkt->frame_duration,
+                                                    (AVRational){1, 
par->sample_rate},
+                                                    st->time_base);
+            if (parsed_duration != duration)
+                ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, 
duration);
+        }
+    }
 
     av_log(logctx, AV_LOG_DEBUG,
            "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", "
@@ -2999,6 +3026,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, 
const AVPacket *pkt)
 {
     MatroskaMuxContext *mkv = s->priv_data;
     AVIOContext *pb;
+    AVStream *st            = s->streams[pkt->stream_index];
     AVCodecParameters *par  = s->streams[pkt->stream_index]->codecpar;
     mkv_track *track        = &mkv->tracks[pkt->stream_index];
     int is_sub              = par->codec_type == AVMEDIA_TYPE_SUBTITLE;
@@ -3045,7 +3073,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, 
const AVPacket *pkt)
 
     /* The WebM spec requires WebVTT to be muxed in BlockGroups;
      * so we force it even for packets without duration. */
-    ret = mkv_write_block(s, mkv, pb, par, track, pkt,
+    ret = mkv_write_block(s, mkv, pb, st, track, pkt,
                           keyframe, ts, duration,
                           par->codec_id == AV_CODEC_ID_WEBVTT,
                           relative_packet_pos);
@@ -3467,6 +3495,10 @@ static int mkv_init(struct AVFormatContext *s)
         case AV_CODEC_ID_WEBVTT:
             track->reformat = webm_reformat_vtt;
             break;
+        case AV_CODEC_ID_OPUS:
+            avpriv_opus_parse_extradata(&track->opus, par->extradata, 
par->extradata_size,
+                                        par->ch_layout.nb_channels, s);
+            break;
         }
 
         if (s->flags & AVFMT_FLAG_BITEXACT) {
diff --git a/tests/ref/fate/matroska-ogg-opus-remux 
b/tests/ref/fate/matroska-ogg-opus-remux
index 6e0d91a2d4..600083c134 100644
--- a/tests/ref/fate/matroska-ogg-opus-remux
+++ b/tests/ref/fate/matroska-ogg-opus-remux
@@ -1,5 +1,5 @@
-87d0185c5b780dd9509aafd957236bdd 
*tests/data/fate/matroska-ogg-opus-remux.matroska
-10203 tests/data/fate/matroska-ogg-opus-remux.matroska
+c8596f7b31a8b6693f53759942c3754f 
*tests/data/fate/matroska-ogg-opus-remux.matroska
+10206 tests/data/fate/matroska-ogg-opus-remux.matroska
 #extradata 0:       19, 0x399c0471
 #tb 0: 1/1000
 #media_type 0: audio
@@ -46,7 +46,7 @@
 0,        733,        733,       20,      219, 0xe2906c62
 0,        753,        753,       20,      217, 0xcf316ba1
 0,        773,        773,       20,      217, 0x470b6eea
-0,        793,        793,       20,      359, 0x36c2a18a, S=1, Skip Samples,  
     10, 0x0232005e
+0,        793,        793,        7,      359, 0x36c2a18a, S=1, Skip Samples,  
     10, 0x0232005e
 [PACKET]
 codec_type=audio
 stream_index=0

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to