[FFmpeg-devel] [PATCH] avformat/matroskaenc: Ignore attachments for track limit

Andreas Rheinhardt andreas.rheinhardt at gmail.com
Tue Nov 26 13:28:57 EET 2019


Attachments are streams in FFmpeg, but they are not tracks in Matroska.
Yet they were counted when checking a limit for the number of tracks that
the Matroska muxer imposes. This is unnecessary and has been changed.

(The Matroska file format actually has practically no limit on the
number of tracks and this is purely what our muxer supports. But even if
this limit were removed/relaxed in the future, it still makes sense to
use small track numbers as this patch does, because greater numbers need
more bytes to encode.)

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
---
I forgot to update the av_log call in mkv_write_vtt_block.

 libavformat/matroskaenc.c | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index be98832a13..43ee9c8a92 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -95,6 +95,7 @@ typedef struct mkv_cues {
 typedef struct mkv_track {
     int             write_dts;
     int             has_cue;
+    int             track_num;
     uint32_t        uid;
     int             sample_rate;
     int64_t         sample_rate_offset;
@@ -1138,8 +1139,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
     }
 
     track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
-    put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER,
-                   mkv->is_dash ? mkv->dash_track_number : i + 1);
+    put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER, mkv->tracks[i].track_num);
     put_ebml_uint (pb, MATROSKA_ID_TRACKUID, mkv->tracks[i].uid);
     put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0);    // no lacing (yet)
 
@@ -1989,7 +1989,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
     uint64_t additional_id = 0;
     int64_t discard_padding = 0;
-    uint8_t track_number = (mkv->is_dash ? mkv->dash_track_number : (pkt->stream_index + 1));
+    int track_number = track->track_num;
     ebml_master block_group, block_additions, block_more;
 
     ts += track->ts_offset;
@@ -2088,6 +2088,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
 static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
 {
     MatroskaMuxContext *mkv = s->priv_data;
+    mkv_track *track = &mkv->tracks[pkt->stream_index];
     ebml_master blockgroup;
     int id_size, settings_size, size;
     uint8_t *id, *settings;
@@ -2111,13 +2112,13 @@ static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *p
            "duration %" PRId64 " at relative offset %" PRId64 " in cluster "
            "at offset %" PRId64 ". TrackNumber %d, keyframe %d\n",
            size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb),
-           mkv->cluster_pos, pkt->stream_index + 1, 1);
+           mkv->cluster_pos, track->track_num, 1);
 
     blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size));
 
     put_ebml_id(pb, MATROSKA_ID_BLOCK);
     put_ebml_num(pb, size + 4, 0);
-    avio_w8(pb, 0x80 | (pkt->stream_index + 1));     // this assumes stream_index is less than 126
+    avio_w8(pb, 0x80 | track->track_num);     // this assumes track_num is less than 126
     avio_wb16(pb, ts - mkv->cluster_pts);
     avio_w8(pb, flags);
     avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size, id, settings_size, settings, pkt->size, pkt->data);
@@ -2256,7 +2257,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
     int ret;
     int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
     int64_t relative_packet_pos;
-    int tracknum = mkv->is_dash ? mkv->dash_track_number : pkt->stream_index + 1;
+    int tracknum = track->track_num;
 
     if (ts == AV_NOPTS_VALUE) {
         av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n");
@@ -2592,14 +2593,7 @@ static int mkv_init(struct AVFormatContext *s)
 {
     MatroskaMuxContext *mkv = s->priv_data;
     AVLFG c;
-    int i;
-
-    if (s->nb_streams > MAX_TRACKS) {
-        av_log(s, AV_LOG_ERROR,
-               "At most %d streams are supported for muxing in Matroska\n",
-               MAX_TRACKS);
-        return AVERROR(EINVAL);
-    }
+    int i, nb_tracks = 0;
 
     for (i = 0; i < s->nb_streams; i++) {
         if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||
@@ -2634,6 +2628,7 @@ static int mkv_init(struct AVFormatContext *s)
     }
 
     for (i = 0; i < s->nb_streams; i++) {
+        AVStream     *st = s->streams[i];
         mkv_track *track = &mkv->tracks[i];
 
         if (s->flags & AVFMT_FLAG_BITEXACT) {
@@ -2644,6 +2639,19 @@ static int mkv_init(struct AVFormatContext *s)
 
         // ms precision is the de-facto standard timescale for mkv files
         avpriv_set_pts_info(s->streams[i], 64, 1, 1000);
+
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
+            continue;
+
+        nb_tracks++;
+        track->track_num = mkv->is_dash ? mkv->dash_track_number : nb_tracks;
+    }
+
+    if (nb_tracks > MAX_TRACKS) {
+        av_log(s, AV_LOG_ERROR,
+               "%d > "AV_STRINGIFY(MAX_TRACKS)" tracks (excluding attachments)"
+               " not supported for muxing in Matroska\n", nb_tracks);
+        return AVERROR(EINVAL);
     }
 
     return 0;
-- 
2.20.1



More information about the ffmpeg-devel mailing list