682 lines
22 KiB
C++
682 lines
22 KiB
C++
/*
|
|
*******************************************************************************
|
|
* INCLUDE
|
|
*******************************************************************************
|
|
*/
|
|
#include "VideoEncoder.h"
|
|
#include "ResourceManager.h"
|
|
#include "Logger.h"
|
|
#include "util/Math.h"
|
|
#include <errno.h>
|
|
|
|
using namespace Util;
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* CONSTANTS
|
|
*******************************************************************************
|
|
*/
|
|
#define MIN_ALIGN 2
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* MACROS
|
|
*******************************************************************************
|
|
*/
|
|
#define __set_basic(attr, gop, sfr, dfr) \
|
|
attr.gop = (gop); \
|
|
attr.src_frame_rate = (sfr); \
|
|
attr.dst_frame_rate = (dfr);
|
|
|
|
#define __set_cbr(attr, gop, st, sfr, dfr, br) \
|
|
__set_basic(attr, gop, sfr, dfr) attr.stats_time = (st); \
|
|
attr.bit_rate = (br);
|
|
|
|
#define __set_vbr(attr, gop, st, sfr, dfr, br) \
|
|
__set_basic(attr, gop, sfr, dfr) attr.stats_time = (st); \
|
|
attr.max_bit_rate = (br);
|
|
|
|
#define __set_avbr __set_vbr
|
|
|
|
#define __set_qvbr(attr, gop, st, sfr, dfr, br) \
|
|
__set_basic(attr, gop, sfr, dfr) attr.stats_time = (st); \
|
|
attr.target_bit_rate = (br);
|
|
|
|
namespace Video
|
|
{
|
|
namespace MPP5
|
|
{
|
|
/*
|
|
*******************************************************************************
|
|
* CLASS DEFINE
|
|
*******************************************************************************
|
|
*/
|
|
VideoEncoder::Preprocessor::Preprocessor(const std::string& name, uint32_t id)
|
|
: MPPChannel((uint32_t)HI_ID_VPSS, id, 0), _name(Poco::format("%s(VPSS#%u)", name, id))
|
|
{
|
|
}
|
|
|
|
VideoEncoder::Preprocessor::~Preprocessor()
|
|
{
|
|
}
|
|
|
|
void VideoEncoder::Preprocessor::start(uint32_t iwidth, uint32_t iheight, uint32_t owidth, uint32_t oheight)
|
|
{
|
|
hi_vpss_grp_attr attr = {};
|
|
attr.nr_en = HI_FALSE;
|
|
attr.ie_en = HI_FALSE;
|
|
attr.dci_en = HI_FALSE;
|
|
attr.buf_share_en = HI_FALSE;
|
|
attr.buf_share_chn = 0;
|
|
attr.mcf_en = HI_FALSE;
|
|
attr.max_width = iwidth;
|
|
attr.max_height = iheight;
|
|
attr.max_dei_width = iwidth;
|
|
attr.max_dei_height = iheight;
|
|
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
attr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
|
|
attr.frame_rate.src_frame_rate = -1;
|
|
attr.frame_rate.dst_frame_rate = -1;
|
|
attr.dei_mode = HI_VPSS_DEI_MODE_OFF;
|
|
|
|
int rc = hi_mpi_vpss_create_grp(groupID(), &attr);
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(Poco::format("%s: Create group FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
|
|
rc);
|
|
|
|
hi_mpi_vpss_reset_grp(groupID());
|
|
rc = hi_mpi_vpss_start_grp(groupID());
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(Poco::format("%s: Start group FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
|
|
|
|
hi_vpss_chn_attr chnAttr = {};
|
|
chnAttr.chn_mode = HI_VPSS_CHN_MODE_USER;
|
|
|
|
chnAttr.width = owidth;
|
|
chnAttr.height = oheight;
|
|
chnAttr.video_format = HI_VIDEO_FORMAT_LINEAR;
|
|
chnAttr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
|
|
chnAttr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
|
|
chnAttr.compress_mode = HI_COMPRESS_MODE_NONE;
|
|
|
|
chnAttr.frame_rate.src_frame_rate = -1;
|
|
chnAttr.frame_rate.dst_frame_rate = -1;
|
|
chnAttr.mirror_en = HI_FALSE;
|
|
chnAttr.flip_en = HI_FALSE;
|
|
chnAttr.depth = 0;
|
|
chnAttr.aspect_ratio.mode = HI_ASPECT_RATIO_NONE;
|
|
rc = hi_mpi_vpss_set_chn_attr(groupID(), channelID(), &chnAttr);
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(
|
|
Poco::format("%s: Set channel#%u attr FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
|
|
|
|
rc = hi_mpi_vpss_enable_chn(groupID(), channelID());
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(
|
|
Poco::format("%s: Enable channel#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
|
|
}
|
|
|
|
void VideoEncoder::Preprocessor::stop()
|
|
{
|
|
int rc = hi_mpi_vpss_disable_chn(groupID(), channelID());
|
|
if (rc != HI_SUCCESS)
|
|
logger().error("%s: Disable channel#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc);
|
|
|
|
rc = hi_mpi_vpss_stop_grp(groupID());
|
|
if (rc != HI_SUCCESS)
|
|
logger().error("%s: Stop group FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
|
|
|
|
rc = hi_mpi_vpss_destroy_grp(groupID());
|
|
if (rc != HI_SUCCESS)
|
|
logger().error("%s: Destroy group FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
|
|
}
|
|
|
|
uint32_t VideoEncoder::Preprocessor::groupID() const
|
|
{
|
|
return deviceID();
|
|
}
|
|
|
|
const std::string& VideoEncoder::Preprocessor::name() const
|
|
{
|
|
return _name;
|
|
}
|
|
|
|
/*
|
|
*******************************************************************************
|
|
* CLASS DEFINE
|
|
*******************************************************************************
|
|
*/
|
|
Core::CodecCapabilityManager VideoEncoder::_capabilityManager(1920 * 1080 * 30 * 4 + 720 * 480 * 30 * 4);
|
|
|
|
VideoEncoder::VideoEncoder(Core::CodecID codecID)
|
|
: MPPChannel((uint32_t)HI_ID_VENC, 0, ResourceManager::allocVENCChannelID()),
|
|
Core::VideoEncoder(Poco::format("MPP5::VENC#%u(%s)", channelID(), Core::codecIDToString(codecID)), codecID),
|
|
_handle(Core::CodecCapabilityManager::INVALID_HANDLE), _preprocessor(name(), ResourceManager::allocVPSSGroupID())
|
|
{
|
|
registerNotificationHandle<Core::ParameterChangedNotification>(*this,
|
|
&VideoEncoder::handlePreviousParameterChanged);
|
|
}
|
|
|
|
VideoEncoder::~VideoEncoder()
|
|
{
|
|
ResourceManager::freeVPSSGroupID(_preprocessor.groupID());
|
|
ResourceManager::freeVENCChannelID(channelID());
|
|
releaseCapabilityHandle();
|
|
}
|
|
|
|
void VideoEncoder::start()
|
|
{
|
|
if (previousComponents().size() == 0)
|
|
throw Poco::BugcheckException(Poco::format("%s: No previous component", name()));
|
|
|
|
auto pPrevious = previousComponents().first().cast<VideoComponent>();
|
|
if (!pPrevious)
|
|
throw Poco::BugcheckException(Poco::format("%s: First previous component '%s' convert to 'VideoComponent' FAIL",
|
|
name(), previousComponents().first()->name()));
|
|
|
|
uint32_t width;
|
|
uint32_t height;
|
|
getEncodeResolution(pPrevious, width, height);
|
|
_preprocessor.start(pPrevious->getWidth(), pPrevious->getHeight(), width, height);
|
|
|
|
hi_venc_chn_attr attr = {};
|
|
|
|
attr.venc_attr.max_pic_width = width;
|
|
|
|
attr.venc_attr.max_pic_height = height;
|
|
|
|
attr.venc_attr.pic_width = width;
|
|
|
|
attr.venc_attr.pic_height = height;
|
|
|
|
attr.venc_attr.buf_size =
|
|
Util::Math::alignup(attr.venc_attr.max_pic_width * attr.venc_attr.max_pic_height * 3 / 2, 64);
|
|
|
|
attr.venc_attr.is_by_frame = HI_TRUE;
|
|
|
|
switch (getCodecID())
|
|
{
|
|
default:
|
|
case Core::CodecID::H264:
|
|
attr.venc_attr.type = HI_PT_H264;
|
|
|
|
switch (getCodecProfile())
|
|
{
|
|
case Core::CodecProfile::H264_BASELINE:
|
|
attr.venc_attr.profile = 0;
|
|
break;
|
|
|
|
default:
|
|
case Core::CodecProfile::H264_MAIN:
|
|
attr.venc_attr.profile = 1;
|
|
break;
|
|
|
|
case Core::CodecProfile::H264_HIGH:
|
|
attr.venc_attr.profile = 2;
|
|
break;
|
|
|
|
case Core::CodecProfile::H264_SVC_T:
|
|
attr.venc_attr.profile = 3;
|
|
break;
|
|
}
|
|
|
|
attr.venc_attr.h264_attr.rcn_ref_share_buf_en = HI_FALSE;
|
|
|
|
attr.venc_attr.h264_attr.frame_buf_ratio = 100;
|
|
break;
|
|
|
|
case Core::CodecID::H265:
|
|
attr.venc_attr.type = HI_PT_H265;
|
|
|
|
switch (getCodecProfile())
|
|
{
|
|
default:
|
|
case Core::CodecProfile::H265_MAIN:
|
|
attr.venc_attr.profile = 0;
|
|
break;
|
|
|
|
case Core::CodecProfile::H265_MAIN_10:
|
|
attr.venc_attr.profile = 1;
|
|
break;
|
|
}
|
|
|
|
attr.venc_attr.h265_attr.rcn_ref_share_buf_en = HI_FALSE;
|
|
|
|
attr.venc_attr.h265_attr.frame_buf_ratio = 100;
|
|
}
|
|
|
|
setChnAttrRateControl(attr, getCodecID(), getBitrateControl(), getSuitableGOP(), getSuitableSFR(), getSuitableDFR(),
|
|
getSuitableBitrate());
|
|
setChnAttrGOPMode(attr, getGOPMode(), getSuitableGOP());
|
|
|
|
int rc = hi_mpi_venc_create_chn(channelID(), &attr);
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(Poco::format("%s: Create channel FAIL: %#x", name(), (uint32_t)rc), rc);
|
|
|
|
rc = hi_mpi_venc_reset_chn(channelID());
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(Poco::format("%s: Reset channel recv FAIL: %#x", name(), (uint32_t)rc), rc);
|
|
|
|
hi_venc_start_param param;
|
|
|
|
param.recv_pic_num = -1;
|
|
rc = hi_mpi_venc_start_chn(channelID(), ¶m);
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(Poco::format("%s: Start channel recv FAIL: %#x", name(), (uint32_t)rc), rc);
|
|
|
|
task().run(
|
|
[this](std::atomic<bool>& isCancelled) -> void
|
|
{
|
|
while (!isCancelled)
|
|
{
|
|
try
|
|
{
|
|
postToNextComponents(sharedFromThis(), readPacket(1000), Core::MediaType::VIDEO);
|
|
}
|
|
catch (Poco::Exception& e)
|
|
{
|
|
logger().error("%s: %s", name(), e.displayText());
|
|
Poco::Thread::sleep(1000);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void VideoEncoder::stop()
|
|
{
|
|
task().cancel();
|
|
|
|
hi_mpi_venc_stop_chn(channelID());
|
|
hi_mpi_venc_reset_chn(channelID());
|
|
hi_mpi_venc_destroy_chn(channelID());
|
|
|
|
_preprocessor.stop();
|
|
}
|
|
|
|
void VideoEncoder::initialize()
|
|
{
|
|
uint32_t width;
|
|
uint32_t height;
|
|
getEncodeResolution(getPrevious(), width, height);
|
|
|
|
setWidth(width);
|
|
setHeight(height);
|
|
}
|
|
|
|
void VideoEncoder::deinitialize()
|
|
{
|
|
releaseCapabilityHandle();
|
|
}
|
|
|
|
void VideoEncoder::onConfigChanged(ParameterNames& names)
|
|
{
|
|
if (!started())
|
|
return;
|
|
|
|
if (names.exists(_CodecProfile) || names.exists(_Width) || names.exists(_Height) || names.exists(_FrameRate))
|
|
{
|
|
serialCodeManager().put(_Width, getWidth());
|
|
serialCodeManager().put(_Height, getHeight());
|
|
|
|
stop();
|
|
deinitialize();
|
|
initialize();
|
|
start();
|
|
return;
|
|
}
|
|
|
|
hi_venc_chn_attr attr;
|
|
hi_mpi_venc_get_chn_attr(channelID(), &attr);
|
|
if (names.exists(_GOPMode) || names.exists(_GOP) || names.exists(_BitrateControl) || names.exists(_Bitrate))
|
|
{
|
|
setChnAttrGOPMode(attr, getGOPMode(), getGOP());
|
|
setChnAttrRateControl(attr, getCodecID(), getBitrateControl(), getSuitableGOP(), getSuitableSFR(),
|
|
getSuitableDFR(), getSuitableBitrate());
|
|
}
|
|
hi_mpi_venc_set_chn_attr(channelID(), &attr);
|
|
}
|
|
|
|
void VideoEncoder::onLink(Core::Component::Ptr pPrevious)
|
|
{
|
|
_preprocessor.doLink(pPrevious);
|
|
_preprocessor.bind(*this);
|
|
}
|
|
|
|
void VideoEncoder::onUnlink(Core::Component::Ptr pPrevious)
|
|
{
|
|
_preprocessor.doUnlink(pPrevious);
|
|
_preprocessor.unbind(*this);
|
|
}
|
|
|
|
void VideoEncoder::handlePreviousParameterChanged(const Poco::AutoPtr<Core::ParameterChangedNotification>& pNotication)
|
|
{
|
|
if (!started())
|
|
return;
|
|
|
|
const auto& parameters = pNotication->parameters();
|
|
auto pPrevious = getPrevious();
|
|
if (parameters.exists(_Width) || parameters.exists(_Height))
|
|
{
|
|
uint32_t width;
|
|
uint32_t height;
|
|
getEncodeResolution(pPrevious, width, height);
|
|
|
|
if (getWidth() == width && getHeight() == height)
|
|
{
|
|
_preprocessor.stop();
|
|
_preprocessor.start(pPrevious->getWidth(), pPrevious->getHeight(), width, height);
|
|
}
|
|
else
|
|
{
|
|
setWidth(width);
|
|
setHeight(height);
|
|
commit();
|
|
}
|
|
}
|
|
|
|
if (parameters.exists(_FrameRate))
|
|
{
|
|
hi_venc_chn_attr attr;
|
|
hi_mpi_venc_get_chn_attr(channelID(), &attr);
|
|
setChnAttrRateControl(attr, getCodecID(), getBitrateControl(), getSuitableGOP(), getSuitableSFR(),
|
|
getSuitableDFR(), getSuitableBitrate());
|
|
hi_mpi_venc_set_chn_attr(channelID(), &attr);
|
|
}
|
|
}
|
|
|
|
Core::VideoComponent::Ptr VideoEncoder::getPrevious()
|
|
{
|
|
auto pPrevious = previousComponents().first().cast<VideoComponent>();
|
|
if (!pPrevious)
|
|
throw Poco::BugcheckException(Poco::format("%s: First previous component '%s' convert to 'VideoComponent' FAIL",
|
|
name(), previousComponents().first()->name()));
|
|
|
|
return pPrevious;
|
|
}
|
|
|
|
int VideoEncoder::getSuitableGOP()
|
|
{
|
|
return Math::clamp(getGOP(), 1, 65535);
|
|
}
|
|
|
|
int VideoEncoder::getSuitableSFR()
|
|
{
|
|
return Math::clamp(getPrevious()->getFrameRate(), HI_VENC_MIN_INPUT_FRAME_RATE, HI_VENC_MAX_INPUT_FRAME_RATE);
|
|
}
|
|
|
|
int VideoEncoder::getSuitableDFR()
|
|
{
|
|
return Math::clamp(Math::min(getFrameRate(), getSuitableSFR()), HI_VENC_MIN_INPUT_FRAME_RATE,
|
|
HI_VENC_MAX_INPUT_FRAME_RATE);
|
|
;
|
|
}
|
|
|
|
uint32_t VideoEncoder::getSuitableBitrate()
|
|
{
|
|
return Math::clamp(getBitrate() / 1000, (int64_t)HI_VENC_MIN_BITRATE, (int64_t)HI_VENC_MAX_BITRATE);
|
|
}
|
|
|
|
void VideoEncoder::getEncodeResolution(Core::VideoComponent::Ptr pPrevious, uint32_t& width, uint32_t& height)
|
|
{
|
|
if (getAdaptable() && !pPrevious.isNull())
|
|
{
|
|
width = pPrevious->getWidth();
|
|
height = pPrevious->getHeight();
|
|
}
|
|
else
|
|
{
|
|
width = getWidth();
|
|
height = getHeight();
|
|
}
|
|
|
|
width = Math::alignup(Math::clamp(width, (uint32_t)HI_VENC_H264_MIN_WIDTH, (uint32_t)HI_VENC_H264_MAX_WIDTH),
|
|
MIN_ALIGN);
|
|
height = Math::alignup(Math::clamp(height, (uint32_t)HI_VENC_H264_MIN_HEIGHT, (uint32_t)HI_VENC_H264_MAX_HEIGHT),
|
|
MIN_ALIGN);
|
|
if (width == 0 || height == 0)
|
|
{
|
|
width = 1920;
|
|
height = 1080;
|
|
}
|
|
}
|
|
|
|
Core::Packet::Ptr VideoEncoder::readPacket(uint32_t timeout)
|
|
{
|
|
static const int PACKET_DATA_SIZE_MAX = (1024 * 1024 * 2);
|
|
|
|
Core::Packet::Ptr pPacket = nullptr;
|
|
|
|
const long tvsec = timeout / 1000;
|
|
const long tvusec = 0;
|
|
|
|
int fd = hi_mpi_venc_get_fd(channelID());
|
|
while (true)
|
|
{
|
|
struct timeval tm = {
|
|
.tv_sec = tvsec,
|
|
.tv_usec = tvusec,
|
|
};
|
|
|
|
fd_set read_fds;
|
|
FD_ZERO(&read_fds);
|
|
FD_SET(fd, &read_fds);
|
|
|
|
int rc = select(fd + 1, &read_fds, NULL, NULL, &tm);
|
|
if (rc < 0)
|
|
throw Poco::InvalidAccessException(
|
|
Poco::format("%s: Read stream FAIL: %s", name(), std::string(strerror(rc))), rc);
|
|
else if (0 == rc)
|
|
throw Poco::TimeoutException(Poco::format("%s: Read encoder stream timeout!", name()), rc);
|
|
|
|
if (!FD_ISSET(fd, &read_fds))
|
|
continue;
|
|
|
|
hi_venc_chn_status status;
|
|
hi_mpi_venc_query_status(channelID(), &status);
|
|
|
|
hi_venc_stream stream;
|
|
stream.pack = (hi_venc_pack*)malloc(sizeof(hi_venc_pack) * status.cur_packs);
|
|
if (!stream.pack)
|
|
continue;
|
|
|
|
stream.pack_cnt = status.cur_packs;
|
|
rc = hi_mpi_venc_get_stream(channelID(), &stream, timeout);
|
|
if (rc != HI_SUCCESS)
|
|
{
|
|
free(stream.pack);
|
|
throw Poco::InvalidAccessException(Poco::format("%s: Get encoder stream FAIL: %#x", name(), (uint32_t)rc),
|
|
rc);
|
|
}
|
|
|
|
bool done = false;
|
|
uint8_t* pBuffer = new uint8_t[PACKET_DATA_SIZE_MAX];
|
|
if (!pBuffer)
|
|
{
|
|
free(stream.pack);
|
|
throw Poco::OutOfMemoryException(Poco::format("%s: Alloc memory for encoded data: FAIL", name()), 0);
|
|
}
|
|
|
|
uint32_t length = 0;
|
|
uint32_t flags = Core::Packet::FLAG_IS_VIDEO;
|
|
for (uint32_t i = 0; i < stream.pack_cnt; i++)
|
|
{
|
|
hi_venc_pack* pack = &stream.pack[i];
|
|
uint32_t chucksize = pack->len - pack->offset;
|
|
if (chucksize < PACKET_DATA_SIZE_MAX - length)
|
|
{
|
|
memcpy(&pBuffer[length], pack->addr + pack->offset, chucksize);
|
|
length += chucksize;
|
|
}
|
|
else
|
|
logger().error("%s: Buffer size(%d) is insufficient to hold the encoded data!", PACKET_DATA_SIZE_MAX);
|
|
|
|
if (pack->is_frame_end)
|
|
{
|
|
switch (getCodecID())
|
|
{
|
|
default:
|
|
case Core::CodecID::H264:
|
|
if (stream.h264_info.ref_type == HI_VENC_BASE_IDR_SLICE)
|
|
flags |= Core::Packet::FLAG_IS_KEY;
|
|
break;
|
|
|
|
case Core::CodecID::H265:
|
|
if (stream.h265_info.ref_type == HI_VENC_BASE_IDR_SLICE)
|
|
flags |= Core::Packet::FLAG_IS_KEY;
|
|
break;
|
|
}
|
|
|
|
pPacket = new Core::Packet(serialCodeManager().code(), flags, pBuffer, length, pack->pts, pack->pts);
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rc = hi_mpi_venc_release_stream(channelID(), &stream);
|
|
free(stream.pack);
|
|
stream.pack = NULL;
|
|
|
|
if (done)
|
|
break;
|
|
}
|
|
|
|
return pPacket;
|
|
}
|
|
|
|
void VideoEncoder::setChnAttrGOPMode(hi_venc_chn_attr& attr, const Core::GOPMode mode, int gop)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case Core::GOPMode::NORMAL_P:
|
|
attr.gop_attr.gop_mode = HI_VENC_GOP_MODE_NORMAL_P;
|
|
|
|
attr.gop_attr.normal_p.ip_qp_delta = 2;
|
|
break;
|
|
|
|
case Core::GOPMode::SMART_P:
|
|
attr.gop_attr.gop_mode = HI_VENC_GOP_MODE_SMART_P;
|
|
|
|
attr.gop_attr.smart_p.bg_interval = gop;
|
|
|
|
attr.gop_attr.smart_p.bg_qp_delta = 4;
|
|
|
|
attr.gop_attr.smart_p.vi_qp_delta = 2;
|
|
break;
|
|
|
|
default:
|
|
throw Poco::InvalidArgumentException(
|
|
Poco::format("%s: Invalid gop-mode: %s", name(), Core::gopModeToString(getGOPMode())), -1);
|
|
}
|
|
}
|
|
|
|
void VideoEncoder::setChnAttrRateControl(hi_venc_chn_attr& attr, Core::CodecID codec, Core::BitrateControl bc, int gop,
|
|
int sfr, int dfr, uint32_t bitrate)
|
|
{
|
|
logger().debug("%s: confiure: %s, %s, GOP:%d, sfr:%d, dfr:%d, %uKbps", name(), Core::codecIDToString(codec),
|
|
Core::bitrateControlToString(bc), gop, sfr, dfr, bitrate);
|
|
if (Core::CodecID::H264 == codec)
|
|
{
|
|
switch (bc)
|
|
{
|
|
case Core::BitrateControl::CBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_CBR;
|
|
__set_cbr(attr.rc_attr.h264_cbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::VBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_VBR;
|
|
__set_vbr(attr.rc_attr.h264_vbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::AVBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_AVBR;
|
|
__set_avbr(attr.rc_attr.h264_avbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::QVBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_QVBR;
|
|
__set_qvbr(attr.rc_attr.h264_qvbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::CVBR:
|
|
case Core::BitrateControl::FIXQP:
|
|
case Core::BitrateControl::QPMAP:
|
|
default:
|
|
throw Poco::NotImplementedException(Poco::format("%s: Not implemented H.264 bitrate-control: %s", name(),
|
|
Core::bitrateControlToString(getBitrateControl())),
|
|
-1);
|
|
}
|
|
}
|
|
else if (Core::CodecID::H265 == codec)
|
|
{
|
|
switch (bc)
|
|
{
|
|
case Core::BitrateControl::CBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_CBR;
|
|
__set_cbr(attr.rc_attr.h265_cbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::VBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_VBR;
|
|
__set_vbr(attr.rc_attr.h265_vbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::AVBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_AVBR;
|
|
__set_avbr(attr.rc_attr.h265_avbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::QVBR:
|
|
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_QVBR;
|
|
__set_qvbr(attr.rc_attr.h265_qvbr, gop, 1, sfr, dfr, bitrate);
|
|
break;
|
|
|
|
case Core::BitrateControl::CVBR:
|
|
case Core::BitrateControl::FIXQP:
|
|
case Core::BitrateControl::QPMAP:
|
|
default:
|
|
throw Poco::NotImplementedException(Poco::format("%s: Not implemented H.265 bitrate-control: %s", name(),
|
|
Core::bitrateControlToString(getBitrateControl())),
|
|
-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VideoEncoder::releaseCapabilityHandle()
|
|
{
|
|
}
|
|
|
|
void VideoEncoder::initModule()
|
|
{
|
|
hi_venc_mod_param param = {};
|
|
|
|
param.mod_type = HI_VENC_MOD_H264;
|
|
param.h264_mod_param.one_stream_buf = 0;
|
|
param.h264_mod_param.mini_buf_mode = 0;
|
|
param.h264_mod_param.low_power_mode = 0;
|
|
param.h264_mod_param.vb_src = HI_VB_SRC_PRIVATE;
|
|
param.h264_mod_param.qp_hist_en = HI_FALSE;
|
|
param.h264_mod_param.max_user_data_len = 1024;
|
|
int rc = hi_mpi_venc_set_mod_param(¶m);
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(
|
|
Poco::format("MPP5::VENC: Set module H264 param FAIL: %u(%#x)", (uint32_t)rc, (uint32_t)rc));
|
|
|
|
param.mod_type = HI_VENC_MOD_H265;
|
|
param.h265_mod_param.one_stream_buf = 0;
|
|
param.h265_mod_param.mini_buf_mode = 0;
|
|
param.h265_mod_param.low_power_mode = 0;
|
|
param.h265_mod_param.vb_src = HI_VB_SRC_PRIVATE;
|
|
param.h265_mod_param.qp_hist_en = HI_FALSE;
|
|
param.h265_mod_param.max_user_data_len = 32768;
|
|
rc = hi_mpi_venc_set_mod_param(¶m);
|
|
if (rc != HI_SUCCESS)
|
|
throw Poco::InvalidAccessException(
|
|
Poco::format("MPP5::VENC: Set module H265 param FAIL: %u(%#x)", (uint32_t)rc, (uint32_t)rc));
|
|
}
|
|
|
|
void VideoEncoder::deinitModule()
|
|
{
|
|
}
|
|
}
|
|
}
|