Skip to content

Commit

Permalink
Get rid of deprecated ticks_per_frame.
Browse files Browse the repository at this point in the history
Breaks NVENC B-frames, but add a low latency mode which disables B-frames.
  • Loading branch information
Themaister committed Oct 15, 2023
1 parent 98f1810 commit 7ac1a10
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 10 deletions.
22 changes: 12 additions & 10 deletions video/ffmpeg_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct CodecStream
AVFrame *av_frame = nullptr;
AVCodecContext *av_ctx = nullptr;
AVPacket *av_pkt = nullptr;
int ticks_per_frame = 1;
};

struct VideoEncoder::YCbCrPipelineData
Expand Down Expand Up @@ -478,15 +479,15 @@ bool VideoEncoder::Impl::encode_frame(const uint8_t *buffer, const PlaneLayout *
if (encode_video_pts)
{
int64_t delta = std::abs(target_pts - encode_video_pts);
if (delta > 8 * video.av_ctx->ticks_per_frame)
if (delta > 8 * video.ticks_per_frame)
{
// If we're way off (8 frames), catch up instantly.
encode_video_pts = target_pts;

// Force an I-frame here since there is a large discontinuity.
video.av_frame->pict_type = AV_PICTURE_TYPE_I;
}
else if (delta >= video.av_ctx->ticks_per_frame / 4)
else if (delta >= video.ticks_per_frame / 4)
{
// If we're more than a quarter frame off, nudge the PTS by one subtick to catch up with real value.
// Nudging slowly avoids broken DTS timestamps.
Expand All @@ -503,8 +504,8 @@ bool VideoEncoder::Impl::encode_frame(const uint8_t *buffer, const PlaneLayout *
// This helps avoid DTS issues in misc hardware encoders since they treat DTS as just subtracted reordered PTS,
// or something weird like that ...
video.av_frame->pts = encode_video_pts;
video.av_frame->duration = video.av_ctx->ticks_per_frame;
encode_video_pts += video.av_ctx->ticks_per_frame;
video.av_frame->duration = video.ticks_per_frame;
encode_video_pts += video.ticks_per_frame;
}
else
video.av_frame->pts = encode_video_pts++;
Expand Down Expand Up @@ -571,7 +572,7 @@ bool VideoEncoder::Impl::drain_packets(CodecStream &stream)

if (options.realtime)
if (&stream == &video)
stream.av_pkt->duration = video.av_ctx->ticks_per_frame;
stream.av_pkt->duration = video.ticks_per_frame;

if (av_format_ctx_local)
{
Expand Down Expand Up @@ -802,17 +803,18 @@ bool VideoEncoder::Impl::init_video_codec()

video.av_ctx->framerate = { options.frame_timebase.den, options.frame_timebase.num };

if (options.low_latency)
video.av_ctx->max_b_frames = 0;

if (options.realtime)
{
video.av_ctx->ticks_per_frame = 16;
video.av_ctx->time_base = { options.frame_timebase.num, options.frame_timebase.den * video.av_ctx->ticks_per_frame };
// This seems to be important for NVENC.
// Need more fine-grained timebase to account for realtime jitter in PTS.
video.ticks_per_frame = 16;
video.av_ctx->time_base = { options.frame_timebase.num, options.frame_timebase.den * video.ticks_per_frame };
}
else
{
video.av_ctx->time_base = { options.frame_timebase.num, options.frame_timebase.den };
video.av_ctx->ticks_per_frame = 1;
video.ticks_per_frame = 1;
}

video.av_ctx->color_range = AVCOL_RANGE_MPEG;
Expand Down
1 change: 1 addition & 0 deletions video/ffmpeg_encode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class VideoEncoder
// Correlate PTS with wall time.
bool realtime = false;
const char *encoder = "libx264";
bool low_latency = false;

struct
{
Expand Down

0 comments on commit 7ac1a10

Please sign in to comment.