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
This commit is contained in:
Sebastian Parborg 2021-05-28 18:37:36 +02:00 committed by Jeroen Bakker
parent fe4cbe62df
commit 14308b0a5e
Notes: blender-bot 2023-02-14 09:36:46 +01:00
Referenced by issue #88449, Blender LTS: Maintenance Task 2.93
3 changed files with 63 additions and 5 deletions

View File

@ -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)
{

View File

@ -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) {

View File

@ -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) {