| /****************************************************************************** |
| * |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * 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. |
| * |
| ***************************************************************************** |
| * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| */ |
| #include <cmath> |
| #include <cstdlib> |
| #include <cstring> |
| #include <memory> |
| #include <numeric> |
| #include <utility> |
| #include <vector> |
| |
| #include "ih264_typedefs.h" |
| #include "iv2.h" |
| #include "ive2.h" |
| #include "isvce.h" |
| |
| constexpr WORD32 kMeSpeedPreset[] = {100}; |
| constexpr WORD32 kDeblkLevel[] = {0, 2, 3, 4}; |
| constexpr IVE_AIR_MODE_T kAirMode[] = {IVE_AIR_MODE_NONE}; |
| constexpr IVE_SPEED_CONFIG kEncSpeed[] = {IVE_CONFIG, IVE_SLOWEST, IVE_NORMAL, |
| IVE_FAST, IVE_HIGH_SPEED, IVE_FASTEST}; |
| constexpr IV_PROFILE_T kProfile[] = {IV_PROFILE_BASE, IV_PROFILE_MAIN}; |
| constexpr IVE_RC_MODE_T kRCMode[] = {IVE_RC_NONE, IVE_RC_STORAGE, IVE_RC_CBR_NON_LOW_DELAY, |
| IVE_RC_CBR_LOW_DELAY}; |
| constexpr IV_COLOR_FORMAT_T kSupportedColorFormats[] = {IV_YUV_420P, IV_YUV_420SP_UV}; |
| constexpr WORD32 kSupportedLevels[] = {10, 9, 11, 12, 13, 20, 21, 22, |
| 30, 31, 32, 40, 41, 42, 50, 51}; |
| constexpr IVE_SLICE_MODE_T kSliceMode[] = {IVE_SLICE_MODE_NONE}; |
| constexpr IV_ARCH_T kArchs[] = { |
| ARCH_ARM_NONEON, ARCH_ARM_A9Q, ARCH_ARM_A9A, ARCH_ARM_A9, ARCH_ARM_A7, |
| ARCH_ARM_A5, ARCH_ARM_A15, ARCH_ARM_NEONINTR, ARCH_X86_GENERIC, ARCH_X86_SSSE3, |
| ARCH_X86_SSE42, ARCH_ARM_A53, ARCH_ARM_A57, ARCH_ARM_V8_NEON}; |
| constexpr DOUBLE kSpatialResRatio[] = {1.5, 2}; |
| constexpr UWORD8 kSpatialLayers[] = {1, 2, 3}; |
| constexpr UWORD8 kTemporalLayers[] = {1, 2, 3}; |
| constexpr size_t kAirModeNum = std::size(kAirMode); |
| constexpr size_t kEncSpeedNum = std::size(kEncSpeed); |
| constexpr size_t kMeSpeedPresetNum = std::size(kMeSpeedPreset); |
| constexpr size_t kDeblkLevelNum = std::size(kDeblkLevel); |
| constexpr size_t kProfileNum = std::size(kProfile); |
| constexpr size_t kRCModeNum = std::size(kRCMode); |
| constexpr size_t kSupportedColorFormatsNum = std::size(kSupportedColorFormats); |
| constexpr size_t kSupportedLevelsNum = std::size(kSupportedLevels); |
| constexpr size_t kSliceModeNum = std::size(kSliceMode); |
| constexpr size_t kSpatialResRatioNum = std::size(kSpatialResRatio); |
| constexpr size_t kSpatialLayersNum = std::size(kSpatialLayers); |
| constexpr size_t kTemporalLayersNum = std::size(kTemporalLayers); |
| constexpr size_t kMinQP = 0; |
| constexpr size_t kMaxQP = 51; |
| constexpr size_t kMaxWidth = 2560; |
| constexpr size_t kMaxHeight = 2560; |
| constexpr size_t kMaxBitrate = 500000000; |
| constexpr UWORD8 kNumSeiMdcvPrimaries = 3; |
| constexpr UWORD8 kNumSeiCcvPrimaries = 3; |
| constexpr double kSvcCompliantDimProb = 0.75; |
| constexpr size_t kMaxEncodeCalls = 100; |
| |
| typedef enum ARG_INDICES_T |
| { |
| IDX_WD_BYTE_1, |
| IDX_WD_BYTE_2, |
| IDX_HT_BYTE_1, |
| IDX_HT_BYTE_2, |
| IDX_COLOR_FORMAT, |
| IDX_ARCH_TYPE, |
| IDX_RC_MODE, |
| IDX_NUM_CORES, |
| IDX_NUM_ARCH, |
| IDX_NUM_B_FRAMES, |
| IDX_ENC_SPEED, |
| IDX_CONSTRAINED_INTRA_FLAG, |
| IDX_INTRA_4x4, |
| IDX_I_FRAME_QP, |
| IDX_P_FRAME_QP, |
| IDX_B_FRAME_QP, |
| IDX_BITRATE_BYTE_1, |
| IDX_BITRATE_BYTE_2, |
| IDX_FRAME_RATE, |
| IDX_INTRA_REFRESH, |
| IDX_ENABLE_HALF_PEL, |
| IDX_ENABLE_Q_PEL, |
| IDX_ME_SPEED_PRESET, |
| IDX_AIR_MODE, |
| IDX_DISABLE_DEBLOCK_LEVEL, |
| IDX_SEARCH_RANGE_X, |
| IDX_SEARCH_RANGE_Y, |
| IDX_I_INTERVAL, |
| IDX_IDR_INTERVAL, |
| IDX_SEI_MDCV_FLAG, |
| IDX_SEI_CLL_FLAG, |
| IDX_SEI_AVE_FLAG, |
| IDX_SEI_CCV_FLAG, |
| IDX_PROFILE, |
| IDX_ASPECT_RATIO_FLAG, |
| IDX_NAL_HRD_FLAG, |
| IDX_VCL_HRD_FLAG, |
| IDX_ENABLE_FORCE_IDR, |
| IDX_ENABLE_DYNAMIC_BITRATE, |
| IDX_ENABLE_DYNAMIC_FRAME_RATE, |
| IDX_FORCE_IDR_INTERVAL, |
| IDX_DYNAMIC_BITRATE_INTERVAL, |
| IDX_DYNAMIC_FRAME_RATE_INTERVAL, |
| IDX_ENC_LEVEL, |
| IDX_RECON_FMT, |
| IDX_SLICE_MODE, |
| IDX_ENABLE_FAST_SAD, |
| IDX_NUM_SPATIAL_LAYERS, |
| IDX_NUM_TEMPORAL_LAYERS, |
| IDX_SPATIAL_RES_RATIO, |
| IDX_SVC_COMPLIANT_DIMS, |
| IDX_ENABLE_RECON, |
| IDX_ENABLE_NALU_INFO_EXPORT, |
| IDX_LAST |
| } ARG_INDICES_T; |
| |
| class Codec |
| { |
| public: |
| struct FrameDims |
| { |
| size_t mWidth; |
| size_t mHeight; |
| |
| FrameDims(size_t w, size_t h) : mWidth(w), mHeight(h) {} |
| FrameDims(const std::pair<size_t, size_t> &dimPair) |
| : FrameDims(dimPair.first, dimPair.second) |
| { |
| } |
| FrameDims(const FrameDims &other) : FrameDims(other.mWidth, other.mHeight) {} |
| |
| void operator=(const FrameDims &other) |
| { |
| mWidth = other.mWidth; |
| mHeight = other.mHeight; |
| } |
| |
| size_t getFrameSize() const { return (mWidth * mHeight * 3) / 2; }; |
| }; |
| |
| struct EncBufs |
| { |
| std::vector<UWORD8> mInputBuf; |
| std::vector<UWORD8> mOutputBuf; |
| std::vector<UWORD8> mReconBuf; |
| std::vector<isvce_nalu_info_buf_t> mNaluInfoStructBuf; |
| std::vector<std::vector<UWORD8>> mNaluInfoDataBuf; |
| }; |
| |
| Codec() |
| : mCodecCtx(nullptr), |
| mMemRecords(), |
| mMemRecBufs(), |
| mEncBufs(), |
| mAirMode(IVE_AIR_MODE_NONE), |
| mEncSpeed(IVE_NORMAL), |
| mRCMode(IVE_RC_NONE), |
| mArch(ARCH_NA), |
| mSliceMode(IVE_SLICE_MODE_NONE), |
| mIvVideoColorFormat(IV_YUV_420P), |
| mProfile(IV_PROFILE_BASE), |
| mSvcCompDims{kMaxWidth, kMaxHeight}, |
| mInputDims{kMaxWidth, kMaxHeight}, |
| mHalfPelEnable(1), |
| mQPelEnable(1), |
| mIntra4x4(0), |
| mEnableFastSad(0), |
| mEnableAltRef(0), |
| mConstrainedIntraFlag(0), |
| mSeiCllFlag(1), |
| mSeiAveFlag(1), |
| mSeiCcvFlag(1), |
| mSeiMdcvFlag(1), |
| mAspectRatioFlag(0), |
| mNalHrdFlag(0), |
| mVclHrdFlag(0), |
| mIsForceIdrEnabled(false), |
| mIsDynamicBitRateChangeEnabled(false), |
| mIsDynamicFrameRateChangeEnabled(false), |
| mEnableRecon(false), |
| mEnableNaluInfoExport(false), |
| mAvcEncLevel(41), |
| mNumMemRecords(0), |
| mNumCores(1), |
| mBframes(0), |
| mSliceParam(256), |
| mMeSpeedPreset(100), |
| mIInterval(60), |
| mIDRInterval(60), |
| mDisableDeblockLevel(0), |
| m_I_QP(22), |
| m_P_QP(28), |
| m_B_QP(22), |
| mIntraRefresh(30), |
| mSearchRangeX(64), |
| mSearchRangeY(48), |
| mForceIdrInterval(0), |
| mDynamicBitRateInterval(0), |
| mDynamicFrameRateInterval(0), |
| mBitrate(6000000), |
| mFrameRate(30), |
| mNumSpatialLayers(1), |
| mNumTemporalLayers(1), |
| mSpatialResRatio(2) |
| { |
| } |
| |
| ~Codec() { delMemRecs(); }; |
| |
| bool initEncoder(const UWORD8 *data); |
| bool encodeFrames(const UWORD8 *data, size_t size); |
| |
| private: |
| void setEncParams(iv_raw_buf_t *psInpRawBuf, std::vector<UWORD8> &buf, const FrameDims &dims, |
| IV_COLOR_FORMAT_T colorFormat = IV_YUV_420P); |
| void setFrameType(IV_PICTURE_CODING_TYPE_T eFrameType); |
| void setQp(); |
| void setEncMode(IVE_ENC_MODE_T eEncMode); |
| void setDimensions(); |
| void setNumCores(); |
| void setFrameRate(); |
| void setIpeParams(); |
| void setBitRate(); |
| void setAirParams(); |
| void setMeParams(); |
| void setGopParams(); |
| void setProfileParams(); |
| void setDeblockParams(); |
| void setVbvParams(); |
| void setDefault(); |
| void setVuiParams(); |
| void getBufInfo(); |
| void setSeiMdcvParams(); |
| void setSeiCllParams(); |
| void setSeiAveParams(); |
| void setSeiCcvParams(); |
| void logVersion(); |
| void initEncBufs(); |
| bool initMemRecs(); |
| void delMemRecs(); |
| |
| iv_obj_t *mCodecCtx; |
| std::vector<iv_mem_rec_t> mMemRecords; |
| std::vector<UWORD8 *> mMemRecBufs; |
| EncBufs mEncBufs; |
| |
| IVE_AIR_MODE_T mAirMode; |
| IVE_SPEED_CONFIG mEncSpeed; |
| IVE_RC_MODE_T mRCMode; |
| IV_ARCH_T mArch; |
| IVE_SLICE_MODE_T mSliceMode; |
| IV_COLOR_FORMAT_T mIvVideoColorFormat; |
| IV_PROFILE_T mProfile; |
| FrameDims mSvcCompDims; |
| FrameDims mInputDims; |
| |
| bool mHalfPelEnable; |
| bool mQPelEnable; |
| bool mIntra4x4; |
| bool mEnableFastSad; |
| bool mEnableAltRef; |
| bool mConstrainedIntraFlag; |
| bool mSeiCllFlag; |
| bool mSeiAveFlag; |
| bool mSeiCcvFlag; |
| bool mSeiMdcvFlag; |
| bool mAspectRatioFlag; |
| bool mNalHrdFlag; |
| bool mVclHrdFlag; |
| bool mIsForceIdrEnabled; |
| bool mIsDynamicBitRateChangeEnabled; |
| bool mIsDynamicFrameRateChangeEnabled; |
| bool mEnableRecon; |
| bool mEnableNaluInfoExport; |
| UWORD32 mAvcEncLevel; |
| UWORD32 mNumMemRecords; |
| UWORD32 mNumCores; |
| UWORD32 mBframes; |
| UWORD32 mSliceParam; |
| UWORD32 mMeSpeedPreset; |
| UWORD32 mIInterval; |
| UWORD32 mIDRInterval; |
| UWORD32 mDisableDeblockLevel; |
| UWORD32 m_I_QP; |
| UWORD32 m_P_QP; |
| UWORD32 m_B_QP; |
| UWORD32 mIntraRefresh; |
| UWORD32 mSearchRangeX; |
| UWORD32 mSearchRangeY; |
| /* Units - number of frames */ |
| UWORD32 mForceIdrInterval; |
| /* Units - number of frames */ |
| UWORD32 mDynamicBitRateInterval; |
| /* Units - number of frames */ |
| UWORD32 mDynamicFrameRateInterval; |
| UWORD64 mBitrate; |
| DOUBLE mFrameRate; |
| UWORD8 mNumSpatialLayers; |
| UWORD8 mNumTemporalLayers; |
| DOUBLE mSpatialResRatio; |
| }; |
| |
| void Codec::initEncBufs() |
| { |
| size_t frameSize = mInputDims.getFrameSize(); |
| constexpr size_t minOutBufSize = 0x800; |
| size_t outBufSize = std::max(minOutBufSize, frameSize * mNumSpatialLayers); |
| size_t naluInfoBufSize = 460 * mNumSpatialLayers; |
| |
| mEncBufs.mInputBuf.resize(frameSize); |
| mEncBufs.mOutputBuf.resize(outBufSize); |
| |
| if(mEnableRecon) |
| { |
| mEncBufs.mReconBuf.resize(frameSize); |
| } |
| |
| if(mEnableNaluInfoExport) |
| { |
| mEncBufs.mNaluInfoStructBuf.resize(mNumSpatialLayers * 2); |
| mEncBufs.mNaluInfoDataBuf.resize(mNumSpatialLayers); |
| |
| for(auto i = 0; i < mNumSpatialLayers; i++) |
| { |
| mEncBufs.mNaluInfoDataBuf[i].resize(naluInfoBufSize); |
| } |
| } |
| } |
| |
| bool Codec::initMemRecs() |
| { |
| std::fill(mMemRecBufs.begin(), mMemRecBufs.end(), nullptr); |
| |
| for(auto i = 0u; i < mNumMemRecords; i++) |
| { |
| mMemRecBufs[i] = reinterpret_cast<UWORD8 *>( |
| aligned_alloc(mMemRecords[i].u4_mem_alignment, mMemRecords[i].u4_mem_size)); |
| mMemRecords[i].pv_base = mMemRecBufs[i]; |
| |
| if(nullptr == mMemRecBufs[i]) |
| { |
| for(auto j = 0u; j < i; j++) |
| { |
| free(mMemRecBufs[j]); |
| } |
| |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| void Codec::delMemRecs() |
| { |
| for(auto i = 0u; i < mNumMemRecords; i++) |
| { |
| if(mMemRecBufs[i]) |
| { |
| free(mMemRecBufs[i]); |
| } |
| } |
| |
| std::fill(mMemRecBufs.begin(), mMemRecBufs.end(), nullptr); |
| } |
| |
| bool Codec::initEncoder(const UWORD8 *data) |
| { |
| mInputDims = FrameDims{((data[IDX_WD_BYTE_1] << 8) | data[IDX_WD_BYTE_2]) % kMaxWidth, |
| ((data[IDX_HT_BYTE_1] << 8) | data[IDX_HT_BYTE_2]) % kMaxHeight}; |
| |
| mNumSpatialLayers = kSpatialLayers[data[IDX_NUM_SPATIAL_LAYERS] % kSpatialLayersNum]; |
| mNumTemporalLayers = kTemporalLayers[data[IDX_NUM_TEMPORAL_LAYERS] % kTemporalLayersNum]; |
| mSpatialResRatio = kSpatialResRatio[data[IDX_SPATIAL_RES_RATIO] % kSpatialResRatioNum]; |
| bool useSvcCompliantDims = |
| data[IDX_SVC_COMPLIANT_DIMS] < |
| static_cast<UWORD8>(std::numeric_limits<UWORD8>::max() * kSvcCompliantDimProb); |
| |
| if(useSvcCompliantDims) |
| { |
| auto getSvcCompliantDims = [&]() -> FrameDims |
| { |
| auto maxResRatio = pow(mSpatialResRatio, mNumSpatialLayers - 1); |
| UWORD32 dimPadding = 0; |
| UWORD32 numDecimalDigits = mNumSpatialLayers; |
| constexpr auto minDimGcd = 16; |
| UWORD32 decPtDelMultiplier = static_cast<UWORD32>(std::pow(10, numDecimalDigits)); |
| FrameDims dims{mInputDims}; |
| |
| if(std::fmod(minDimGcd, maxResRatio)) |
| { |
| dimPadding = std::lcm(minDimGcd * decPtDelMultiplier, |
| static_cast<UWORD32>(maxResRatio * decPtDelMultiplier)) / |
| decPtDelMultiplier; |
| } |
| else |
| { |
| dimPadding = static_cast<UWORD32>(minDimGcd * maxResRatio); |
| } |
| |
| if(mInputDims.mWidth % dimPadding) |
| { |
| dims.mWidth = mInputDims.mWidth - ((mInputDims.mWidth) % dimPadding) + dimPadding; |
| } |
| |
| if(mInputDims.mHeight % dimPadding) |
| { |
| dims.mHeight = |
| mInputDims.mHeight - ((mInputDims.mHeight) % dimPadding) + dimPadding; |
| } |
| |
| return dims; |
| }; |
| |
| mSvcCompDims = getSvcCompliantDims(); |
| mInputDims = mSvcCompDims; |
| } |
| |
| mIvVideoColorFormat = |
| kSupportedColorFormats[data[IDX_COLOR_FORMAT] % kSupportedColorFormatsNum]; |
| mArch = kArchs[data[IDX_ARCH_TYPE] % std::size(kArchs)]; |
| mRCMode = kRCMode[data[IDX_RC_MODE] % kRCModeNum]; |
| mNumCores = (data[IDX_NUM_CORES] & 0x07) + 1; |
| mBframes = 0; |
| |
| mEncSpeed = kEncSpeed[data[IDX_ENC_SPEED] % kEncSpeedNum]; |
| mConstrainedIntraFlag = data[IDX_CONSTRAINED_INTRA_FLAG] & 0x01; |
| mIntra4x4 = data[IDX_INTRA_4x4] & 0x01; |
| m_I_QP = data[IDX_I_FRAME_QP]; |
| m_P_QP = data[IDX_P_FRAME_QP]; |
| m_B_QP = data[IDX_B_FRAME_QP]; |
| mBitrate = (((data[IDX_BITRATE_BYTE_1] << 8) | data[IDX_BITRATE_BYTE_2]) * 1000) % kMaxBitrate; |
| mFrameRate = data[IDX_FRAME_RATE] % 120; |
| mIntraRefresh = data[IDX_INTRA_REFRESH] + 1; |
| mHalfPelEnable = data[IDX_ENABLE_HALF_PEL] & 0x01; |
| mQPelEnable = data[IDX_ENABLE_Q_PEL] & 0x01; |
| mMeSpeedPreset = kMeSpeedPreset[data[IDX_ME_SPEED_PRESET] % kMeSpeedPresetNum]; |
| mAirMode = kAirMode[data[IDX_AIR_MODE] % kAirModeNum]; |
| mDisableDeblockLevel = kDeblkLevel[data[IDX_DISABLE_DEBLOCK_LEVEL] % kDeblkLevelNum]; |
| mSearchRangeX = data[IDX_SEARCH_RANGE_X]; |
| mSearchRangeY = data[IDX_SEARCH_RANGE_Y]; |
| mIInterval = data[IDX_I_INTERVAL] + 1; |
| mIDRInterval = data[IDX_IDR_INTERVAL] + 1; |
| mSeiMdcvFlag = data[IDX_SEI_MDCV_FLAG] & 0x01; |
| mSeiCllFlag = data[IDX_SEI_CLL_FLAG] & 0x01; |
| mSeiAveFlag = data[IDX_SEI_AVE_FLAG] & 0x01; |
| mSeiCcvFlag = data[IDX_SEI_CCV_FLAG] & 0x01; |
| mProfile = kProfile[data[IDX_PROFILE] % kProfileNum]; |
| mAspectRatioFlag = data[IDX_ASPECT_RATIO_FLAG] & 0x01; |
| mNalHrdFlag = data[IDX_NAL_HRD_FLAG] & 0x01; |
| mVclHrdFlag = data[IDX_VCL_HRD_FLAG] & 0x01; |
| mIsForceIdrEnabled = data[IDX_ENABLE_FORCE_IDR] & 0x01; |
| mIsDynamicBitRateChangeEnabled = data[IDX_ENABLE_DYNAMIC_BITRATE] & 0x01; |
| mIsDynamicFrameRateChangeEnabled = data[IDX_ENABLE_DYNAMIC_FRAME_RATE] & 0x01; |
| mForceIdrInterval = data[IDX_FORCE_IDR_INTERVAL] & 0x07; |
| mDynamicBitRateInterval = data[IDX_DYNAMIC_BITRATE_INTERVAL] & 0x07; |
| mDynamicFrameRateInterval = data[IDX_DYNAMIC_FRAME_RATE_INTERVAL] & 0x07; |
| |
| mSliceParam = std::min(256u, static_cast<UWORD32>(mInputDims.mHeight >> 4)); |
| mAvcEncLevel = kSupportedLevels[data[IDX_ENC_LEVEL] % kSupportedLevelsNum]; |
| mSliceMode = kSliceMode[data[IDX_SLICE_MODE] % kSliceModeNum]; |
| mEnableFastSad = data[IDX_ENABLE_FAST_SAD] & 0x01; |
| |
| mEnableRecon = !!(data[IDX_ENABLE_RECON] & 1); |
| mEnableNaluInfoExport = !!(data[IDX_ENABLE_NALU_INFO_EXPORT] & 1); |
| |
| isvce_num_mem_rec_ip_t s_num_mem_rec_ip{}; |
| isvce_num_mem_rec_op_t s_num_mem_rec_op{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_GET_NUM_MEM_REC, ISVCE_CMD_CT_NA}; |
| |
| /* Getting Number of MemRecords */ |
| s_num_mem_rec_ip.s_ive_ip.u4_size = sizeof(isvce_num_mem_rec_ip_t); |
| s_num_mem_rec_op.s_ive_op.u4_size = sizeof(isvce_num_mem_rec_op_t); |
| |
| if(IV_SUCCESS != isvce_api_function(0, &s_num_mem_rec_ip, &s_num_mem_rec_op, &s_api_cmds)) |
| { |
| return false; |
| } |
| |
| mNumMemRecords = s_num_mem_rec_op.s_ive_op.u4_num_mem_rec; |
| mMemRecords.resize(mNumMemRecords); |
| mMemRecBufs.resize(mNumMemRecords); |
| |
| for(auto i = 0u; i < mNumMemRecords; i++) |
| { |
| mMemRecords[i].u4_size = sizeof(iv_mem_rec_t); |
| mMemRecords[i].pv_base = nullptr; |
| mMemRecords[i].u4_mem_size = 0; |
| mMemRecords[i].u4_mem_alignment = 0; |
| mMemRecords[i].e_mem_type = IV_NA_MEM_TYPE; |
| } |
| |
| isvce_fill_mem_rec_ip_t sFillMemRecIp{}; |
| isvce_fill_mem_rec_op_t sFillMemRecOp{}; |
| |
| s_api_cmds = {ISVCE_CMD_FILL_NUM_MEM_REC, ISVCE_CMD_CT_NA}; |
| |
| sFillMemRecIp.s_ive_ip.u4_size = sizeof(isvce_fill_mem_rec_ip_t); |
| sFillMemRecOp.s_ive_op.u4_size = sizeof(isvce_fill_mem_rec_op_t); |
| |
| sFillMemRecIp.s_ive_ip.ps_mem_rec = mMemRecords.data(); |
| sFillMemRecIp.s_ive_ip.u4_num_mem_rec = mNumMemRecords; |
| sFillMemRecIp.s_ive_ip.u4_max_wd = mInputDims.mWidth; |
| sFillMemRecIp.s_ive_ip.u4_max_ht = mInputDims.mHeight; |
| sFillMemRecIp.u4_wd = mInputDims.mWidth; |
| sFillMemRecIp.u4_ht = mInputDims.mHeight; |
| sFillMemRecIp.s_ive_ip.u4_max_level = mAvcEncLevel; |
| sFillMemRecIp.s_ive_ip.e_color_format = mIvVideoColorFormat; |
| sFillMemRecIp.s_ive_ip.u4_max_ref_cnt = 2; |
| sFillMemRecIp.s_ive_ip.u4_max_reorder_cnt = 0; |
| sFillMemRecIp.s_ive_ip.u4_max_srch_rng_x = 256; |
| sFillMemRecIp.s_ive_ip.u4_max_srch_rng_y = 256; |
| |
| sFillMemRecIp.s_svc_inp_params.u1_num_temporal_layers = mNumTemporalLayers; |
| sFillMemRecIp.s_svc_inp_params.u1_num_spatial_layers = mNumSpatialLayers; |
| sFillMemRecIp.s_svc_inp_params.d_spatial_res_ratio = mSpatialResRatio; |
| |
| if(IV_SUCCESS != isvce_api_function(0, &sFillMemRecIp, &sFillMemRecOp, &s_api_cmds)) |
| { |
| return false; |
| } |
| |
| if(!initMemRecs()) |
| { |
| return false; |
| } |
| |
| /* Codec Instance Creation */ |
| isvce_init_ip_t sInitIp{}; |
| isvce_init_op_t sInitOp{}; |
| |
| std::vector<UWORD32> sMaxBitrates(mNumSpatialLayers, 240000000); |
| |
| mCodecCtx = reinterpret_cast<iv_obj_t *>(mMemRecords[0].pv_base); |
| mCodecCtx->u4_size = sizeof(iv_obj_t); |
| mCodecCtx->pv_fxns = reinterpret_cast<void *>(isvce_api_function); |
| |
| sInitIp.s_ive_ip.u4_size = sizeof(isvce_init_ip_t); |
| sInitOp.s_ive_op.u4_size = sizeof(isvce_init_op_t); |
| |
| s_api_cmds = {ISVCE_CMD_INIT, ISVCE_CMD_CT_NA}; |
| |
| sInitIp.s_ive_ip.u4_num_mem_rec = mNumMemRecords; |
| sInitIp.s_ive_ip.ps_mem_rec = mMemRecords.data(); |
| sInitIp.s_ive_ip.u4_max_wd = mInputDims.mWidth; |
| sInitIp.s_ive_ip.u4_max_ht = mInputDims.mHeight; |
| sInitIp.u4_wd = mInputDims.mWidth; |
| sInitIp.u4_ht = mInputDims.mHeight; |
| |
| sInitIp.s_ive_ip.u4_max_ref_cnt = 2; |
| sInitIp.s_ive_ip.u4_max_reorder_cnt = 0; |
| sInitIp.s_ive_ip.u4_max_level = mAvcEncLevel; |
| sInitIp.s_ive_ip.e_inp_color_fmt = mIvVideoColorFormat; |
| |
| sInitIp.s_ive_ip.u4_enable_recon = mEnableRecon; |
| sInitIp.s_ive_ip.e_recon_color_fmt = IV_YUV_420P; |
| sInitIp.b_nalu_info_export_enable = mEnableNaluInfoExport; |
| sInitIp.s_ive_ip.e_rc_mode = mRCMode; |
| sInitIp.s_ive_ip.u4_max_framerate = 120000; |
| sInitIp.pu4_max_bitrate = sMaxBitrates.data(); |
| sInitIp.s_svc_inp_params.u1_num_temporal_layers = mNumTemporalLayers; |
| sInitIp.s_svc_inp_params.u1_num_spatial_layers = mNumSpatialLayers; |
| sInitIp.s_svc_inp_params.d_spatial_res_ratio = mSpatialResRatio; |
| |
| sInitIp.s_ive_ip.u4_num_bframes = mBframes; |
| sInitIp.s_ive_ip.e_content_type = IV_PROGRESSIVE; |
| sInitIp.s_ive_ip.u4_max_srch_rng_x = 256; |
| sInitIp.s_ive_ip.u4_max_srch_rng_y = 256; |
| sInitIp.s_ive_ip.e_slice_mode = mSliceMode; |
| sInitIp.s_ive_ip.u4_slice_param = mSliceParam; |
| sInitIp.s_ive_ip.e_arch = mArch; |
| sInitIp.s_ive_ip.e_soc = SOC_GENERIC; |
| sInitIp.b_use_default_vui = true; |
| |
| if(IV_SUCCESS != isvce_api_function(mCodecCtx, &sInitIp, &sInitOp, &s_api_cmds)) |
| { |
| delMemRecs(); |
| |
| return false; |
| } |
| |
| setDefault(); |
| setNumCores(); |
| logVersion(); |
| getBufInfo(); |
| setDimensions(); |
| setFrameRate(); |
| setIpeParams(); |
| setBitRate(); |
| setQp(); |
| setAirParams(); |
| setVbvParams(); |
| setMeParams(); |
| setGopParams(); |
| setDeblockParams(); |
| setProfileParams(); |
| setEncMode(IVE_ENC_MODE_HEADER); |
| setVuiParams(); |
| setSeiMdcvParams(); |
| setSeiCllParams(); |
| setSeiAveParams(); |
| setSeiCcvParams(); |
| |
| initEncBufs(); |
| |
| return true; |
| } |
| |
| void Codec::setDimensions() |
| { |
| isvce_ctl_set_dimensions_ip_t s_frame_dimensions_ip{}; |
| isvce_ctl_set_dimensions_op_t s_frame_dimensions_op{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_DIMENSIONS}; |
| |
| s_frame_dimensions_ip.s_ive_ip.u4_ht = mInputDims.mHeight; |
| s_frame_dimensions_ip.s_ive_ip.u4_wd = mInputDims.mWidth; |
| |
| s_frame_dimensions_ip.s_ive_ip.u4_timestamp_high = 0; |
| s_frame_dimensions_ip.s_ive_ip.u4_timestamp_low = 0; |
| |
| s_frame_dimensions_ip.s_ive_ip.u4_size = sizeof(isvce_ctl_set_dimensions_ip_t); |
| s_frame_dimensions_op.s_ive_op.u4_size = sizeof(isvce_ctl_set_dimensions_op_t); |
| |
| isvce_api_function(mCodecCtx, &s_frame_dimensions_ip, &s_frame_dimensions_op, &s_api_cmds); |
| } |
| |
| void Codec::setNumCores() |
| { |
| isvce_ctl_set_num_cores_ip_t sNumCoresIp{}; |
| isvce_ctl_set_num_cores_op_t sNumCoresOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_NUM_CORES}; |
| |
| sNumCoresIp.s_ive_ip.u4_num_cores = mNumCores; |
| |
| sNumCoresIp.s_ive_ip.u4_timestamp_high = 0; |
| sNumCoresIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sNumCoresIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_num_cores_ip_t); |
| sNumCoresOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_num_cores_op_t); |
| |
| isvce_api_function(mCodecCtx, (void *) &sNumCoresIp, (void *) &sNumCoresOp, &s_api_cmds); |
| } |
| |
| void Codec::setDefault() |
| { |
| isvce_ctl_setdefault_ip_t sDefaultIp{}; |
| isvce_ctl_setdefault_op_t sDefaultOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SETDEFAULT}; |
| |
| sDefaultIp.s_ive_ip.u4_timestamp_high = 0; |
| sDefaultIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sDefaultIp.s_ive_ip.u4_size = sizeof(isvce_ctl_setdefault_ip_t); |
| sDefaultOp.s_ive_op.u4_size = sizeof(isvce_ctl_setdefault_op_t); |
| |
| isvce_api_function(mCodecCtx, &sDefaultIp, &sDefaultOp, &s_api_cmds); |
| } |
| |
| void Codec::getBufInfo() |
| { |
| isvce_ctl_getbufinfo_ip_t s_get_buf_info_ip{}; |
| isvce_ctl_getbufinfo_op_t s_get_buf_info_op{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_GETBUFINFO}; |
| |
| s_get_buf_info_ip.s_ive_ip.u4_size = sizeof(isvce_ctl_getbufinfo_ip_t); |
| s_get_buf_info_op.s_ive_op.u4_size = sizeof(isvce_ctl_getbufinfo_op_t); |
| |
| s_get_buf_info_ip.s_ive_ip.u4_max_ht = mInputDims.mHeight; |
| s_get_buf_info_ip.s_ive_ip.u4_max_wd = mInputDims.mWidth; |
| s_get_buf_info_ip.s_ive_ip.e_inp_color_fmt = mIvVideoColorFormat; |
| |
| isvce_api_function(mCodecCtx, &s_get_buf_info_ip, &s_get_buf_info_op, &s_api_cmds); |
| } |
| |
| void Codec::setFrameRate() |
| { |
| isvce_ctl_set_frame_rate_ip_t sFrameRateIp{}; |
| isvce_ctl_set_frame_rate_op_t sFrameRateOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_FRAMERATE}; |
| |
| sFrameRateIp.s_ive_ip.u4_src_frame_rate = (UWORD32) mFrameRate; |
| sFrameRateIp.s_ive_ip.u4_tgt_frame_rate = (UWORD32) mFrameRate; |
| |
| sFrameRateIp.s_ive_ip.u4_timestamp_high = 0; |
| sFrameRateIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sFrameRateIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_frame_rate_ip_t); |
| sFrameRateOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_frame_rate_op_t); |
| |
| isvce_api_function(mCodecCtx, &sFrameRateIp, &sFrameRateOp, &s_api_cmds); |
| } |
| |
| void Codec::setIpeParams() |
| { |
| isvce_ctl_set_ipe_params_ip_t sIpeParamsIp{}; |
| isvce_ctl_set_ipe_params_op_t sIpeParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_IPE_PARAMS}; |
| |
| sIpeParamsIp.s_ive_ip.u4_enable_intra_4x4 = mIntra4x4; |
| sIpeParamsIp.s_ive_ip.u4_enc_speed_preset = mEncSpeed; |
| |
| sIpeParamsIp.s_ive_ip.u4_timestamp_high = 0; |
| sIpeParamsIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sIpeParamsIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_ipe_params_ip_t); |
| sIpeParamsOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_ipe_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sIpeParamsIp, &sIpeParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setBitRate() |
| { |
| isvce_ctl_set_bitrate_ip_t sBitrateIp{}; |
| isvce_ctl_set_bitrate_op_t sBitrateOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_BITRATE}; |
| std::vector<UWORD32> sTargetBitrates(mNumSpatialLayers, mBitrate); |
| |
| sBitrateIp.pu4_target_bitrate = sTargetBitrates.data(); |
| |
| sBitrateIp.s_ive_ip.u4_timestamp_high = 0; |
| sBitrateIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sBitrateIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_bitrate_ip_t); |
| sBitrateOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_bitrate_op_t); |
| |
| isvce_api_function(mCodecCtx, &sBitrateIp, &sBitrateOp, &s_api_cmds); |
| } |
| |
| void Codec::setFrameType(IV_PICTURE_CODING_TYPE_T eFrameType) |
| { |
| isvce_ctl_set_frame_type_ip_t sFrameTypeIp{}; |
| isvce_ctl_set_frame_type_op_t sFrameTypeOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_FRAMETYPE}; |
| |
| sFrameTypeIp.s_ive_ip.e_frame_type = eFrameType; |
| |
| sFrameTypeIp.s_ive_ip.u4_timestamp_high = 0; |
| sFrameTypeIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sFrameTypeIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_frame_type_ip_t); |
| sFrameTypeOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_frame_type_op_t); |
| |
| isvce_api_function(mCodecCtx, &sFrameTypeIp, &sFrameTypeOp, &s_api_cmds); |
| } |
| |
| void Codec::setQp() |
| { |
| constexpr UWORD8 u1NumSliceTypes = 3; |
| isvce_ctl_set_qp_ip_t s_QpIp{}; |
| isvce_ctl_set_qp_op_t s_QpOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_QP}; |
| std::vector<UWORD32> sQps(u1NumSliceTypes * mNumSpatialLayers); |
| std::vector<UWORD32> sMinQps(u1NumSliceTypes * mNumSpatialLayers); |
| std::vector<UWORD32> sMaxQps(u1NumSliceTypes * mNumSpatialLayers); |
| |
| s_QpIp.pu4_i_qp = sQps.data(); |
| s_QpIp.pu4_i_qp_min = sMinQps.data(); |
| s_QpIp.pu4_i_qp_max = sMaxQps.data(); |
| |
| s_QpIp.pu4_p_qp = sQps.data() + mNumSpatialLayers; |
| s_QpIp.pu4_p_qp_min = sMinQps.data() + mNumSpatialLayers; |
| s_QpIp.pu4_p_qp_max = sMaxQps.data() + mNumSpatialLayers; |
| |
| s_QpIp.pu4_b_qp = sQps.data() + mNumSpatialLayers * 2; |
| s_QpIp.pu4_b_qp_min = sMinQps.data() + mNumSpatialLayers * 2; |
| s_QpIp.pu4_b_qp_max = sMaxQps.data() + mNumSpatialLayers * 2; |
| |
| for(auto i = 0; i < mNumSpatialLayers; i++) |
| { |
| s_QpIp.pu4_i_qp[i] = m_I_QP; |
| s_QpIp.pu4_i_qp_max[i] = kMaxQP; |
| s_QpIp.pu4_i_qp_min[i] = kMinQP; |
| |
| s_QpIp.pu4_p_qp[i] = m_P_QP; |
| s_QpIp.pu4_p_qp_max[i] = kMaxQP; |
| s_QpIp.pu4_p_qp_min[i] = kMinQP; |
| |
| s_QpIp.pu4_b_qp[i] = m_B_QP; |
| s_QpIp.pu4_b_qp_max[i] = kMaxQP; |
| s_QpIp.pu4_b_qp_min[i] = kMinQP; |
| } |
| |
| s_QpIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_qp_ip_t); |
| s_QpOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_qp_op_t); |
| |
| isvce_api_function(mCodecCtx, &s_QpIp, &s_QpOp, &s_api_cmds); |
| } |
| |
| void Codec::setEncMode(IVE_ENC_MODE_T eEncMode) |
| { |
| isvce_ctl_set_enc_mode_ip_t sEncModeIp{}; |
| isvce_ctl_set_enc_mode_op_t sEncModeOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_ENC_MODE}; |
| |
| sEncModeIp.s_ive_ip.e_enc_mode = eEncMode; |
| |
| sEncModeIp.s_ive_ip.u4_timestamp_high = 0; |
| sEncModeIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sEncModeIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_enc_mode_ip_t); |
| sEncModeOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_enc_mode_op_t); |
| |
| isvce_api_function(mCodecCtx, &sEncModeIp, &sEncModeOp, &s_api_cmds); |
| } |
| |
| void Codec::setVbvParams() |
| { |
| isvce_ctl_set_vbv_params_ip_t sVbvIp{}; |
| isvce_ctl_set_vbv_params_op_t sVbvOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_VBV_PARAMS}; |
| std::vector<UWORD32> sBufferDelays(mNumSpatialLayers, 1000); |
| |
| sVbvIp.pu4_vbv_buffer_delay = sBufferDelays.data(); |
| |
| sVbvIp.s_ive_ip.u4_timestamp_high = 0; |
| sVbvIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sVbvIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_vbv_params_ip_t); |
| sVbvOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_vbv_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sVbvIp, &sVbvOp, &s_api_cmds); |
| } |
| |
| void Codec::setAirParams() |
| { |
| isvce_ctl_set_air_params_ip_t sAirIp{}; |
| isvce_ctl_set_air_params_op_t sAirOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_AIR_PARAMS}; |
| |
| sAirIp.s_ive_ip.e_air_mode = mAirMode; |
| sAirIp.s_ive_ip.u4_air_refresh_period = mIntraRefresh; |
| |
| sAirIp.s_ive_ip.u4_timestamp_high = 0; |
| sAirIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sAirIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_air_params_ip_t); |
| sAirOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_air_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sAirIp, &sAirOp, &s_api_cmds); |
| } |
| |
| void Codec::setMeParams() |
| { |
| isvce_ctl_set_me_params_ip_t sMeParamsIp{}; |
| isvce_ctl_set_me_params_op_t sMeParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_ME_PARAMS}; |
| |
| sMeParamsIp.s_ive_ip.u4_enable_fast_sad = mEnableFastSad; |
| sMeParamsIp.s_ive_ip.u4_enable_alt_ref = mEnableAltRef; |
| |
| sMeParamsIp.s_ive_ip.u4_enable_hpel = mHalfPelEnable; |
| sMeParamsIp.s_ive_ip.u4_enable_qpel = mQPelEnable; |
| sMeParamsIp.s_ive_ip.u4_me_speed_preset = mMeSpeedPreset; |
| sMeParamsIp.s_ive_ip.u4_srch_rng_x = mSearchRangeX; |
| sMeParamsIp.s_ive_ip.u4_srch_rng_y = mSearchRangeY; |
| |
| sMeParamsIp.s_ive_ip.u4_timestamp_high = 0; |
| sMeParamsIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sMeParamsIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_me_params_ip_t); |
| sMeParamsOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_me_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sMeParamsIp, &sMeParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setGopParams() |
| { |
| isvce_ctl_set_gop_params_ip_t sGopParamsIp{}; |
| isvce_ctl_set_gop_params_op_t sGopParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_GOP_PARAMS}; |
| |
| sGopParamsIp.s_ive_ip.u4_i_frm_interval = mIInterval; |
| sGopParamsIp.s_ive_ip.u4_idr_frm_interval = mIDRInterval; |
| |
| sGopParamsIp.s_ive_ip.u4_timestamp_high = 0; |
| sGopParamsIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sGopParamsIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_gop_params_ip_t); |
| sGopParamsOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_gop_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sGopParamsIp, &sGopParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setProfileParams() |
| { |
| isvce_ctl_set_profile_params_ip_t sProfileParamsIp{}; |
| isvce_ctl_set_profile_params_op_t sProfileParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_PROFILE_PARAMS}; |
| |
| sProfileParamsIp.s_ive_ip.e_profile = mProfile; |
| if(sProfileParamsIp.s_ive_ip.e_profile == IV_PROFILE_BASE) |
| { |
| sProfileParamsIp.s_ive_ip.u4_entropy_coding_mode = 0; |
| } |
| else |
| { |
| sProfileParamsIp.s_ive_ip.u4_entropy_coding_mode = 1; |
| } |
| |
| sProfileParamsIp.s_ive_ip.u4_timestamp_high = 0; |
| sProfileParamsIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sProfileParamsIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_profile_params_ip_t); |
| sProfileParamsOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_profile_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sProfileParamsIp, &sProfileParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setDeblockParams() |
| { |
| isvce_ctl_set_deblock_params_ip_t sDeblockParamsIp{}; |
| isvce_ctl_set_deblock_params_op_t sDeblockParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_DEBLOCK_PARAMS}; |
| |
| sDeblockParamsIp.s_ive_ip.u4_disable_deblock_level = mDisableDeblockLevel; |
| |
| sDeblockParamsIp.s_ive_ip.u4_timestamp_high = 0; |
| sDeblockParamsIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| sDeblockParamsIp.s_ive_ip.u4_size = sizeof(isvce_ctl_set_deblock_params_ip_t); |
| sDeblockParamsOp.s_ive_op.u4_size = sizeof(isvce_ctl_set_deblock_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sDeblockParamsIp, &sDeblockParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setVuiParams() |
| { |
| isvce_vui_ip_t sVuiParamsIp{}; |
| isvce_vui_op_t sVuiParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_VUI_PARAMS}; |
| |
| sVuiParamsIp.u1_aspect_ratio_info_present_flag = mAspectRatioFlag; |
| sVuiParamsIp.u1_aspect_ratio_idc = 0; |
| sVuiParamsIp.u2_sar_width = 0; |
| sVuiParamsIp.u2_sar_height = 0; |
| sVuiParamsIp.u1_overscan_info_present_flag = 0; |
| sVuiParamsIp.u1_overscan_appropriate_flag = 0; |
| sVuiParamsIp.u1_video_signal_type_present_flag = 1; |
| sVuiParamsIp.u1_video_format = 0; |
| sVuiParamsIp.u1_video_full_range_flag = 0; |
| sVuiParamsIp.u1_colour_description_present_flag = 0; |
| sVuiParamsIp.u1_colour_primaries = 0; |
| sVuiParamsIp.u1_transfer_characteristics = 0; |
| sVuiParamsIp.u1_matrix_coefficients = 0; |
| sVuiParamsIp.u1_chroma_loc_info_present_flag = 0; |
| sVuiParamsIp.u1_chroma_sample_loc_type_top_field = 0; |
| sVuiParamsIp.u1_chroma_sample_loc_type_bottom_field = 0; |
| sVuiParamsIp.u1_vui_timing_info_present_flag = 0; |
| sVuiParamsIp.u4_vui_num_units_in_tick = 0; |
| sVuiParamsIp.u4_vui_time_scale = 0; |
| sVuiParamsIp.u1_fixed_frame_rate_flag = 0; |
| sVuiParamsIp.u1_nal_hrd_parameters_present_flag = mNalHrdFlag; |
| sVuiParamsIp.u1_vcl_hrd_parameters_present_flag = mVclHrdFlag; |
| sVuiParamsIp.u1_low_delay_hrd_flag = 0; |
| sVuiParamsIp.u1_pic_struct_present_flag = 0; |
| sVuiParamsIp.u1_bitstream_restriction_flag = 0; |
| sVuiParamsIp.u1_motion_vectors_over_pic_boundaries_flag = 0; |
| sVuiParamsIp.u1_max_bytes_per_pic_denom = 0; |
| sVuiParamsIp.u1_max_bits_per_mb_denom = 0; |
| sVuiParamsIp.u1_log2_max_mv_length_horizontal = 0; |
| sVuiParamsIp.u1_log2_max_mv_length_vertical = 0; |
| sVuiParamsIp.u1_num_reorder_frames = 0; |
| sVuiParamsIp.u1_max_dec_frame_buffering = 0; |
| |
| sVuiParamsIp.u4_size = sizeof(isvce_vui_ip_t); |
| sVuiParamsOp.u4_size = sizeof(isvce_vui_op_t); |
| |
| isvce_api_function(mCodecCtx, &sVuiParamsIp, &sVuiParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setSeiMdcvParams() |
| { |
| isvce_ctl_set_sei_mdcv_params_ip_t sSeiMdcvParamsIp{}; |
| isvce_ctl_set_sei_mdcv_params_op_t sSeiMdcvParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_SEI_MDCV_PARAMS}; |
| |
| sSeiMdcvParamsIp.u1_sei_mdcv_params_present_flag = mSeiMdcvFlag; |
| if(mSeiMdcvFlag) |
| { |
| for(int i4_count = 0; i4_count < kNumSeiMdcvPrimaries; ++i4_count) |
| { |
| sSeiMdcvParamsIp.au2_display_primaries_x[i4_count] = 30000; |
| sSeiMdcvParamsIp.au2_display_primaries_y[i4_count] = 35000; |
| } |
| sSeiMdcvParamsIp.u2_white_point_x = 30000; |
| sSeiMdcvParamsIp.u2_white_point_y = 35000; |
| sSeiMdcvParamsIp.u4_max_display_mastering_luminance = 100000000; |
| sSeiMdcvParamsIp.u4_min_display_mastering_luminance = 50000; |
| } |
| |
| sSeiMdcvParamsIp.u4_timestamp_high = 0; |
| sSeiMdcvParamsIp.u4_timestamp_low = 0; |
| |
| sSeiMdcvParamsIp.u4_size = sizeof(isvce_ctl_set_sei_mdcv_params_ip_t); |
| sSeiMdcvParamsOp.u4_size = sizeof(isvce_ctl_set_sei_mdcv_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sSeiMdcvParamsIp, &sSeiMdcvParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setSeiCllParams() |
| { |
| isvce_ctl_set_sei_cll_params_ip_t sSeiCllParamsIp{}; |
| isvce_ctl_set_sei_cll_params_op_t sSeiCllParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_SEI_CLL_PARAMS}; |
| |
| sSeiCllParamsIp.u1_sei_cll_params_present_flag = mSeiCllFlag; |
| |
| if(mSeiCllFlag) |
| { |
| sSeiCllParamsIp.u2_max_content_light_level = 0; |
| sSeiCllParamsIp.u2_max_pic_average_light_level = 0; |
| } |
| |
| sSeiCllParamsIp.u4_timestamp_high = 0; |
| sSeiCllParamsIp.u4_timestamp_low = 0; |
| |
| sSeiCllParamsIp.u4_size = sizeof(isvce_ctl_set_sei_cll_params_ip_t); |
| sSeiCllParamsOp.u4_size = sizeof(isvce_ctl_set_sei_cll_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sSeiCllParamsIp, &sSeiCllParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setSeiAveParams() |
| { |
| isvce_ctl_set_sei_ave_params_ip_t sSeiAveParamsIp{}; |
| isvce_ctl_set_sei_ave_params_op_t sSeiAveParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_SEI_AVE_PARAMS}; |
| |
| sSeiAveParamsIp.u1_sei_ave_params_present_flag = mSeiAveFlag; |
| |
| if(mSeiAveFlag) |
| { |
| sSeiAveParamsIp.u4_ambient_illuminance = 1; |
| sSeiAveParamsIp.u2_ambient_light_x = 0; |
| sSeiAveParamsIp.u2_ambient_light_y = 0; |
| } |
| |
| sSeiAveParamsIp.u4_timestamp_high = 0; |
| sSeiAveParamsIp.u4_timestamp_low = 0; |
| |
| sSeiAveParamsIp.u4_size = sizeof(isvce_ctl_set_sei_ave_params_ip_t); |
| sSeiAveParamsOp.u4_size = sizeof(isvce_ctl_set_sei_ave_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sSeiAveParamsIp, &sSeiAveParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::setSeiCcvParams() |
| { |
| isvce_ctl_set_sei_ccv_params_ip_t sSeiCcvParamsIp{}; |
| isvce_ctl_set_sei_ccv_params_op_t sSeiCcvParamsOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_SET_SEI_CCV_PARAMS}; |
| |
| sSeiCcvParamsIp.u1_sei_ccv_params_present_flag = mSeiCcvFlag; |
| |
| if(mSeiCcvFlag) |
| { |
| sSeiCcvParamsIp.u1_ccv_cancel_flag = 0; |
| sSeiCcvParamsIp.u1_ccv_persistence_flag = 1; |
| sSeiCcvParamsIp.u1_ccv_primaries_present_flag = 1; |
| sSeiCcvParamsIp.u1_ccv_min_luminance_value_present_flag = 1; |
| sSeiCcvParamsIp.u1_ccv_max_luminance_value_present_flag = 1; |
| sSeiCcvParamsIp.u1_ccv_avg_luminance_value_present_flag = 1; |
| sSeiCcvParamsIp.u1_ccv_reserved_zero_2bits = 0; |
| for(int i4_count = 0; i4_count < kNumSeiCcvPrimaries; ++i4_count) |
| { |
| sSeiCcvParamsIp.ai4_ccv_primaries_x[i4_count] = 1; |
| sSeiCcvParamsIp.ai4_ccv_primaries_y[i4_count] = 1; |
| } |
| sSeiCcvParamsIp.u4_ccv_min_luminance_value = 1; |
| sSeiCcvParamsIp.u4_ccv_max_luminance_value = 1; |
| sSeiCcvParamsIp.u4_ccv_avg_luminance_value = 1; |
| } |
| |
| sSeiCcvParamsIp.u4_timestamp_high = 0; |
| sSeiCcvParamsIp.u4_timestamp_low = 0; |
| |
| sSeiCcvParamsIp.u4_size = sizeof(isvce_ctl_set_sei_ccv_params_ip_t); |
| sSeiCcvParamsOp.u4_size = sizeof(isvce_ctl_set_sei_ccv_params_op_t); |
| |
| isvce_api_function(mCodecCtx, &sSeiCcvParamsIp, &sSeiCcvParamsOp, &s_api_cmds); |
| } |
| |
| void Codec::logVersion() |
| { |
| isvce_ctl_getversioninfo_ip_t s_ctl_set_getversioninfo_ip{}; |
| isvce_ctl_getversioninfo_op_t s_ctl_set_getversioninfo_op{}; |
| |
| CHAR ac_version_string[512]; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_CTL, ISVCE_CMD_CTL_GETVERSION}; |
| |
| s_ctl_set_getversioninfo_ip.s_ive_ip.pu1_version = (UWORD8 *) ac_version_string; |
| s_ctl_set_getversioninfo_ip.s_ive_ip.u4_version_bufsize = sizeof(ac_version_string); |
| s_ctl_set_getversioninfo_ip.s_ive_ip.u4_size = sizeof(isvce_ctl_getversioninfo_ip_t); |
| s_ctl_set_getversioninfo_op.s_ive_op.u4_size = sizeof(isvce_ctl_getversioninfo_op_t); |
| |
| isvce_api_function(mCodecCtx, (void *) &s_ctl_set_getversioninfo_ip, |
| (void *) &s_ctl_set_getversioninfo_op, &s_api_cmds); |
| } |
| |
| bool Codec::encodeFrames(const UWORD8 *data, size_t size) |
| { |
| isvce_video_encode_ip_t sEncodeIp{}; |
| isvce_video_encode_op_t sEncodeOp{}; |
| |
| isvce_api_cmds_t s_api_cmds{ISVCE_CMD_VIDEO_ENCODE, ISVCE_CMD_CT_NA}; |
| iv_raw_buf_t *psInpRawBuf = &sEncodeIp.s_ive_ip.s_inp_buf; |
| iv_raw_buf_t *psRecRawBuf = &sEncodeIp.s_ive_ip.s_recon_buf; |
| |
| size_t frameSize = mInputDims.getFrameSize(); |
| auto bytesLeft = std::min(size, frameSize); |
| auto bytesConsumed = 0; |
| UWORD32 numFrames = 0; |
| |
| sEncodeIp.s_ive_ip.s_out_buf.pv_buf = mEncBufs.mOutputBuf.data(); |
| sEncodeIp.s_ive_ip.s_out_buf.u4_bytes = 0; |
| sEncodeIp.s_ive_ip.s_out_buf.u4_bufsize = static_cast<UWORD32>(mEncBufs.mOutputBuf.size()); |
| sEncodeOp.s_ive_op.s_out_buf.pv_buf = nullptr; |
| sEncodeIp.s_ive_ip.pv_bufs = nullptr; |
| sEncodeIp.s_ive_ip.pv_mb_info = nullptr; |
| sEncodeIp.s_ive_ip.pv_pic_info = nullptr; |
| sEncodeIp.s_ive_ip.u4_mb_info_type = 0; |
| sEncodeIp.s_ive_ip.u4_pic_info_type = 0; |
| sEncodeIp.s_ive_ip.u4_is_last = 0; |
| |
| sEncodeIp.s_ive_ip.u4_timestamp_high = 0; |
| sEncodeIp.s_ive_ip.u4_timestamp_low = 0; |
| |
| memset(psInpRawBuf, 0, sizeof(iv_raw_buf_t)); |
| psInpRawBuf->u4_size = sizeof(iv_raw_buf_t); |
| psInpRawBuf->e_color_fmt = mIvVideoColorFormat; |
| |
| sEncodeIp.s_ive_ip.u4_size = sizeof(isvce_video_encode_ip_t); |
| sEncodeOp.s_ive_op.u4_size = sizeof(isvce_video_encode_op_t); |
| |
| isvce_api_function(mCodecCtx, &sEncodeIp, &sEncodeOp, &s_api_cmds); |
| |
| if(mEnableNaluInfoExport) |
| { |
| sEncodeIp.ps_nalu_info_buf = mEncBufs.mNaluInfoStructBuf.data(); |
| sEncodeOp.ps_nalu_info_buf = mEncBufs.mNaluInfoStructBuf.data() + mNumSpatialLayers; |
| } |
| |
| while(!sEncodeOp.s_ive_op.u4_is_last && (kMaxEncodeCalls > (mNumSpatialLayers * numFrames))) |
| { |
| if(mEnableRecon) |
| { |
| setEncParams(psRecRawBuf, mEncBufs.mReconBuf, mInputDims); |
| } |
| |
| if(mEnableNaluInfoExport) |
| { |
| for(auto i = 0; i < mNumSpatialLayers; i++) |
| { |
| sEncodeIp.ps_nalu_info_buf[i].pu1_buf = mEncBufs.mNaluInfoDataBuf[i].data(); |
| sEncodeIp.ps_nalu_info_buf[i].u4_num_bytes = 0; |
| sEncodeIp.ps_nalu_info_buf[i].u4_buf_size = |
| static_cast<UWORD32>(mEncBufs.mNaluInfoDataBuf[i].size()); |
| } |
| } |
| |
| if(size > 0) |
| { |
| bytesLeft = std::min(size, frameSize); |
| std::copy(data, data + bytesLeft, mEncBufs.mInputBuf.begin()); |
| std::fill(std::next(mEncBufs.mInputBuf.begin(), bytesLeft), mEncBufs.mInputBuf.end(), |
| data[0]); |
| setEncParams(psInpRawBuf, mEncBufs.mInputBuf, mInputDims, mIvVideoColorFormat); |
| |
| bytesConsumed = bytesLeft; |
| } |
| else |
| { |
| sEncodeIp.s_ive_ip.u4_is_last = 1; |
| |
| for(auto i = 0; i < 3; i++) |
| { |
| psInpRawBuf->apv_bufs[i] = nullptr; |
| } |
| |
| bytesConsumed = 0; |
| } |
| |
| if(mIsForceIdrEnabled && !sEncodeIp.s_ive_ip.u4_is_last) |
| { |
| if(numFrames == mForceIdrInterval) |
| { |
| setFrameType(IV_IDR_FRAME); |
| } |
| } |
| |
| if(mIsDynamicBitRateChangeEnabled && !sEncodeIp.s_ive_ip.u4_is_last) |
| { |
| if(numFrames == mDynamicBitRateInterval) |
| { |
| if(data[0] & 0x01) |
| { |
| mBitrate *= 2; |
| } |
| else |
| { |
| mBitrate /= 2; |
| } |
| |
| setBitRate(); |
| } |
| } |
| |
| if(mIsDynamicFrameRateChangeEnabled && !sEncodeIp.s_ive_ip.u4_is_last) |
| { |
| if(numFrames == mDynamicFrameRateInterval) |
| { |
| if(size > 1 && data[1] & 0x01) |
| { |
| mFrameRate *= 2; |
| } |
| else |
| { |
| mFrameRate /= 2; |
| } |
| |
| setFrameRate(); |
| } |
| } |
| |
| isvce_api_function(mCodecCtx, &sEncodeIp, &sEncodeOp, &s_api_cmds); |
| |
| if(!sEncodeOp.s_ive_op.u4_is_last) |
| { |
| numFrames++; |
| data += bytesConsumed; |
| size -= bytesConsumed; |
| } |
| } |
| |
| return true; |
| } |
| |
| void Codec::setEncParams(iv_raw_buf_t *psInpRawBuf, std::vector<UWORD8> &buf, const FrameDims &dims, |
| IV_COLOR_FORMAT_T colorFormat) |
| { |
| switch(colorFormat) |
| { |
| case IV_YUV_420SP_UV: |
| case IV_YUV_420SP_VU: |
| { |
| WORD32 yStride = dims.mWidth; |
| WORD32 uStride = dims.mWidth / 2; |
| |
| psInpRawBuf->apv_bufs[0] = buf.data(); |
| psInpRawBuf->apv_bufs[1] = buf.data() + dims.mWidth * dims.mHeight; |
| |
| psInpRawBuf->au4_wd[0] = dims.mWidth; |
| psInpRawBuf->au4_wd[1] = dims.mWidth; |
| |
| psInpRawBuf->au4_ht[0] = dims.mHeight; |
| psInpRawBuf->au4_ht[1] = dims.mHeight / 2; |
| |
| psInpRawBuf->au4_strd[0] = yStride; |
| psInpRawBuf->au4_strd[1] = uStride; |
| |
| break; |
| } |
| default: |
| { |
| WORD32 yStride = dims.mWidth; |
| WORD32 uStride = dims.mWidth / 2; |
| WORD32 vStride = dims.mWidth / 2; |
| |
| psInpRawBuf->apv_bufs[0] = buf.data(); |
| psInpRawBuf->apv_bufs[1] = buf.data() + dims.mWidth * dims.mHeight; |
| psInpRawBuf->apv_bufs[2] = buf.data() + (dims.mWidth * dims.mHeight * 5) / 4; |
| |
| psInpRawBuf->au4_wd[0] = dims.mWidth; |
| psInpRawBuf->au4_wd[1] = dims.mWidth / 2; |
| psInpRawBuf->au4_wd[2] = dims.mWidth / 2; |
| |
| psInpRawBuf->au4_ht[0] = dims.mHeight; |
| psInpRawBuf->au4_ht[1] = dims.mHeight / 2; |
| psInpRawBuf->au4_ht[2] = dims.mHeight / 2; |
| |
| psInpRawBuf->au4_strd[0] = yStride; |
| psInpRawBuf->au4_strd[1] = uStride; |
| psInpRawBuf->au4_strd[2] = vStride; |
| |
| break; |
| } |
| } |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const UWORD8 *data, size_t size) |
| { |
| if(size < IDX_LAST) |
| { |
| return 0; |
| } |
| |
| std::unique_ptr<Codec> codec = std::make_unique<Codec>(); |
| |
| if(codec->initEncoder(data)) |
| { |
| codec->encodeFrames(data, size); |
| } |
| |
| return 0; |
| } |