From b5fe8ba0fc88121496207c492c2a693c5906469a Mon Sep 17 00:00:00 2001 From: Keukhan Date: Tue, 10 Dec 2024 00:43:24 +0900 Subject: [PATCH] Added lookahead encoding option --- src/projects/base/info/video_track.cpp | 13 ++++++++++++- src/projects/base/info/video_track.h | 7 +++++++ .../output_profiles/encodes/video_profile.h | 4 ++++ .../transcoder/codec/decoder/decoder_avc_qsv.cpp | 6 ++++++ .../codec/encoder/encoder_avc_nilogan.cpp | 6 ++++++ .../transcoder/codec/encoder/encoder_avc_nv.cpp | 6 ++++++ .../codec/encoder/encoder_avc_openh264.cpp | 6 ++++++ .../transcoder/codec/encoder/encoder_avc_qsv.cpp | 6 ++++++ .../transcoder/codec/encoder/encoder_avc_x264.cpp | 6 ++++++ .../transcoder/codec/encoder/encoder_avc_xma.cpp | 7 +++++++ .../codec/encoder/encoder_hevc_nilogan.cpp | 6 ++++++ .../transcoder/codec/encoder/encoder_hevc_nv.cpp | 6 ++++++ .../transcoder/codec/encoder/encoder_hevc_xma.cpp | 7 +++++++ .../transcoder/transcoder_stream_internal.cpp | 6 ++++++ 14 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/projects/base/info/video_track.cpp b/src/projects/base/info/video_track.cpp index 6aa1dce81..b1fc38672 100644 --- a/src/projects/base/info/video_track.cpp +++ b/src/projects/base/info/video_track.cpp @@ -22,7 +22,8 @@ VideoTrack::VideoTrack() _has_bframe(false), _preset(""), _thread_count(0), - _skip_frames_conf(-1) // Default value is -1 + _skip_frames_conf(-1), // Default value is -1 + _lookahead_conf(-1) { } @@ -270,3 +271,13 @@ void VideoTrack::SetKeyframeDecodeOnly(bool keyframe_decode_only) { _keyframe_decode_only = keyframe_decode_only; } + +void VideoTrack::SetLookaheadByConfig(int32_t lookahead) +{ + _lookahead_conf = lookahead; +} + +int32_t VideoTrack::GetLookaheadByConfig() const +{ + return _lookahead_conf; +} \ No newline at end of file diff --git a/src/projects/base/info/video_track.h b/src/projects/base/info/video_track.h index 26d30965c..cc4723264 100644 --- a/src/projects/base/info/video_track.h +++ b/src/projects/base/info/video_track.h @@ -94,6 +94,9 @@ class VideoTrack bool IsKeyframeDecodeOnly() const; void SetKeyframeDecodeOnly(bool keyframe_decode_only); + void SetLookaheadByConfig(int32_t lookahead); + int32_t GetLookaheadByConfig() const; + protected: // framerate (measurement) @@ -156,4 +159,8 @@ class VideoTrack // @decoder // Keyframe Decode Only (set by user) bool _keyframe_decode_only = false; + + // @encoder + // Lookahead (set by user) + int32_t _lookahead_conf = -1; }; diff --git a/src/projects/config/items/virtual_hosts/applications/output_profiles/encodes/video_profile.h b/src/projects/config/items/virtual_hosts/applications/output_profiles/encodes/video_profile.h index 9c9041b3e..c4b43c8ed 100644 --- a/src/projects/config/items/virtual_hosts/applications/output_profiles/encodes/video_profile.h +++ b/src/projects/config/items/virtual_hosts/applications/output_profiles/encodes/video_profile.h @@ -38,6 +38,7 @@ namespace cfg int _b_frames = 0; BypassIfMatch _bypass_if_match; ov::String _profile; + int _lookahead = -1; // SkipFrames // If the set value is greater than or equal to 0, the skip frame is automatically calculated. @@ -64,6 +65,7 @@ namespace cfg CFG_DECLARE_CONST_REF_GETTER_OF(GetBypassIfMatch, _bypass_if_match) CFG_DECLARE_CONST_REF_GETTER_OF(GetProfile, _profile) CFG_DECLARE_CONST_REF_GETTER_OF(GetSkipFrames, _skip_frames) + CFG_DECLARE_CONST_REF_GETTER_OF(GetLookahead, _lookahead) void SetName(const ov::String &name){_name = name;} void SetBypass(bool bypass){_bypass = bypass;} @@ -77,6 +79,7 @@ namespace cfg void SetThreadCount(int thread_count){_thread_count = thread_count;} void SetKeyFrameInterval(int key_frame_interval){_key_frame_interval = key_frame_interval;} void SetBFrames(int b_frames){_b_frames = b_frames;} + void SetLookahead(int lookahead){_lookahead = lookahead;} protected: void MakeList() override @@ -166,6 +169,7 @@ namespace cfg } return CreateConfigErrorPtr("Profile must be baseline, main or high"); }); + Register("Lookahead", &_lookahead); } }; diff --git a/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp b/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp index 9c712382d..f84bf5b68 100644 --- a/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp +++ b/src/projects/transcoder/codec/decoder/decoder_avc_qsv.cpp @@ -32,6 +32,12 @@ bool DecoderAVCxQSV::InitCodec() ::av_opt_set(_context->priv_data, "gpu_copy", "on", 0); + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + logtw("Lookahead is not supported in QSV."); + } + if (::avcodec_open2(_context, _codec, nullptr) < 0) { logte("Could not open codec: %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp index aaac8f1af..c9673929f 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_nilogan.cpp @@ -59,6 +59,12 @@ bool EncoderAVCxNILOGAN::SetCodecParams() // Bframes _codec_context->max_b_frames = GetRefTrack()->GetBFrames(); + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "rc-lookahead", GetRefTrack()->GetLookaheadByConfig(), 0); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile.IsEmpty() == true) diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp index f3ab0ad50..7e3a5fb4a 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_nv.cpp @@ -42,6 +42,12 @@ bool EncoderAVCxNV::SetCodecParams() // Bframes _codec_context->max_b_frames = GetRefTrack()->GetBFrames(); + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "rc-lookahead", GetRefTrack()->GetLookaheadByConfig(), 0); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile.IsEmpty() == true) diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp index 876b4d9eb..34324c24f 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_openh264.cpp @@ -48,6 +48,12 @@ bool EncoderAVCxOpenH264::SetCodecParams() // 'Warning:bEnableFrameSkip = 0,bitrate can't be controlled for RC_QUALITY_MODE,RC_BITRATE_MODE and RC_TIMESTAMP_MODE without enabling skip frame' ::av_opt_set(_codec_context->priv_data, "allow_skip_frames", "false", 0); + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + logtw("Lookahead is not supported in OpenH264."); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile.IsEmpty() == true) diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp index 878a3c770..28aa89411 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_qsv.cpp @@ -43,6 +43,12 @@ bool EncoderAVCxQSV::SetCodecParams() // Bframes _codec_context->max_b_frames = GetRefTrack()->GetBFrames(); + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + logtw("Lookahead is not supported in QSV."); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile.IsEmpty() == true) diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp index 2ea9f7ed2..a87aebe99 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp @@ -54,6 +54,12 @@ bool EncoderAVCx264::SetCodecParams() // >1 => Set _codec_context->thread_count = GetRefTrack()->GetThreadCount() < 0 ? FFMIN(FFMAX(4, av_cpu_count() / 3), 8) : GetRefTrack()->GetThreadCount(); + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "rc-lookahead", GetRefTrack()->GetLookaheadByConfig(), 0); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile.IsEmpty() == true) diff --git a/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp b/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp index 498040377..03b771a06 100644 --- a/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_avc_xma.cpp @@ -45,6 +45,13 @@ bool EncoderAVCxXMA::SetCodecParams() // Bframes ::av_opt_set_int(_codec_context->priv_data, "bf", GetRefTrack()->GetBFrames(), 0); + // Lookahead (1 ~ 30) + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "lookahead_depth", GetRefTrack()->GetLookaheadByConfig(), 0); + // ::av_opt_set(_codec_context->priv_data, "expert-options", "lookahead-rc-off=0", 0); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile == "baseline" || profile.IsEmpty() == true) diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp index 2cff1a0a8..651117400 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_nilogan.cpp @@ -39,6 +39,12 @@ bool EncoderHEVCxNILOGAN::SetCodecParams() _codec_context->gop_size = (GetRefTrack()->GetKeyFrameInterval() == 0) ? (_codec_context->framerate.num / _codec_context->framerate.den) : GetRefTrack()->GetKeyFrameInterval(); } + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "rc-lookahead", GetRefTrack()->GetLookaheadByConfig(), 0); + } + //disable b-frames /* 1 : I-I-I-I,..I (all intra, gop_size=1) diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp index 2bc064305..18646e9a1 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_nv.cpp @@ -40,6 +40,12 @@ bool EncoderHEVCxNV::SetCodecParams() _codec_context->gop_size = (GetRefTrack()->GetKeyFrameInterval() == 0) ? (_codec_context->framerate.num / _codec_context->framerate.den) : GetRefTrack()->GetKeyFrameInterval(); } + // Lookahead + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "rc-lookahead", GetRefTrack()->GetLookaheadByConfig(), 0); + } + // Preset if (GetRefTrack()->GetPreset() == "slower") { diff --git a/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp b/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp index d47a8830d..27836eee1 100644 --- a/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp +++ b/src/projects/transcoder/codec/encoder/encoder_hevc_xma.cpp @@ -45,6 +45,13 @@ bool EncoderHEVCxXMA::SetCodecParams() // Bframes ::av_opt_set_int(_codec_context->priv_data, "bf", GetRefTrack()->GetBFrames(), 0); + // Lookahead (1 ~ 30) + if (GetRefTrack()->GetLookaheadByConfig() >= 0) + { + av_opt_set_int(_codec_context->priv_data, "lookahead_depth", GetRefTrack()->GetLookaheadByConfig(), 0); + // ::av_opt_set(_codec_context->priv_data, "expert-options", "lookahead-rc-off=0", 0); + } + // Profile auto profile = GetRefTrack()->GetProfile(); if (profile == "main" || profile.IsEmpty() == true) diff --git a/src/projects/transcoder/transcoder_stream_internal.cpp b/src/projects/transcoder/transcoder_stream_internal.cpp index b358cecac..c3df517ac 100644 --- a/src/projects/transcoder/transcoder_stream_internal.cpp +++ b/src/projects/transcoder/transcoder_stream_internal.cpp @@ -173,6 +173,12 @@ std::shared_ptr TranscoderStreamInternal::CreateOutputTrack( output_track->SetSkipFramesByConfig(profile.GetSkipFrames()); } + profile.GetLookahead(&is_parsed); + if (is_parsed == true) + { + output_track->SetLookaheadByConfig(profile.GetLookahead()); + } + output_track->SetMediaType(cmn::MediaType::Video); output_track->SetId(NewTrackId()); output_track->SetVariantName(profile.GetName());