]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mux.c
Merge commit '7a76371437f9562c3414f985523f883489e3936a'
[ffmpeg] / libavformat / mux.c
index bbfc0fccb867a031f93a039dc5b28d5363771e0a..e500531789ecbcc526edb186e24e9b4c4b6665ec 100644 (file)
@@ -309,12 +309,6 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-        /* update internal context from codecpar, old bsf api needs this
-         * FIXME: remove when autobsf uses new bsf API */
-        ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
-        if (ret < 0)
-            goto fail;
-
         if (!st->time_base.num) {
             /* fall back on the default timebase values */
             if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->sample_rate)
@@ -423,10 +417,13 @@ FF_ENABLE_DEPRECATION_WARNINGS
          *options = tmp;
     }
 
-    if (s->oformat->init && (ret = s->oformat->init(s)) < 0) {
-        if (s->oformat->deinit)
-            s->oformat->deinit(s);
-        goto fail;
+    if (s->oformat->init) {
+        if ((ret = s->oformat->init(s)) < 0) {
+            if (s->oformat->deinit)
+                s->oformat->deinit(s);
+            return ret;
+        }
+        return ret == 0;
     }
 
     return 0;
@@ -493,31 +490,64 @@ static int write_header_internal(AVFormatContext *s)
     return 0;
 }
 
-int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+int avformat_init_output(AVFormatContext *s, AVDictionary **options)
 {
     int ret = 0;
 
     if ((ret = init_muxer(s, options)) < 0)
         return ret;
 
+    s->internal->initialized = 1;
+    s->internal->streams_initialized = ret;
+
+    if (s->oformat->init && ret) {
+        if ((ret = init_pts(s)) < 0)
+            return ret;
+
+        if (s->avoid_negative_ts < 0) {
+            av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
+            if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
+                s->avoid_negative_ts = 0;
+            } else
+                s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+        }
+
+        return AVSTREAM_INIT_IN_INIT_OUTPUT;
+    }
+
+    return AVSTREAM_INIT_IN_WRITE_HEADER;
+}
+
+int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+{
+    int ret = 0;
+    int already_initialized = s->internal->initialized;
+    int streams_already_initialized = s->internal->streams_initialized;
+
+    if (!already_initialized)
+        if ((ret = avformat_init_output(s, options)) < 0)
+            return ret;
+
     if (!(s->oformat->check_bitstream && s->flags & AVFMT_FLAG_AUTO_BSF)) {
         ret = write_header_internal(s);
         if (ret < 0)
             goto fail;
     }
 
-    if ((ret = init_pts(s)) < 0)
-        goto fail;
+    if (!s->internal->streams_initialized) {
+        if ((ret = init_pts(s)) < 0)
+            goto fail;
 
-    if (s->avoid_negative_ts < 0) {
-        av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
-        if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
-            s->avoid_negative_ts = 0;
-        } else
-            s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+        if (s->avoid_negative_ts < 0) {
+            av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
+            if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
+                s->avoid_negative_ts = 0;
+            } else
+                s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+        }
     }
 
-    return 0;
+    return streams_already_initialized;
 
 fail:
     if (s->oformat->deinit)
@@ -545,6 +575,7 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *
 
     if (!s->internal->missing_ts_warning &&
         !(s->oformat->flags & AVFMT_NOTIMESTAMPS) &&
+        (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC) || (st->disposition & AV_DISPOSITION_TIMED_THUMBNAILS)) &&
         (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE)) {
         av_log(s, AV_LOG_WARNING,
                "Timestamps are unset in a packet for stream %d. "
@@ -662,6 +693,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
     pts_backup = pkt->pts;
     dts_backup = pkt->dts;
 
+    // If the timestamp offsetting below is adjusted, adjust
+    // ff_interleaved_peek similarly.
     if (s->output_ts_offset) {
         AVStream *st = s->streams[pkt->stream_index];
         int64_t offset = av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base);
@@ -842,6 +875,9 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) {
         }
     }
 
+    if (st->internal->nb_bsfcs)
+        av_packet_split_side_data(pkt);
+
     for (i = 0; i < st->internal->nb_bsfcs; i++) {
         AVBSFContext *ctx = st->internal->bsfcs[i];
         if (i > 0) {
@@ -855,7 +891,7 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) {
         // flush each stream's BSF chain on write_trailer.
         if ((ret = av_bsf_send_packet(ctx, pkt)) < 0) {
             av_log(ctx, AV_LOG_ERROR,
-                    "Failed to send packet to filter %s for stream %d",
+                    "Failed to send packet to filter %s for stream %d\n",
                     ctx->filter->name, pkt->stream_index);
             return ret;
         }
@@ -866,7 +902,7 @@ static int do_packet_auto_bsf(AVFormatContext *s, AVPacket *pkt) {
             if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                 return 0;
             av_log(ctx, AV_LOG_ERROR,
-                    "Failed to send packet to filter %s for stream %d",
+                    "Failed to send packet to filter %s for stream %d\n",
                     ctx->filter->name, pkt->stream_index);
             return ret;
         }
@@ -1147,23 +1183,30 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
     }
 }
 
-const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream, int64_t *ts_offset)
+int ff_interleaved_peek(AVFormatContext *s, int stream,
+                        AVPacket *pkt, int add_offset)
 {
     AVPacketList *pktl = s->internal->packet_buffer;
     while (pktl) {
         if (pktl->pkt.stream_index == stream) {
-            AVPacket *pkt = &pktl->pkt;
-            AVStream *st = s->streams[pkt->stream_index];
-            *ts_offset = st->mux_ts_offset;
-
-            if (s->output_ts_offset)
-                *ts_offset += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base);
-
-            return pkt;
+            *pkt = pktl->pkt;
+            if (add_offset) {
+                AVStream *st = s->streams[pkt->stream_index];
+                int64_t offset = st->mux_ts_offset;
+
+                if (s->output_ts_offset)
+                    offset += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base);
+
+                if (pkt->dts != AV_NOPTS_VALUE)
+                    pkt->dts += offset;
+                if (pkt->pts != AV_NOPTS_VALUE)
+                    pkt->pts += offset;
+            }
+            return 0;
         }
         pktl = pktl->next;
     }
-    return NULL;
+    return AVERROR(ENOENT);
 }
 
 /**
@@ -1292,6 +1335,10 @@ fail:
     if (s->oformat->deinit)
         s->oformat->deinit(s);
 
+    s->internal->header_written =
+    s->internal->initialized =
+    s->internal->streams_initialized = 0;
+
     if (s->pb)
        avio_flush(s->pb);
     if (ret == 0)