/* * Copyright 2020 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. */ #include #include "mpp_mem.h" #include "mpp_2str.h" #include "mpp_debug.h" #include "mpp_common.h" #include "hal_info.h" typedef struct HalInfoImpl_t { MppCtxType type; MppCodingType coding; RK_U32 updated; RK_U32 elem_nb; /* info data for output */ MppDevInfoCfg *elems; } HalInfoImpl; MPP_RET hal_info_init(HalInfo *ctx, MppCtxType type, MppCodingType coding) { if (NULL == ctx) { mpp_err_f("found NULL input ctx\n"); return MPP_ERR_NULL_PTR; } MPP_RET ret = MPP_NOK; RK_U32 elem_nb = (type == MPP_CTX_DEC) ? (ENC_INFO_BUTT) : (DEC_INFO_BUTT); HalInfoImpl *impl = mpp_calloc_size(HalInfoImpl, sizeof(HalInfoImpl) + sizeof(MppDevInfoCfg) * elem_nb); if (impl) { impl->type = type; impl->coding = coding; impl->elem_nb = elem_nb; impl->elems = (MppDevInfoCfg *)(impl + 1); ret = MPP_OK; } *ctx = impl; return ret; } MPP_RET hal_info_deinit(HalInfo ctx) { MPP_FREE(ctx); return MPP_OK; } MPP_RET hal_info_set(HalInfo ctx, RK_U32 type, RK_U32 flag, RK_U64 data) { if (NULL == ctx) { mpp_err_f("found NULL input ctx\n"); return MPP_ERR_NULL_PTR; } if (flag <= CODEC_INFO_FLAG_NULL || flag >= CODEC_INFO_FLAG_BUTT) { mpp_err_f("found invalid flag %d\n", flag); return MPP_ERR_VALUE; } HalInfoImpl *info = (HalInfoImpl *)ctx; MppDevInfoCfg *elems = NULL; switch (info->type) { case MPP_CTX_DEC : { if (type <= DEC_INFO_BASE || type >= DEC_INFO_BUTT) { mpp_err_f("found invalid dec info type %d [%d:%d]\n", type, DEC_INFO_BASE, DEC_INFO_BUTT); return MPP_ERR_VALUE; } /* shift enum base */ type -= DEC_INFO_BASE; } break; case MPP_CTX_ENC : { if (type <= ENC_INFO_BASE || type >= ENC_INFO_BUTT) { mpp_err_f("found invalid enc info type %d [%d:%d]\n", type, ENC_INFO_BASE, ENC_INFO_BUTT); return MPP_ERR_VALUE; } /* shift enum base */ type -= ENC_INFO_BASE; } break; default : { mpp_err_f("found invalid ctx type %d\n", info->type); return MPP_ERR_VALUE; } break; } elems = &info->elems[type]; if (elems->type != type || elems->flag != flag || elems->data != data) { /* set enc info */ elems->type = type; elems->flag = flag; elems->data = data; info->updated |= (1 << type); } return MPP_OK; } MPP_RET hal_info_get(HalInfo ctx, MppDevInfoCfg *data, RK_S32 *size) { if (NULL == ctx) { mpp_err_f("found NULL input ctx\n"); return MPP_ERR_NULL_PTR; } if (NULL == data || NULL == size || *size == 0) { mpp_err_f("found invalid output cfg data %p size %p\n", data, size); return MPP_ERR_NULL_PTR; } HalInfoImpl *info = (HalInfoImpl *)ctx; if (!info->updated) { *size = 0; return MPP_OK; } RK_S32 max_size = *size; RK_S32 elem_size = sizeof(info->elems[0]); RK_S32 out_size = 0; RK_S32 type_max = 0; RK_S32 i; switch (info->type) { case MPP_CTX_DEC : { type_max = DEC_INFO_BUTT - DEC_INFO_BASE; } break; case MPP_CTX_ENC : { type_max = ENC_INFO_BUTT - ENC_INFO_BASE; } break; default : { mpp_err_f("found invalid ctx type %d\n", info->type); return MPP_ERR_VALUE; } break; } for (i = 0; i < type_max; i++) { if (!(info->updated & (1 << i))) continue; if (out_size + elem_size > max_size) { mpp_err_f("out data size %d is too small for %d\n", max_size, out_size + elem_size); break; } memcpy(data, &info->elems[i], elem_size); data++; out_size += elem_size; info->updated &= ~(1 << i); } *size = out_size; return MPP_OK; } RK_U64 hal_info_to_string(HalInfo ctx, RK_U32 type, void *val) { RK_U64 ret = 0; if (NULL == ctx || NULL == val) { mpp_err_f("found NULL input ctx %p val %p\n", ctx, val); return ret; } HalInfoImpl *info = (HalInfoImpl *)ctx; const char *str = NULL; switch (info->type) { case MPP_CTX_DEC : { switch (type) { case DEC_INFO_FORMAT : { MppCodingType coding = *((MppCodingType *)val); mpp_assert(coding == info->coding); str = strof_coding_type(coding); } break; default : { } break; } } break; case MPP_CTX_ENC : { switch (type) { case ENC_INFO_FORMAT : { MppCodingType coding = *((MppCodingType *)val); mpp_assert(coding == info->coding); str = strof_coding_type(coding); } break; case ENC_INFO_RC_MODE : { MppEncRcMode rc_mode = *((MppEncRcMode *)val); str = strof_rc_mode(rc_mode); } break; case ENC_INFO_PROFILE : { RK_U32 profile = *((RK_U32 *)val); str = strof_profle(info->coding, profile); } break; default : { } break; } } break; default : { mpp_err_f("found invalid ctx type %d\n", info->type); return MPP_ERR_VALUE; } break; } if (str) snprintf((void *)&ret, sizeof(ret) - 1, "%s", str); return ret; } RK_U64 hal_info_to_float(RK_S32 num, RK_S32 denorm) { RK_U64 ret = 0; if (!denorm) snprintf((void *)&ret, sizeof(ret) - 1, "%d", num); else snprintf((void *)&ret, sizeof(ret) - 1, "%.2f", (float)num / denorm); return ret; } MPP_RET hal_info_from_enc_cfg(HalInfo ctx, MppEncCfgSet *cfg) { MppEncRcCfg *rc = &cfg->rc; MppEncPrepCfg *prep = &cfg->prep; MppEncCodecCfg *codec = &cfg->codec; HalInfoImpl *info = (HalInfoImpl *)ctx; RK_U32 profile = 0; RK_U64 val = 0; hal_info_set(ctx, ENC_INFO_WIDTH, CODEC_INFO_FLAG_NUMBER, prep->width); hal_info_set(ctx, ENC_INFO_HEIGHT, CODEC_INFO_FLAG_NUMBER, prep->height); val = hal_info_to_string(ctx, ENC_INFO_FORMAT, &info->coding); hal_info_set(ctx, ENC_INFO_FORMAT, CODEC_INFO_FLAG_STRING, val); hal_info_set(ctx, ENC_INFO_FPS_IN, CODEC_INFO_FLAG_NUMBER, rc->fps_in_num / rc->fps_in_denorm); hal_info_set(ctx, ENC_INFO_FPS_OUT, CODEC_INFO_FLAG_NUMBER, rc->fps_out_num / rc->fps_out_denorm); val = hal_info_to_string(ctx, ENC_INFO_RC_MODE, &rc->rc_mode); hal_info_set(ctx, ENC_INFO_RC_MODE, CODEC_INFO_FLAG_STRING, val); hal_info_set(ctx, ENC_INFO_BITRATE, CODEC_INFO_FLAG_NUMBER, rc->bps_target); hal_info_set(ctx, ENC_INFO_GOP_SIZE, CODEC_INFO_FLAG_NUMBER, rc->gop); switch (info->coding) { case MPP_VIDEO_CodingAVC : { profile = codec->h264.profile; } break; case MPP_VIDEO_CodingHEVC : { profile = codec->h265.profile; } break; case MPP_VIDEO_CodingMJPEG : case MPP_VIDEO_CodingVP8 : default : { } break; } val = hal_info_to_string(ctx, ENC_INFO_PROFILE, &profile); hal_info_set(ctx, ENC_INFO_PROFILE, CODEC_INFO_FLAG_STRING, val); return MPP_OK; }