Skip to content

Commit 2b181e3

Browse files
committed
Added ExtraOptions video encoding settings for the x264 encoder
1 parent 3537652 commit 2b181e3

File tree

9 files changed

+160
-22
lines changed

9 files changed

+160
-22
lines changed

src/projects/base/info/video_track.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,23 @@ double VideoTrack::GetKeyFrameIntervalByMeasured() const
155155
return _key_frame_interval;
156156
}
157157

158+
void VideoTrack::AddToMeasuredFramerateWindow(double framerate)
159+
{
160+
size_t kAbnormalFpsCheckWindowSize = 60;
161+
162+
_measured_framerate_window.push_back(framerate);
163+
164+
if (_measured_framerate_window.size() > kAbnormalFpsCheckWindowSize)
165+
{
166+
_measured_framerate_window.pop_front();
167+
}
168+
}
169+
170+
std::deque<double> VideoTrack::GetMeasuredFramerateWindow() const
171+
{
172+
return _measured_framerate_window;
173+
}
174+
158175
void VideoTrack::SetKeyFrameIntervalLastet(double key_frame_interval)
159176
{
160177
_key_frame_interval_latest = key_frame_interval;
@@ -263,6 +280,26 @@ int32_t VideoTrack::GetDeltaFramesSinceLastKeyFrame() const
263280
return _delta_frame_count_since_last_key_frame;
264281
}
265282

283+
void VideoTrack::SetDetectLongKeyFrameInterval(bool detect_long_key_frame_interval)
284+
{
285+
_detect_long_key_frame_interval = detect_long_key_frame_interval;
286+
}
287+
288+
int32_t VideoTrack::GetDetectLongKeyFrameInterval() const
289+
{
290+
return _detect_long_key_frame_interval;
291+
}
292+
293+
void VideoTrack::SetDetectAbnormalFramerate(bool detect_abnormal_framerate)
294+
{
295+
_detect_abnormal_framerate = detect_abnormal_framerate;
296+
}
297+
298+
bool VideoTrack::GetDetectAbnormalFramerate() const
299+
{
300+
return _detect_abnormal_framerate;
301+
}
302+
266303
void VideoTrack::SetWidthByConfig(int32_t width)
267304
{
268305
_width_conf = width;
@@ -337,4 +374,14 @@ size_t VideoTrack::GetOverlaySignature() const
337374
{
338375
std::shared_lock<std::shared_mutex> lock(_overlay_mutex);
339376
return _overlay_signature;
377+
}
378+
379+
void VideoTrack::SetExtraEncoderOptionsByConfig(const ov::String &options)
380+
{
381+
_extra_encoder_options = options;
382+
}
383+
384+
ov::String VideoTrack::GetExtraEncoderOptionsByConfig() const
385+
{
386+
return _extra_encoder_options;
340387
}

src/projects/base/info/video_track.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class VideoTrack
2525
void SetFrameRateByMeasured(double framerate);
2626
double GetFrameRateByMeasured() const;
2727

28+
void AddToMeasuredFramerateWindow(double framerate);
29+
std::deque<double> GetMeasuredFramerateWindow() const;
30+
2831
void SetFrameRateLastSecond(double framerate);
2932
double GetFrameRateLastSecond() const;
3033

@@ -86,6 +89,12 @@ class VideoTrack
8689
void SetDeltaFrameCountSinceLastKeyFrame(int32_t delta_frame_count);
8790
int32_t GetDeltaFramesSinceLastKeyFrame() const;
8891

92+
void SetDetectLongKeyFrameInterval(bool detect_long_key_frame_interval);
93+
int32_t GetDetectLongKeyFrameInterval() const;
94+
95+
void SetDetectAbnormalFramerate(bool detect_abnormal_framerate);
96+
bool GetDetectAbnormalFramerate() const;
97+
8998
void SetBFrames(int32_t b_frames);
9099
int32_t GetBFrames();
91100

@@ -99,6 +108,9 @@ class VideoTrack
99108
void SetLookaheadByConfig(int32_t lookahead);
100109
int32_t GetLookaheadByConfig() const;
101110

111+
void SetExtraEncoderOptionsByConfig(const ov::String &options);
112+
ov::String GetExtraEncoderOptionsByConfig() const;
113+
102114
protected:
103115

104116
// framerate (measurement)
@@ -129,6 +141,9 @@ class VideoTrack
129141
// Delta Frame Count since last key frame
130142
int32_t _delta_frame_count_since_last_key_frame = 0;
131143

144+
// Detect long key frame interval (set by mediarouter)
145+
bool _detect_long_key_frame_interval = false;
146+
132147
// Key Frame Interval Type (set by user)
133148
cmn::KeyFrameIntervalType _key_frame_interval_type_conf = cmn::KeyFrameIntervalType::FRAME;
134149

@@ -166,6 +181,11 @@ class VideoTrack
166181
// Lookahead (set by user)
167182
int32_t _lookahead_conf = -1;
168183

184+
// Abnormal key frame interval detection
185+
bool _detect_abnormal_framerate = false;
186+
std::deque<double> _measured_framerate_window;
187+
188+
ov::String _extra_encoder_options;
169189
public:
170190
// Overlay (set by user)
171191
void SetOverlays(const std::vector<std::shared_ptr<info::Overlay>> &overlays);

src/projects/config/items/virtual_hosts/applications/output_profiles/encodes/video_profile.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ namespace cfg
4747
// 0 ~ 120 : minimum value of SkipFrames. it is automatically calculated and the SkipFrames value is changed.
4848
int _skip_frames = -1;
4949

50+
// User-defined encoder options passed directly to the underlying encoder without validation.
51+
// example: "nal-hrd=cbr:force-cfr=1"
52+
ov::String _extra_options = "";
53+
5054
public:
5155
CFG_DECLARE_CONST_REF_GETTER_OF(GetName, _name)
5256
CFG_DECLARE_CONST_REF_GETTER_OF(IsBypass, _bypass)
@@ -66,6 +70,7 @@ namespace cfg
6670
CFG_DECLARE_CONST_REF_GETTER_OF(GetProfile, _profile)
6771
CFG_DECLARE_CONST_REF_GETTER_OF(GetSkipFrames, _skip_frames)
6872
CFG_DECLARE_CONST_REF_GETTER_OF(GetLookahead, _lookahead)
73+
CFG_DECLARE_CONST_REF_GETTER_OF(GetExtraOptions, _extra_options)
6974

7075
void SetName(const ov::String &name)
7176
{
@@ -119,6 +124,10 @@ namespace cfg
119124
{
120125
_lookahead = lookahead;
121126
}
127+
void SetExtraOptions(const ov::String &extra_options)
128+
{
129+
_extra_options = extra_options;
130+
}
122131

123132
protected:
124133
void MakeList() override
@@ -205,6 +214,7 @@ namespace cfg
205214
return CreateConfigErrorPtr("Profile must be baseline, main or high");
206215
});
207216
Register<Optional>("Lookahead", &_lookahead);
217+
Register<Optional>("ExtraOptions", &_extra_options);
208218
}
209219
};
210220
} // namespace oprf

src/projects/modules/ffmpeg/compat.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,29 @@ namespace ffmpeg
333333

334334
return pix_fmt;
335335
}
336+
337+
ov::String compat::GetAVOptionsString(void *opts)
338+
{
339+
ov::String result;
340+
341+
if (opts == nullptr)
342+
{
343+
return result;
344+
}
345+
346+
const AVOption *opt = NULL;
347+
while ((opt = av_opt_next(opts, opt)))
348+
{
349+
uint8_t *value = NULL;
350+
351+
if (av_opt_get(opts, opt->name, 0, &value) == 0)
352+
{
353+
result += ov::String::FormatString("%s=%s,", opt->name, value);
354+
av_free(value);
355+
}
356+
}
357+
358+
return result;
359+
}
360+
336361
} // namespace ffmpeg

src/projects/modules/ffmpeg/compat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ namespace ffmpeg
5656
static AVPixelFormat ToAVPixelFormat(cmn::VideoPixelFormatId pixel_format);
5757
static cmn::VideoPixelFormatId ToVideoPixelFormat(int32_t pixel_format);
5858
static AVPixelFormat GetAVPixelFormatOfHWDevice(cmn::MediaCodecModuleId module_id, cmn::DeviceId gpu_id, bool is_sw_format = true);
59+
static ov::String GetAVOptionsString(void *opts);
5960

6061
static std::shared_ptr<MediaTrack> CreateMediaTrack(AVStream* stream)
6162
{

src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,23 @@ bool EncoderAVCx264::SetCodecParams()
127127
.CStr(),
128128
0);
129129

130+
// Do not use 'sliced-threads' option from encoding delay. Can't not compatible with macOS evironment.
131+
ov::String extra_options = ov::String::FormatString(
132+
"bframes=%d:sliced-threads=0:b-adapt=1:no-scenecut:keyint=%d:min-keyint=%d",
133+
GetRefTrack()->GetBFrames(), _codec_context->gop_size, _codec_context->gop_size);
134+
135+
// If user has defined extra options, append them.
136+
if (!GetRefTrack()->GetExtraEncoderOptionsByConfig().IsEmpty())
137+
{
138+
if (!GetRefTrack()->GetExtraEncoderOptionsByConfig().HasPrefix(":"))
139+
extra_options += ":";
140+
141+
extra_options += GetRefTrack()->GetExtraEncoderOptionsByConfig();
142+
}
143+
::av_opt_set(_codec_context->priv_data, "x264opts", extra_options.CStr(), 0);
144+
145+
logtd("opts: %s", ffmpeg::compat::GetAVOptionsString(_codec_context->priv_data).CStr());
146+
130147
_bitstream_format = cmn::BitstreamFormat::H264_ANNEXB;
131148

132149
_packet_type = cmn::PacketType::NALU;

src/projects/transcoder/transcoder_stream.cpp

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,9 +1163,9 @@ bool TranscoderStream::CreateDecoders()
11631163
// Create Decoder
11641164
if (CreateDecoder(decoder_id, GetInputStream(), input_track) == false)
11651165
{
1166-
logte("%s Failed to create decoder. InputTrack(%d), Decoder(%d) [Codec(%s), Module(%s), Device(%u)]",
1167-
_log_prefix.CStr(), input_track->GetId(), decoder_id, cmn::GetCodecIdString(input_track->GetCodecId()),
1168-
cmn::GetCodecModuleIdString(input_track->GetCodecModuleId()), input_track->GetCodecDeviceId());
1166+
logte("%s Failed to create decoder. Id(%d)<Codec(%s), Module(%s), Device(%u)>, InputTrack(%d)",
1167+
_log_prefix.CStr(), decoder_id, cmn::GetCodecIdString(input_track->GetCodecId()),
1168+
cmn::GetCodecModuleIdString(input_track->GetCodecModuleId()), input_track->GetCodecDeviceId(), input_track->GetId());
11691169

11701170
#if NOTIFICATION_ENABLED
11711171
TranscoderAlerts::UpdateErrorWithoutCount(
@@ -1180,9 +1180,9 @@ bool TranscoderStream::CreateDecoders()
11801180
return false;
11811181
}
11821182

1183-
logti("%s Decoder has been created. InputTrack(%d), Decoder(%d) [Codec(%s), Module(%s), Device(%u)]",
1184-
_log_prefix.CStr(), input_track->GetId(), decoder_id, cmn::GetCodecIdString(input_track->GetCodecId()),
1185-
cmn::GetCodecModuleIdString(input_track->GetCodecModuleId()), input_track->GetCodecDeviceId());
1183+
logti("%s Decoder has been created. Id(%d)<Codec(%s), Module(%s), Device(%u)>, InputTrack(%d)",
1184+
_log_prefix.CStr(), decoder_id, cmn::GetCodecIdString(input_track->GetCodecId()),
1185+
cmn::GetCodecModuleIdString(input_track->GetCodecModuleId()), input_track->GetCodecDeviceId(), input_track->GetId());
11861186
}
11871187

11881188
return true;
@@ -1286,8 +1286,8 @@ bool TranscoderStream::CreateEncoders(std::shared_ptr<MediaFrame> buffer)
12861286

12871287
if (CreateEncoder(encoder_id, output_stream, output_track) == false)
12881288
{
1289-
logte("%s Could not create encoder. Encoder(%d) OutputTrack(%d) <Codec:%s,Module:%s:%d>", _log_prefix.CStr(),
1290-
encoder_id, output_track->GetId(), cmn::GetCodecIdString(output_track->GetCodecId()), cmn::GetCodecModuleIdString(output_track->GetCodecModuleId()), output_track->GetCodecDeviceId());
1289+
logte("%s Could not create encoder. Id(%d)<Codec:%s,Module:%s:%d>, OutputTrack(%d)", _log_prefix.CStr(),
1290+
encoder_id, cmn::GetCodecIdString(output_track->GetCodecId()), cmn::GetCodecModuleIdString(output_track->GetCodecModuleId()), output_track->GetCodecDeviceId(), output_track->GetId());
12911291

12921292
#if NOTIFICATION_ENABLED
12931293
auto output_profile_ptr = GetOutputProfileByName(output_stream->GetOutputProfileName());
@@ -1304,9 +1304,8 @@ bool TranscoderStream::CreateEncoders(std::shared_ptr<MediaFrame> buffer)
13041304
return false;
13051305
}
13061306

1307-
// TODO(Keukhan): Add encoding option logs
1308-
logti("%s Encoder has been created. Encoder(%d) OutputTrack(%d) <Codec:%s,Module:%s:%d>", _log_prefix.CStr(),
1309-
encoder_id, output_track->GetId(), cmn::GetCodecIdString(output_track->GetCodecId()), cmn::GetCodecModuleIdString(output_track->GetCodecModuleId()), output_track->GetCodecDeviceId());
1307+
logti("%s Encoder has been created. Id(%d)<Codec:%s,Module:%s:%d>, OutputTrack(%d)", _log_prefix.CStr(),
1308+
encoder_id, cmn::GetCodecIdString(output_track->GetCodecId()), cmn::GetCodecModuleIdString(output_track->GetCodecModuleId()), output_track->GetCodecDeviceId(), output_track->GetId());
13101309
}
13111310
}
13121311

@@ -1498,10 +1497,7 @@ bool TranscoderStream::CreateFilters(std::shared_ptr<MediaFrame> buffer)
14981497
return false;
14991498
}
15001499

1501-
logti("%s Filter has been created. Filter(%d), Decoder(%d) <Codec:%s, Module:%s:%d>, Encoder(%d) <Codec:%s, Module:%s:%d>, %s", _log_prefix.CStr(), filter_id,
1502-
decoder_id, cmn::GetCodecIdString(output_track->GetCodecId()), cmn::GetCodecModuleIdString(output_track->GetCodecModuleId()), output_track->GetCodecDeviceId(),
1503-
encoder_id, cmn::GetCodecIdString(output_track->GetCodecId()), cmn::GetCodecModuleIdString(output_track->GetCodecModuleId()), output_track->GetCodecDeviceId(),
1504-
GetFilter(filter_id)->GetDescription().CStr());
1500+
logti("%s Filter has been created. Id(%d), %s", _log_prefix.CStr(), filter_id, GetFilter(filter_id)->GetDescription().CStr());
15051501
}
15061502

15071503
return true;
@@ -1664,7 +1660,7 @@ void TranscoderStream::UpdateOutputTrack(std::shared_ptr<MediaFrame> buffer)
16641660
// Case Of Transcode
16651661
else
16661662
{
1667-
UpdateOutputTrackTranscode(output_track, input_track, buffer);
1663+
UpdateOutputTrackByDecodedFrame(output_track, input_track, buffer);
16681664
}
16691665
}
16701666
}

src/projects/transcoder/transcoder_stream_internal.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,21 @@ std::shared_ptr<MediaTrack> TranscoderStreamInternal::CreateOutputTrack(
234234
output_track->SetLookaheadByConfig(profile.GetLookahead());
235235
}
236236

237+
profile.GetExtraOptions(&is_parsed);
238+
if (is_parsed == true)
239+
{
240+
output_track->SetExtraEncoderOptionsByConfig(profile.GetExtraOptions());
241+
}
242+
243+
profile.GetName(&is_parsed);
244+
if (is_parsed == true)
245+
{
246+
output_track->SetVariantName(profile.GetName());
247+
}
248+
249+
//
237250
output_track->SetMediaType(cmn::MediaType::Video);
238251
output_track->SetId(NewTrackId());
239-
output_track->SetVariantName(profile.GetName());
240252
output_track->SetPublicName(input_track->GetPublicName());
241253
output_track->SetLanguage(input_track->GetLanguage());
242254
output_track->SetCharacteristics(input_track->GetCharacteristics());
@@ -333,10 +345,15 @@ std::shared_ptr<MediaTrack> TranscoderStreamInternal::CreateOutputTrack(const st
333345
output_track->SetBitrateByConfig(profile.GetBitrate());
334346
}
335347

348+
profile.GetName(&is_parsed);
349+
if (is_parsed == true)
350+
{
351+
output_track->SetVariantName(profile.GetName());
352+
}
353+
336354
output_track->SetMediaType(cmn::MediaType::Audio);
337355
output_track->SetId(NewTrackId());
338-
output_track->SetVariantName(profile.GetName());
339-
356+
340357
ov::String public_name = ov::String::FormatString("%s_%d", input_track->GetPublicName().CStr(), output_track->GetId());
341358
output_track->SetPublicName(public_name);
342359
output_track->SetLanguage(input_track->GetLanguage());
@@ -468,10 +485,15 @@ std::shared_ptr<MediaTrack> TranscoderStreamInternal::CreateOutputTrack(const st
468485
}
469486
}
470487

488+
profile.GetName(&is_parsed);
489+
if (is_parsed == true)
490+
{
491+
output_track->SetVariantName(profile.GetName());
492+
}
493+
471494
output_track->SetPublicName(input_track->GetPublicName());
472495
output_track->SetLanguage(input_track->GetLanguage());
473496
output_track->SetCharacteristics(input_track->GetCharacteristics());
474-
output_track->SetVariantName(profile.GetName());
475497
output_track->SetOriginBitstream(input_track->GetOriginBitstream());
476498

477499
output_track->SetMediaType(cmn::MediaType::Video);
@@ -805,7 +827,7 @@ void TranscoderStreamInternal::UpdateOutputTrackPassthrough(const std::shared_pt
805827
}
806828
}
807829

808-
void TranscoderStreamInternal::UpdateOutputTrackTranscode(const std::shared_ptr<MediaTrack> &output_track, const std::shared_ptr<MediaTrack> &input_track, std::shared_ptr<MediaFrame> buffer)
830+
void TranscoderStreamInternal::UpdateOutputTrackByDecodedFrame(const std::shared_ptr<MediaTrack> &output_track, const std::shared_ptr<MediaTrack> &input_track, std::shared_ptr<MediaFrame> buffer)
809831
{
810832
if (output_track->GetMediaType() == cmn::MediaType::Video)
811833
{

src/projects/transcoder/transcoder_stream_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class TranscoderStreamInternal
5050
static double MeasurementToRecommendFramerate(double framerate);
5151

5252
void UpdateOutputTrackPassthrough(const std::shared_ptr<MediaTrack> &output_track, std::shared_ptr<MediaFrame> buffer);
53-
void UpdateOutputTrackTranscode(const std::shared_ptr<MediaTrack> &output_track, const std::shared_ptr<MediaTrack> &input_track, std::shared_ptr<MediaFrame> buffer);
53+
void UpdateOutputTrackByDecodedFrame(const std::shared_ptr<MediaTrack> &output_track, const std::shared_ptr<MediaTrack> &input_track, std::shared_ptr<MediaFrame> buffer);
5454

5555

5656
// This is used to check if only keyframes can be decoded.

0 commit comments

Comments
 (0)