871 lines
26 KiB
C++
Executable File
871 lines
26 KiB
C++
Executable File
/*
|
|
* Copyright 2021 Rockchip Electronics Co. LTD
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* author: zj@rock-chips.com
|
|
*/
|
|
|
|
//#define OPEN_DEBUG 1
|
|
#define LOG_TAG "RKMppEncApi"
|
|
#include "Log.h"
|
|
#include "RKMppEncApi.h"
|
|
|
|
#include <media/stagefright/MediaCodecConstants.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
RKMppEncApi::RKMppEncApi()
|
|
: mMppCtx(nullptr),
|
|
mMppMpi(nullptr),
|
|
mEncCfg(nullptr),
|
|
mCodingType(MPP_VIDEO_CodingAVC),
|
|
mStarted(false),
|
|
mSpsPpsHeaderReceived(false),
|
|
mSawInputEOS(false),
|
|
mOutputEOS(false),
|
|
mSignalledError(false),
|
|
mHorStride(0),
|
|
mVerStride(0),
|
|
mInFile(nullptr),
|
|
mOutFile(nullptr) {
|
|
Trace();
|
|
}
|
|
|
|
RKMppEncApi::~RKMppEncApi() {
|
|
Trace();
|
|
releaseEncoder();
|
|
}
|
|
|
|
bool RKMppEncApi::init(EncCfgInfo* cfg) {
|
|
Trace();
|
|
bool ret = true;
|
|
int err = 0;
|
|
MppPollType timeout = MPP_POLL_NON_BLOCK;
|
|
//MppPollType timeoutOutput = MPP_POLL_BLOCK;
|
|
RK_S64 outPutTimout =48;
|
|
/* default stride */
|
|
|
|
mCodingType = MPP_VIDEO_CodingAVC;
|
|
mWidth = cfg->width;
|
|
mHeight = cfg->height;
|
|
mHorStride = _ALIGN(cfg->width, 16);
|
|
mVerStride = _ALIGN(cfg->height, 16);
|
|
|
|
mFormat = cfg->format;
|
|
mIDRInterval = cfg->IDRInterval;
|
|
mBitrateMode = cfg->bitrateMode;
|
|
mBitRate = cfg->bitRate;
|
|
mFrameRate = cfg->framerate;
|
|
mQp = cfg->qp;
|
|
mScaleWidth = cfg->scaleWidth;
|
|
mSaleHeight = cfg->scaleHeight;
|
|
mProfile = cfg->profile;
|
|
mLevel = cfg->level;
|
|
mRotation = cfg->rotation;
|
|
|
|
/*
|
|
* create vpumem for mpp input
|
|
*
|
|
* NOTE: We need temporary buffer to store rga nv12 output for some rgba
|
|
* input, since mpp can't process rgba input properly. in addition to this,
|
|
* alloc buffer within 4G in view of rga efficiency.
|
|
*/
|
|
// create mpp and init mpp
|
|
err = mpp_create(&mMppCtx, &mMppMpi);
|
|
if (err) {
|
|
ALOGE("failed to mpp_create, ret %d", err);
|
|
ret = false;
|
|
goto error;
|
|
}
|
|
err = mMppMpi->control(mMppCtx, MPP_SET_INPUT_TIMEOUT, &timeout);
|
|
|
|
err = mMppMpi->control(mMppCtx, MPP_SET_OUTPUT_TIMEOUT, &outPutTimout);
|
|
if (MPP_OK != err) {
|
|
ALOGE("failed to set output timeout %d, ret %d", timeout, err);
|
|
ret = false;
|
|
goto error;
|
|
}
|
|
|
|
err = mpp_init(mMppCtx, MPP_CTX_ENC, mCodingType);
|
|
if (err) {
|
|
ALOGE("failed to mpp_init, ret %d", err);
|
|
ret = false;
|
|
goto error;
|
|
}
|
|
|
|
ret = setupEncCfg();
|
|
if (ret == false) {
|
|
ALOGE("failed to set config, ret=0x%x", ret);
|
|
goto error;
|
|
}
|
|
|
|
mStarted = true;
|
|
return true;
|
|
error:
|
|
releaseEncoder();
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool RKMppEncApi::onInit() {
|
|
Trace();
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::onStop() {
|
|
Trace();
|
|
return onFlush_sm();
|
|
}
|
|
|
|
bool RKMppEncApi::onReset() {
|
|
Trace();
|
|
return onStop();
|
|
}
|
|
|
|
bool RKMppEncApi::onRelease() {
|
|
Trace();
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::onFlush_sm() {
|
|
bool ret = true;
|
|
|
|
Trace();
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool RKMppEncApi::sendFrame(MyDmaBuffer_t dBuffer, int32_t size, uint64_t pts,
|
|
uint32_t flags) {
|
|
Trace();
|
|
int err = 0;
|
|
bool ret = true;
|
|
MppFrame frame = nullptr;
|
|
|
|
MppBufferInfo commit;
|
|
memset(&commit, 0, sizeof(commit));
|
|
commit.type = MPP_BUFFER_TYPE_ION;
|
|
|
|
mpp_frame_init(&frame);
|
|
|
|
if (flags & BUFFER_FLAG_END_OF_STREAM) {
|
|
ALOGD("send input eos");
|
|
mpp_frame_set_eos(frame, 1);
|
|
}
|
|
|
|
ALOGD("send frame fd %d size %d pts %lld", dBuffer.fd, dBuffer.size, pts);
|
|
|
|
if (dBuffer.fd > 0) {
|
|
MppBuffer buffer = nullptr;
|
|
|
|
commit.fd = dBuffer.fd;
|
|
commit.size = dBuffer.size;
|
|
|
|
commit.index = dBuffer.index;
|
|
err = mpp_buffer_import(&buffer, &commit);
|
|
if (err) {
|
|
ALOGE("failed to import input buffer");
|
|
ret = false;
|
|
goto error;
|
|
}
|
|
mpp_frame_set_buffer(frame, buffer);
|
|
mpp_buffer_put(buffer);
|
|
buffer = nullptr;
|
|
} else {
|
|
mpp_frame_set_buffer(frame, nullptr);
|
|
}
|
|
|
|
mpp_frame_set_width(frame, mWidth);
|
|
mpp_frame_set_height(frame, mHeight);
|
|
mpp_frame_set_hor_stride(frame, mHorStride);
|
|
mpp_frame_set_ver_stride(frame, mVerStride);
|
|
mpp_frame_set_pts(frame, pts);
|
|
mpp_frame_set_fmt(frame, MPP_FMT_YUV420SP);
|
|
|
|
err = mMppMpi->encode_put_frame(mMppCtx, frame);
|
|
if (err) {
|
|
ALOGE("failed to put_frame, err %d", err);
|
|
ret = false;
|
|
goto error;
|
|
}
|
|
|
|
ret = true;
|
|
return ret;
|
|
error:
|
|
if (frame) {
|
|
mpp_frame_deinit(&frame);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool RKMppEncApi::getoutpacket(OutWorkEntry* entry) {
|
|
Trace();
|
|
int err = 0;
|
|
MppPacket packet = nullptr;
|
|
|
|
err = mMppMpi->encode_get_packet(mMppCtx, &packet);
|
|
if (err) {
|
|
return false;
|
|
} else {
|
|
int64_t pts = mpp_packet_get_pts(packet);
|
|
size_t len = mpp_packet_get_length(packet);
|
|
uint32_t eos = mpp_packet_get_eos(packet);
|
|
|
|
ALOGD("get outpacket pts %lld size %d eos %d", pts, len, eos);
|
|
|
|
if (eos) {
|
|
ALOGD("get output eos");
|
|
mOutputEOS = true;
|
|
if (pts == 0 || !len) {
|
|
ALOGD("eos with empty pkt");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!len) {
|
|
ALOGD("ignore empty output with pts %lld", pts);
|
|
return false;
|
|
}
|
|
|
|
entry->frameIndex = pts;
|
|
entry->outPacket = packet;
|
|
if (mpp_packet_has_meta(packet)) {
|
|
MppMeta meta = mpp_packet_get_meta(packet);
|
|
MppFrame frm = NULL;
|
|
RK_S32 temporal_id = 0;
|
|
RK_S32 lt_idx = -1;
|
|
RK_S32 avg_qp = -1;
|
|
|
|
if (MPP_OK ==
|
|
mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id)) {
|
|
}
|
|
|
|
if (MPP_OK == mpp_meta_get_s32(meta, KEY_LONG_REF_IDX, <_idx)) {
|
|
}
|
|
|
|
if (MPP_OK == mpp_meta_get_s32(meta, KEY_ENC_AVERAGE_QP, &avg_qp)) {
|
|
}
|
|
|
|
if (MPP_OK == mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frm)) {
|
|
MppBuffer frm_buf = NULL;
|
|
|
|
if (NULL == frm) {
|
|
ALOGE("mpp_meta_get_frame failed");
|
|
}
|
|
frm_buf = mpp_frame_get_buffer(frm);
|
|
if (NULL == frm_buf) {
|
|
ALOGE("mpp_frame_get_buffer failed");
|
|
}
|
|
|
|
entry->index = mpp_buffer_get_index(frm_buf);
|
|
ALOGE("mpp_buffer_get_index %d", entry->index);
|
|
{
|
|
// AutoMutex autolock(list_buf->mutex());
|
|
// list_buf->add_at_tail(&frm_buf, sizeof(frm_buf));
|
|
// list_buf->signal();
|
|
}
|
|
|
|
mpp_frame_deinit(&frm);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::sendFrame(char* data, int32_t size, int64_t pts,
|
|
int32_t flag) {
|
|
Trace();
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::sendFrame(int32_t fd, int32_t size, int64_t pts,
|
|
int32_t flag) {
|
|
Trace();
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::getOutStream(EncoderOut_t* encOut) {
|
|
Trace();
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupBaseCodec() {
|
|
// ALOGD("setupBaseCodec: coding %d w %d h %d hor %d ver %d",
|
|
// mCodingType, width, height, mHorStride, mVerStride);
|
|
|
|
mpp_enc_cfg_set_s32(mEncCfg, "codec:type", mCodingType);
|
|
|
|
mpp_enc_cfg_set_s32(mEncCfg, "prep:width", mWidth);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "prep:height", mHeight);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "prep:hor_stride", mHorStride);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "prep:ver_stride", mVerStride);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "prep:format", mFormat);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "prep:rotation", mRotation);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupSceneMode() {
|
|
// ALOGD("setupSceneMode: scene-mode %d", c2Mode->value);
|
|
|
|
/*
|
|
* scene-mode of encoder, this feature only support on rk3588
|
|
* - 0: deault none ipc mode
|
|
* - 1: ipc mode
|
|
*/
|
|
// mpp_enc_cfg_set_s32(mEncCfg, "tune:scene_mode", c2Mode->value);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupFrameRate() {
|
|
float frameRate = mFrameRate;
|
|
uint32_t idrInterval = mIDRInterval, gop = mFrameRate * mIDRInterval;
|
|
|
|
// std::shared_ptr<C2StreamGopTuning::output> c2Gop = mIntf->getGop_l();
|
|
// std::shared_ptr<C2StreamFrameRateInfo::output> c2FrameRate
|
|
// = mIntf->getFrameRate_l();
|
|
|
|
// idrInterval = mIntf->getSyncFramePeriod_l();
|
|
// frameRate = c2FrameRate->value;
|
|
|
|
if (frameRate == 1) {
|
|
// set default frameRate 30
|
|
frameRate = 60;
|
|
}
|
|
|
|
// if (c2Gop && c2Gop->flexCount() > 0) {
|
|
// uint32_t syncInterval = 30;
|
|
// uint32_t iInterval = 0;
|
|
// uint32_t maxBframes = 0;
|
|
|
|
// ParseGop(*c2Gop, &syncInterval, &iInterval, &maxBframes);
|
|
// if (syncInterval > 0) {
|
|
// ALOGD("updating IDR interval: %d -> %d", idrInterval,
|
|
// syncInterval); idrInterval = syncInterval;
|
|
// }
|
|
// }
|
|
|
|
ALOGD("setupFrameRate: framerate %.2f idrInterval %d gop %d", frameRate,
|
|
idrInterval, gop);
|
|
|
|
gop = (idrInterval < 8640000 && idrInterval > 1)
|
|
? idrInterval
|
|
: mFrameRate * mIDRInterval;
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:gop", gop);
|
|
|
|
/* fix input / output frame rate */
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:fps_in_flex", 0);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:fps_in_num", frameRate);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:fps_in_denorm", 1);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:fps_out_flex", 0);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:fps_out_num", frameRate);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:fps_out_denorm", 1);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupBitRate() {
|
|
uint32_t bitrate = mBitRate;
|
|
uint32_t bitrateMode = mBitrateMode;
|
|
// IntfImpl::Lock lock = mIntf->lock();
|
|
|
|
// mBitrate = mIntf->getBitrate_l();
|
|
// mBitrateMode = mIntf->getBitrateMode_l();
|
|
|
|
// bitrate = mBitrate->value;
|
|
// bitrateMode = mBitrateMode->value;
|
|
|
|
ALOGD("setupBitRate: mode %d bitrate %d", bitrateMode, bitrate);
|
|
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_target", bitrate);
|
|
switch (bitrateMode) {
|
|
case BITRATE_CONST_SKIP_ALLOWED:
|
|
case BITRATE_CONST: {
|
|
/* CBR mode has narrow bound */
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:mode", MPP_ENC_RC_MODE_CBR);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_max", bitrate * 17 / 16);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_min", bitrate * 15 / 16);
|
|
} break;
|
|
case BITRATE_IGNORE:
|
|
case BITRATE_VARIABLE_SKIP_ALLOWED:
|
|
case BITRATE_VARIABLE: {
|
|
/* VBR mode has wide bound */
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:mode", MPP_ENC_RC_MODE_VBR);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_max", bitrate * 17 / 16);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_min", bitrate * 1 / 16);
|
|
} break;
|
|
default: {
|
|
/* default use CBR mode */
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:mode", MPP_ENC_RC_MODE_CBR);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_max", bitrate * 17 / 16);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:bps_min", bitrate * 15 / 16);
|
|
} break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupProfileParams() {
|
|
int32_t profile, level;
|
|
|
|
// IntfImpl::Lock lock = mIntf->lock();
|
|
|
|
// profile = mIntf->getProfile_l(mCodingType);
|
|
// level = mIntf->getLevel_l(mCodingType);
|
|
profile = mProfile;
|
|
level = mLevel;
|
|
ALOGD("setupProfileParams: profile %d level %d", profile, level);
|
|
|
|
switch (mCodingType) {
|
|
case MPP_VIDEO_CodingAVC: {
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h264:profile", profile);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h264:level", level);
|
|
if (profile >= H264_PROFILE_HIGH) {
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h264:cabac_en", 1);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h264:cabac_idc", 0);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h264:trans8x8", 1);
|
|
}
|
|
} break;
|
|
case MPP_VIDEO_CodingHEVC: {
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h265:profile", profile);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h265:level", level);
|
|
} break;
|
|
default: {
|
|
ALOGE("setupProfileParams: unsupport coding type %d", mCodingType);
|
|
} break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupQp() {
|
|
int32_t defaultIMin = 0, defaultIMax = 0;
|
|
int32_t defaultPMin = 0, defaultPMax = 0;
|
|
int32_t qpInit = 0;
|
|
|
|
if (mCodingType == MPP_VIDEO_CodingVP8) {
|
|
defaultIMin = defaultPMin = 0;
|
|
defaultIMax = defaultPMax = 127;
|
|
qpInit = 40;
|
|
} else {
|
|
/* the quality of h264/265 range from 10~51 */
|
|
defaultIMin = defaultPMin = 10;
|
|
defaultIMax = 51;
|
|
// TODO: CTS testEncoderQualityAVCCBR 49
|
|
defaultPMax = 49;
|
|
qpInit = 26;
|
|
}
|
|
// qpInit = mQp;
|
|
int32_t iMin = defaultIMin, iMax = defaultIMax;
|
|
int32_t pMin = defaultPMin, pMax = defaultPMax;
|
|
|
|
// // IntfImpl::Lock lock = mIntf->lock();
|
|
|
|
// // std::shared_ptr<C2StreamPictureQuantizationTuning::output> qp =
|
|
// // mIntf->getPictureQuantization_l();
|
|
|
|
// for (size_t i = 0; i < qp->flexCount(); ++i) {
|
|
// const C2PictureQuantizationStruct &layer = qp->m.values[i];
|
|
|
|
// if (layer.type_ == C2Config::picture_type_t(I_FRAME)) {
|
|
// iMax = layer.max;
|
|
// iMin = layer.min;
|
|
// ALOGD("PictureQuanlitySetter: iMin %d iMax %d", iMin, iMax);
|
|
// } else if (layer.type_ == C2Config::picture_type_t(P_FRAME)) {
|
|
// pMax = layer.max;
|
|
// pMin = layer.min;
|
|
// ALOGD("PictureQuanlitySetter: pMin %d pMax %d", pMin, pMax);
|
|
// }
|
|
// }
|
|
|
|
// iMax = std::clamp(iMax, defaultIMin, defaultIMax);
|
|
// iMin = std::clamp(iMin, defaultIMin, defaultIMax);
|
|
// pMax = std::clamp(pMax, defaultPMin, defaultPMax);
|
|
// pMin = std::clamp(pMin, defaultPMin, defaultPMax);
|
|
|
|
if (qpInit > iMax || qpInit < iMin) {
|
|
qpInit = iMin;
|
|
}
|
|
|
|
ALOGD("setupQp: qpInit %d i %d-%d p %d-%d", qpInit, iMin, iMax, pMin, pMax);
|
|
|
|
switch (mCodingType) {
|
|
case MPP_VIDEO_CodingAVC:
|
|
case MPP_VIDEO_CodingHEVC: {
|
|
/*
|
|
* disable mb_rc for vepu, this cfg does not apply to rkvenc.
|
|
* since the vepu has pool performance, mb_rc will cause mosaic.
|
|
*/
|
|
mpp_enc_cfg_set_s32(mEncCfg, "hw:mb_rc_disable", 1);
|
|
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_min", pMin);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_max", pMax);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_min_i", iMin);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_max_i", iMax);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_init", qpInit);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_ip", 2);
|
|
} break;
|
|
case MPP_VIDEO_CodingVP8: {
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_min", pMin);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_max", pMax);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_min_i", iMin);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_max_i", iMax);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_init", qpInit);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "rc:qp_ip", 6);
|
|
} break;
|
|
default: {
|
|
ALOGE("setupQp: unsupport coding type %d", mCodingType);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupVuiParams() {
|
|
// ColorAspects sfAspects;
|
|
// int32_t primaries, transfer, matrixCoeffs;
|
|
// bool range;
|
|
|
|
// IntfImpl::Lock lock = mIntf->lock();
|
|
|
|
// std::shared_ptr<C2StreamColorAspectsInfo::output> colorAspects
|
|
// = mIntf->getCodedColorAspects_l();
|
|
|
|
// if (!C2Mapper::map(colorAspects->primaries, &sfAspects.mPrimaries)) {
|
|
// sfAspects.mPrimaries = android::ColorAspects::PrimariesUnspecified;
|
|
// }
|
|
// if (!C2Mapper::map(colorAspects->range, &sfAspects.mRange)) {
|
|
// sfAspects.mRange = android::ColorAspects::RangeUnspecified;
|
|
// }
|
|
// if (!C2Mapper::map(colorAspects->matrix, &sfAspects.mMatrixCoeffs)) {
|
|
// sfAspects.mMatrixCoeffs = android::ColorAspects::MatrixUnspecified;
|
|
// }
|
|
// if (!C2Mapper::map(colorAspects->transfer, &sfAspects.mTransfer)) {
|
|
// sfAspects.mTransfer = android::ColorAspects::TransferUnspecified;
|
|
// }
|
|
|
|
// ColorUtils::convertCodecColorAspectsToIsoAspects(
|
|
// sfAspects, &primaries, &transfer,
|
|
// &matrixCoeffs, &range);
|
|
|
|
// if (mEncCfg != NULL) {
|
|
// mpp_enc_cfg_set_s32(mEncCfg, "prep:range", range ? 2 : 0);
|
|
// mpp_enc_cfg_set_s32(mEncCfg, "prep:colorprim", primaries);
|
|
// mpp_enc_cfg_set_s32(mEncCfg, "prep:colortrc", transfer);
|
|
// mpp_enc_cfg_set_s32(mEncCfg, "prep:colorspace", matrixCoeffs);
|
|
// }
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupTemporalLayers() {
|
|
// size_t temporalLayers = 0;
|
|
|
|
// IntfImpl::Lock lock = mIntf->lock();
|
|
|
|
// std::shared_ptr<C2StreamTemporalLayeringTuning::output> layering =
|
|
// mIntf->getTemporalLayers_l();
|
|
|
|
// temporalLayers = layering->m.layerCount;
|
|
// if (temporalLayers == 0) {
|
|
// return true;
|
|
// }
|
|
|
|
// if (temporalLayers < 2 || temporalLayers > 4) {
|
|
// ALOGD("only support tsvc layer 2 ~ 4(%zu); ignored.",
|
|
// temporalLayers); return true;
|
|
// }
|
|
|
|
// /*
|
|
// * NOTE:
|
|
// * 1. not support set bLayerCount and bitrateRatios yet.
|
|
// * - layering->m.bLayerCount
|
|
// * - layering->m.bitrateRatios
|
|
// * 2. only support tsvc layer 2 ~ 4.
|
|
// */
|
|
|
|
// int ret = 0;
|
|
// MppEncRefCfg ref;
|
|
// MppEncRefLtFrmCfg ltRef[4];
|
|
// MppEncRefStFrmCfg stRef[16];
|
|
// RK_S32 ltCnt = 0;
|
|
// RK_S32 stCnt = 0;
|
|
|
|
// memset(<Ref, 0, sizeof(ltRef));
|
|
// memset(&stRef, 0, sizeof(stRef));
|
|
|
|
// mpp_enc_ref_cfg_init(&ref);
|
|
|
|
// ALOGD("setupTemporalLayers: layers %zu", temporalLayers);
|
|
|
|
// switch (temporalLayers) {
|
|
// case 4: {
|
|
// // tsvc4
|
|
// // /-> P1 /-> P3 /-> P5 /-> P7
|
|
// // / / / /
|
|
// // //--------> P2 //--------> P6
|
|
// // // //
|
|
// // ///---------------------> P4
|
|
// // ///
|
|
// // P0 ------------------------------------------------> P8
|
|
// ltCnt = 1;
|
|
|
|
// /* set 8 frame lt-ref gap */
|
|
// ltRef[0].lt_idx = 0;
|
|
// ltRef[0].temporal_id = 0;
|
|
// ltRef[0].ref_mode = REF_TO_PREV_LT_REF;
|
|
// ltRef[0].lt_gap = 8;
|
|
// ltRef[0].lt_delay = 0;
|
|
|
|
// stCnt = 9;
|
|
// /* set tsvc4 st-ref struct */
|
|
// /* st 0 layer 0 - ref */
|
|
// stRef[0].is_non_ref = 0;
|
|
// stRef[0].temporal_id = 0;
|
|
// stRef[0].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
// stRef[0].ref_arg = 0;
|
|
// stRef[0].repeat = 0;
|
|
// /* st 1 layer 3 - non-ref */
|
|
// stRef[1].is_non_ref = 1;
|
|
// stRef[1].temporal_id = 3;
|
|
// stRef[1].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[1].ref_arg = 0;
|
|
// stRef[1].repeat = 0;
|
|
// /* st 2 layer 2 - ref */
|
|
// stRef[2].is_non_ref = 0;
|
|
// stRef[2].temporal_id = 2;
|
|
// stRef[2].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[2].ref_arg = 0;
|
|
// stRef[2].repeat = 0;
|
|
// /* st 3 layer 3 - non-ref */
|
|
// stRef[3].is_non_ref = 1;
|
|
// stRef[3].temporal_id = 3;
|
|
// stRef[3].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[3].ref_arg = 0;
|
|
// stRef[3].repeat = 0;
|
|
// /* st 4 layer 1 - ref */
|
|
// stRef[4].is_non_ref = 0;
|
|
// stRef[4].temporal_id = 1;
|
|
// stRef[4].ref_mode = REF_TO_PREV_LT_REF;
|
|
// stRef[4].ref_arg = 0;
|
|
// stRef[4].repeat = 0;
|
|
// /* st 5 layer 3 - non-ref */
|
|
// stRef[5].is_non_ref = 1;
|
|
// stRef[5].temporal_id = 3;
|
|
// stRef[5].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[5].ref_arg = 0;
|
|
// stRef[5].repeat = 0;
|
|
// /* st 6 layer 2 - ref */
|
|
// stRef[6].is_non_ref = 0;
|
|
// stRef[6].temporal_id = 2;
|
|
// stRef[6].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[6].ref_arg = 0;
|
|
// stRef[6].repeat = 0;
|
|
// /* st 7 layer 3 - non-ref */
|
|
// stRef[7].is_non_ref = 1;
|
|
// stRef[7].temporal_id = 3;
|
|
// stRef[7].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[7].ref_arg = 0;
|
|
// stRef[7].repeat = 0;
|
|
// /* st 8 layer 0 - ref */
|
|
// stRef[8].is_non_ref = 0;
|
|
// stRef[8].temporal_id = 0;
|
|
// stRef[8].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
// stRef[8].ref_arg = 0;
|
|
// stRef[8].repeat = 0;
|
|
// } break;
|
|
// case 3: {
|
|
// // tsvc3
|
|
// // /-> P1 /-> P3
|
|
// // / /
|
|
// // //--------> P2
|
|
// // //
|
|
// // P0/---------------------> P4
|
|
// ltCnt = 0;
|
|
|
|
// stCnt = 5;
|
|
// /* set tsvc4 st-ref struct */
|
|
// /* st 0 layer 0 - ref */
|
|
// stRef[0].is_non_ref = 0;
|
|
// stRef[0].temporal_id = 0;
|
|
// stRef[0].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
// stRef[0].ref_arg = 0;
|
|
// stRef[0].repeat = 0;
|
|
// /* st 1 layer 2 - non-ref */
|
|
// stRef[1].is_non_ref = 1;
|
|
// stRef[1].temporal_id = 2;
|
|
// stRef[1].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[1].ref_arg = 0;
|
|
// stRef[1].repeat = 0;
|
|
// /* st 2 layer 1 - ref */
|
|
// stRef[2].is_non_ref = 0;
|
|
// stRef[2].temporal_id = 1;
|
|
// stRef[2].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[2].ref_arg = 0;
|
|
// stRef[2].repeat = 0;
|
|
// /* st 3 layer 2 - non-ref */
|
|
// stRef[3].is_non_ref = 1;
|
|
// stRef[3].temporal_id = 2;
|
|
// stRef[3].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[3].ref_arg = 0;
|
|
// stRef[3].repeat = 0;
|
|
// /* st 4 layer 0 - ref */
|
|
// stRef[4].is_non_ref = 0;
|
|
// stRef[4].temporal_id = 0;
|
|
// stRef[4].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
// stRef[4].ref_arg = 0;
|
|
// stRef[4].repeat = 0;
|
|
// } break;
|
|
// case 2: {
|
|
// // tsvc2
|
|
// // /-> P1
|
|
// // /
|
|
// // P0--------> P2
|
|
// ltCnt = 0;
|
|
|
|
// stCnt = 3;
|
|
// /* set tsvc4 st-ref struct */
|
|
// /* st 0 layer 0 - ref */
|
|
// stRef[0].is_non_ref = 0;
|
|
// stRef[0].temporal_id = 0;
|
|
// stRef[0].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
// stRef[0].ref_arg = 0;
|
|
// stRef[0].repeat = 0;
|
|
// /* st 1 layer 2 - non-ref */
|
|
// stRef[1].is_non_ref = 1;
|
|
// stRef[1].temporal_id = 1;
|
|
// stRef[1].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[1].ref_arg = 0;
|
|
// stRef[1].repeat = 0;
|
|
// /* st 2 layer 1 - ref */
|
|
// stRef[2].is_non_ref = 0;
|
|
// stRef[2].temporal_id = 0;
|
|
// stRef[2].ref_mode = REF_TO_PREV_REF_FRM;
|
|
// stRef[2].ref_arg = 0;
|
|
// stRef[2].repeat = 0;
|
|
// } break;
|
|
// default : {
|
|
// } break;
|
|
// }
|
|
|
|
// if (ltCnt || stCnt) {
|
|
// mpp_enc_ref_cfg_set_cfg_cnt(ref, ltCnt, stCnt);
|
|
|
|
// if (ltCnt)
|
|
// mpp_enc_ref_cfg_add_lt_cfg(ref, ltCnt, ltRef);
|
|
|
|
// if (stCnt)
|
|
// mpp_enc_ref_cfg_add_st_cfg(ref, stCnt, stRef);
|
|
|
|
// /* check and get dpb size */
|
|
// mpp_enc_ref_cfg_check(ref);
|
|
// }
|
|
|
|
// ret = mMppMpi->control(mMppCtx, MPP_ENC_SET_REF_CFG, ref);
|
|
// if (ret) {
|
|
// ALOGE("setupTemporalLayers: failed to set ref cfg ret %d", ret);
|
|
// return C2_CORRUPTED;
|
|
// }
|
|
|
|
return true;
|
|
}
|
|
|
|
bool RKMppEncApi::setupEncCfg() {
|
|
bool ret = true;
|
|
int err = 0;
|
|
|
|
err = mpp_enc_cfg_init(&mEncCfg);
|
|
if (err) {
|
|
ALOGE("failed to get enc_cfg, ret %d", err);
|
|
return false;
|
|
}
|
|
/* Video control Set Base Codec */
|
|
setupBaseCodec();
|
|
|
|
/* Video control Set Scene Mode */
|
|
setupSceneMode();
|
|
|
|
/* Video control Set FrameRates and gop */
|
|
setupFrameRate();
|
|
|
|
/* Video control Set Bitrate */
|
|
setupBitRate();
|
|
|
|
/* Video control Set Profile params */
|
|
setupProfileParams();
|
|
|
|
/* Video control Set QP */
|
|
setupQp();
|
|
|
|
/* Video control Set VUI params */
|
|
setupVuiParams();
|
|
|
|
/* Video control Set Temporal Layers */
|
|
setupTemporalLayers();
|
|
|
|
err = mMppMpi->control(mMppCtx, MPP_ENC_SET_CFG, mEncCfg);
|
|
if (err) {
|
|
ALOGE("failed to setup codec cfg, ret %d", err);
|
|
ret = false;
|
|
} else {
|
|
/* optional */
|
|
MppEncSeiMode seiMode = MPP_ENC_SEI_MODE_ONE_FRAME;
|
|
err = mMppMpi->control(mMppCtx, MPP_ENC_SET_SEI_CFG, &seiMode);
|
|
if (err) {
|
|
ALOGE("failed to setup sei cfg, ret %d", err);
|
|
ret = false;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool RKMppEncApi::initEncoder() { return true; }
|
|
|
|
bool RKMppEncApi::releaseEncoder() {
|
|
mStarted = false;
|
|
mSpsPpsHeaderReceived = false;
|
|
mSawInputEOS = false;
|
|
mOutputEOS = false;
|
|
mSignalledError = false;
|
|
|
|
if (mEncCfg) {
|
|
mpp_enc_cfg_deinit(mEncCfg);
|
|
mEncCfg = nullptr;
|
|
}
|
|
|
|
if (mMppCtx) {
|
|
mpp_destroy(mMppCtx);
|
|
mMppCtx = nullptr;
|
|
}
|
|
|
|
if (mInFile != nullptr) {
|
|
fclose(mInFile);
|
|
mInFile = nullptr;
|
|
}
|
|
|
|
if (mOutFile != nullptr) {
|
|
fclose(mOutFile);
|
|
mOutFile = nullptr;
|
|
}
|
|
return true;
|
|
}
|