[Bf-blender-cvs] [14308b0a5ef] blender-v2.93-release: Make encoded video fps correct with ffmpeg < 4.4

Sebastian Parborg noreply at git.blender.org
Wed Jun 30 09:47:15 CEST 2021


Commit: 14308b0a5ef019c0997034ee4a4953c55fa1ca06
Author: Sebastian Parborg
Date:   Fri May 28 18:37:36 2021 +0200
Branches: blender-v2.93-release
https://developer.blender.org/rB14308b0a5ef019c0997034ee4a4953c55fa1ca06

Make encoded video fps correct with ffmpeg < 4.4

Before the FFmpeg commit: github.com/FFmpeg/FFmpeg/commit/1c0885334dda9ee8652e60c586fa2e3674056586
FFmpeg would use deprecated variables to calculate the video fps.

We don't use these deprecated variables anymore, so ensure that the
duration is correct in ffmpeg versions without this fix.

Reviewed By: Sergey, Richard Antalik

Differential Revision: http://developer.blender.org/D11417

===================================================================

M	intern/ffmpeg/ffmpeg_compat.h
M	source/blender/blenkernel/intern/writeffmpeg.c
M	source/blender/imbuf/intern/indexer.c

===================================================================

diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h
index 1b1e2fad594..3f168894cd9 100644
--- a/intern/ffmpeg/ffmpeg_compat.h
+++ b/intern/ffmpeg/ffmpeg_compat.h
@@ -43,6 +43,55 @@
 #  define FFMPEG_INLINE static inline
 #endif
 
+#if (LIBAVFORMAT_VERSION_MAJOR < 58) || \
+    ((LIBAVFORMAT_VERSION_MAJOR == 58) && (LIBAVFORMAT_VERSION_MINOR < 76))
+#  define FFMPEG_USE_DURATION_WORKAROUND 1
+
+/* Before ffmpeg 4.4, package duration calculation used depricated variables to calculate the
+ * packet duration. Use the function from commit
+ * github.com/FFmpeg/FFmpeg/commit/1c0885334dda9ee8652e60c586fa2e3674056586
+ * to calculate the correct framerate for ffmpeg < 4.4.
+ */
+
+FFMPEG_INLINE
+void my_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;
+    }
+    default:
+      break;
+  }
+}
+#endif
+
 FFMPEG_INLINE
 void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
 {
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 5d03278f3c1..3960a48e01f 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -205,12 +205,11 @@ static int write_audio_frame(FFMpegContext *context)
       success = -1;
     }
 
-    av_packet_rescale_ts(pkt, c->time_base, context->audio_stream->time_base);
-    if (pkt->duration > 0) {
-      pkt->duration = av_rescale_q(pkt->duration, c->time_base, context->audio_stream->time_base);
-    }
-
     pkt->stream_index = context->audio_stream->index;
+    av_packet_rescale_ts(pkt, c->time_base, context->audio_stream->time_base);
+#    ifdef FFMPEG_USE_DURATION_WORKAROUND
+    my_guess_pkt_duration(context->outfile, context->audio_stream, pkt);
+#    endif
 
     pkt->flags |= AV_PKT_FLAG_KEY;
 
@@ -349,6 +348,10 @@ static int write_video_frame(FFMpegContext *context, int cfra, AVFrame *frame, R
 
     packet->stream_index = context->video_stream->index;
     av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base);
+#  ifdef FFMPEG_USE_DURATION_WORKAROUND
+    my_guess_pkt_duration(context->outfile, context->video_stream, packet);
+#  endif
+
     if (av_interleaved_write_frame(context->outfile, packet) != 0) {
       success = -1;
       break;
@@ -1181,6 +1184,9 @@ static void flush_ffmpeg(FFMpegContext *context)
 
     packet->stream_index = context->video_stream->index;
     av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base);
+#  ifdef FFMPEG_USE_DURATION_WORKAROUND
+    my_guess_pkt_duration(context->outfile, context->video_stream, packet);
+#  endif
 
     int write_ret = av_interleaved_write_frame(context->outfile, packet);
     if (write_ret != 0) {
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 26f332bd575..453df6078ce 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -683,6 +683,9 @@ static void add_to_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, AVFrame *fr
 
     packet->stream_index = ctx->st->index;
     av_packet_rescale_ts(packet, ctx->c->time_base, ctx->st->time_base);
+#  ifdef FFMPEG_USE_DURATION_WORKAROUND
+    my_guess_pkt_duration(ctx->of, ctx->st, packet);
+#  endif
 
     int write_ret = av_interleaved_write_frame(ctx->of, packet);
     if (write_ret != 0) {



More information about the Bf-blender-cvs mailing list