1da853ecaSopenharmony_ci/* 2da853ecaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3da853ecaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4da853ecaSopenharmony_ci * you may not use this file except in compliance with the License. 5da853ecaSopenharmony_ci * You may obtain a copy of the License at 6da853ecaSopenharmony_ci * 7da853ecaSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8da853ecaSopenharmony_ci * 9da853ecaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10da853ecaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11da853ecaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12da853ecaSopenharmony_ci * See the License for the specific language governing permissions and 13da853ecaSopenharmony_ci * limitations under the License. 14da853ecaSopenharmony_ci */ 15da853ecaSopenharmony_ci 16da853ecaSopenharmony_ci#include "hencoder.h" 17da853ecaSopenharmony_ci#include <map> 18da853ecaSopenharmony_ci#include <utility> 19da853ecaSopenharmony_ci#include "utils/hdf_base.h" 20da853ecaSopenharmony_ci#include "OMX_VideoExt.h" 21da853ecaSopenharmony_ci#include "media_description.h" // foundation/multimedia/av_codec/interfaces/inner_api/native/ 22da853ecaSopenharmony_ci#include "type_converter.h" 23da853ecaSopenharmony_ci#include "hcodec_log.h" 24da853ecaSopenharmony_ci#include "hcodec_dfx.h" 25da853ecaSopenharmony_ci#include "v3_0/codec_ext_types.h" 26da853ecaSopenharmony_ci 27da853ecaSopenharmony_cinamespace OHOS::MediaAVCodec { 28da853ecaSopenharmony_ciusing namespace std; 29da853ecaSopenharmony_ci 30da853ecaSopenharmony_ciHEncoder::~HEncoder() 31da853ecaSopenharmony_ci{ 32da853ecaSopenharmony_ci MsgHandleLoop::Stop(); 33da853ecaSopenharmony_ci} 34da853ecaSopenharmony_ci 35da853ecaSopenharmony_ciint32_t HEncoder::OnConfigure(const Format &format) 36da853ecaSopenharmony_ci{ 37da853ecaSopenharmony_ci configFormat_ = make_shared<Format>(format); 38da853ecaSopenharmony_ci int32_t ret = ConfigureBufferType(); 39da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 40da853ecaSopenharmony_ci return ret; 41da853ecaSopenharmony_ci } 42da853ecaSopenharmony_ci 43da853ecaSopenharmony_ci optional<double> frameRate = GetFrameRateFromUser(format); 44da853ecaSopenharmony_ci ret = SetupPort(format, frameRate); 45da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 46da853ecaSopenharmony_ci return ret; 47da853ecaSopenharmony_ci } 48da853ecaSopenharmony_ci ConfigureProtocol(format, frameRate); 49da853ecaSopenharmony_ci 50da853ecaSopenharmony_ci ret = ConfigureOutputBitrate(format); 51da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 52da853ecaSopenharmony_ci HLOGW("ConfigureOutputBitrate failed"); 53da853ecaSopenharmony_ci } 54da853ecaSopenharmony_ci ret = SetColorAspects(format); 55da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 56da853ecaSopenharmony_ci HLOGW("set color aspect failed"); 57da853ecaSopenharmony_ci } 58da853ecaSopenharmony_ci (void)SetProcessName(); 59da853ecaSopenharmony_ci (void)SetFrameRateAdaptiveMode(format); 60da853ecaSopenharmony_ci CheckIfEnableCb(format); 61da853ecaSopenharmony_ci ret = SetTemperalLayer(format); 62da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 63da853ecaSopenharmony_ci return ret; 64da853ecaSopenharmony_ci } 65da853ecaSopenharmony_ci ret = SetLTRParam(format); 66da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 67da853ecaSopenharmony_ci return ret; 68da853ecaSopenharmony_ci } 69da853ecaSopenharmony_ci ret = SetQpRange(format, false); 70da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 71da853ecaSopenharmony_ci return ret; 72da853ecaSopenharmony_ci } 73da853ecaSopenharmony_ci ret = SetLowLatency(format); 74da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 75da853ecaSopenharmony_ci return ret; 76da853ecaSopenharmony_ci } 77da853ecaSopenharmony_ci ret = SetRepeat(format); 78da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 79da853ecaSopenharmony_ci return ret; 80da853ecaSopenharmony_ci } 81da853ecaSopenharmony_ci (void)EnableEncoderParamsFeedback(format); 82da853ecaSopenharmony_ci return AVCS_ERR_OK; 83da853ecaSopenharmony_ci} 84da853ecaSopenharmony_ci 85da853ecaSopenharmony_ciint32_t HEncoder::ConfigureBufferType() 86da853ecaSopenharmony_ci{ 87da853ecaSopenharmony_ci UseBufferType useBufferTypes; 88da853ecaSopenharmony_ci InitOMXParamExt(useBufferTypes); 89da853ecaSopenharmony_ci useBufferTypes.portIndex = OMX_DirInput; 90da853ecaSopenharmony_ci useBufferTypes.bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE; 91da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamUseBufferType, useBufferTypes)) { 92da853ecaSopenharmony_ci HLOGE("component don't support CODEC_BUFFER_TYPE_DYNAMIC_HANDLE"); 93da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 94da853ecaSopenharmony_ci } 95da853ecaSopenharmony_ci return AVCS_ERR_OK; 96da853ecaSopenharmony_ci} 97da853ecaSopenharmony_ci 98da853ecaSopenharmony_civoid HEncoder::CheckIfEnableCb(const Format &format) 99da853ecaSopenharmony_ci{ 100da853ecaSopenharmony_ci int32_t enableCb = 0; 101da853ecaSopenharmony_ci if (format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_SURFACE_INPUT_CALLBACK, enableCb)) { 102da853ecaSopenharmony_ci HLOGI("enable surface mode callback flag %d", enableCb); 103da853ecaSopenharmony_ci enableSurfaceModeInputCb_ = static_cast<bool>(enableCb); 104da853ecaSopenharmony_ci } 105da853ecaSopenharmony_ci} 106da853ecaSopenharmony_ci 107da853ecaSopenharmony_ciint32_t HEncoder::SetRepeat(const Format &format) 108da853ecaSopenharmony_ci{ 109da853ecaSopenharmony_ci int repeatMs = 0; 110da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, repeatMs)) { 111da853ecaSopenharmony_ci return AVCS_ERR_OK; 112da853ecaSopenharmony_ci } 113da853ecaSopenharmony_ci if (repeatMs <= 0) { 114da853ecaSopenharmony_ci HLOGW("invalid repeatMs %d", repeatMs); 115da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 116da853ecaSopenharmony_ci } 117da853ecaSopenharmony_ci repeatUs_ = static_cast<uint64_t>(repeatMs * TIME_RATIO_S_TO_MS); 118da853ecaSopenharmony_ci 119da853ecaSopenharmony_ci int repeatMaxCnt = 0; 120da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, repeatMaxCnt)) { 121da853ecaSopenharmony_ci return AVCS_ERR_OK; 122da853ecaSopenharmony_ci } 123da853ecaSopenharmony_ci if (repeatMaxCnt == 0) { 124da853ecaSopenharmony_ci HLOGW("invalid repeatMaxCnt %d", repeatMaxCnt); 125da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 126da853ecaSopenharmony_ci } 127da853ecaSopenharmony_ci repeatMaxCnt_ = repeatMaxCnt; 128da853ecaSopenharmony_ci return AVCS_ERR_OK; 129da853ecaSopenharmony_ci} 130da853ecaSopenharmony_ci 131da853ecaSopenharmony_ciint32_t HEncoder::SetLTRParam(const Format &format) 132da853ecaSopenharmony_ci{ 133da853ecaSopenharmony_ci int32_t ltrFrameNum = -1; 134da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_LTR_FRAME_COUNT, ltrFrameNum)) { 135da853ecaSopenharmony_ci return AVCS_ERR_OK; 136da853ecaSopenharmony_ci } 137da853ecaSopenharmony_ci if (!caps_.port.video.isSupportLTR) { 138da853ecaSopenharmony_ci HLOGW("platform not support LTR"); 139da853ecaSopenharmony_ci return AVCS_ERR_OK; 140da853ecaSopenharmony_ci } 141da853ecaSopenharmony_ci if (ltrFrameNum <= 0 || ltrFrameNum > caps_.port.video.maxLTRFrameNum) { 142da853ecaSopenharmony_ci HLOGE("invalid ltrFrameNum %d", ltrFrameNum); 143da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 144da853ecaSopenharmony_ci } 145da853ecaSopenharmony_ci if (enableTSVC_) { 146da853ecaSopenharmony_ci HLOGW("user has enabled temporal scale, can not set LTR param"); 147da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 148da853ecaSopenharmony_ci } 149da853ecaSopenharmony_ci CodecLTRParam info; 150da853ecaSopenharmony_ci InitOMXParamExt(info); 151da853ecaSopenharmony_ci info.ltrFrameListLen = static_cast<uint32_t>(ltrFrameNum); 152da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamLTR, info)) { 153da853ecaSopenharmony_ci HLOGE("configure LTR failed"); 154da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 155da853ecaSopenharmony_ci } 156da853ecaSopenharmony_ci enableLTR_ = true; 157da853ecaSopenharmony_ci return AVCS_ERR_OK; 158da853ecaSopenharmony_ci} 159da853ecaSopenharmony_ci 160da853ecaSopenharmony_ciint32_t HEncoder::EnableEncoderParamsFeedback(const Format &format) 161da853ecaSopenharmony_ci{ 162da853ecaSopenharmony_ci int32_t enableParamsFeedback {}; 163da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_PARAMS_FEEDBACK, enableParamsFeedback)) { 164da853ecaSopenharmony_ci return AVCS_ERR_OK; 165da853ecaSopenharmony_ci } 166da853ecaSopenharmony_ci OMX_CONFIG_BOOLEANTYPE param {}; 167da853ecaSopenharmony_ci InitOMXParam(param); 168da853ecaSopenharmony_ci param.bEnabled = enableParamsFeedback ? OMX_TRUE : OMX_FALSE; 169da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamEncParamsFeedback, param)) { 170da853ecaSopenharmony_ci HLOGE("configure encoder params feedback[%d] failed", enableParamsFeedback); 171da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 172da853ecaSopenharmony_ci } 173da853ecaSopenharmony_ci HLOGI("configure encoder params feedback[%d] success", enableParamsFeedback); 174da853ecaSopenharmony_ci return AVCS_ERR_OK; 175da853ecaSopenharmony_ci} 176da853ecaSopenharmony_ci 177da853ecaSopenharmony_ciint32_t HEncoder::SetQpRange(const Format &format, bool isCfg) 178da853ecaSopenharmony_ci{ 179da853ecaSopenharmony_ci int32_t minQp; 180da853ecaSopenharmony_ci int32_t maxQp; 181da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, minQp) || 182da853ecaSopenharmony_ci !format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, maxQp)) { 183da853ecaSopenharmony_ci return AVCS_ERR_OK; 184da853ecaSopenharmony_ci } 185da853ecaSopenharmony_ci 186da853ecaSopenharmony_ci CodecQPRangeParam QPRangeParam; 187da853ecaSopenharmony_ci InitOMXParamExt(QPRangeParam); 188da853ecaSopenharmony_ci QPRangeParam.minQp = static_cast<uint32_t>(minQp); 189da853ecaSopenharmony_ci QPRangeParam.maxQp = static_cast<uint32_t>(maxQp); 190da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamQPRange, QPRangeParam, isCfg)) { 191da853ecaSopenharmony_ci HLOGE("set qp range (%d~%d) failed", minQp, maxQp); 192da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 193da853ecaSopenharmony_ci } 194da853ecaSopenharmony_ci HLOGI("set qp range (%d~%d) succ", minQp, maxQp); 195da853ecaSopenharmony_ci return AVCS_ERR_OK; 196da853ecaSopenharmony_ci} 197da853ecaSopenharmony_ci 198da853ecaSopenharmony_ciint32_t HEncoder::SetTemperalLayer(const Format &format) 199da853ecaSopenharmony_ci{ 200da853ecaSopenharmony_ci int32_t enableTemporalScale = 0; 201da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, enableTemporalScale) || 202da853ecaSopenharmony_ci (enableTemporalScale == 0)) { 203da853ecaSopenharmony_ci return AVCS_ERR_OK; 204da853ecaSopenharmony_ci } 205da853ecaSopenharmony_ci if (!caps_.port.video.isSupportTSVC) { 206da853ecaSopenharmony_ci HLOGW("platform not support temporal scale"); 207da853ecaSopenharmony_ci return AVCS_ERR_OK; 208da853ecaSopenharmony_ci } 209da853ecaSopenharmony_ci Media::Plugins::TemporalGopReferenceMode GopReferenceMode{}; 210da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, 211da853ecaSopenharmony_ci *reinterpret_cast<int *>(&GopReferenceMode)) || 212da853ecaSopenharmony_ci static_cast<int32_t>(GopReferenceMode) != 2) { // 2: gop mode 213da853ecaSopenharmony_ci HLOGE("user enable temporal scalability but not set invalid temporal gop mode"); 214da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 215da853ecaSopenharmony_ci } 216da853ecaSopenharmony_ci int32_t temporalGopSize = 0; 217da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporalGopSize)) { 218da853ecaSopenharmony_ci HLOGE("user enable temporal scalability but not set invalid temporal gop size"); 219da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 220da853ecaSopenharmony_ci } 221da853ecaSopenharmony_ci 222da853ecaSopenharmony_ci CodecTemperalLayerParam temperalLayerParam; 223da853ecaSopenharmony_ci InitOMXParamExt(temperalLayerParam); 224da853ecaSopenharmony_ci switch (temporalGopSize) { 225da853ecaSopenharmony_ci case 2: // 2: picture size of the temporal group 226da853ecaSopenharmony_ci temperalLayerParam.layerCnt = 2; // 2: layer of the temporal group 227da853ecaSopenharmony_ci break; 228da853ecaSopenharmony_ci case 4: // 4: picture size of the temporal group 229da853ecaSopenharmony_ci temperalLayerParam.layerCnt = 3; // 3: layer of the temporal group 230da853ecaSopenharmony_ci break; 231da853ecaSopenharmony_ci default: 232da853ecaSopenharmony_ci HLOGE("user set invalid temporal gop size %d", temporalGopSize); 233da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 234da853ecaSopenharmony_ci } 235da853ecaSopenharmony_ci 236da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamTemperalLayer, temperalLayerParam)) { 237da853ecaSopenharmony_ci HLOGE("set temporal layer param failed"); 238da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 239da853ecaSopenharmony_ci } 240da853ecaSopenharmony_ci HLOGI("set temporal layer param %d succ", temperalLayerParam.layerCnt); 241da853ecaSopenharmony_ci enableTSVC_ = true; 242da853ecaSopenharmony_ci return AVCS_ERR_OK; 243da853ecaSopenharmony_ci} 244da853ecaSopenharmony_ci 245da853ecaSopenharmony_ciint32_t HEncoder::OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer) 246da853ecaSopenharmony_ci{ 247da853ecaSopenharmony_ci if (!caps_.port.video.isSupportWaterMark) { 248da853ecaSopenharmony_ci HLOGE("this device dont support water mark"); 249da853ecaSopenharmony_ci return AVCS_ERR_UNSUPPORT; 250da853ecaSopenharmony_ci } 251da853ecaSopenharmony_ci if (buffer == nullptr || buffer->memory_ == nullptr || buffer->meta_ == nullptr) { 252da853ecaSopenharmony_ci HLOGE("invalid buffer"); 253da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 254da853ecaSopenharmony_ci } 255da853ecaSopenharmony_ci sptr<SurfaceBuffer> waterMarkBuffer = buffer->memory_->GetSurfaceBuffer(); 256da853ecaSopenharmony_ci if (waterMarkBuffer == nullptr) { 257da853ecaSopenharmony_ci HLOGE("null surfacebuffer"); 258da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 259da853ecaSopenharmony_ci } 260da853ecaSopenharmony_ci if (waterMarkBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_8888) { 261da853ecaSopenharmony_ci HLOGE("pixel fmt should be RGBA8888"); 262da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 263da853ecaSopenharmony_ci } 264da853ecaSopenharmony_ci bool enableWaterMark = false; 265da853ecaSopenharmony_ci int32_t x = 0; 266da853ecaSopenharmony_ci int32_t y = 0; 267da853ecaSopenharmony_ci int32_t w = 0; 268da853ecaSopenharmony_ci int32_t h = 0; 269da853ecaSopenharmony_ci if (!buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_ENCODER_ENABLE_WATERMARK, enableWaterMark) || 270da853ecaSopenharmony_ci !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_X, x) || 271da853ecaSopenharmony_ci !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_Y, y) || 272da853ecaSopenharmony_ci !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_W, w) || 273da853ecaSopenharmony_ci !buffer->meta_->GetData(OHOS::Media::Tag::VIDEO_COORDINATE_H, h)) { 274da853ecaSopenharmony_ci HLOGE("invalid value"); 275da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 276da853ecaSopenharmony_ci } 277da853ecaSopenharmony_ci if (x < 0 || y < 0 || w <= 0 || h <= 0) { 278da853ecaSopenharmony_ci HLOGE("invalid coordinate, x %d, y %d, w %d, h %d", x, y, w, h); 279da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 280da853ecaSopenharmony_ci } 281da853ecaSopenharmony_ci CodecHDI::CodecParamOverlay param { 282da853ecaSopenharmony_ci .size = sizeof(param), .enable = enableWaterMark, .dstX = static_cast<uint32_t>(x), 283da853ecaSopenharmony_ci .dstY = static_cast<uint32_t>(y), .dstW = static_cast<uint32_t>(w), .dstH = static_cast<uint32_t>(h), 284da853ecaSopenharmony_ci }; 285da853ecaSopenharmony_ci int8_t* p = reinterpret_cast<int8_t*>(¶m); 286da853ecaSopenharmony_ci std::vector<int8_t> inVec(p, p + sizeof(param)); 287da853ecaSopenharmony_ci CodecHDI::OmxCodecBuffer omxbuffer {}; 288da853ecaSopenharmony_ci omxbuffer.bufferhandle = new HDI::Base::NativeBuffer(waterMarkBuffer->GetBufferHandle()); 289da853ecaSopenharmony_ci int32_t ret = compNode_->SetParameterWithBuffer(CodecHDI::Codec_IndexParamOverlayBuffer, inVec, omxbuffer); 290da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 291da853ecaSopenharmony_ci HLOGE("SetParameterWithBuffer failed"); 292da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 293da853ecaSopenharmony_ci } 294da853ecaSopenharmony_ci HLOGI("SetParameterWithBuffer succ"); 295da853ecaSopenharmony_ci return AVCS_ERR_OK; 296da853ecaSopenharmony_ci} 297da853ecaSopenharmony_ci 298da853ecaSopenharmony_ciint32_t HEncoder::SetColorAspects(const Format &format) 299da853ecaSopenharmony_ci{ 300da853ecaSopenharmony_ci int range = 0; 301da853ecaSopenharmony_ci int primary = static_cast<int>(COLOR_PRIMARY_UNSPECIFIED); 302da853ecaSopenharmony_ci int transfer = static_cast<int>(TRANSFER_CHARACTERISTIC_UNSPECIFIED); 303da853ecaSopenharmony_ci int matrix = static_cast<int>(MATRIX_COEFFICIENT_UNSPECIFIED); 304da853ecaSopenharmony_ci 305da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, range)) { 306da853ecaSopenharmony_ci HLOGI("user set range flag %d", range); 307da853ecaSopenharmony_ci } 308da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, primary)) { 309da853ecaSopenharmony_ci HLOGI("user set primary %d", primary); 310da853ecaSopenharmony_ci } 311da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, transfer)) { 312da853ecaSopenharmony_ci HLOGI("user set transfer %d", transfer); 313da853ecaSopenharmony_ci } 314da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, matrix)) { 315da853ecaSopenharmony_ci HLOGI("user set matrix %d", matrix); 316da853ecaSopenharmony_ci } 317da853ecaSopenharmony_ci if (primary < 0 || primary > UINT8_MAX || 318da853ecaSopenharmony_ci transfer < 0 || transfer > UINT8_MAX || 319da853ecaSopenharmony_ci matrix < 0 || matrix > UINT8_MAX) { 320da853ecaSopenharmony_ci HLOGW("invalid color"); 321da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 322da853ecaSopenharmony_ci } 323da853ecaSopenharmony_ci 324da853ecaSopenharmony_ci CodecVideoColorspace param; 325da853ecaSopenharmony_ci InitOMXParamExt(param); 326da853ecaSopenharmony_ci param.portIndex = OMX_DirInput; 327da853ecaSopenharmony_ci param.aspects.range = static_cast<bool>(range); 328da853ecaSopenharmony_ci param.aspects.primaries = static_cast<uint8_t>(primary); 329da853ecaSopenharmony_ci param.aspects.transfer = static_cast<uint8_t>(transfer); 330da853ecaSopenharmony_ci param.aspects.matrixCoeffs = static_cast<uint8_t>(matrix); 331da853ecaSopenharmony_ci 332da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexColorAspects, param, true)) { 333da853ecaSopenharmony_ci HLOGE("failed to set CodecVideoColorSpace"); 334da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 335da853ecaSopenharmony_ci } 336da853ecaSopenharmony_ci HLOGI("set color aspects (isFullRange %d, primary %u, transfer %u, matrix %u) succ", 337da853ecaSopenharmony_ci param.aspects.range, param.aspects.primaries, 338da853ecaSopenharmony_ci param.aspects.transfer, param.aspects.matrixCoeffs); 339da853ecaSopenharmony_ci return AVCS_ERR_OK; 340da853ecaSopenharmony_ci} 341da853ecaSopenharmony_ci 342da853ecaSopenharmony_civoid HEncoder::CalcInputBufSize(PortInfo &info, VideoPixelFormat pixelFmt) 343da853ecaSopenharmony_ci{ 344da853ecaSopenharmony_ci uint32_t inSize = AlignTo(info.width, 128u) * AlignTo(info.height, 128u); // 128: block size 345da853ecaSopenharmony_ci if (pixelFmt == VideoPixelFormat::RGBA) { 346da853ecaSopenharmony_ci inSize = inSize * 4; // 4 byte per pixel 347da853ecaSopenharmony_ci } else { 348da853ecaSopenharmony_ci inSize = inSize * 3 / 2; // 3: nom, 2: denom 349da853ecaSopenharmony_ci } 350da853ecaSopenharmony_ci info.inputBufSize = inSize; 351da853ecaSopenharmony_ci} 352da853ecaSopenharmony_ci 353da853ecaSopenharmony_ciint32_t HEncoder::SetupPort(const Format &format, std::optional<double> frameRate) 354da853ecaSopenharmony_ci{ 355da853ecaSopenharmony_ci constexpr int32_t MAX_ENCODE_WIDTH = 10000; 356da853ecaSopenharmony_ci constexpr int32_t MAX_ENCODE_HEIGHT = 10000; 357da853ecaSopenharmony_ci int32_t width; 358da853ecaSopenharmony_ci if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width) || width <= 0 || width > MAX_ENCODE_WIDTH) { 359da853ecaSopenharmony_ci HLOGE("format should contain width"); 360da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 361da853ecaSopenharmony_ci } 362da853ecaSopenharmony_ci int32_t height; 363da853ecaSopenharmony_ci if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height) || height <= 0 || height > MAX_ENCODE_HEIGHT) { 364da853ecaSopenharmony_ci HLOGE("format should contain height"); 365da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 366da853ecaSopenharmony_ci } 367da853ecaSopenharmony_ci width_ = static_cast<uint32_t>(width); 368da853ecaSopenharmony_ci height_ = static_cast<uint32_t>(height); 369da853ecaSopenharmony_ci HLOGI("user set width %d, height %d", width, height); 370da853ecaSopenharmony_ci if (!GetPixelFmtFromUser(format)) { 371da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 372da853ecaSopenharmony_ci } 373da853ecaSopenharmony_ci 374da853ecaSopenharmony_ci if (!frameRate.has_value()) { 375da853ecaSopenharmony_ci HLOGI("user don't set valid frame rate, use default 60.0"); 376da853ecaSopenharmony_ci frameRate = 60.0; // default frame rate 60.0 377da853ecaSopenharmony_ci } 378da853ecaSopenharmony_ci 379da853ecaSopenharmony_ci PortInfo inputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 380da853ecaSopenharmony_ci OMX_VIDEO_CodingUnused, configuredFmt_, frameRate.value()}; 381da853ecaSopenharmony_ci CalcInputBufSize(inputPortInfo, configuredFmt_.innerFmt); 382da853ecaSopenharmony_ci int32_t ret = SetVideoPortInfo(OMX_DirInput, inputPortInfo); 383da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 384da853ecaSopenharmony_ci return ret; 385da853ecaSopenharmony_ci } 386da853ecaSopenharmony_ci 387da853ecaSopenharmony_ci PortInfo outputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 388da853ecaSopenharmony_ci codingType_, std::nullopt, frameRate.value()}; 389da853ecaSopenharmony_ci ret = SetVideoPortInfo(OMX_DirOutput, outputPortInfo); 390da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 391da853ecaSopenharmony_ci return ret; 392da853ecaSopenharmony_ci } 393da853ecaSopenharmony_ci return AVCS_ERR_OK; 394da853ecaSopenharmony_ci} 395da853ecaSopenharmony_ci 396da853ecaSopenharmony_ciint32_t HEncoder::UpdateInPortFormat() 397da853ecaSopenharmony_ci{ 398da853ecaSopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE def; 399da853ecaSopenharmony_ci InitOMXParam(def); 400da853ecaSopenharmony_ci def.nPortIndex = OMX_DirInput; 401da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 402da853ecaSopenharmony_ci HLOGE("get input port definition failed"); 403da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 404da853ecaSopenharmony_ci } 405da853ecaSopenharmony_ci PrintPortDefinition(def); 406da853ecaSopenharmony_ci uint32_t w = def.format.video.nFrameWidth; 407da853ecaSopenharmony_ci uint32_t h = def.format.video.nFrameHeight; 408da853ecaSopenharmony_ci inBufferCnt_ = def.nBufferCountActual; 409da853ecaSopenharmony_ci 410da853ecaSopenharmony_ci // save into member variable 411da853ecaSopenharmony_ci requestCfg_.timeout = 0; 412da853ecaSopenharmony_ci requestCfg_.width = static_cast<int32_t>(w); 413da853ecaSopenharmony_ci requestCfg_.height = static_cast<int32_t>(h); 414da853ecaSopenharmony_ci requestCfg_.strideAlignment = STRIDE_ALIGNMENT; 415da853ecaSopenharmony_ci requestCfg_.format = configuredFmt_.graphicFmt; 416da853ecaSopenharmony_ci requestCfg_.usage = BUFFER_MODE_REQUEST_USAGE; 417da853ecaSopenharmony_ci 418da853ecaSopenharmony_ci if (inputFormat_ == nullptr) { 419da853ecaSopenharmony_ci inputFormat_ = make_shared<Format>(); 420da853ecaSopenharmony_ci } 421da853ecaSopenharmony_ci inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, w); 422da853ecaSopenharmony_ci inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, h); 423da853ecaSopenharmony_ci inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, 424da853ecaSopenharmony_ci static_cast<int32_t>(configuredFmt_.innerFmt)); 425da853ecaSopenharmony_ci return AVCS_ERR_OK; 426da853ecaSopenharmony_ci} 427da853ecaSopenharmony_ci 428da853ecaSopenharmony_ciint32_t HEncoder::UpdateOutPortFormat() 429da853ecaSopenharmony_ci{ 430da853ecaSopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE def; 431da853ecaSopenharmony_ci InitOMXParam(def); 432da853ecaSopenharmony_ci def.nPortIndex = OMX_DirOutput; 433da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 434da853ecaSopenharmony_ci HLOGE("get output port definition failed"); 435da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 436da853ecaSopenharmony_ci } 437da853ecaSopenharmony_ci PrintPortDefinition(def); 438da853ecaSopenharmony_ci if (outputFormat_ == nullptr) { 439da853ecaSopenharmony_ci outputFormat_ = make_shared<Format>(); 440da853ecaSopenharmony_ci } 441da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, def.format.video.nFrameWidth); 442da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, def.format.video.nFrameHeight); 443da853ecaSopenharmony_ci return AVCS_ERR_OK; 444da853ecaSopenharmony_ci} 445da853ecaSopenharmony_ci 446da853ecaSopenharmony_cistatic uint32_t SetPFramesSpacing(int32_t iFramesIntervalInMs, double frameRate, uint32_t bFramesSpacing = 0) 447da853ecaSopenharmony_ci{ 448da853ecaSopenharmony_ci if (iFramesIntervalInMs < 0) { // IPPPP... 449da853ecaSopenharmony_ci return UINT32_MAX - 1; 450da853ecaSopenharmony_ci } 451da853ecaSopenharmony_ci if (iFramesIntervalInMs == 0) { // IIIII... 452da853ecaSopenharmony_ci return 0; 453da853ecaSopenharmony_ci } 454da853ecaSopenharmony_ci uint32_t iFramesInterval = iFramesIntervalInMs * frameRate / TIME_RATIO_S_TO_MS; 455da853ecaSopenharmony_ci uint32_t pFramesSpacing = iFramesInterval / (bFramesSpacing + 1); 456da853ecaSopenharmony_ci return pFramesSpacing > 0 ? pFramesSpacing - 1 : 0; 457da853ecaSopenharmony_ci} 458da853ecaSopenharmony_ci 459da853ecaSopenharmony_cistd::optional<uint32_t> HEncoder::GetBitRateFromUser(const Format &format) 460da853ecaSopenharmony_ci{ 461da853ecaSopenharmony_ci int64_t bitRateLong; 462da853ecaSopenharmony_ci if (format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateLong) && bitRateLong > 0 && 463da853ecaSopenharmony_ci bitRateLong <= UINT32_MAX) { 464da853ecaSopenharmony_ci LOGI("user set bit rate %" PRId64 "", bitRateLong); 465da853ecaSopenharmony_ci return static_cast<uint32_t>(bitRateLong); 466da853ecaSopenharmony_ci } 467da853ecaSopenharmony_ci int32_t bitRateInt; 468da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_BITRATE, bitRateInt) && bitRateInt > 0) { 469da853ecaSopenharmony_ci LOGI("user set bit rate %d", bitRateInt); 470da853ecaSopenharmony_ci return static_cast<uint32_t>(bitRateInt); 471da853ecaSopenharmony_ci } 472da853ecaSopenharmony_ci return nullopt; 473da853ecaSopenharmony_ci} 474da853ecaSopenharmony_ci 475da853ecaSopenharmony_cistd::optional<VideoEncodeBitrateMode> HEncoder::GetBitRateModeFromUser(const Format &format) 476da853ecaSopenharmony_ci{ 477da853ecaSopenharmony_ci VideoEncodeBitrateMode mode; 478da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, *reinterpret_cast<int *>(&mode))) { 479da853ecaSopenharmony_ci return mode; 480da853ecaSopenharmony_ci } 481da853ecaSopenharmony_ci return nullopt; 482da853ecaSopenharmony_ci} 483da853ecaSopenharmony_ci 484da853ecaSopenharmony_ciint32_t HEncoder::SetConstantQualityMode(int32_t quality) 485da853ecaSopenharmony_ci{ 486da853ecaSopenharmony_ci ControlRateConstantQuality bitrateType; 487da853ecaSopenharmony_ci InitOMXParamExt(bitrateType); 488da853ecaSopenharmony_ci bitrateType.portIndex = OMX_DirOutput; 489da853ecaSopenharmony_ci bitrateType.qualityValue = static_cast<uint32_t>(quality); 490da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamControlRateConstantQuality, bitrateType)) { 491da853ecaSopenharmony_ci HLOGE("failed to set OMX_IndexParamControlRateConstantQuality"); 492da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 493da853ecaSopenharmony_ci } 494da853ecaSopenharmony_ci HLOGI("set CQ mode and target quality %u succ", bitrateType.qualityValue); 495da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, CQ); 496da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality); 497da853ecaSopenharmony_ci return AVCS_ERR_OK; 498da853ecaSopenharmony_ci} 499da853ecaSopenharmony_ci 500da853ecaSopenharmony_ciint32_t HEncoder::ConfigureOutputBitrate(const Format &format) 501da853ecaSopenharmony_ci{ 502da853ecaSopenharmony_ci OMX_VIDEO_PARAM_BITRATETYPE bitrateType; 503da853ecaSopenharmony_ci InitOMXParam(bitrateType); 504da853ecaSopenharmony_ci bitrateType.nPortIndex = OMX_DirOutput; 505da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamVideoBitrate, bitrateType)) { 506da853ecaSopenharmony_ci HLOGE("get OMX_IndexParamVideoBitrate failed"); 507da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 508da853ecaSopenharmony_ci } 509da853ecaSopenharmony_ci optional<VideoEncodeBitrateMode> bitRateMode = GetBitRateModeFromUser(format); 510da853ecaSopenharmony_ci int32_t quality; 511da853ecaSopenharmony_ci if (bitRateMode.has_value() && bitRateMode.value() == CQ && 512da853ecaSopenharmony_ci format.GetIntValue(MediaDescriptionKey::MD_KEY_QUALITY, quality) && quality >= 0) { 513da853ecaSopenharmony_ci return SetConstantQualityMode(quality); 514da853ecaSopenharmony_ci } 515da853ecaSopenharmony_ci optional<uint32_t> bitRate = GetBitRateFromUser(format); 516da853ecaSopenharmony_ci if (bitRate.has_value()) { 517da853ecaSopenharmony_ci bitrateType.nTargetBitrate = bitRate.value(); 518da853ecaSopenharmony_ci } 519da853ecaSopenharmony_ci if (bitRateMode.has_value()) { 520da853ecaSopenharmony_ci auto omxBitrateMode = TypeConverter::InnerModeToOmxBitrateMode(bitRateMode.value()); 521da853ecaSopenharmony_ci if (omxBitrateMode.has_value()) { 522da853ecaSopenharmony_ci bitrateType.eControlRate = omxBitrateMode.value(); 523da853ecaSopenharmony_ci } 524da853ecaSopenharmony_ci } 525da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamVideoBitrate, bitrateType)) { 526da853ecaSopenharmony_ci HLOGE("failed to set OMX_IndexParamVideoBitrate"); 527da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 528da853ecaSopenharmony_ci } 529da853ecaSopenharmony_ci outputFormat_->PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, 530da853ecaSopenharmony_ci static_cast<int64_t>(bitrateType.nTargetBitrate)); 531da853ecaSopenharmony_ci auto innerMode = TypeConverter::OmxBitrateModeToInnerMode(bitrateType.eControlRate); 532da853ecaSopenharmony_ci if (innerMode.has_value()) { 533da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, 534da853ecaSopenharmony_ci static_cast<int32_t>(innerMode.value())); 535da853ecaSopenharmony_ci HLOGI("set %d mode and target bitrate %u bps succ", bitRateMode.value(), bitrateType.nTargetBitrate); 536da853ecaSopenharmony_ci } else { 537da853ecaSopenharmony_ci HLOGI("set default bitratemode and target bitrate %u bps succ", bitrateType.nTargetBitrate); 538da853ecaSopenharmony_ci } 539da853ecaSopenharmony_ci return AVCS_ERR_OK; 540da853ecaSopenharmony_ci} 541da853ecaSopenharmony_ci 542da853ecaSopenharmony_civoid HEncoder::ConfigureProtocol(const Format &format, std::optional<double> frameRate) 543da853ecaSopenharmony_ci{ 544da853ecaSopenharmony_ci int32_t ret = AVCS_ERR_OK; 545da853ecaSopenharmony_ci switch (static_cast<int>(codingType_)) { 546da853ecaSopenharmony_ci case OMX_VIDEO_CodingAVC: 547da853ecaSopenharmony_ci ret = SetupAVCEncoderParameters(format, frameRate); 548da853ecaSopenharmony_ci break; 549da853ecaSopenharmony_ci case CODEC_OMX_VIDEO_CodingHEVC: 550da853ecaSopenharmony_ci ret = SetupHEVCEncoderParameters(format, frameRate); 551da853ecaSopenharmony_ci break; 552da853ecaSopenharmony_ci default: 553da853ecaSopenharmony_ci break; 554da853ecaSopenharmony_ci } 555da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 556da853ecaSopenharmony_ci HLOGW("set protocol param failed"); 557da853ecaSopenharmony_ci } 558da853ecaSopenharmony_ci} 559da853ecaSopenharmony_ci 560da853ecaSopenharmony_ciint32_t HEncoder::SetupAVCEncoderParameters(const Format &format, std::optional<double> frameRate) 561da853ecaSopenharmony_ci{ 562da853ecaSopenharmony_ci OMX_VIDEO_PARAM_AVCTYPE avcType; 563da853ecaSopenharmony_ci InitOMXParam(avcType); 564da853ecaSopenharmony_ci avcType.nPortIndex = OMX_DirOutput; 565da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamVideoAvc, avcType)) { 566da853ecaSopenharmony_ci HLOGE("get OMX_IndexParamVideoAvc parameter fail"); 567da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 568da853ecaSopenharmony_ci } 569da853ecaSopenharmony_ci avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 570da853ecaSopenharmony_ci avcType.nBFrames = 0; 571da853ecaSopenharmony_ci 572da853ecaSopenharmony_ci AVCProfile profile; 573da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int *>(&profile))) { 574da853ecaSopenharmony_ci optional<OMX_VIDEO_AVCPROFILETYPE> omxAvcProfile = TypeConverter::InnerAvcProfileToOmxProfile(profile); 575da853ecaSopenharmony_ci if (omxAvcProfile.has_value()) { 576da853ecaSopenharmony_ci avcType.eProfile = omxAvcProfile.value(); 577da853ecaSopenharmony_ci } 578da853ecaSopenharmony_ci } 579da853ecaSopenharmony_ci int32_t iFrameInterval; 580da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) && frameRate.has_value()) { 581da853ecaSopenharmony_ci SetAvcFields(avcType, iFrameInterval, frameRate.value()); 582da853ecaSopenharmony_ci } 583da853ecaSopenharmony_ci 584da853ecaSopenharmony_ci if (avcType.nBFrames != 0) { 585da853ecaSopenharmony_ci avcType.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; 586da853ecaSopenharmony_ci } 587da853ecaSopenharmony_ci avcType.bEnableUEP = OMX_FALSE; 588da853ecaSopenharmony_ci avcType.bEnableFMO = OMX_FALSE; 589da853ecaSopenharmony_ci avcType.bEnableASO = OMX_FALSE; 590da853ecaSopenharmony_ci avcType.bEnableRS = OMX_FALSE; 591da853ecaSopenharmony_ci avcType.bFrameMBsOnly = OMX_TRUE; 592da853ecaSopenharmony_ci avcType.bMBAFF = OMX_FALSE; 593da853ecaSopenharmony_ci avcType.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable; 594da853ecaSopenharmony_ci 595da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamVideoAvc, avcType)) { 596da853ecaSopenharmony_ci HLOGE("failed to set OMX_IndexParamVideoAvc"); 597da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 598da853ecaSopenharmony_ci } 599da853ecaSopenharmony_ci return AVCS_ERR_OK; 600da853ecaSopenharmony_ci} 601da853ecaSopenharmony_ci 602da853ecaSopenharmony_civoid HEncoder::SetAvcFields(OMX_VIDEO_PARAM_AVCTYPE &avcType, int32_t iFrameInterval, double frameRate) 603da853ecaSopenharmony_ci{ 604da853ecaSopenharmony_ci HLOGI("iFrameInterval:%d, frameRate:%.2f, eProfile:0x%x, eLevel:0x%x", 605da853ecaSopenharmony_ci iFrameInterval, frameRate, avcType.eProfile, avcType.eLevel); 606da853ecaSopenharmony_ci 607da853ecaSopenharmony_ci if (avcType.eProfile == OMX_VIDEO_AVCProfileBaseline) { 608da853ecaSopenharmony_ci avcType.nSliceHeaderSpacing = 0; 609da853ecaSopenharmony_ci avcType.bUseHadamard = OMX_TRUE; 610da853ecaSopenharmony_ci avcType.nRefFrames = 1; 611da853ecaSopenharmony_ci avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames); 612da853ecaSopenharmony_ci if (avcType.nPFrames == 0) { 613da853ecaSopenharmony_ci avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; 614da853ecaSopenharmony_ci } 615da853ecaSopenharmony_ci avcType.nRefIdx10ActiveMinus1 = 0; 616da853ecaSopenharmony_ci avcType.nRefIdx11ActiveMinus1 = 0; 617da853ecaSopenharmony_ci avcType.bEntropyCodingCABAC = OMX_FALSE; 618da853ecaSopenharmony_ci avcType.bWeightedPPrediction = OMX_FALSE; 619da853ecaSopenharmony_ci avcType.bconstIpred = OMX_FALSE; 620da853ecaSopenharmony_ci avcType.bDirect8x8Inference = OMX_FALSE; 621da853ecaSopenharmony_ci avcType.bDirectSpatialTemporal = OMX_FALSE; 622da853ecaSopenharmony_ci avcType.nCabacInitIdc = 0; 623da853ecaSopenharmony_ci } else if (avcType.eProfile == OMX_VIDEO_AVCProfileMain || avcType.eProfile == OMX_VIDEO_AVCProfileHigh) { 624da853ecaSopenharmony_ci avcType.nSliceHeaderSpacing = 0; 625da853ecaSopenharmony_ci avcType.bUseHadamard = OMX_TRUE; 626da853ecaSopenharmony_ci avcType.nRefFrames = avcType.nBFrames == 0 ? 1 : 2; // 2 is number of reference frames 627da853ecaSopenharmony_ci avcType.nPFrames = SetPFramesSpacing(iFrameInterval, frameRate, avcType.nBFrames); 628da853ecaSopenharmony_ci avcType.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; 629da853ecaSopenharmony_ci avcType.nRefIdx10ActiveMinus1 = 0; 630da853ecaSopenharmony_ci avcType.nRefIdx11ActiveMinus1 = 0; 631da853ecaSopenharmony_ci avcType.bEntropyCodingCABAC = OMX_TRUE; 632da853ecaSopenharmony_ci avcType.bWeightedPPrediction = OMX_TRUE; 633da853ecaSopenharmony_ci avcType.bconstIpred = OMX_TRUE; 634da853ecaSopenharmony_ci avcType.bDirect8x8Inference = OMX_TRUE; 635da853ecaSopenharmony_ci avcType.bDirectSpatialTemporal = OMX_TRUE; 636da853ecaSopenharmony_ci avcType.nCabacInitIdc = 1; 637da853ecaSopenharmony_ci } 638da853ecaSopenharmony_ci} 639da853ecaSopenharmony_ci 640da853ecaSopenharmony_ciint32_t HEncoder::SetupHEVCEncoderParameters(const Format &format, std::optional<double> frameRate) 641da853ecaSopenharmony_ci{ 642da853ecaSopenharmony_ci CodecVideoParamHevc hevcType; 643da853ecaSopenharmony_ci InitOMXParamExt(hevcType); 644da853ecaSopenharmony_ci hevcType.portIndex = OMX_DirOutput; 645da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamVideoHevc, hevcType)) { 646da853ecaSopenharmony_ci HLOGE("get OMX_IndexParamVideoHevc parameter fail"); 647da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 648da853ecaSopenharmony_ci } 649da853ecaSopenharmony_ci 650da853ecaSopenharmony_ci HEVCProfile profile; 651da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PROFILE, *reinterpret_cast<int *>(&profile))) { 652da853ecaSopenharmony_ci optional<CodecHevcProfile> omxHevcProfile = TypeConverter::InnerHevcProfileToOmxProfile(profile); 653da853ecaSopenharmony_ci if (omxHevcProfile.has_value()) { 654da853ecaSopenharmony_ci hevcType.profile = omxHevcProfile.value(); 655da853ecaSopenharmony_ci HLOGI("HEVCProfile %d, CodecHevcProfile 0x%x", profile, hevcType.profile); 656da853ecaSopenharmony_ci } 657da853ecaSopenharmony_ci } 658da853ecaSopenharmony_ci 659da853ecaSopenharmony_ci int32_t iFrameInterval; 660da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval) && frameRate.has_value()) { 661da853ecaSopenharmony_ci if (iFrameInterval < 0) { // IPPPP... 662da853ecaSopenharmony_ci hevcType.keyFrameInterval = UINT32_MAX - 1; 663da853ecaSopenharmony_ci } else if (iFrameInterval == 0) { // all intra 664da853ecaSopenharmony_ci hevcType.keyFrameInterval = 1; 665da853ecaSopenharmony_ci } else { 666da853ecaSopenharmony_ci hevcType.keyFrameInterval = iFrameInterval * frameRate.value() / TIME_RATIO_S_TO_MS; 667da853ecaSopenharmony_ci } 668da853ecaSopenharmony_ci HLOGI("frameRate %.2f, iFrameInterval %d, keyFrameInterval %u", frameRate.value(), 669da853ecaSopenharmony_ci iFrameInterval, hevcType.keyFrameInterval); 670da853ecaSopenharmony_ci } 671da853ecaSopenharmony_ci 672da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamVideoHevc, hevcType)) { 673da853ecaSopenharmony_ci HLOGE("failed to set OMX_IndexParamVideoHevc"); 674da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 675da853ecaSopenharmony_ci } 676da853ecaSopenharmony_ci return AVCS_ERR_OK; 677da853ecaSopenharmony_ci} 678da853ecaSopenharmony_ci 679da853ecaSopenharmony_ciint32_t HEncoder::RequestIDRFrame() 680da853ecaSopenharmony_ci{ 681da853ecaSopenharmony_ci OMX_CONFIG_INTRAREFRESHVOPTYPE params; 682da853ecaSopenharmony_ci InitOMXParam(params); 683da853ecaSopenharmony_ci params.nPortIndex = OMX_DirOutput; 684da853ecaSopenharmony_ci params.IntraRefreshVOP = OMX_TRUE; 685da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexConfigVideoIntraVOPRefresh, params, true)) { 686da853ecaSopenharmony_ci HLOGE("failed to request IDR frame"); 687da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 688da853ecaSopenharmony_ci } 689da853ecaSopenharmony_ci HLOGI("Set IDR Frame success"); 690da853ecaSopenharmony_ci return AVCS_ERR_OK; 691da853ecaSopenharmony_ci} 692da853ecaSopenharmony_ci 693da853ecaSopenharmony_ciint32_t HEncoder::OnSetParameters(const Format &format) 694da853ecaSopenharmony_ci{ 695da853ecaSopenharmony_ci optional<uint32_t> bitRate = GetBitRateFromUser(format); 696da853ecaSopenharmony_ci if (bitRate.has_value()) { 697da853ecaSopenharmony_ci OMX_VIDEO_CONFIG_BITRATETYPE bitrateCfgType; 698da853ecaSopenharmony_ci InitOMXParam(bitrateCfgType); 699da853ecaSopenharmony_ci bitrateCfgType.nPortIndex = OMX_DirOutput; 700da853ecaSopenharmony_ci bitrateCfgType.nEncodeBitrate = bitRate.value(); 701da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexConfigVideoBitrate, bitrateCfgType, true)) { 702da853ecaSopenharmony_ci HLOGW("failed to config OMX_IndexConfigVideoBitrate"); 703da853ecaSopenharmony_ci } 704da853ecaSopenharmony_ci } 705da853ecaSopenharmony_ci 706da853ecaSopenharmony_ci optional<double> frameRate = GetFrameRateFromUser(format); 707da853ecaSopenharmony_ci if (frameRate.has_value()) { 708da853ecaSopenharmony_ci OMX_CONFIG_FRAMERATETYPE framerateCfgType; 709da853ecaSopenharmony_ci InitOMXParam(framerateCfgType); 710da853ecaSopenharmony_ci framerateCfgType.nPortIndex = OMX_DirInput; 711da853ecaSopenharmony_ci framerateCfgType.xEncodeFramerate = frameRate.value() * FRAME_RATE_COEFFICIENT; 712da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexConfigVideoFramerate, framerateCfgType, true)) { 713da853ecaSopenharmony_ci HLOGW("failed to config OMX_IndexConfigVideoFramerate"); 714da853ecaSopenharmony_ci } 715da853ecaSopenharmony_ci } 716da853ecaSopenharmony_ci 717da853ecaSopenharmony_ci int32_t requestIdr; 718da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, requestIdr) && requestIdr != 0) { 719da853ecaSopenharmony_ci int32_t ret = RequestIDRFrame(); 720da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 721da853ecaSopenharmony_ci return ret; 722da853ecaSopenharmony_ci } 723da853ecaSopenharmony_ci } 724da853ecaSopenharmony_ci 725da853ecaSopenharmony_ci int32_t ret = SetQpRange(format, true); 726da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 727da853ecaSopenharmony_ci return ret; 728da853ecaSopenharmony_ci } 729da853ecaSopenharmony_ci return AVCS_ERR_OK; 730da853ecaSopenharmony_ci} 731da853ecaSopenharmony_ci 732da853ecaSopenharmony_ciint32_t HEncoder::SubmitOutputBuffersToOmxNode() 733da853ecaSopenharmony_ci{ 734da853ecaSopenharmony_ci for (BufferInfo &info : outputBufferPool_) { 735da853ecaSopenharmony_ci if (info.owner == BufferOwner::OWNED_BY_US) { 736da853ecaSopenharmony_ci int32_t ret = NotifyOmxToFillThisOutBuffer(info); 737da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 738da853ecaSopenharmony_ci return ret; 739da853ecaSopenharmony_ci } 740da853ecaSopenharmony_ci } else { 741da853ecaSopenharmony_ci HLOGE("buffer should be owned by us"); 742da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 743da853ecaSopenharmony_ci } 744da853ecaSopenharmony_ci } 745da853ecaSopenharmony_ci return AVCS_ERR_OK; 746da853ecaSopenharmony_ci} 747da853ecaSopenharmony_ci 748da853ecaSopenharmony_cibool HEncoder::ReadyToStart() 749da853ecaSopenharmony_ci{ 750da853ecaSopenharmony_ci if (callback_ == nullptr || outputFormat_ == nullptr || inputFormat_ == nullptr) { 751da853ecaSopenharmony_ci return false; 752da853ecaSopenharmony_ci } 753da853ecaSopenharmony_ci if (inputSurface_) { 754da853ecaSopenharmony_ci HLOGI("surface mode, surface id = %" PRIu64, inputSurface_->GetUniqueId()); 755da853ecaSopenharmony_ci } else { 756da853ecaSopenharmony_ci HLOGI("buffer mode"); 757da853ecaSopenharmony_ci } 758da853ecaSopenharmony_ci return true; 759da853ecaSopenharmony_ci} 760da853ecaSopenharmony_ci 761da853ecaSopenharmony_ciint32_t HEncoder::AllocateBuffersOnPort(OMX_DIRTYPE portIndex) 762da853ecaSopenharmony_ci{ 763da853ecaSopenharmony_ci if (portIndex == OMX_DirOutput) { 764da853ecaSopenharmony_ci return AllocateAvLinearBuffers(portIndex); 765da853ecaSopenharmony_ci } 766da853ecaSopenharmony_ci if (inputSurface_) { 767da853ecaSopenharmony_ci return AllocInBufsForDynamicSurfaceBuf(); 768da853ecaSopenharmony_ci } else { 769da853ecaSopenharmony_ci int32_t ret = AllocateAvSurfaceBuffers(portIndex); 770da853ecaSopenharmony_ci if (ret == AVCS_ERR_OK) { 771da853ecaSopenharmony_ci UpdateFormatFromSurfaceBuffer(); 772da853ecaSopenharmony_ci } 773da853ecaSopenharmony_ci return ret; 774da853ecaSopenharmony_ci } 775da853ecaSopenharmony_ci} 776da853ecaSopenharmony_ci 777da853ecaSopenharmony_civoid HEncoder::UpdateFormatFromSurfaceBuffer() 778da853ecaSopenharmony_ci{ 779da853ecaSopenharmony_ci if (inputBufferPool_.empty()) { 780da853ecaSopenharmony_ci return; 781da853ecaSopenharmony_ci } 782da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = inputBufferPool_.front().surfaceBuffer; 783da853ecaSopenharmony_ci if (surfaceBuffer == nullptr) { 784da853ecaSopenharmony_ci return; 785da853ecaSopenharmony_ci } 786da853ecaSopenharmony_ci int32_t stride = surfaceBuffer->GetStride(); 787da853ecaSopenharmony_ci HLOGI("input stride = %d", stride); 788da853ecaSopenharmony_ci inputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, stride); 789da853ecaSopenharmony_ci} 790da853ecaSopenharmony_ci 791da853ecaSopenharmony_civoid HEncoder::ClearDirtyList() 792da853ecaSopenharmony_ci{ 793da853ecaSopenharmony_ci sptr<SurfaceBuffer> buffer; 794da853ecaSopenharmony_ci sptr<SyncFence> fence; 795da853ecaSopenharmony_ci int64_t pts = -1; 796da853ecaSopenharmony_ci OHOS::Rect damage; 797da853ecaSopenharmony_ci while (true) { 798da853ecaSopenharmony_ci GSError ret = inputSurface_->AcquireBuffer(buffer, fence, pts, damage); 799da853ecaSopenharmony_ci if (ret != GSERROR_OK || buffer == nullptr) { 800da853ecaSopenharmony_ci return; 801da853ecaSopenharmony_ci } 802da853ecaSopenharmony_ci HLOGI("return stale buffer to surface, seq = %u, pts = %" PRId64 "", buffer->GetSeqNum(), pts); 803da853ecaSopenharmony_ci inputSurface_->ReleaseBuffer(buffer, -1); 804da853ecaSopenharmony_ci } 805da853ecaSopenharmony_ci} 806da853ecaSopenharmony_ci 807da853ecaSopenharmony_ciint32_t HEncoder::SubmitAllBuffersOwnedByUs() 808da853ecaSopenharmony_ci{ 809da853ecaSopenharmony_ci HLOGI(">>"); 810da853ecaSopenharmony_ci if (isBufferCirculating_) { 811da853ecaSopenharmony_ci HLOGI("buffer is already circulating, no need to do again"); 812da853ecaSopenharmony_ci return AVCS_ERR_OK; 813da853ecaSopenharmony_ci } 814da853ecaSopenharmony_ci int32_t ret = SubmitOutputBuffersToOmxNode(); 815da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 816da853ecaSopenharmony_ci return ret; 817da853ecaSopenharmony_ci } 818da853ecaSopenharmony_ci if (inputSurface_) { 819da853ecaSopenharmony_ci ClearDirtyList(); 820da853ecaSopenharmony_ci sptr<IBufferConsumerListener> listener = new EncoderBuffersConsumerListener(this); 821da853ecaSopenharmony_ci inputSurface_->RegisterConsumerListener(listener); 822da853ecaSopenharmony_ci SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr); 823da853ecaSopenharmony_ci } else { 824da853ecaSopenharmony_ci for (BufferInfo &info : inputBufferPool_) { 825da853ecaSopenharmony_ci if (info.owner == BufferOwner::OWNED_BY_US) { 826da853ecaSopenharmony_ci NotifyUserToFillThisInBuffer(info); 827da853ecaSopenharmony_ci } 828da853ecaSopenharmony_ci } 829da853ecaSopenharmony_ci } 830da853ecaSopenharmony_ci 831da853ecaSopenharmony_ci isBufferCirculating_ = true; 832da853ecaSopenharmony_ci return AVCS_ERR_OK; 833da853ecaSopenharmony_ci} 834da853ecaSopenharmony_ci 835da853ecaSopenharmony_cisptr<Surface> HEncoder::OnCreateInputSurface() 836da853ecaSopenharmony_ci{ 837da853ecaSopenharmony_ci if (inputSurface_) { 838da853ecaSopenharmony_ci HLOGE("inputSurface_ already exists"); 839da853ecaSopenharmony_ci return nullptr; 840da853ecaSopenharmony_ci } 841da853ecaSopenharmony_ci 842da853ecaSopenharmony_ci sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer("HEncoderSurface"); 843da853ecaSopenharmony_ci if (consumerSurface == nullptr) { 844da853ecaSopenharmony_ci HLOGE("Create the surface consummer fail"); 845da853ecaSopenharmony_ci return nullptr; 846da853ecaSopenharmony_ci } 847da853ecaSopenharmony_ci GSError err = consumerSurface->SetDefaultUsage(SURFACE_MODE_CONSUMER_USAGE); 848da853ecaSopenharmony_ci if (err == GSERROR_OK) { 849da853ecaSopenharmony_ci HLOGI("set consumer usage 0x%x succ", SURFACE_MODE_CONSUMER_USAGE); 850da853ecaSopenharmony_ci } else { 851da853ecaSopenharmony_ci HLOGW("set consumer usage 0x%x failed", SURFACE_MODE_CONSUMER_USAGE); 852da853ecaSopenharmony_ci } 853da853ecaSopenharmony_ci 854da853ecaSopenharmony_ci sptr<IBufferProducer> producer = consumerSurface->GetProducer(); 855da853ecaSopenharmony_ci if (producer == nullptr) { 856da853ecaSopenharmony_ci HLOGE("Get the surface producer fail"); 857da853ecaSopenharmony_ci return nullptr; 858da853ecaSopenharmony_ci } 859da853ecaSopenharmony_ci 860da853ecaSopenharmony_ci sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer); 861da853ecaSopenharmony_ci if (producerSurface == nullptr) { 862da853ecaSopenharmony_ci HLOGE("CreateSurfaceAsProducer fail"); 863da853ecaSopenharmony_ci return nullptr; 864da853ecaSopenharmony_ci } 865da853ecaSopenharmony_ci 866da853ecaSopenharmony_ci inputSurface_ = consumerSurface; 867da853ecaSopenharmony_ci if (inBufferCnt_ > inputSurface_->GetQueueSize()) { 868da853ecaSopenharmony_ci inputSurface_->SetQueueSize(inBufferCnt_); 869da853ecaSopenharmony_ci } 870da853ecaSopenharmony_ci HLOGI("succ, surface id = %" PRIu64 ", queue size %u", 871da853ecaSopenharmony_ci inputSurface_->GetUniqueId(), inputSurface_->GetQueueSize()); 872da853ecaSopenharmony_ci return producerSurface; 873da853ecaSopenharmony_ci} 874da853ecaSopenharmony_ci 875da853ecaSopenharmony_ciint32_t HEncoder::OnSetInputSurface(sptr<Surface> &inputSurface) 876da853ecaSopenharmony_ci{ 877da853ecaSopenharmony_ci if (inputSurface_) { 878da853ecaSopenharmony_ci HLOGW("inputSurface_ already exists"); 879da853ecaSopenharmony_ci } 880da853ecaSopenharmony_ci 881da853ecaSopenharmony_ci if (inputSurface == nullptr) { 882da853ecaSopenharmony_ci HLOGE("surface is null"); 883da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 884da853ecaSopenharmony_ci } 885da853ecaSopenharmony_ci if (!inputSurface->IsConsumer()) { 886da853ecaSopenharmony_ci HLOGE("expect consumer surface"); 887da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 888da853ecaSopenharmony_ci } 889da853ecaSopenharmony_ci 890da853ecaSopenharmony_ci inputSurface_ = inputSurface; 891da853ecaSopenharmony_ci if (inBufferCnt_ > inputSurface_->GetQueueSize()) { 892da853ecaSopenharmony_ci inputSurface_->SetQueueSize(inBufferCnt_); 893da853ecaSopenharmony_ci } 894da853ecaSopenharmony_ci HLOGI("succ"); 895da853ecaSopenharmony_ci return AVCS_ERR_OK; 896da853ecaSopenharmony_ci} 897da853ecaSopenharmony_ci 898da853ecaSopenharmony_civoid HEncoder::WrapPerFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, 899da853ecaSopenharmony_ci const shared_ptr<Media::Meta> &meta) 900da853ecaSopenharmony_ci{ 901da853ecaSopenharmony_ci omxBuffer->alongParam.clear(); 902da853ecaSopenharmony_ci WrapLTRParamIntoOmxBuffer(omxBuffer, meta); 903da853ecaSopenharmony_ci WrapRequestIFrameParamIntoOmxBuffer(omxBuffer, meta); 904da853ecaSopenharmony_ci WrapQPRangeParamIntoOmxBuffer(omxBuffer, meta); 905da853ecaSopenharmony_ci WrapStartQPIntoOmxBuffer(omxBuffer, meta); 906da853ecaSopenharmony_ci WrapIsSkipFrameIntoOmxBuffer(omxBuffer, meta); 907da853ecaSopenharmony_ci meta->Clear(); 908da853ecaSopenharmony_ci} 909da853ecaSopenharmony_ci 910da853ecaSopenharmony_civoid HEncoder::WrapLTRParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, 911da853ecaSopenharmony_ci const shared_ptr<Media::Meta> &meta) 912da853ecaSopenharmony_ci{ 913da853ecaSopenharmony_ci if (!enableLTR_) { 914da853ecaSopenharmony_ci return; 915da853ecaSopenharmony_ci } 916da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, OMX_IndexParamLTR); 917da853ecaSopenharmony_ci CodecLTRPerFrameParam param; 918da853ecaSopenharmony_ci bool markLTR = false; 919da853ecaSopenharmony_ci meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_MARK_LTR, markLTR); 920da853ecaSopenharmony_ci param.markAsLTR = markLTR; 921da853ecaSopenharmony_ci int32_t useLtrPoc = 0; 922da853ecaSopenharmony_ci param.useLTR = meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_USE_LTR, useLtrPoc); 923da853ecaSopenharmony_ci param.useLTRPoc = static_cast<uint32_t>(useLtrPoc); 924da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, param); 925da853ecaSopenharmony_ci} 926da853ecaSopenharmony_ci 927da853ecaSopenharmony_civoid HEncoder::WrapRequestIFrameParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, 928da853ecaSopenharmony_ci const shared_ptr<Media::Meta> &meta) 929da853ecaSopenharmony_ci{ 930da853ecaSopenharmony_ci bool requestIFrame = false; 931da853ecaSopenharmony_ci meta->GetData(OHOS::Media::Tag::VIDEO_REQUEST_I_FRAME, requestIFrame); 932da853ecaSopenharmony_ci if (!requestIFrame) { 933da853ecaSopenharmony_ci return; 934da853ecaSopenharmony_ci } 935da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, OMX_IndexConfigVideoIntraVOPRefresh); 936da853ecaSopenharmony_ci OMX_CONFIG_INTRAREFRESHVOPTYPE params; 937da853ecaSopenharmony_ci InitOMXParam(params); 938da853ecaSopenharmony_ci params.nPortIndex = OMX_DirOutput; 939da853ecaSopenharmony_ci params.IntraRefreshVOP = OMX_TRUE; 940da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, params); 941da853ecaSopenharmony_ci HLOGI("pts=%" PRId64 ", requestIFrame", omxBuffer->pts); 942da853ecaSopenharmony_ci} 943da853ecaSopenharmony_ci 944da853ecaSopenharmony_civoid HEncoder::WrapQPRangeParamIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, 945da853ecaSopenharmony_ci const shared_ptr<Media::Meta> &meta) 946da853ecaSopenharmony_ci{ 947da853ecaSopenharmony_ci int32_t minQp; 948da853ecaSopenharmony_ci int32_t maxQp; 949da853ecaSopenharmony_ci if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MIN, minQp) || 950da853ecaSopenharmony_ci !meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_MAX, maxQp)) { 951da853ecaSopenharmony_ci return; 952da853ecaSopenharmony_ci } 953da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, OMX_IndexParamQPRange); 954da853ecaSopenharmony_ci CodecQPRangeParam param; 955da853ecaSopenharmony_ci InitOMXParamExt(param); 956da853ecaSopenharmony_ci param.minQp = static_cast<uint32_t>(minQp); 957da853ecaSopenharmony_ci param.maxQp = static_cast<uint32_t>(maxQp); 958da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, param); 959da853ecaSopenharmony_ci HLOGI("pts=%" PRId64 ", qp=(%d~%d)", omxBuffer->pts, minQp, maxQp); 960da853ecaSopenharmony_ci} 961da853ecaSopenharmony_ci 962da853ecaSopenharmony_civoid HEncoder::WrapStartQPIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, 963da853ecaSopenharmony_ci const shared_ptr<Media::Meta> &meta) 964da853ecaSopenharmony_ci{ 965da853ecaSopenharmony_ci int32_t startQp {}; 966da853ecaSopenharmony_ci if (!meta->GetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_START, startQp)) { 967da853ecaSopenharmony_ci return; 968da853ecaSopenharmony_ci } 969da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, OMX_IndexParamQPStsart); 970da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, startQp); 971da853ecaSopenharmony_ci} 972da853ecaSopenharmony_ci 973da853ecaSopenharmony_civoid HEncoder::WrapIsSkipFrameIntoOmxBuffer(shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, 974da853ecaSopenharmony_ci const shared_ptr<Media::Meta> &meta) 975da853ecaSopenharmony_ci{ 976da853ecaSopenharmony_ci bool isSkip {}; 977da853ecaSopenharmony_ci if (!meta->GetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_SKIP, isSkip)) { 978da853ecaSopenharmony_ci return; 979da853ecaSopenharmony_ci } 980da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, OMX_IndexParamSkipFrame); 981da853ecaSopenharmony_ci AppendToVector(omxBuffer->alongParam, isSkip); 982da853ecaSopenharmony_ci} 983da853ecaSopenharmony_ci 984da853ecaSopenharmony_civoid HEncoder::DealWithResolutionChange(uint32_t newWidth, uint32_t newHeight) 985da853ecaSopenharmony_ci{ 986da853ecaSopenharmony_ci if (width_ != newWidth || height_ != newHeight) { 987da853ecaSopenharmony_ci HLOGI("resolution changed, %ux%u -> %ux%u", width_, height_, newWidth, newHeight); 988da853ecaSopenharmony_ci width_ = newWidth; 989da853ecaSopenharmony_ci height_ = newHeight; 990da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_); 991da853ecaSopenharmony_ci outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_); 992da853ecaSopenharmony_ci outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_); 993da853ecaSopenharmony_ci outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_); 994da853ecaSopenharmony_ci HLOGI("output format changed: %s", outputFormat_->Stringify().c_str()); 995da853ecaSopenharmony_ci callback_->OnOutputFormatChanged(*(outputFormat_.get())); 996da853ecaSopenharmony_ci } 997da853ecaSopenharmony_ci} 998da853ecaSopenharmony_ci 999da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameParamFromOmxBuffer( 1000da853ecaSopenharmony_ci const shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer, shared_ptr<Media::Meta> &meta) 1001da853ecaSopenharmony_ci{ 1002da853ecaSopenharmony_ci meta->Clear(); 1003da853ecaSopenharmony_ci BinaryReader reader(static_cast<uint8_t*>(omxBuffer->alongParam.data()), omxBuffer->alongParam.size()); 1004da853ecaSopenharmony_ci int* index = nullptr; 1005da853ecaSopenharmony_ci while ((index = reader.Read<int>()) != nullptr) { 1006da853ecaSopenharmony_ci switch (*index) { 1007da853ecaSopenharmony_ci case OMX_IndexConfigCommonOutputSize: { 1008da853ecaSopenharmony_ci auto *param = reader.Read<OMX_FRAMESIZETYPE>(); 1009da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(param == nullptr); 1010da853ecaSopenharmony_ci DealWithResolutionChange(param->nWidth, param->nHeight); 1011da853ecaSopenharmony_ci break; 1012da853ecaSopenharmony_ci } 1013da853ecaSopenharmony_ci case OMX_IndexParamEncOutQp: 1014da853ecaSopenharmony_ci ExtractPerFrameAveQpParam(reader, meta); 1015da853ecaSopenharmony_ci break; 1016da853ecaSopenharmony_ci case OMX_IndexParamEncOutMse: 1017da853ecaSopenharmony_ci ExtractPerFrameMSEParam(reader, meta); 1018da853ecaSopenharmony_ci break; 1019da853ecaSopenharmony_ci case OMX_IndexParamEncOutLTR: 1020da853ecaSopenharmony_ci ExtractPerFrameLTRParam(reader, meta); 1021da853ecaSopenharmony_ci break; 1022da853ecaSopenharmony_ci case OMX_IndexParamEncOutFrameLayer: 1023da853ecaSopenharmony_ci ExtractPerFrameLayerParam(reader, meta); 1024da853ecaSopenharmony_ci break; 1025da853ecaSopenharmony_ci case OMX_IndexParamEncOutRealBitrate: 1026da853ecaSopenharmony_ci ExtractPerFrameRealBitrateParam(reader, meta); 1027da853ecaSopenharmony_ci break; 1028da853ecaSopenharmony_ci case OMX_IndexParamEncOutFrameQp: 1029da853ecaSopenharmony_ci ExtractPerFrameFrameQpParam(reader, meta); 1030da853ecaSopenharmony_ci break; 1031da853ecaSopenharmony_ci case OMX_IndexParamEncOutMad: 1032da853ecaSopenharmony_ci ExtractPerFrameMadParam(reader, meta); 1033da853ecaSopenharmony_ci break; 1034da853ecaSopenharmony_ci case OMX_IndexParamEncOutIRatio: 1035da853ecaSopenharmony_ci ExtractPerFrameIRitioParam(reader, meta); 1036da853ecaSopenharmony_ci break; 1037da853ecaSopenharmony_ci default: 1038da853ecaSopenharmony_ci break; 1039da853ecaSopenharmony_ci } 1040da853ecaSopenharmony_ci } 1041da853ecaSopenharmony_ci omxBuffer->alongParam.clear(); 1042da853ecaSopenharmony_ci if (debugMode_) { 1043da853ecaSopenharmony_ci auto metaStr = StringifyMeta(meta); 1044da853ecaSopenharmony_ci HLOGI("%s", metaStr.c_str()); 1045da853ecaSopenharmony_ci } 1046da853ecaSopenharmony_ci} 1047da853ecaSopenharmony_ci 1048da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameLTRParam(BinaryReader &reader, shared_ptr<Media::Meta> &meta) 1049da853ecaSopenharmony_ci{ 1050da853ecaSopenharmony_ci auto *ltrParam = reader.Read<CodecEncOutLTRParam>(); 1051da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(ltrParam == nullptr); 1052da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_IS_LTR, ltrParam->isLTR); 1053da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_PER_FRAME_POC, static_cast<int32_t>(ltrParam->poc)); 1054da853ecaSopenharmony_ci} 1055da853ecaSopenharmony_ci 1056da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameMadParam(BinaryReader &reader, shared_ptr<Media::Meta> &meta) 1057da853ecaSopenharmony_ci{ 1058da853ecaSopenharmony_ci auto *madParam = reader.Read<CodecEncOutMadParam>(); 1059da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(madParam == nullptr); 1060da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_MADI, madParam->frameMadi); 1061da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_MADP, madParam->frameMadp); 1062da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_SUM_MADI, madParam->sumMadi); 1063da853ecaSopenharmony_ci} 1064da853ecaSopenharmony_ci 1065da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameRealBitrateParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta) 1066da853ecaSopenharmony_ci{ 1067da853ecaSopenharmony_ci auto *realBitrate = reader.Read<OMX_S32>(); 1068da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(realBitrate == nullptr); 1069da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_REAL_BITRATE, *realBitrate); 1070da853ecaSopenharmony_ci} 1071da853ecaSopenharmony_ci 1072da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameFrameQpParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta) 1073da853ecaSopenharmony_ci{ 1074da853ecaSopenharmony_ci auto *frameQp = reader.Read<OMX_S32>(); 1075da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(frameQp == nullptr); 1076da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_QP, *frameQp); 1077da853ecaSopenharmony_ci} 1078da853ecaSopenharmony_ci 1079da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameIRitioParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta) 1080da853ecaSopenharmony_ci{ 1081da853ecaSopenharmony_ci auto *iRatio = reader.Read<OMX_S32>(); 1082da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(iRatio == nullptr); 1083da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_I_RATIO, *iRatio); 1084da853ecaSopenharmony_ci} 1085da853ecaSopenharmony_ci 1086da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameAveQpParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta) 1087da853ecaSopenharmony_ci{ 1088da853ecaSopenharmony_ci auto *averageQp = reader.Read<OMX_S32>(); 1089da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(averageQp == nullptr); 1090da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_QP_AVERAGE, *averageQp); 1091da853ecaSopenharmony_ci} 1092da853ecaSopenharmony_ci 1093da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameMSEParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta) 1094da853ecaSopenharmony_ci{ 1095da853ecaSopenharmony_ci auto *averageMseLcu = reader.Read<double>(); 1096da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(averageMseLcu == nullptr); 1097da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_MSE, *averageMseLcu); 1098da853ecaSopenharmony_ci} 1099da853ecaSopenharmony_ci 1100da853ecaSopenharmony_civoid HEncoder::ExtractPerFrameLayerParam(BinaryReader &reader, std::shared_ptr<Media::Meta> &meta) 1101da853ecaSopenharmony_ci{ 1102da853ecaSopenharmony_ci auto *frameLayer = reader.Read<OMX_S32>(); 1103da853ecaSopenharmony_ci IF_TRUE_RETURN_VOID(frameLayer == nullptr); 1104da853ecaSopenharmony_ci meta->SetData(OHOS::Media::Tag::VIDEO_ENCODER_FRAME_TEMPORAL_ID, *frameLayer); 1105da853ecaSopenharmony_ci} 1106da853ecaSopenharmony_ci 1107da853ecaSopenharmony_ciint32_t HEncoder::AllocInBufsForDynamicSurfaceBuf() 1108da853ecaSopenharmony_ci{ 1109da853ecaSopenharmony_ci inputBufferPool_.clear(); 1110da853ecaSopenharmony_ci for (uint32_t i = 0; i < inBufferCnt_; ++i) { 1111da853ecaSopenharmony_ci shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer = DynamicSurfaceBufferToOmxBuffer(); 1112da853ecaSopenharmony_ci shared_ptr<CodecHDI::OmxCodecBuffer> outBuffer = make_shared<CodecHDI::OmxCodecBuffer>(); 1113da853ecaSopenharmony_ci int32_t ret = compNode_->UseBuffer(OMX_DirInput, *omxBuffer, *outBuffer); 1114da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 1115da853ecaSopenharmony_ci HLOGE("Failed to UseBuffer on input port"); 1116da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1117da853ecaSopenharmony_ci } 1118da853ecaSopenharmony_ci BufferInfo info {}; 1119da853ecaSopenharmony_ci info.isInput = true; 1120da853ecaSopenharmony_ci info.owner = BufferOwner::OWNED_BY_SURFACE; 1121da853ecaSopenharmony_ci info.surfaceBuffer = nullptr; 1122da853ecaSopenharmony_ci info.avBuffer = AVBuffer::CreateAVBuffer(); 1123da853ecaSopenharmony_ci info.omxBuffer = outBuffer; 1124da853ecaSopenharmony_ci info.bufferId = outBuffer->bufferId; 1125da853ecaSopenharmony_ci inputBufferPool_.push_back(info); 1126da853ecaSopenharmony_ci } 1127da853ecaSopenharmony_ci 1128da853ecaSopenharmony_ci return AVCS_ERR_OK; 1129da853ecaSopenharmony_ci} 1130da853ecaSopenharmony_ci 1131da853ecaSopenharmony_civoid HEncoder::EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i) 1132da853ecaSopenharmony_ci{ 1133da853ecaSopenharmony_ci vector<BufferInfo> &pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1134da853ecaSopenharmony_ci if (i >= pool.size()) { 1135da853ecaSopenharmony_ci return; 1136da853ecaSopenharmony_ci } 1137da853ecaSopenharmony_ci const BufferInfo &info = pool[i]; 1138da853ecaSopenharmony_ci FreeOmxBuffer(portIndex, info); 1139da853ecaSopenharmony_ci ReduceOwner((portIndex == OMX_DirInput), info.owner); 1140da853ecaSopenharmony_ci pool.erase(pool.begin() + i); 1141da853ecaSopenharmony_ci} 1142da853ecaSopenharmony_ci 1143da853ecaSopenharmony_civoid HEncoder::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode) 1144da853ecaSopenharmony_ci{ 1145da853ecaSopenharmony_ci if (inputSurface_ && !enableSurfaceModeInputCb_) { 1146da853ecaSopenharmony_ci HLOGE("cannot queue input on surface mode"); 1147da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION); 1148da853ecaSopenharmony_ci return; 1149da853ecaSopenharmony_ci } 1150da853ecaSopenharmony_ci // buffer mode or surface callback mode 1151da853ecaSopenharmony_ci uint32_t bufferId = 0; 1152da853ecaSopenharmony_ci (void)msg.param->GetValue(BUFFER_ID, bufferId); 1153da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(bufferId); 1154da853ecaSopenharmony_ci BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId); 1155da853ecaSopenharmony_ci if (bufferInfo == nullptr) { 1156da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1157da853ecaSopenharmony_ci return; 1158da853ecaSopenharmony_ci } 1159da853ecaSopenharmony_ci if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) { 1160da853ecaSopenharmony_ci HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(bufferInfo->owner)); 1161da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1162da853ecaSopenharmony_ci return; 1163da853ecaSopenharmony_ci } 1164da853ecaSopenharmony_ci 1165da853ecaSopenharmony_ci bool discard = false; 1166da853ecaSopenharmony_ci if (inputSurface_ && bufferInfo->avBuffer->meta_->GetData( 1167da853ecaSopenharmony_ci OHOS::Media::Tag::VIDEO_ENCODER_PER_FRAME_DISCARD, discard) && discard) { 1168da853ecaSopenharmony_ci HLOGI("inBufId = %u, discard by user, pts = %" PRId64, bufferId, bufferInfo->avBuffer->pts_); 1169da853ecaSopenharmony_ci bufferInfo->avBuffer->meta_->Clear(); 1170da853ecaSopenharmony_ci ResetSlot(*bufferInfo); 1171da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_OK); 1172da853ecaSopenharmony_ci return; 1173da853ecaSopenharmony_ci } 1174da853ecaSopenharmony_ci ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US); 1175da853ecaSopenharmony_ci WrapSurfaceBufferToSlot(*bufferInfo, bufferInfo->surfaceBuffer, bufferInfo->avBuffer->pts_, 1176da853ecaSopenharmony_ci UserFlagToOmxFlag(static_cast<AVCodecBufferFlag>(bufferInfo->avBuffer->flag_))); 1177da853ecaSopenharmony_ci WrapPerFrameParamIntoOmxBuffer(bufferInfo->omxBuffer, bufferInfo->avBuffer->meta_); 1178da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_OK); 1179da853ecaSopenharmony_ci int32_t err = HCodec::OnQueueInputBuffer(mode, bufferInfo); 1180da853ecaSopenharmony_ci if (err != AVCS_ERR_OK) { 1181da853ecaSopenharmony_ci ResetSlot(*bufferInfo); 1182da853ecaSopenharmony_ci callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR); 1183da853ecaSopenharmony_ci } 1184da853ecaSopenharmony_ci} 1185da853ecaSopenharmony_ci 1186da853ecaSopenharmony_civoid HEncoder::OnGetBufferFromSurface(const ParamSP& param) 1187da853ecaSopenharmony_ci{ 1188da853ecaSopenharmony_ci if (GetOneBufferFromSurface()) { 1189da853ecaSopenharmony_ci TraverseAvaliableBuffers(); 1190da853ecaSopenharmony_ci } 1191da853ecaSopenharmony_ci} 1192da853ecaSopenharmony_ci 1193da853ecaSopenharmony_cibool HEncoder::GetOneBufferFromSurface() 1194da853ecaSopenharmony_ci{ 1195da853ecaSopenharmony_ci SCOPED_TRACE(); 1196da853ecaSopenharmony_ci InSurfaceBufferEntry entry{}; 1197da853ecaSopenharmony_ci entry.item = make_shared<BufferItem>(); 1198da853ecaSopenharmony_ci GSError ret = inputSurface_->AcquireBuffer( 1199da853ecaSopenharmony_ci entry.item->buffer, entry.item->fence, entry.pts, entry.item->damage); 1200da853ecaSopenharmony_ci if (ret != GSERROR_OK || entry.item->buffer == nullptr) { 1201da853ecaSopenharmony_ci return false; 1202da853ecaSopenharmony_ci } 1203da853ecaSopenharmony_ci if (!CheckBufPixFmt(entry.item->buffer)) { 1204da853ecaSopenharmony_ci return false; 1205da853ecaSopenharmony_ci } 1206da853ecaSopenharmony_ci entry.item->generation = ++currGeneration_; 1207da853ecaSopenharmony_ci entry.item->surface = inputSurface_; 1208da853ecaSopenharmony_ci avaliableBuffers_.push_back(entry); 1209da853ecaSopenharmony_ci newestBuffer_ = entry; 1210da853ecaSopenharmony_ci HLOGD("generation = %" PRIu64 ", seq = %u, pts = %" PRId64 ", now list size = %zu", 1211da853ecaSopenharmony_ci entry.item->generation, entry.item->buffer->GetSeqNum(), entry.pts, avaliableBuffers_.size()); 1212da853ecaSopenharmony_ci if (repeatUs_ != 0) { 1213da853ecaSopenharmony_ci SendRepeatMsg(entry.item->generation); 1214da853ecaSopenharmony_ci } 1215da853ecaSopenharmony_ci return true; 1216da853ecaSopenharmony_ci} 1217da853ecaSopenharmony_ci 1218da853ecaSopenharmony_civoid HEncoder::SendRepeatMsg(uint64_t generation) 1219da853ecaSopenharmony_ci{ 1220da853ecaSopenharmony_ci ParamSP param = make_shared<ParamBundle>(); 1221da853ecaSopenharmony_ci param->SetValue("generation", generation); 1222da853ecaSopenharmony_ci SendAsyncMsg(MsgWhat::CHECK_IF_REPEAT, param, repeatUs_); 1223da853ecaSopenharmony_ci} 1224da853ecaSopenharmony_ci 1225da853ecaSopenharmony_civoid HEncoder::RepeatIfNecessary(const ParamSP& param) 1226da853ecaSopenharmony_ci{ 1227da853ecaSopenharmony_ci uint64_t generation = 0; 1228da853ecaSopenharmony_ci param->GetValue("generation", generation); 1229da853ecaSopenharmony_ci if (inputPortEos_ || (repeatUs_ == 0) || newestBuffer_.item == nullptr || 1230da853ecaSopenharmony_ci newestBuffer_.item->generation != generation) { 1231da853ecaSopenharmony_ci return; 1232da853ecaSopenharmony_ci } 1233da853ecaSopenharmony_ci if (repeatMaxCnt_ > 0 && newestBuffer_.repeatTimes >= repeatMaxCnt_) { 1234da853ecaSopenharmony_ci HLOGD("stop repeat generation = %" PRIu64 ", seq = %u, pts = %" PRId64 ", which has been repeated %d times", 1235da853ecaSopenharmony_ci generation, newestBuffer_.item->buffer->GetSeqNum(), newestBuffer_.pts, newestBuffer_.repeatTimes); 1236da853ecaSopenharmony_ci return; 1237da853ecaSopenharmony_ci } 1238da853ecaSopenharmony_ci if (avaliableBuffers_.size() >= MAX_LIST_SIZE) { 1239da853ecaSopenharmony_ci HLOGW("stop repeat, list size to big: %zu", avaliableBuffers_.size()); 1240da853ecaSopenharmony_ci return; 1241da853ecaSopenharmony_ci } 1242da853ecaSopenharmony_ci int64_t newPts = newestBuffer_.pts + static_cast<int64_t>(repeatUs_); 1243da853ecaSopenharmony_ci HLOGD("generation = %" PRIu64 ", seq = %u, pts %" PRId64 " -> %" PRId64, 1244da853ecaSopenharmony_ci generation, newestBuffer_.item->buffer->GetSeqNum(), newestBuffer_.pts, newPts); 1245da853ecaSopenharmony_ci newestBuffer_.pts = newPts; 1246da853ecaSopenharmony_ci newestBuffer_.repeatTimes++; 1247da853ecaSopenharmony_ci avaliableBuffers_.push_back(newestBuffer_); 1248da853ecaSopenharmony_ci SendRepeatMsg(generation); 1249da853ecaSopenharmony_ci TraverseAvaliableBuffers(); 1250da853ecaSopenharmony_ci} 1251da853ecaSopenharmony_ci 1252da853ecaSopenharmony_civoid HEncoder::TraverseAvaliableBuffers() 1253da853ecaSopenharmony_ci{ 1254da853ecaSopenharmony_ci while (!avaliableBuffers_.empty()) { 1255da853ecaSopenharmony_ci auto it = find_if(inputBufferPool_.begin(), inputBufferPool_.end(), 1256da853ecaSopenharmony_ci [](const BufferInfo &info) { return info.owner == BufferOwner::OWNED_BY_SURFACE; }); 1257da853ecaSopenharmony_ci if (it == inputBufferPool_.end()) { 1258da853ecaSopenharmony_ci HLOGD("buffer cnt = %zu, but no avaliable slot", avaliableBuffers_.size()); 1259da853ecaSopenharmony_ci return; 1260da853ecaSopenharmony_ci } 1261da853ecaSopenharmony_ci InSurfaceBufferEntry entry = avaliableBuffers_.front(); 1262da853ecaSopenharmony_ci avaliableBuffers_.pop_front(); 1263da853ecaSopenharmony_ci SubmitOneBuffer(entry, *it); 1264da853ecaSopenharmony_ci } 1265da853ecaSopenharmony_ci} 1266da853ecaSopenharmony_ci 1267da853ecaSopenharmony_civoid HEncoder::TraverseAvaliableSlots() 1268da853ecaSopenharmony_ci{ 1269da853ecaSopenharmony_ci for (BufferInfo& info : inputBufferPool_) { 1270da853ecaSopenharmony_ci if (info.owner != BufferOwner::OWNED_BY_SURFACE) { 1271da853ecaSopenharmony_ci continue; 1272da853ecaSopenharmony_ci } 1273da853ecaSopenharmony_ci if (avaliableBuffers_.empty() && !GetOneBufferFromSurface()) { 1274da853ecaSopenharmony_ci HLOGD("slot %u is avaliable, but no buffer", info.bufferId); 1275da853ecaSopenharmony_ci return; 1276da853ecaSopenharmony_ci } 1277da853ecaSopenharmony_ci InSurfaceBufferEntry entry = avaliableBuffers_.front(); 1278da853ecaSopenharmony_ci avaliableBuffers_.pop_front(); 1279da853ecaSopenharmony_ci SubmitOneBuffer(entry, info); 1280da853ecaSopenharmony_ci } 1281da853ecaSopenharmony_ci} 1282da853ecaSopenharmony_ci 1283da853ecaSopenharmony_civoid HEncoder::SubmitOneBuffer(InSurfaceBufferEntry& entry, BufferInfo &info) 1284da853ecaSopenharmony_ci{ 1285da853ecaSopenharmony_ci if (entry.item == nullptr) { 1286da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_US); 1287da853ecaSopenharmony_ci HLOGI("got input eos"); 1288da853ecaSopenharmony_ci inputPortEos_ = true; 1289da853ecaSopenharmony_ci info.omxBuffer->flag = OMX_BUFFERFLAG_EOS; 1290da853ecaSopenharmony_ci info.omxBuffer->bufferhandle = nullptr; 1291da853ecaSopenharmony_ci info.omxBuffer->filledLen = 0; 1292da853ecaSopenharmony_ci info.surfaceBuffer = nullptr; 1293da853ecaSopenharmony_ci NotifyOmxToEmptyThisInBuffer(info); 1294da853ecaSopenharmony_ci return; 1295da853ecaSopenharmony_ci } 1296da853ecaSopenharmony_ci if (!WaitFence(entry.item->fence)) { 1297da853ecaSopenharmony_ci return; 1298da853ecaSopenharmony_ci } 1299da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_US); 1300da853ecaSopenharmony_ci WrapSurfaceBufferToSlot(info, entry.item->buffer, entry.pts, 0); 1301da853ecaSopenharmony_ci encodingBuffers_[info.bufferId] = entry; 1302da853ecaSopenharmony_ci if (enableSurfaceModeInputCb_) { 1303da853ecaSopenharmony_ci info.avBuffer->pts_ = entry.pts; 1304da853ecaSopenharmony_ci NotifyUserToFillThisInBuffer(info); 1305da853ecaSopenharmony_ci } else { 1306da853ecaSopenharmony_ci int32_t err = NotifyOmxToEmptyThisInBuffer(info); 1307da853ecaSopenharmony_ci if (err != AVCS_ERR_OK) { 1308da853ecaSopenharmony_ci ResetSlot(info); 1309da853ecaSopenharmony_ci callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR); 1310da853ecaSopenharmony_ci } 1311da853ecaSopenharmony_ci } 1312da853ecaSopenharmony_ci} 1313da853ecaSopenharmony_ci 1314da853ecaSopenharmony_civoid HEncoder::OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode) 1315da853ecaSopenharmony_ci{ 1316da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(bufferId); 1317da853ecaSopenharmony_ci BufferInfo *info = FindBufferInfoByID(OMX_DirInput, bufferId); 1318da853ecaSopenharmony_ci if (info == nullptr) { 1319da853ecaSopenharmony_ci HLOGE("unknown buffer id %u", bufferId); 1320da853ecaSopenharmony_ci return; 1321da853ecaSopenharmony_ci } 1322da853ecaSopenharmony_ci if (info->owner != BufferOwner::OWNED_BY_OMX) { 1323da853ecaSopenharmony_ci HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info->owner)); 1324da853ecaSopenharmony_ci return; 1325da853ecaSopenharmony_ci } 1326da853ecaSopenharmony_ci if (inputSurface_) { 1327da853ecaSopenharmony_ci ResetSlot(*info); 1328da853ecaSopenharmony_ci if (mode == RESUBMIT_BUFFER && !inputPortEos_) { 1329da853ecaSopenharmony_ci TraverseAvaliableSlots(); 1330da853ecaSopenharmony_ci } 1331da853ecaSopenharmony_ci } else { 1332da853ecaSopenharmony_ci ChangeOwner(*info, BufferOwner::OWNED_BY_US); 1333da853ecaSopenharmony_ci if (mode == RESUBMIT_BUFFER && !inputPortEos_) { 1334da853ecaSopenharmony_ci NotifyUserToFillThisInBuffer(*info); 1335da853ecaSopenharmony_ci } 1336da853ecaSopenharmony_ci } 1337da853ecaSopenharmony_ci} 1338da853ecaSopenharmony_ci 1339da853ecaSopenharmony_civoid HEncoder::ResetSlot(BufferInfo& info) 1340da853ecaSopenharmony_ci{ 1341da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE); 1342da853ecaSopenharmony_ci encodingBuffers_.erase(info.bufferId); 1343da853ecaSopenharmony_ci info.surfaceBuffer = nullptr; 1344da853ecaSopenharmony_ci} 1345da853ecaSopenharmony_ci 1346da853ecaSopenharmony_civoid HEncoder::EncoderBuffersConsumerListener::OnBufferAvailable() 1347da853ecaSopenharmony_ci{ 1348da853ecaSopenharmony_ci codec_->SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr); 1349da853ecaSopenharmony_ci} 1350da853ecaSopenharmony_ci 1351da853ecaSopenharmony_civoid HEncoder::OnSignalEndOfInputStream(const MsgInfo &msg) 1352da853ecaSopenharmony_ci{ 1353da853ecaSopenharmony_ci if (inputSurface_ == nullptr) { 1354da853ecaSopenharmony_ci HLOGE("can only be called in surface mode"); 1355da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION); 1356da853ecaSopenharmony_ci return; 1357da853ecaSopenharmony_ci } 1358da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_OK); 1359da853ecaSopenharmony_ci avaliableBuffers_.push_back(InSurfaceBufferEntry {}); 1360da853ecaSopenharmony_ci TraverseAvaliableBuffers(); 1361da853ecaSopenharmony_ci} 1362da853ecaSopenharmony_ci 1363da853ecaSopenharmony_civoid HEncoder::OnEnterUninitializedState() 1364da853ecaSopenharmony_ci{ 1365da853ecaSopenharmony_ci if (inputSurface_) { 1366da853ecaSopenharmony_ci inputSurface_->UnregisterConsumerListener(); 1367da853ecaSopenharmony_ci } 1368da853ecaSopenharmony_ci avaliableBuffers_.clear(); 1369da853ecaSopenharmony_ci newestBuffer_.item.reset(); 1370da853ecaSopenharmony_ci encodingBuffers_.clear(); 1371da853ecaSopenharmony_ci} 1372da853ecaSopenharmony_ci 1373da853ecaSopenharmony_ciHEncoder::BufferItem::~BufferItem() 1374da853ecaSopenharmony_ci{ 1375da853ecaSopenharmony_ci if (surface && buffer) { 1376da853ecaSopenharmony_ci LOGD("release seq = %u", buffer->GetSeqNum()); 1377da853ecaSopenharmony_ci surface->ReleaseBuffer(buffer, -1); 1378da853ecaSopenharmony_ci } 1379da853ecaSopenharmony_ci} 1380da853ecaSopenharmony_ci 1381da853ecaSopenharmony_ci} // namespace OHOS::MediaAVCodec 1382