312 lines
9.6 KiB
C++
Executable File
312 lines
9.6 KiB
C++
Executable File
/*
|
|
* Copyright (C) 2022 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.
|
|
*/
|
|
|
|
#undef ROCKCHIP_LOG_TAG
|
|
#define ROCKCHIP_LOG_TAG "C2RKMlvecLegacy"
|
|
|
|
#include <string.h>
|
|
|
|
#include "C2RKMlvecLegacy.h"
|
|
#include "C2RKLog.h"
|
|
|
|
C2RKMlvecLegacy::C2RKMlvecLegacy(MppCtx ctx, MppApi *mpi, MppEncCfg cfg) :
|
|
mMppCtx(ctx),
|
|
mMppMpi(mpi),
|
|
mEncCfg(cfg) {
|
|
/* default disable frame_qp setup */
|
|
mDynamicCfg.frameQP = -1;
|
|
}
|
|
|
|
C2RKMlvecLegacy::~C2RKMlvecLegacy() {
|
|
}
|
|
|
|
bool C2RKMlvecLegacy::setupMaxTid(int32_t maxTid) {
|
|
MppEncRefLtFrmCfg ltRef[16];
|
|
MppEncRefStFrmCfg stRef[16];
|
|
int32_t ltCfgCnt = 0;
|
|
int32_t stCfgCnt = 0;
|
|
int32_t tid0Loop = 0;
|
|
int32_t numLtrFrms = mStaticCfg.ltrFrames;
|
|
int ret;
|
|
|
|
memset(ltRef, 0, sizeof(ltRef));
|
|
memset(stRef, 0, sizeof(stRef));
|
|
|
|
c2_info("max_tid %d numLtrFrms %d ", maxTid, numLtrFrms);
|
|
|
|
switch (maxTid) {
|
|
case 1: {
|
|
stRef[0].is_non_ref = 0;
|
|
stRef[0].temporal_id = 0;
|
|
stRef[0].ref_mode = REF_TO_PREV_REF_FRM;
|
|
stRef[0].ref_arg = 0;
|
|
stRef[0].repeat = 0;
|
|
|
|
stCfgCnt = 1;
|
|
tid0Loop = 1;
|
|
c2_info("no tsvc");
|
|
} break;
|
|
case 2: {
|
|
/* set tsvc2 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_PREV_REF_FRM;
|
|
stRef[0].ref_arg = 0;
|
|
stRef[0].repeat = 0;
|
|
/* st 1 layer 1 - 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 0 - 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;
|
|
|
|
stCfgCnt = 3;
|
|
tid0Loop = 2;
|
|
c2_info("tsvc2");
|
|
} break;
|
|
case 3: {
|
|
/* set tsvc3 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 = 0;
|
|
stRef[1].temporal_id = 2;
|
|
stRef[1].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
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_TEMPORAL_LAYER;
|
|
stRef[2].ref_arg = 0;
|
|
stRef[2].repeat = 0;
|
|
/* st 3 layer 2 - non-ref */
|
|
stRef[3].is_non_ref = 0;
|
|
stRef[3].temporal_id = 2;
|
|
stRef[3].ref_mode = REF_TO_TEMPORAL_LAYER;
|
|
stRef[3].ref_arg = 1;
|
|
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;
|
|
|
|
stCfgCnt = 5;
|
|
tid0Loop = 4;
|
|
c2_info("tsvc3");
|
|
} break;
|
|
case 4: {
|
|
/* set tsvc3 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_TEMPORAL_LAYER;
|
|
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_PREV_REF_FRM;
|
|
stRef[8].ref_arg = 0;
|
|
stRef[8].repeat = 0;
|
|
|
|
stCfgCnt = 9;
|
|
tid0Loop = 8;
|
|
c2_info("tsvc4");
|
|
} break;
|
|
default : {
|
|
c2_err("invalid max temporal layer id %d", maxTid);
|
|
} break;
|
|
}
|
|
|
|
if (numLtrFrms) {
|
|
int32_t i;
|
|
|
|
ltCfgCnt = numLtrFrms;
|
|
for (i = 0; i < numLtrFrms; i++) {
|
|
ltRef[i].lt_idx = i;
|
|
ltRef[i].temporal_id = 0;
|
|
ltRef[i].ref_mode = REF_TO_PREV_LT_REF;
|
|
ltRef[i].lt_gap = 0;
|
|
ltRef[i].lt_delay = tid0Loop * i;
|
|
}
|
|
}
|
|
|
|
c2_info("ltCfgCnt %d stCfgCnt %d", ltCfgCnt, stCfgCnt);
|
|
if (ltCfgCnt || stCfgCnt) {
|
|
MppEncRefCfg ref = nullptr;
|
|
|
|
mpp_enc_ref_cfg_init(&ref);
|
|
|
|
mpp_enc_ref_cfg_set_cfg_cnt(ref, ltCfgCnt, stCfgCnt);
|
|
mpp_enc_ref_cfg_add_lt_cfg(ref, ltCfgCnt, ltRef);
|
|
mpp_enc_ref_cfg_add_st_cfg(ref, stCfgCnt, stRef);
|
|
mpp_enc_ref_cfg_set_keep_cpb(ref, 1);
|
|
mpp_enc_ref_cfg_check(ref);
|
|
|
|
ret = mMppMpi->control(mMppCtx, MPP_ENC_SET_REF_CFG, ref);
|
|
if (ret) {
|
|
c2_err("failed to set ref cfg, ret %d", ret);
|
|
return false;
|
|
}
|
|
|
|
mpp_enc_ref_cfg_deinit(&ref);
|
|
} else {
|
|
ret = mMppMpi->control(mMppCtx, MPP_ENC_SET_REF_CFG, nullptr);
|
|
if (ret) {
|
|
c2_err("failed to set ref cfg, ret %d", ret);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool C2RKMlvecLegacy::setupStaticConfig(MStaticCfg *cfg) {
|
|
int32_t magic = cfg->magic;
|
|
|
|
if ((((magic >> 24) & 0xff) != MLVEC_MAGIC) ||
|
|
(((magic >> 16) & 0xff) != MLVEC_VERSION)) {
|
|
c2_err("failed to check mlvec cfg magic %08x", magic);
|
|
return false;
|
|
}
|
|
|
|
c2_info("add_prefix %d", cfg->addPrefix);
|
|
mpp_enc_cfg_set_s32(mEncCfg, "h264:prefix_mode", cfg->addPrefix);
|
|
|
|
c2_info("slice_mbs %d", cfg->sliceMbs);
|
|
if (cfg->sliceMbs) {
|
|
mpp_enc_cfg_set_u32(mEncCfg, "split:mode", MPP_ENC_SPLIT_BY_CTU);
|
|
mpp_enc_cfg_set_u32(mEncCfg, "split:arg", cfg->sliceMbs);
|
|
} else {
|
|
mpp_enc_cfg_set_u32(mEncCfg, "split:mode", MPP_ENC_SPLIT_NONE);
|
|
}
|
|
|
|
memcpy(&mStaticCfg, cfg, sizeof(mStaticCfg));
|
|
|
|
/* NOTE: ltr_frames is already configured */
|
|
setupMaxTid(cfg->maxTid);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool C2RKMlvecLegacy::setupDynamicConfig(MDynamicCfg *cfg, MppMeta meta) {
|
|
MDynamicCfg *dst = &mDynamicCfg;
|
|
|
|
/* clear non-sticky flag first */
|
|
dst->markLtr = -1;
|
|
dst->useLtr = -1;
|
|
/* frame qp and base layer pid is sticky flag */
|
|
|
|
/* update flags */
|
|
if (cfg->updated) {
|
|
if (cfg->updated & MLVEC_ENC_MARK_LTR_UPDATED)
|
|
dst->markLtr = cfg->markLtr;
|
|
|
|
if (cfg->updated & MLVEC_ENC_USE_LTR_UPDATED) {
|
|
int32_t i = 0, found = 0;
|
|
for (i = 0; i < (MLVEC_MAX_LAYER_COUNT - 1); i++) {
|
|
if (((cfg->useLtr >> i) & 1) == 1) {
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
dst->useLtr = (found == 1) ? i : 0;
|
|
}
|
|
|
|
if (cfg->updated & MLVEC_ENC_FRAME_QP_UPDATED)
|
|
dst->frameQP = cfg->frameQP;
|
|
|
|
if (cfg->updated & MLVEC_ENC_BASE_PID_UPDATED)
|
|
dst->baseLayerPid = cfg->baseLayerPid;
|
|
|
|
cfg->updated = 0;
|
|
}
|
|
|
|
c2_info("ltr mark %2d use %2d frm qp %2d blpid %d", dst->markLtr,
|
|
dst->useLtr, dst->frameQP, dst->baseLayerPid);
|
|
|
|
/* setup next frame configure */
|
|
if (dst->markLtr >= 0)
|
|
mpp_meta_set_s32(meta, KEY_ENC_MARK_LTR, dst->markLtr);
|
|
|
|
if (dst->useLtr >= 0)
|
|
mpp_meta_set_s32(meta, KEY_ENC_USE_LTR, dst->useLtr);
|
|
|
|
if (dst->frameQP >= 0)
|
|
mpp_meta_set_s32(meta, KEY_ENC_FRAME_QP, dst->frameQP);
|
|
|
|
if (dst->baseLayerPid >= 0)
|
|
mpp_meta_set_s32(meta, KEY_ENC_BASE_LAYER_PID, dst->baseLayerPid);
|
|
|
|
return true;
|
|
}
|