-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added libx264 library, change to default h264 codec
- Loading branch information
Showing
8 changed files
with
315 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
162 changes: 162 additions & 0 deletions
162
src/projects/transcoder/codec/encoder/encoder_avc_x264.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
//============================================================================== | ||
// | ||
// Transcoder | ||
// | ||
// Created by Kwon Keuk Han | ||
// Copyright (c) 2018 AirenSoft. All rights reserved. | ||
// | ||
//============================================================================== | ||
#include "encoder_avc_x264.h" | ||
|
||
#include <unistd.h> | ||
|
||
#include "../../transcoder_private.h" | ||
|
||
|
||
bool EncoderAVCx264::SetCodecParams() | ||
{ | ||
_codec_context->bit_rate = GetRefTrack()->GetBitrate(); | ||
_codec_context->rc_min_rate = _codec_context->rc_max_rate = _codec_context->bit_rate; | ||
_codec_context->rc_buffer_size = static_cast<int>(_codec_context->bit_rate / 2); | ||
_codec_context->framerate = ::av_d2q((GetRefTrack()->GetFrameRateByConfig() > 0) ? GetRefTrack()->GetFrameRateByConfig() : GetRefTrack()->GetEstimateFrameRate(), AV_TIME_BASE); | ||
_codec_context->sample_aspect_ratio = ::av_make_q(1, 1); | ||
|
||
// From avcodec.h: | ||
// For some codecs, the time base is closer to the field rate than the frame rate. | ||
// Most notably, H.264 and MPEG-2 specify time_base as half of frame duration | ||
// if no telecine is used ... | ||
// Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2. | ||
_codec_context->ticks_per_frame = 2; | ||
|
||
// From avcodec.h: | ||
// For fixed-fps content, timebase should be 1/framerate and timestamp increments should be identically 1. | ||
// This often, but not always is the inverse of the frame rate or field rate for video. 1/time_base is not the average frame rate if the frame rate is not constant. | ||
_codec_context->time_base = (AVRational){GetRefTrack()->GetTimeBase().GetNum(), GetRefTrack()->GetTimeBase().GetDen()}; | ||
_codec_context->max_b_frames = GetRefTrack()->GetBFrames(); | ||
_codec_context->pix_fmt = (AVPixelFormat)GetSupportedFormat(); | ||
_codec_context->width = GetRefTrack()->GetWidth(); | ||
_codec_context->height = GetRefTrack()->GetHeight(); | ||
|
||
// Keyframe Interval | ||
//@see transcoder_encoder.cpp / force_keyframe_by_time_interval | ||
auto key_frame_interval_type = GetRefTrack()->GetKeyFrameIntervalTypeByConfig(); | ||
if (key_frame_interval_type == cmn::KeyFrameIntervalType::TIME) | ||
{ | ||
_codec_context->gop_size = (int32_t)(GetRefTrack()->GetFrameRate() * (double)GetRefTrack()->GetKeyFrameInterval() / 1000 * 2); | ||
} | ||
else if (key_frame_interval_type == cmn::KeyFrameIntervalType::FRAME) | ||
{ | ||
_codec_context->gop_size = (GetRefTrack()->GetKeyFrameInterval() == 0) ? (_codec_context->framerate.num / _codec_context->framerate.den) : GetRefTrack()->GetKeyFrameInterval(); | ||
} | ||
|
||
// -1(Default) => FFMIN(FFMAX(4, av_cpu_count() / 3), 8) | ||
// 0 => Auto | ||
// >1 => Set | ||
_codec_context->thread_count = GetRefTrack()->GetThreadCount() < 0 ? FFMIN(FFMAX(4, av_cpu_count() / 3), 8) : GetRefTrack()->GetThreadCount(); | ||
|
||
// Preset | ||
if (GetRefTrack()->GetPreset() == "slower") | ||
{ | ||
::av_opt_set(_codec_context->priv_data, "preset", "slower", 0); | ||
} | ||
else if (GetRefTrack()->GetPreset() == "slow") | ||
{ | ||
::av_opt_set(_codec_context->priv_data, "preset", "slow", 0); | ||
} | ||
else if (GetRefTrack()->GetPreset() == "medium") | ||
{ | ||
::av_opt_set(_codec_context->priv_data, "preset", "medium", 0); | ||
} | ||
else if (GetRefTrack()->GetPreset() == "fast") | ||
{ | ||
::av_opt_set(_codec_context->priv_data, "preset", "fast", 0); | ||
} | ||
else if (GetRefTrack()->GetPreset() == "faster") | ||
{ | ||
::av_opt_set(_codec_context->priv_data, "preset", "faster", 0); | ||
} | ||
else | ||
{ | ||
// Default | ||
::av_opt_set(_codec_context->priv_data, "preset", "faster", 0); | ||
} | ||
|
||
// Profile | ||
::av_opt_set(_codec_context->priv_data, "profile", "main", 0); | ||
|
||
// Tune | ||
::av_opt_set(_codec_context->priv_data, "tune", "zerolatency", 0); | ||
|
||
// Remove the sliced-thread option from encoding delay. Browser compatibility in MAC environment | ||
::av_opt_set(_codec_context->priv_data, "x264opts", | ||
ov::String::FormatString( | ||
"bframes=%d:sliced-threads=0:b-adapt=1:no-scenecut:keyint=%d:min-keyint=%d", | ||
GetRefTrack()->GetBFrames(), | ||
_codec_context->gop_size, | ||
_codec_context->gop_size) | ||
.CStr(), | ||
0); | ||
|
||
_bitstream_format = cmn::BitstreamFormat::H264_ANNEXB; | ||
|
||
_packet_type = cmn::PacketType::NALU; | ||
|
||
return true; | ||
} | ||
|
||
// Notes. | ||
// | ||
// - B-frame must be disabled. because, WEBRTC does not support B-Frame. | ||
// | ||
bool EncoderAVCx264::Configure(std::shared_ptr<MediaTrack> context) | ||
{ | ||
if (TranscodeEncoder::Configure(context) == false) | ||
{ | ||
return false; | ||
} | ||
|
||
auto codec_id = GetCodecID(); | ||
|
||
const AVCodec *codec = ::avcodec_find_encoder_by_name("libx264"); | ||
if (codec == nullptr) | ||
{ | ||
logte("Could not find encoder: %s (%d)", ::avcodec_get_name(codec_id), codec_id); | ||
return false; | ||
} | ||
|
||
_codec_context = ::avcodec_alloc_context3(codec); | ||
if (_codec_context == nullptr) | ||
{ | ||
logte("Could not allocate codec context for %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); | ||
return false; | ||
} | ||
|
||
if (SetCodecParams() == false) | ||
{ | ||
logte("Could not set codec parameters for %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); | ||
return false; | ||
} | ||
if (::avcodec_open2(_codec_context, _codec_context->codec, nullptr) < 0) | ||
{ | ||
logte("Could not open codec: %s (%d)", ::avcodec_get_name(GetCodecID()), GetCodecID()); | ||
return false; | ||
} | ||
|
||
// Generates a thread that reads and encodes frames in the input_buffer queue and places them in the output queue. | ||
try | ||
{ | ||
_kill_flag = false; | ||
|
||
_codec_thread = std::thread(&EncoderAVCx264::CodecThread, this); | ||
pthread_setname_np(_codec_thread.native_handle(), ov::String::FormatString("Enc%s", avcodec_get_name(GetCodecID())).CStr()); | ||
} | ||
catch (const std::system_error &e) | ||
{ | ||
logte("Failed to start encoder thread."); | ||
_kill_flag = true; | ||
|
||
return false; | ||
} | ||
|
||
return true; | ||
} |
Oops, something went wrong.
Are you sure that folder is maintained? Revision 2245 is quite old, current one is 3194. Sadly videolan does not provide proper versioning for x264, I guess you need to check https://artifacts.videolan.org/x264/release-debian-amd64/ and use the noted commit hash: https://code.videolan.org/videolan/x264/-/archive/master/x264-1243d9f.tar.bz2