]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mux.c
lavf/mux: rewrite guessing the packet duration
[ffmpeg] / libavformat / mux.c
index d2a56d216b93d2863a1db071382395042e0daab8..84c56ac6bab8a6d34b0c253a6b580a7f9fb2819f 100644 (file)
@@ -546,7 +546,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
 static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 {
     int delay = FFMAX(st->codecpar->video_delay, st->internal->avctx->max_b_frames > 0);
-    int num, den, i;
+    int i;
     int frame_size;
 
     if (!s->internal->missing_ts_warning &&
@@ -564,20 +564,6 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *
         av_log(s, AV_LOG_DEBUG, "compute_muxer_pkt_fields: pts:%s dts:%s cur_dts:%s b:%d size:%d st:%d\n",
             av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts), delay, pkt->size, pkt->stream_index);
 
-    if (pkt->duration < 0 && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
-        av_log(s, AV_LOG_WARNING, "Packet with invalid duration %"PRId64" in stream %d\n",
-               pkt->duration, pkt->stream_index);
-        pkt->duration = 0;
-    }
-
-    /* duration field */
-    if (pkt->duration == 0) {
-        ff_compute_frame_duration(s, &num, &den, st, NULL, pkt);
-        if (den && num) {
-            pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den * st->codec->ticks_per_frame, den * (int64_t)st->time_base.num);
-        }
-    }
-
     if (pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && delay == 0)
         pkt->pts = pkt->dts;
 
@@ -652,6 +638,37 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
+static void guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
+{
+    if (pkt->duration < 0 && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
+        av_log(s, AV_LOG_WARNING, "Packet with invalid duration %"PRId64" in stream %d\n",
+               pkt->duration, pkt->stream_index);
+        pkt->duration = 0;
+    }
+
+    if (pkt->duration)
+        return;
+
+    switch (st->codecpar->codec_type) {
+    case AVMEDIA_TYPE_VIDEO:
+        if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0) {
+            pkt->duration = av_rescale_q(1, av_inv_q(st->avg_frame_rate),
+                                         st->time_base);
+        } else if (st->time_base.num * 1000LL > st->time_base.den)
+            pkt->duration = 1;
+        break;
+    case AVMEDIA_TYPE_AUDIO: {
+        int frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size);
+        if (frame_size && st->codecpar->sample_rate) {
+            pkt->duration = av_rescale_q(frame_size,
+                                         (AVRational){1, st->codecpar->sample_rate},
+                                         st->time_base);
+        }
+        break;
+        }
+    }
+}
+
 /**
  * Shift timestamps and call muxer; the original pts/dts are not kept.
  *
@@ -1118,6 +1135,8 @@ static int write_packet_common(AVFormatContext *s, AVStream *st, AVPacket *pkt,
         av_log(s, AV_LOG_DEBUG, "%s size:%d dts:%s pts:%s\n", __FUNCTION__,
                pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts));
 
+    guess_pkt_duration(s, st, pkt);
+
 #if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX
     if ((ret = compute_muxer_pkt_fields(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
         return ret;