fftools/ffmpeg: rework -enc_time_base handling

Read the timebase from FrameData rather than the input stream. This
should fix #10393 and generally be more reliable.

Replace the use of '-1' to indicate demuxing timebase with the string
'demux'. Also allow to request filter timebase with
'-enc_time_base filter'.
This commit is contained in:
Anton Khirnov 2023-07-07 11:31:53 +02:00
parent 4d06742b93
commit dff3a283cd
5 changed files with 44 additions and 18 deletions

View File

@ -1812,10 +1812,11 @@ Assign a default value according to the media type.
For video - use 1/framerate, for audio - use 1/samplerate.
@item -1
Use the input stream timebase when possible.
@item demux
Use the timebase from the demuxer.
If an input stream is not available, the default timebase will be used.
@item filter
Use the timebase from the filtergraph.
@item >0
Use the provided number as the timebase.

View File

@ -56,6 +56,7 @@
#define FFMPEG_ROTATION_METADATA 1
#define FFMPEG_OPT_QPHIST 1
#define FFMPEG_OPT_ADRIFT_THRESHOLD 1
#define FFMPEG_OPT_ENC_TIME_BASE_NUM 1
enum VideoSyncMethod {
VSYNC_AUTO = -1,
@ -66,6 +67,11 @@ enum VideoSyncMethod {
VSYNC_DROP,
};
enum EncTimeBase {
ENC_TIME_BASE_DEMUX = -1,
ENC_TIME_BASE_FILTER = -2,
};
#define MAX_STREAMS 1024 /* arbitrary sanity check value */
enum HWAccelID {

View File

@ -264,8 +264,20 @@ int enc_open(OutputStream *ost, AVFrame *frame)
fr.num, fr.den, 65535);
}
enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase :
av_inv_q(fr);
if (ost->enc_timebase.num == ENC_TIME_BASE_DEMUX) {
if (fd->dec.tb.num <= 0 || fd->dec.tb.den <= 0) {
av_log(ost, AV_LOG_ERROR,
"Demuxing timebase not available - cannot use it for encoding\n");
return AVERROR(EINVAL);
}
enc_ctx->time_base = fd->dec.tb;
} else if (ost->enc_timebase.num == ENC_TIME_BASE_FILTER) {
enc_ctx->time_base = frame->time_base;
} else {
enc_ctx->time_base = ost->enc_timebase.num > 0 ? ost->enc_timebase :
av_inv_q(fr);
}
if (!(enc_ctx->time_base.num && enc_ctx->time_base.den))
enc_ctx->time_base = frame->time_base;

View File

@ -1171,20 +1171,27 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
MATCH_PER_STREAM_OPT(enc_time_bases, str, enc_time_base, oc, st);
if (enc_time_base) {
AVRational q;
if (av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL) < 0 ||
q.den <= 0) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base);
return AVERROR(EINVAL);
}
if (q.num < 0) {
if (!ost->ist) {
av_log(ost, AV_LOG_FATAL,
"Cannot use input stream timebase for encoding - "
"no input stream available\n");
return AVERROR(EINVAL);
if (!strcmp(enc_time_base, "demux")) {
q = (AVRational){ ENC_TIME_BASE_DEMUX, 0 };
} else if (!strcmp(enc_time_base, "filter")) {
q = (AVRational){ ENC_TIME_BASE_FILTER, 0 };
} else {
ret = av_parse_ratio(&q, enc_time_base, INT_MAX, 0, NULL);
if (ret < 0 || q.den <= 0
#if !FFMPEG_OPT_ENC_TIME_BASE_NUM
|| q.num < 0
#endif
) {
av_log(ost, AV_LOG_FATAL, "Invalid time base: %s\n", enc_time_base);
return ret < 0 ? ret : AVERROR(EINVAL);
}
q = ost->ist->st->time_base;
#if FFMPEG_OPT_ENC_TIME_BASE_NUM
if (q.num < 0)
av_log(ost, AV_LOG_WARNING, "-enc_time_base -1 is deprecated,"
" use -enc_timebase demux\n");
#endif
}
ost->enc_timebase = q;
}
} else {

View File

@ -270,7 +270,7 @@ FATE_VIDEO-$(call FRAMECRC, MXG, MXPEG) += fate-mxpeg
fate-mxpeg: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mxpeg/m1.mxg -an
FATE_NUV += fate-nuv-rtjpeg
fate-nuv-rtjpeg: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/Today.nuv -an -enc_time_base -1
fate-nuv-rtjpeg: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/Today.nuv -an -enc_time_base demux
FATE_NUV += fate-nuv-rtjpeg-fh
fate-nuv-rtjpeg-fh: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/rtjpeg_frameheader.nuv -an