]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/matroskaenc.c
avformat/rtpenc_mpegts: stop leaks
[ffmpeg] / libavformat / matroskaenc.c
index 233c472b8f321da5590ade93bbc79eac6a4c1c29..bbf231f2a46900c309fa2e632c518f25a86372d8 100644 (file)
@@ -137,7 +137,7 @@ typedef struct MatroskaMuxContext {
     mkv_cues            cues;
     int64_t             cues_pos;
 
-    AVPacket            cur_audio_pkt;
+    AVPacket           *cur_audio_pkt;
 
     unsigned            nb_attachments;
     int                 have_video;
@@ -451,7 +451,7 @@ static void mkv_deinit(AVFormatContext *s)
 {
     MatroskaMuxContext *mkv = s->priv_data;
 
-    av_packet_unref(&mkv->cur_audio_pkt);
+    av_packet_free(&mkv->cur_audio_pkt);
 
     ffio_free_dyn_buf(&mkv->cluster_bc);
     ffio_free_dyn_buf(&mkv->info.bc);
@@ -1147,7 +1147,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
         put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value);
     tag = av_dict_get(st->metadata, "language", NULL, 0);
     put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE,
-                    tag && tag->value ? tag->value : "und");
+                    tag && tag->value[0] ? tag->value : "und");
 
     // The default value for TRACKFLAGDEFAULT is 1, so add element
     // if we need to clear it.
@@ -1191,6 +1191,18 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
 
         put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id);
     } else {
+        if (st->disposition & AV_DISPOSITION_COMMENT)
+            put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGCOMMENTARY, 1);
+        if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
+            put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, 1);
+        if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
+            put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGVISUALIMPAIRED,  1);
+        if (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB) &&
+            (st->disposition & (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
+                            != (AV_DISPOSITION_ORIGINAL | AV_DISPOSITION_DUB))
+            put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGORIGINAL,
+                          !!(st->disposition & AV_DISPOSITION_ORIGINAL));
+
         // look for a codec ID string specific to mkv to use,
         // if none are found, use AVI codes
         if (par->codec_id != AV_CODEC_ID_RAWVIDEO || par->codec_tag) {
@@ -1352,6 +1364,8 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
             av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id);
             return AVERROR(ENOSYS);
         }
+        if (mkv->mode != MODE_WEBM && st->disposition & AV_DISPOSITION_DESCRIPTIONS)
+            put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1);
 
         if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT)
             native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
@@ -1611,24 +1625,29 @@ static int mkv_write_tags(AVFormatContext *s)
     return 0;
 }
 
+static int mkv_new_chapter_ids_needed(const AVFormatContext *s)
+{
+    for (unsigned i = 0; i < s->nb_chapters; i++) {
+        if (!s->chapters[i]->id)
+            return 1;
+        for (unsigned j = 0; j < i; j++)
+            if (s->chapters[j]->id == s->chapters[i]->id)
+                return 1;
+    }
+    return 0;
+}
+
 static int mkv_write_chapters(AVFormatContext *s)
 {
     MatroskaMuxContext *mkv = s->priv_data;
     AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb;
     ebml_master editionentry;
-    uint64_t chapter_id_offset = 0;
     AVRational scale = {1, 1E9};
-    int i, ret;
+    int ret, create_new_ids;
 
     if (!s->nb_chapters || mkv->wrote_chapters)
         return 0;
 
-    for (i = 0; i < s->nb_chapters; i++)
-        if (!s->chapters[i]->id) {
-            chapter_id_offset = 1;
-            break;
-        }
-
     ret = start_ebml_master_crc32(&dyn_cp, mkv);
     if (ret < 0)
         return ret;
@@ -1642,12 +1661,19 @@ static int mkv_write_chapters(AVFormatContext *s)
     } else
         tags = NULL;
 
-    for (i = 0; i < s->nb_chapters; i++) {
+    create_new_ids = mkv_new_chapter_ids_needed(s);
+
+    for (unsigned i = 0; i < s->nb_chapters; i++) {
         ebml_master chapteratom, chapterdisplay;
         const AVChapter *c   = s->chapters[i];
         int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale);
         int64_t chapterend   = av_rescale_q(c->end,   c->time_base, scale);
         const AVDictionaryEntry *t;
+#if FF_API_CHAPTER_ID_INT
+        uint64_t uid = create_new_ids ? i + 1ULL : (uint32_t)c->id;
+#else
+        uint64_t uid = create_new_ids ? i + 1ULL : c->id;
+#endif
         if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) {
             av_log(s, AV_LOG_ERROR,
                    "Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
@@ -1657,8 +1683,7 @@ static int mkv_write_chapters(AVFormatContext *s)
         }
 
         chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0);
-        put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID,
-                      (uint32_t)c->id + chapter_id_offset);
+        put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, uid);
         put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
         put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
@@ -1671,8 +1696,7 @@ static int mkv_write_chapters(AVFormatContext *s)
 
         if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) {
             ret = mkv_write_tag(mkv, c->metadata, tags, NULL,
-                                MATROSKA_ID_TAGTARGETS_CHAPTERUID,
-                                (uint32_t)c->id + chapter_id_offset);
+                                MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid);
             if (ret < 0)
                 goto fail;
         }
@@ -1919,8 +1943,6 @@ static int mkv_write_header(AVFormatContext *s)
             mkv->reserve_cues_space = -1;
     }
 
-    av_init_packet(&mkv->cur_audio_pkt);
-    mkv->cur_audio_pkt.size = 0;
     mkv->cluster_pos = -1;
 
     // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
@@ -2009,7 +2031,8 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
     mkv_track *track = &mkv->tracks[pkt->stream_index];
     uint8_t *data = NULL, *side_data = NULL;
-    int err = 0, offset = 0, size = pkt->size, side_data_size;
+    buffer_size_t side_data_size;
+    int err = 0, offset = 0, size = pkt->size;
     int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
     uint64_t additional_id;
     int64_t discard_padding = 0;
@@ -2119,7 +2142,8 @@ static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, const AVPac
     MatroskaMuxContext *mkv = s->priv_data;
     mkv_track *track = &mkv->tracks[pkt->stream_index];
     ebml_master blockgroup;
-    int id_size, settings_size, size;
+    buffer_size_t id_size, settings_size;
+    int size;
     const char *id, *settings;
     int64_t ts = track->write_dts ? pkt->dts : pkt->pts;
     const int flags = 0;
@@ -2184,7 +2208,8 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt)
     mkv_track *track        = &mkv->tracks[pkt->stream_index];
     AVCodecParameters *par  = s->streams[pkt->stream_index]->codecpar;
     uint8_t *side_data;
-    int side_data_size, ret;
+    buffer_size_t side_data_size;
+    int ret;
 
     side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
                                         &side_data_size);
@@ -2414,9 +2439,9 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt)
                           keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
 
     // check if we have an audio packet cached
-    if (mkv->cur_audio_pkt.size > 0) {
-        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
-        av_packet_unref(&mkv->cur_audio_pkt);
+    if (mkv->cur_audio_pkt->size > 0) {
+        ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
+        av_packet_unref(mkv->cur_audio_pkt);
         if (ret < 0) {
             av_log(s, AV_LOG_ERROR,
                    "Could not write cached audio packet ret:%d\n", ret);
@@ -2428,7 +2453,7 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt)
     // keyframe's timecode is contained in the same cluster for WebM
     if (codec_type == AVMEDIA_TYPE_AUDIO) {
         if (pkt->size > 0)
-            ret = av_packet_ref(&mkv->cur_audio_pkt, pkt);
+            ret = av_packet_ref(mkv->cur_audio_pkt, pkt);
     } else
         ret = mkv_write_packet_internal(s, pkt);
     return ret;
@@ -2460,8 +2485,8 @@ static int mkv_write_trailer(AVFormatContext *s)
     int ret, ret2 = 0;
 
     // check if we have an audio packet cached
-    if (mkv->cur_audio_pkt.size > 0) {
-        ret = mkv_write_packet_internal(s, &mkv->cur_audio_pkt);
+    if (mkv->cur_audio_pkt->size > 0) {
+        ret = mkv_write_packet_internal(s, mkv->cur_audio_pkt);
         if (ret < 0) {
             av_log(s, AV_LOG_ERROR,
                    "Could not write cached audio packet ret:%d\n", ret);
@@ -2685,6 +2710,9 @@ static int mkv_init(struct AVFormatContext *s)
     } else
         mkv->mode = MODE_MATROSKAv2;
 
+    mkv->cur_audio_pkt = av_packet_alloc();
+    if (!mkv->cur_audio_pkt)
+        return AVERROR(ENOMEM);
     mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
     if (!mkv->tracks)
         return AVERROR(ENOMEM);