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