lavf: deprecate compute_pkt_fields2
authorAnton Khirnov <anton@khirnov.net>
Wed, 7 Oct 2015 13:51:11 +0000 (15:51 +0200)
committerAnton Khirnov <anton@khirnov.net>
Mon, 9 Nov 2015 06:50:55 +0000 (07:50 +0100)
All encoders set pts and dts properly now (and have been doing that for
a while), so there is no good reason to do any timestamp guessing in the
muxer.

The newly added AVStreamInternal will be later used for storing all the
private fields currently living in AVStream.

libavformat/avformat.h
libavformat/internal.h
libavformat/mux.c
libavformat/utils.c
libavformat/version.h

index 470bbc6..e441486 100644 (file)
@@ -688,6 +688,8 @@ typedef struct AVIndexEntry {
  */
 #define AV_DISPOSITION_ATTACHED_PIC      0x0400
 
+typedef struct AVStreamInternal AVStreamInternal;
+
 /**
  * Stream structure.
  * New fields can be added to the end with minor version bumps.
@@ -878,6 +880,12 @@ typedef struct AVStream {
                                     support seeking natively. */
     int nb_index_entries;
     unsigned int index_entries_allocated_size;
+
+    /**
+     * An opaque field for libavformat internal usage.
+     * Must not be accessed in any way by callers.
+     */
+    AVStreamInternal *internal;
 } AVStream;
 
 #define AV_PROGRAM_RUNNING 1
index a65a3b7..7bbf775 100644 (file)
@@ -90,6 +90,18 @@ struct AVFormatInternal {
      * Timebase for the timestamp offset.
      */
     AVRational offset_timebase;
+
+#if FF_API_COMPUTE_PKT_FIELDS2
+    int missing_ts_warning;
+#endif
+};
+
+struct AVStreamInternal {
+    /**
+     * Set to 1 if the codec allows reordering, so pts can be different
+     * from dts.
+     */
+    int reorder;
 };
 
 void ff_dynarray_add(intptr_t **tab_ptr, int *nb_ptr, intptr_t elem);
index 4a81e36..7a51578 100644 (file)
@@ -92,6 +92,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
     AVDictionary *tmp = NULL;
     AVCodecContext *codec = NULL;
     AVOutputFormat *of = s->oformat;
+    const AVCodecDescriptor *desc;
 
     if (options)
         av_dict_copy(&tmp, *options, 0);
@@ -171,6 +172,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
             break;
         }
 
+        desc = avcodec_descriptor_get(codec->codec_id);
+        if (desc && desc->props & AV_CODEC_PROP_REORDER)
+            st->internal->reorder = 1;
+
         if (of->codec_tag) {
             if (codec->codec_tag &&
                 codec->codec_id == AV_CODEC_ID_RAWVIDEO &&
@@ -258,12 +263,23 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
     return 0;
 }
 
+#if FF_API_COMPUTE_PKT_FIELDS2
 //FIXME merge with compute_pkt_fields
 static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 {
     int delay = FFMAX(st->codec->has_b_frames, !!st->codec->max_b_frames);
     int num, den, i;
 
+    if (!s->internal->missing_ts_warning &&
+        !(s->oformat->flags & AVFMT_NOTIMESTAMPS) &&
+        (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. "
+               "This is deprecated and will stop working in the future. "
+               "Fix your code to set the timestamps properly\n", st->index);
+        s->internal->missing_ts_warning = 1;
+    }
+
     av_log(s, AV_LOG_TRACE, "compute_pkt_fields2: pts:%" PRId64 " dts:%" PRId64 " cur_dts:%" PRId64 " b:%d size:%d st:%d\n",
             pkt->pts, pkt->dts, st->cur_dts, delay, pkt->size, pkt->stream_index);
 
@@ -314,6 +330,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 
     return 0;
 }
+#endif
 
 /*
  * FIXME: this function should NEVER get undefined pts/dts beside when the
@@ -381,7 +398,7 @@ static int check_packet(AVFormatContext *s, AVPacket *pkt)
     return 0;
 }
 
-int av_write_frame(AVFormatContext *s, AVPacket *pkt)
+static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int ret;
 
@@ -389,16 +406,70 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
     if (ret < 0)
         return ret;
 
+#if !FF_API_COMPUTE_PKT_FIELDS2
+    /* sanitize the timestamps */
+    if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
+        AVStream *st = s->streams[pkt->stream_index];
+
+        /* when there is no reordering (so dts is equal to pts), but
+         * only one of them is set, set the other as well */
+        if (!st->internal->reorder) {
+            if (pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE)
+                pkt->pts = pkt->dts;
+            if (pkt->dts == AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE)
+                pkt->dts = pkt->pts;
+        }
+
+        /* check that the timestamps are set */
+        if (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE) {
+            av_log(s, AV_LOG_ERROR,
+                   "Timestamps are unset in a packet for stream %d\n", st->index);
+            return AVERROR(EINVAL);
+        }
+
+        /* check that the dts are increasing (or at least non-decreasing,
+         * if the format allows it */
+        if (st->cur_dts != AV_NOPTS_VALUE &&
+            ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) && st->cur_dts >= pkt->dts) ||
+             st->cur_dts > pkt->dts)) {
+            av_log(s, AV_LOG_ERROR,
+                   "Application provided invalid, non monotonically increasing "
+                   "dts to muxer in stream %d: %" PRId64 " >= %" PRId64 "\n",
+                   st->index, st->cur_dts, pkt->dts);
+            return AVERROR(EINVAL);
+        }
+
+        if (pkt->pts < pkt->dts) {
+            av_log(s, AV_LOG_ERROR, "pts %" PRId64 " < dts %" PRId64 " in stream %d\n",
+                   pkt->pts, pkt->dts, st->index);
+            return AVERROR(EINVAL);
+        }
+    }
+#endif
+
+    return 0;
+}
+
+int av_write_frame(AVFormatContext *s, AVPacket *pkt)
+{
+    int ret;
+
+    ret = prepare_input_packet(s, pkt);
+    if (ret < 0)
+        return ret;
+
     if (!pkt) {
         if (s->oformat->flags & AVFMT_ALLOW_FLUSH)
             return s->oformat->write_packet(s, pkt);
         return 1;
     }
 
+#if FF_API_COMPUTE_PKT_FIELDS2
     ret = compute_pkt_fields2(s, s->streams[pkt->stream_index], pkt);
 
     if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
         return ret;
+#endif
 
     ret = write_packet(s, pkt);
 
@@ -552,7 +623,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
 {
     int ret, flush = 0;
 
-    ret = check_packet(s, pkt);
+    ret = prepare_input_packet(s, pkt);
     if (ret < 0)
         goto fail;
 
@@ -561,8 +632,10 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
 
         av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame size:%d dts:%" PRId64 " pts:%" PRId64 "\n",
                 pkt->size, pkt->dts, pkt->pts);
+#if FF_API_COMPUTE_PKT_FIELDS2
         if ((ret = compute_pkt_fields2(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
             goto fail;
+#endif
 
         if (pkt->dts == AV_NOPTS_VALUE && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
             ret = AVERROR(EINVAL);
index 734f83f..bb17b4a 100644 (file)
@@ -2460,6 +2460,8 @@ static void free_stream(AVStream **pst)
     if (st->attached_pic.data)
         av_packet_unref(&st->attached_pic);
 
+    av_freep(&st->internal);
+
     av_dict_free(&st->metadata);
     av_freep(&st->probe_data.buf);
     av_free(st->index_entries);
@@ -2551,6 +2553,11 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
         av_free(st);
         return NULL;
     }
+
+    st->internal = av_mallocz(sizeof(*st->internal));
+    if (!st->internal)
+        goto fail;
+
     if (s->iformat) {
         /* no default bitrate if decoding */
         st->codec->bit_rate = 0;
@@ -2583,6 +2590,9 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
 
     s->streams[s->nb_streams++] = st;
     return st;
+fail:
+    free_stream(&st);
+    return NULL;
 }
 
 AVProgram *av_new_program(AVFormatContext *ac, int id)
index d74968a..d004a55 100644 (file)
@@ -60,5 +60,8 @@
 #ifndef FF_API_LAVF_FMT_RAWPICTURE
 #define FF_API_LAVF_FMT_RAWPICTURE      (LIBAVFORMAT_VERSION_MAJOR < 58)
 #endif
+#ifndef FF_API_COMPUTE_PKT_FIELDS2
+#define FF_API_COMPUTE_PKT_FIELDS2      (LIBAVFORMAT_VERSION_MAJOR < 58)
+#endif
 
 #endif /* AVFORMAT_VERSION_H */