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 "hdecoder.h" 17#include <cassert> 18#include <sys/ioctl.h> 19#include <linux/dma-buf.h> 20#include "utils/hdf_base.h" 21#include "codec_omx_ext.h" 22#include "media_description.h" // foundation/multimedia/av_codec/interfaces/inner_api/native/ 23#include "sync_fence.h" // foundation/graphic/graphic_2d/utils/sync_fence/export/ 24#include "OMX_VideoExt.h" 25#include "hcodec_log.h" 26#include "hcodec_dfx.h" 27#include "type_converter.h" 28#include "surface_buffer.h" 29#include "buffer_extra_data_impl.h" // foundation/graphic/graphic_surface/surface/include/ 30 31namespace OHOS::MediaAVCodec { 32using namespace std; 33using namespace CodecHDI; 34 35HDecoder::~HDecoder() 36{ 37 MsgHandleLoop::Stop(); 38} 39 40int32_t HDecoder::OnConfigure(const Format &format) 41{ 42 configFormat_ = make_shared<Format>(format); 43 44 SupportBufferType type; 45 InitOMXParamExt(type); 46 type.portIndex = OMX_DirOutput; 47 if (GetParameter(OMX_IndexParamSupportBufferType, type) && 48 (type.bufferTypes & CODEC_BUFFER_TYPE_DYNAMIC_HANDLE) && 49 UseHandleOnOutputPort(true)) { 50 HLOGI("dynamic mode"); 51 isDynamic_ = true; 52 } else if (UseHandleOnOutputPort(false)) { 53 HLOGI("normal mode"); 54 isDynamic_ = false; 55 } else { 56 HLOGE("invalid output buffer type"); 57 return AVCS_ERR_UNKNOWN; 58 } 59 int32_t ret = SetLowLatency(format); 60 if (ret != AVCS_ERR_OK) { 61 return ret; 62 } 63 SaveTransform(format); 64 SaveScaleMode(format); 65 (void)SetProcessName(); 66 (void)SetFrameRateAdaptiveMode(format); 67#ifdef USE_VIDEO_PROCESSING_ENGINE 68 ret = SetVrrEnable(format); 69 if (ret != AVCS_ERR_OK) { 70 return ret; 71 } 72#endif 73 return SetupPort(format); 74} 75 76int32_t HDecoder::SetupPort(const Format &format) 77{ 78 int32_t width; 79 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width) || width <= 0) { 80 HLOGE("format should contain width"); 81 return AVCS_ERR_INVALID_VAL; 82 } 83 int32_t height; 84 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height) || height <= 0) { 85 HLOGE("format should contain height"); 86 return AVCS_ERR_INVALID_VAL; 87 } 88 HLOGI("user set width %d, height %d", width, height); 89 if (!GetPixelFmtFromUser(format)) { 90 return AVCS_ERR_INVALID_VAL; 91 } 92 93 optional<double> frameRate = GetFrameRateFromUser(format); 94 if (frameRate.has_value()) { 95 codecRate_ = frameRate.value(); 96 } else { 97 HLOGI("user don't set valid frame rate, use default 60.0"); 98 frameRate = 60.0; // default frame rate 60.0 99 } 100 101 PortInfo inputPortInfo {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 102 codingType_, std::nullopt, frameRate.value()}; 103 int32_t maxInputSize = 0; 104 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize)) { 105 if (maxInputSize > 0) { 106 inputPortInfo.inputBufSize = static_cast<uint32_t>(maxInputSize); 107 } else { 108 HLOGW("user don't set valid input buffer size"); 109 } 110 } 111 112 int32_t ret = SetVideoPortInfo(OMX_DirInput, inputPortInfo); 113 if (ret != AVCS_ERR_OK) { 114 return ret; 115 } 116 117 PortInfo outputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height), 118 OMX_VIDEO_CodingUnused, configuredFmt_, frameRate.value()}; 119 ret = SetVideoPortInfo(OMX_DirOutput, outputPortInfo); 120 if (ret != AVCS_ERR_OK) { 121 return ret; 122 } 123 124 return AVCS_ERR_OK; 125} 126 127int32_t HDecoder::UpdateInPortFormat() 128{ 129 OMX_PARAM_PORTDEFINITIONTYPE def; 130 InitOMXParam(def); 131 def.nPortIndex = OMX_DirInput; 132 if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 133 HLOGE("get input port definition failed"); 134 return AVCS_ERR_UNKNOWN; 135 } 136 PrintPortDefinition(def); 137 if (inputFormat_ == nullptr) { 138 inputFormat_ = make_shared<Format>(); 139 } 140 inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, def.format.video.nFrameWidth); 141 inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, def.format.video.nFrameHeight); 142 return AVCS_ERR_OK; 143} 144 145bool HDecoder::UpdateConfiguredFmt(OMX_COLOR_FORMATTYPE portFmt) 146{ 147 auto graphicFmt = static_cast<GraphicPixelFormat>(portFmt); 148 if (graphicFmt != configuredFmt_.graphicFmt) { 149 optional<PixelFmt> fmt = TypeConverter::GraphicFmtToFmt(graphicFmt); 150 if (!fmt.has_value()) { 151 return false; 152 } 153 HLOGI("GraphicPixelFormat need update: configured(%s) -> portdefinition(%s)", 154 configuredFmt_.strFmt.c_str(), fmt->strFmt.c_str()); 155 configuredFmt_ = fmt.value(); 156 } 157 return true; 158} 159 160int32_t HDecoder::UpdateOutPortFormat() 161{ 162 OMX_PARAM_PORTDEFINITIONTYPE def; 163 InitOMXParam(def); 164 def.nPortIndex = OMX_DirOutput; 165 if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 166 HLOGE("get output port definition failed"); 167 return AVCS_ERR_UNKNOWN; 168 } 169 PrintPortDefinition(def); 170 if (def.nBufferCountActual == 0) { 171 HLOGE("invalid bufferCount"); 172 return AVCS_ERR_UNKNOWN; 173 } 174 (void)UpdateConfiguredFmt(def.format.video.eColorFormat); 175 176 uint32_t w = def.format.video.nFrameWidth; 177 uint32_t h = def.format.video.nFrameHeight; 178 179 // save into member variable 180 OHOS::Rect damage{}; 181 GetCropFromOmx(w, h, damage); 182 outBufferCnt_ = def.nBufferCountActual; 183 requestCfg_.timeout = 0; // never wait when request 184 requestCfg_.width = damage.w; 185 requestCfg_.height = damage.h; 186 requestCfg_.strideAlignment = STRIDE_ALIGNMENT; 187 requestCfg_.format = configuredFmt_.graphicFmt; 188 requestCfg_.usage = GetProducerUsage(); 189 190 // save into format 191 if (outputFormat_ == nullptr) { 192 outputFormat_ = make_shared<Format>(); 193 } 194 if (!outputFormat_->ContainKey(MediaDescriptionKey::MD_KEY_WIDTH)) { 195 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, w); // deprecated 196 } 197 if (!outputFormat_->ContainKey(MediaDescriptionKey::MD_KEY_HEIGHT)) { 198 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, h); // deprecated 199 } 200 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_WIDTH, damage.w); 201 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_HEIGHT, damage.h); 202 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, damage.w); 203 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, damage.h); 204 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, 205 static_cast<int32_t>(configuredFmt_.innerFmt)); 206 HLOGI("output format: %s", outputFormat_->Stringify().c_str()); 207 return AVCS_ERR_OK; 208} 209 210void HDecoder::UpdateColorAspects() 211{ 212 CodecVideoColorspace param; 213 InitOMXParamExt(param); 214 param.portIndex = OMX_DirOutput; 215 if (!GetParameter(OMX_IndexColorAspects, param, true)) { 216 return; 217 } 218 HLOGI("isFullRange %d, primary %u, transfer %u, matrix %u", 219 param.aspects.range, param.aspects.primaries, param.aspects.transfer, param.aspects.matrixCoeffs); 220 if (outputFormat_) { 221 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, param.aspects.range); 222 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, param.aspects.primaries); 223 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, param.aspects.transfer); 224 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, param.aspects.matrixCoeffs); 225 HLOGI("output format changed: %s", outputFormat_->Stringify().c_str()); 226 callback_->OnOutputFormatChanged(*(outputFormat_.get())); 227 } 228} 229 230void HDecoder::GetCropFromOmx(uint32_t w, uint32_t h, OHOS::Rect& damage) 231{ 232 damage.x = 0; 233 damage.y = 0; 234 damage.w = static_cast<int32_t>(w); 235 damage.h = static_cast<int32_t>(h); 236 237 OMX_CONFIG_RECTTYPE rect; 238 InitOMXParam(rect); 239 rect.nPortIndex = OMX_DirOutput; 240 if (!GetParameter(OMX_IndexConfigCommonOutputCrop, rect, true)) { 241 HLOGW("get crop failed, use default"); 242 return; 243 } 244 if (rect.nLeft < 0 || rect.nTop < 0 || 245 rect.nWidth == 0 || rect.nHeight == 0 || 246 rect.nLeft + static_cast<int32_t>(rect.nWidth) > static_cast<int32_t>(w) || 247 rect.nTop + static_cast<int32_t>(rect.nHeight) > static_cast<int32_t>(h)) { 248 HLOGW("wrong crop rect (%d, %d, %u, %u) vs. frame (%u," \ 249 "%u), use default", rect.nLeft, rect.nTop, rect.nWidth, rect.nHeight, w, h); 250 return; 251 } 252 HLOGI("crop rect (%d, %d, %u, %u)", 253 rect.nLeft, rect.nTop, rect.nWidth, rect.nHeight); 254 damage.x = rect.nLeft; 255 damage.y = rect.nTop; 256 damage.w = static_cast<int32_t>(rect.nWidth); 257 damage.h = static_cast<int32_t>(rect.nHeight); 258 if (outputFormat_) { 259 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_CROP_LEFT, rect.nLeft); 260 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_CROP_TOP, rect.nTop); 261 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_CROP_RIGHT, 262 static_cast<int32_t>(rect.nLeft + rect.nWidth) - 1); 263 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_CROP_BOTTOM, 264 static_cast<int32_t>(rect.nTop + rect.nHeight) - 1); 265 } 266} 267 268void HDecoder::OnSetOutputSurface(const MsgInfo &msg, BufferOperationMode mode) 269{ 270 sptr<Surface> surface; 271 (void)msg.param->GetValue("surface", surface); 272 if (mode == KEEP_BUFFER) { 273 ReplyErrorCode(msg.id, OnSetOutputSurfaceWhenCfg(surface)); 274 return; 275 } 276 OnSetOutputSurfaceWhenRunning(surface, msg, mode); 277} 278 279int32_t HDecoder::OnSetOutputSurfaceWhenCfg(const sptr<Surface> &surface) 280{ 281 SCOPED_TRACE(); 282 HLOGI(">>"); 283 if (surface == nullptr) { 284 HLOGE("surface is null"); 285 return AVCS_ERR_INVALID_VAL; 286 } 287 if (surface->IsConsumer()) { 288 HLOGE("expect a producer surface but got a consumer surface"); 289 return AVCS_ERR_INVALID_VAL; 290 } 291 int32_t ret = RegisterListenerToSurface(surface); 292 if (ret != AVCS_ERR_OK) { 293 return ret; 294 } 295 currSurface_ = SurfaceItem(surface); 296 HLOGI("set surface(%" PRIu64 ")(%s) succ", surface->GetUniqueId(), surface->GetName().c_str()); 297 return AVCS_ERR_OK; 298} 299 300int32_t HDecoder::OnSetParameters(const Format &format) 301{ 302 int32_t ret = SaveTransform(format, true); 303 if (ret != AVCS_ERR_OK) { 304 return ret; 305 } 306 ret = SaveScaleMode(format, true); 307 if (ret != AVCS_ERR_OK) { 308 return ret; 309 } 310 optional<double> frameRate = GetFrameRateFromUser(format); 311 if (frameRate.has_value()) { 312 OMX_PARAM_U32TYPE framerateCfgType; 313 InitOMXParam(framerateCfgType); 314 framerateCfgType.nPortIndex = OMX_DirInput; 315 framerateCfgType.nU32 = frameRate.value() * FRAME_RATE_COEFFICIENT; 316 if (SetParameter(OMX_IndexCodecExtConfigOperatingRate, framerateCfgType, true)) { 317 HLOGI("succ to set frameRate %.f", frameRate.value()); 318 } else { 319 HLOGW("succ to set frameRate %.f", frameRate.value()); 320 } 321 codecRate_ = frameRate.value(); 322 } 323 return AVCS_ERR_OK; 324} 325 326int32_t HDecoder::SaveTransform(const Format &format, bool set) 327{ 328 int32_t orientation = 0; 329 if (format.GetIntValue(OHOS::Media::Tag::VIDEO_ORIENTATION_TYPE, orientation)) { 330 HLOGI("GraphicTransformType = %d", orientation); 331 transform_ = static_cast<GraphicTransformType>(orientation); 332 if (set) { 333 return SetTransform(); 334 } 335 return AVCS_ERR_OK; 336 } 337 int32_t rotate; 338 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotate)) { 339 return AVCS_ERR_OK; 340 } 341 optional<GraphicTransformType> transform = TypeConverter::InnerRotateToDisplayRotate( 342 static_cast<VideoRotation>(rotate)); 343 if (!transform.has_value()) { 344 return AVCS_ERR_INVALID_VAL; 345 } 346 HLOGI("VideoRotation = %d, GraphicTransformType = %d", rotate, transform.value()); 347 transform_ = transform.value(); 348 if (set) { 349 return SetTransform(); 350 } 351 return AVCS_ERR_OK; 352} 353 354int32_t HDecoder::SetTransform() 355{ 356 if (currSurface_.surface_ == nullptr) { 357 return AVCS_ERR_INVALID_VAL; 358 } 359 GSError err = currSurface_.surface_->SetTransform(transform_); 360 if (err != GSERROR_OK) { 361 HLOGW("set GraphicTransformType %d to surface failed", transform_); 362 return AVCS_ERR_UNKNOWN; 363 } 364 HLOGI("set GraphicTransformType %d to surface succ", transform_); 365 return AVCS_ERR_OK; 366} 367 368int32_t HDecoder::SaveScaleMode(const Format &format, bool set) 369{ 370 int scaleType; 371 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, scaleType)) { 372 return AVCS_ERR_OK; 373 } 374 auto scaleMode = static_cast<ScalingMode>(scaleType); 375 if (scaleMode != SCALING_MODE_SCALE_TO_WINDOW && scaleMode != SCALING_MODE_SCALE_CROP) { 376 HLOGW("user set invalid scale mode %d", scaleType); 377 return AVCS_ERR_INVALID_VAL; 378 } 379 HLOGI("user set ScalingType = %d", scaleType); 380 scaleMode_ = scaleMode; 381 if (set) { 382 return SetScaleMode(); 383 } 384 return AVCS_ERR_OK; 385} 386 387int32_t HDecoder::SetScaleMode() 388{ 389 if (currSurface_.surface_ == nullptr || !scaleMode_.has_value()) { 390 return AVCS_ERR_INVALID_VAL; 391 } 392 GSError err = currSurface_.surface_->SetScalingMode(scaleMode_.value()); 393 if (err != GSERROR_OK) { 394 HLOGW("set ScalingMode %d to surface failed", scaleMode_.value()); 395 return AVCS_ERR_UNKNOWN; 396 } 397 HLOGI("set ScalingMode %d to surface succ", scaleMode_.value()); 398 return AVCS_ERR_OK; 399} 400 401#ifdef USE_VIDEO_PROCESSING_ENGINE 402int32_t HDecoder::SetVrrEnable(const Format &format) 403{ 404 int32_t vrrEnable = 0; 405 if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_DECODER_ENABLE_VRR, vrrEnable) || vrrEnable == 0) { 406 HLOGI("VRR disabled"); 407 return AVCS_ERR_OK; 408 } 409 optional<double> frameRate = GetFrameRateFromUser(format); 410 if (frameRate.has_value() && floor(frameRate.value()) != VRR_DEFAULT_INPUT_FRAME_RATE 411 && ceil(frameRate.value()) != VRR_DEFAULT_INPUT_FRAME_RATE) { 412 HLOGE("VRR only support for 60fps, current frameRate = %f", frameRate.value()); 413 return AVCS_ERR_UNSUPPORT; 414 } 415 416 OMX_CONFIG_BOOLEANTYPE param {}; 417 InitOMXParam(param); 418 param.bEnabled = OMX_TRUE; 419 if (!SetParameter(OMX_IndexParamIsMvUpload, param)) { 420 HLOGE("VRR SetIsMvUploadParam SetParameter failed"); 421 return AVCS_ERR_UNSUPPORT; 422 } 423 vrrPredictor_ = OHOS::Media::VideoProcessingEngine::VideoRefreshRatePrediction::Create(); 424 if (vrrPredictor_ == nullptr) { 425 HLOGE("VRR VideoRefreshRatePrediction create failed"); 426 return AVCS_ERR_UNSUPPORT; 427 } 428 int32_t ret = vrrPredictor_->CheckLtpoSupport(); 429 if (ret != AVCS_ERR_OK) { 430 HLOGE("VRR SetParameter failed"); 431 return AVCS_ERR_UNKNOWN; 432 } 433 isVrrEnable_ = true; 434 HLOGI("VRR enabled"); 435 return AVCS_ERR_OK; 436} 437#endif 438 439int32_t HDecoder::SubmitOutputBuffersToOmxNode() 440{ 441 for (BufferInfo& info : outputBufferPool_) { 442 if (info.owner != BufferOwner::OWNED_BY_US) { 443 continue; 444 } 445 if (info.surfaceBuffer != nullptr) { 446 int32_t ret = NotifyOmxToFillThisOutBuffer(info); 447 if (ret != AVCS_ERR_OK) { 448 return ret; 449 } 450 } 451 } 452 auto inCnt = std::count_if(inputBufferPool_.begin(), inputBufferPool_.end(), [](const BufferInfo& info) { 453 return info.owner == BufferOwner::OWNED_BY_OMX; 454 }); 455 inCnt++; // at least submit one out buffer to omx 456 while (inCnt > 0) { 457 DynamicModeSubmitBuffer(); 458 inCnt--; 459 } 460 return AVCS_ERR_OK; 461} 462 463bool HDecoder::UseHandleOnOutputPort(bool isDynamic) 464{ 465 UseBufferType useBufferTypes; 466 InitOMXParamExt(useBufferTypes); 467 useBufferTypes.portIndex = OMX_DirOutput; 468 useBufferTypes.bufferType = (isDynamic ? CODEC_BUFFER_TYPE_DYNAMIC_HANDLE : CODEC_BUFFER_TYPE_HANDLE); 469 return SetParameter(OMX_IndexParamUseBufferType, useBufferTypes); 470} 471 472bool HDecoder::ReadyToStart() 473{ 474 if (callback_ == nullptr || outputFormat_ == nullptr || inputFormat_ == nullptr) { 475 return false; 476 } 477 if (currSurface_.surface_) { 478 HLOGI("surface mode"); 479 SetTransform(); 480 SetScaleMode(); 481 } else { 482 HLOGI("buffer mode"); 483 } 484 return true; 485} 486 487int32_t HDecoder::AllocateBuffersOnPort(OMX_DIRTYPE portIndex) 488{ 489 if (portIndex == OMX_DirInput) { 490 return AllocateAvLinearBuffers(portIndex); 491 } 492 int32_t ret; 493 if (isDynamic_) { 494 ret = AllocOutDynamicSurfaceBuf(); 495 } else { 496 ret = (currSurface_.surface_ ? AllocateOutputBuffersFromSurface() : AllocateAvSurfaceBuffers(portIndex)); 497 } 498 if (ret == AVCS_ERR_OK) { 499 UpdateFormatFromSurfaceBuffer(); 500 } 501 return ret; 502} 503 504void HDecoder::SetCallerToBuffer(int fd) 505{ 506 if (currSurface_.surface_ == nullptr) { 507 return; // only set on surface mode 508 } 509 string pid = std::to_string(calledByAvcodec_ ? avcodecCaller_.pid : playerCaller_.pid); 510 int ret = ioctl(fd, DMA_BUF_SET_NAME_A, pid.c_str()); 511 if (ret != 0) { 512 HLOGW("set pid %s to fd %d failed", pid.c_str(), fd); 513 return; 514 } 515 HLOGD("set pid %s to fd %d succ", pid.c_str(), fd); 516} 517 518void HDecoder::UpdateFormatFromSurfaceBuffer() 519{ 520 if (outputBufferPool_.empty()) { 521 return; 522 } 523 sptr<SurfaceBuffer> surfaceBuffer = outputBufferPool_.front().surfaceBuffer; 524 if (surfaceBuffer == nullptr) { 525 return; 526 } 527 HLOGI(">>"); 528 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_WIDTH, surfaceBuffer->GetWidth()); 529 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_HEIGHT, surfaceBuffer->GetHeight()); 530 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, surfaceBuffer->GetWidth()); 531 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, surfaceBuffer->GetHeight()); 532 int32_t stride = surfaceBuffer->GetStride(); 533 if (stride <= 0) { 534 HLOGW("invalid stride %d", stride); 535 return; 536 } 537 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, stride); 538 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, stride); // deprecated 539 540 OH_NativeBuffer_Planes *planes = nullptr; 541 GSError err = surfaceBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes)); 542 if (err != GSERROR_OK || planes == nullptr) { 543 HLOGI("can not get plane info, ignore"); 544 return; 545 } 546 for (uint32_t i = 0; i < planes->planeCount; i++) { 547 HLOGI("plane[%u]: offset=%" PRIu64 ", rowStride=%u, columnStride=%u", 548 i, planes->planes[i].offset, planes->planes[i].rowStride, planes->planes[i].columnStride); 549 } 550 int32_t sliceHeight = static_cast<int32_t>(static_cast<int64_t>(planes->planes[1].offset) / stride); 551 HLOGI("[%dx%d][%dx%d]", surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), stride, sliceHeight); 552 outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, sliceHeight); 553 outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, sliceHeight); 554} 555 556int32_t HDecoder::SubmitAllBuffersOwnedByUs() 557{ 558 HLOGI(">>"); 559 if (isBufferCirculating_) { 560 HLOGI("buffer is already circulating, no need to do again"); 561 return AVCS_ERR_OK; 562 } 563 int32_t ret = SubmitOutputBuffersToOmxNode(); 564 if (ret != AVCS_ERR_OK) { 565 return ret; 566 } 567 for (BufferInfo& info : inputBufferPool_) { 568 if (info.owner == BufferOwner::OWNED_BY_US) { 569 NotifyUserToFillThisInBuffer(info); 570 } 571 } 572 isBufferCirculating_ = true; 573 return AVCS_ERR_OK; 574} 575 576void HDecoder::EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i) 577{ 578 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 579 if (i >= pool.size()) { 580 return; 581 } 582 BufferInfo& info = pool[i]; 583 if (portIndex == OMX_DirOutput && info.owner != BufferOwner::OWNED_BY_SURFACE) { 584 CancelBufferToSurface(info); 585 } 586 FreeOmxBuffer(portIndex, info); 587 ReduceOwner((portIndex == OMX_DirInput), info.owner); 588 pool.erase(pool.begin() + i); 589} 590 591void HDecoder::OnClearBufferPool(OMX_DIRTYPE portIndex) 592{ 593 if ((portIndex == OMX_DirOutput) && currSurface_.surface_) { 594 GSError err = currSurface_.surface_->CleanCache(); 595 if (err != GSERROR_OK) { 596 HLOGW("clean cache failed, GSError=%d", err); 597 } 598 freeList_.clear(); 599 } 600} 601 602uint64_t HDecoder::GetProducerUsage() 603{ 604 uint64_t producerUsage = currSurface_.surface_ ? SURFACE_MODE_PRODUCER_USAGE : BUFFER_MODE_REQUEST_USAGE; 605 606 GetBufferHandleUsageParams vendorUsage; 607 InitOMXParamExt(vendorUsage); 608 vendorUsage.portIndex = static_cast<uint32_t>(OMX_DirOutput); 609 if (GetParameter(OMX_IndexParamGetBufferHandleUsage, vendorUsage)) { 610 HLOGI("vendor producer usage = 0x%" PRIx64 "", vendorUsage.usage); 611 producerUsage |= vendorUsage.usage; 612 } else { 613 HLOGW("get vendor producer usage failed, add CPU_READ"); 614 producerUsage |= BUFFER_USAGE_CPU_READ; 615 } 616 HLOGI("decoder producer usage = 0x%" PRIx64 "", producerUsage); 617 return producerUsage; 618} 619 620void HDecoder::CombineConsumerUsage() 621{ 622 uint32_t consumerUsage = currSurface_.surface_->GetDefaultUsage(); 623 uint64_t finalUsage = requestCfg_.usage | consumerUsage; 624 HLOGI("producer usage 0x%" PRIx64 " | consumer usage 0x%x -> 0x%" PRIx64 "", 625 requestCfg_.usage, consumerUsage, finalUsage); 626 requestCfg_.usage = finalUsage; 627} 628 629int32_t HDecoder::SetQueueSize(const sptr<Surface> &surface, uint32_t targetSize) 630{ 631 GSError err = surface->SetQueueSize(targetSize); 632 if (err != GSERROR_OK) { 633 HLOGE("surface(%" PRIu64 "), SetQueueSize to %u failed, GSError=%d", 634 surface->GetUniqueId(), targetSize, err); 635 return AVCS_ERR_UNKNOWN; 636 } 637 HLOGI("surface(%" PRIu64 "), SetQueueSize to %u succ", surface->GetUniqueId(), targetSize); 638 return AVCS_ERR_OK; 639} 640 641int32_t HDecoder::AllocOutDynamicSurfaceBuf() 642{ 643 SCOPED_TRACE(); 644 if (currSurface_.surface_) { 645 currGeneration_++; 646 currSurface_.surface_->CleanCache(); 647 int32_t ret = SetQueueSize(currSurface_.surface_, outBufferCnt_); 648 if (ret != AVCS_ERR_OK) { 649 return ret; 650 } 651 } 652 outputBufferPool_.clear(); 653 654 for (uint32_t i = 0; i < outBufferCnt_; ++i) { 655 shared_ptr<OmxCodecBuffer> omxBuffer = DynamicSurfaceBufferToOmxBuffer(); 656 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 657 int32_t ret = compNode_->UseBuffer(OMX_DirOutput, *omxBuffer, *outBuffer); 658 if (ret != HDF_SUCCESS) { 659 HLOGE("Failed to UseBuffer on input port"); 660 return AVCS_ERR_UNKNOWN; 661 } 662 BufferInfo info {}; 663 info.isInput = false; 664 info.owner = BufferOwner::OWNED_BY_US; 665 info.surfaceBuffer = nullptr; 666 info.avBuffer = (currSurface_.surface_ ? AVBuffer::CreateAVBuffer() : nullptr); 667 info.omxBuffer = outBuffer; 668 info.bufferId = outBuffer->bufferId; 669 outputBufferPool_.push_back(info); 670 } 671 HLOGI("succ"); 672 return AVCS_ERR_OK; 673} 674 675int32_t HDecoder::AllocateOutputBuffersFromSurface() 676{ 677 SCOPED_TRACE(); 678 currGeneration_++; 679 currSurface_.surface_->CleanCache(); 680 int32_t ret = SetQueueSize(currSurface_.surface_, outBufferCnt_); 681 if (ret != AVCS_ERR_OK) { 682 return ret; 683 } 684 outputBufferPool_.clear(); 685 CombineConsumerUsage(); 686 for (uint32_t i = 0; i < outBufferCnt_; ++i) { 687 sptr<SurfaceBuffer> surfaceBuffer; 688 sptr<SyncFence> fence; 689 GSError err = currSurface_.surface_->RequestBuffer(surfaceBuffer, fence, requestCfg_); 690 if (err != GSERROR_OK || surfaceBuffer == nullptr) { 691 HLOGE("RequestBuffer %u failed, GSError=%d", i, err); 692 return AVCS_ERR_UNKNOWN; 693 } 694 shared_ptr<OmxCodecBuffer> omxBuffer = SurfaceBufferToOmxBuffer(surfaceBuffer); 695 if (omxBuffer == nullptr) { 696 currSurface_.surface_->CancelBuffer(surfaceBuffer); 697 return AVCS_ERR_UNKNOWN; 698 } 699 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 700 int32_t hdfRet = compNode_->UseBuffer(OMX_DirOutput, *omxBuffer, *outBuffer); 701 if (hdfRet != HDF_SUCCESS) { 702 currSurface_.surface_->CancelBuffer(surfaceBuffer); 703 HLOGE("Failed to UseBuffer with output port"); 704 return AVCS_ERR_NO_MEMORY; 705 } 706 SetCallerToBuffer(surfaceBuffer->GetFileDescriptor()); 707 outBuffer->fenceFd = -1; 708 BufferInfo info {}; 709 info.isInput = false; 710 info.owner = BufferOwner::OWNED_BY_US; 711 info.surfaceBuffer = surfaceBuffer; 712 info.avBuffer = AVBuffer::CreateAVBuffer(); 713 info.omxBuffer = outBuffer; 714 info.bufferId = outBuffer->bufferId; 715 outputBufferPool_.push_back(info); 716 HLOGI("generation=%d, bufferId=%u, seq=%u", currGeneration_, info.bufferId, surfaceBuffer->GetSeqNum()); 717 } 718 return AVCS_ERR_OK; 719} 720 721void HDecoder::CancelBufferToSurface(BufferInfo& info) 722{ 723 if (currSurface_.surface_ && info.surfaceBuffer) { 724 GSError err = currSurface_.surface_->CancelBuffer(info.surfaceBuffer); 725 if (err != GSERROR_OK) { 726 HLOGW("surface(%" PRIu64 "), CancelBuffer(seq=%u) failed, GSError=%d", 727 currSurface_.surface_->GetUniqueId(), info.surfaceBuffer->GetSeqNum(), err); 728 } else { 729 HLOGI("surface(%" PRIu64 "), CancelBuffer(seq=%u) succ", 730 currSurface_.surface_->GetUniqueId(), info.surfaceBuffer->GetSeqNum()); 731 } 732 } 733 ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE); // change owner even if cancel failed 734} 735 736int32_t HDecoder::RegisterListenerToSurface(const sptr<Surface> &surface) 737{ 738 uint64_t surfaceId = surface->GetUniqueId(); 739 std::weak_ptr<HCodec> weakThis = weak_from_this(); 740 GSError err = surface->RegisterReleaseListener([weakThis, surfaceId](sptr<SurfaceBuffer>&) { 741 std::shared_ptr<HCodec> codec = weakThis.lock(); 742 if (codec == nullptr) { 743 LOGD("decoder is gone"); 744 return GSERROR_OK; 745 } 746 return codec->OnBufferReleasedByConsumer(surfaceId); 747 }); 748 if (err != GSERROR_OK) { 749 HLOGE("surface(%" PRIu64 "), RegisterReleaseListener failed, GSError=%d", surfaceId, err); 750 return AVCS_ERR_UNKNOWN; 751 } 752 return AVCS_ERR_OK; 753} 754 755GSError HDecoder::OnBufferReleasedByConsumer(uint64_t surfaceId) 756{ 757 ParamSP param = make_shared<ParamBundle>(); 758 param->SetValue("surfaceId", surfaceId); 759 SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, param); 760 return GSERROR_OK; 761} 762 763HDecoder::SurfaceBufferItem HDecoder::RequestBuffer() 764{ 765 SurfaceBufferItem item{}; 766 item.generation = currGeneration_; 767 GSError err = currSurface_.surface_->RequestBuffer(item.buffer, item.fence, requestCfg_); 768 if (err != GSERROR_OK || item.buffer == nullptr || item.buffer->GetBufferHandle() == nullptr) { 769 HLOGW("RequestBuffer failed, GSError=%d", err); 770 return { nullptr, nullptr }; 771 } 772 return item; 773} 774 775std::vector<HCodec::BufferInfo>::iterator HDecoder::FindBelongTo(sptr<SurfaceBuffer>& buffer) 776{ 777 BufferHandle* handle = buffer->GetBufferHandle(); 778 return std::find_if(outputBufferPool_.begin(), outputBufferPool_.end(), [handle](const BufferInfo& info) { 779 return (info.owner == BufferOwner::OWNED_BY_SURFACE) && 780 info.surfaceBuffer && (info.surfaceBuffer->GetBufferHandle() == handle); 781 }); 782} 783 784void HDecoder::OnGetBufferFromSurface(const ParamSP& param) 785{ 786 SCOPED_TRACE(); 787 uint64_t surfaceId = 0; 788 param->GetValue("surfaceId", surfaceId); 789 if (!currSurface_.surface_ || currSurface_.surface_->GetUniqueId() != surfaceId) { 790 return; 791 } 792 SurfaceBufferItem item = RequestBuffer(); 793 if (item.buffer == nullptr) { 794 return; 795 } 796 ScopedTrace tracePoint("requested:" + std::to_string(item.buffer->GetSeqNum())); 797 freeList_.push_back(item); // push to list, retrive it later, to avoid wait fence too early 798 static constexpr size_t MAX_CACHE_CNT = 2; 799 if (item.fence == nullptr || !item.fence->IsValid() || freeList_.size() > MAX_CACHE_CNT) { 800 SurfaceModeSubmitBuffer(); 801 } 802} 803 804void HDecoder::SurfaceModeSubmitBuffer() 805{ 806 if (!isDynamic_) { 807 // in surface normal mode, just get one surfacebuffer 808 SurfaceModeSubmitBufferFromFreeList(); 809 return; 810 } 811 // in dynamic mode, find slot which has null surfacebuffer 812 auto nullSlot = std::find_if(outputBufferPool_.begin(), outputBufferPool_.end(), [](const BufferInfo& info) { 813 return info.surfaceBuffer == nullptr; 814 }); 815 if (nullSlot == outputBufferPool_.end()) { 816 // if every slot is not null, just get one surfacebuffer 817 SurfaceModeSubmitBufferFromFreeList(); 818 return; 819 } 820 SurfaceDynamicModeSubmitBuffer(nullSlot); 821} 822 823void HDecoder::SurfaceModeSubmitBufferFromFreeList() 824{ 825 while (!freeList_.empty()) { 826 SurfaceBufferItem item = freeList_.front(); 827 freeList_.pop_front(); 828 if (SurfaceModeSubmitOneItem(item)) { 829 return; 830 } 831 } 832} 833 834bool HDecoder::SurfaceModeSubmitOneItem(SurfaceBufferItem& item) 835{ 836 SCOPED_TRACE_WITH_ID(item.buffer->GetSeqNum()); 837 if (item.generation != currGeneration_) { 838 HLOGI("buffer generation %d != current generation %d, ignore", item.generation, currGeneration_); 839 return false; 840 } 841 auto iter = FindBelongTo(item.buffer); 842 if (iter == outputBufferPool_.end()) { 843 HLOGI("seq=%u dont belong to output set, ignore", item.buffer->GetSeqNum()); 844 return false; 845 } 846 WaitFence(item.fence); 847 ChangeOwner(*iter, BufferOwner::OWNED_BY_US); 848 NotifyOmxToFillThisOutBuffer(*iter); 849 return true; 850} 851 852void HDecoder::DynamicModeSubmitBuffer() 853{ 854 if (!isDynamic_) { 855 return; 856 } 857 auto nullSlot = std::find_if(outputBufferPool_.begin(), outputBufferPool_.end(), [](const BufferInfo& info) { 858 return info.surfaceBuffer == nullptr; 859 }); 860 if (nullSlot == outputBufferPool_.end()) { 861 return; 862 } 863 if (currSurface_.surface_) { 864 SurfaceDynamicModeSubmitBuffer(nullSlot); 865 } else { 866 BufferDynamicModeSubmitBuffer(nullSlot); 867 } 868} 869 870void HDecoder::SurfaceDynamicModeSubmitBuffer(std::vector<BufferInfo>::iterator nullSlot) 871{ 872 SCOPED_TRACE(); 873 for (size_t i = 0; i < outputBufferPool_.size(); i++) { 874 SurfaceBufferItem item{}; 875 if (!freeList_.empty()) { 876 item = freeList_.front(); 877 freeList_.pop_front(); 878 } else { 879 item = RequestBuffer(); 880 if (item.buffer == nullptr) { 881 return; 882 } 883 } 884 if (item.generation != currGeneration_) { 885 HLOGI("buffer generation %d != current generation %d, ignore", item.generation, currGeneration_); 886 continue; 887 } 888 auto iter = FindBelongTo(item.buffer); 889 WaitFence(item.fence); 890 if (iter != outputBufferPool_.end()) { 891 // familiar buffer 892 ChangeOwner(*iter, BufferOwner::OWNED_BY_US); 893 NotifyOmxToFillThisOutBuffer(*iter); 894 continue; // keep request until we got a new surfacebuffer 895 } 896 // unfamiliar buffer 897 SetCallerToBuffer(item.buffer->GetFileDescriptor()); 898 HLOGI("generation=%d, bufferId=%u, seq=%u", currGeneration_, nullSlot->bufferId, item.buffer->GetSeqNum()); 899 WrapSurfaceBufferToSlot(*nullSlot, item.buffer, 0, 0); 900 if (nullSlot == outputBufferPool_.begin()) { 901 UpdateFormatFromSurfaceBuffer(); 902 } 903 NotifyOmxToFillThisOutBuffer(*nullSlot); 904 nullSlot->omxBuffer->bufferhandle = nullptr; 905 return; 906 } 907} 908 909void HDecoder::BufferDynamicModeSubmitBuffer(std::vector<BufferInfo>::iterator nullSlot) 910{ 911 SCOPED_TRACE(); 912 sptr<SurfaceBuffer> buffer = SurfaceBuffer::Create(); 913 IF_TRUE_RETURN_VOID_WITH_MSG(buffer == nullptr, "CreateSurfaceBuffer failed"); 914 GSError err = buffer->Alloc(requestCfg_); 915 IF_TRUE_RETURN_VOID_WITH_MSG(err != GSERROR_OK, "AllocSurfaceBuffer failed"); 916 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(buffer); 917 if (avBuffer == nullptr || avBuffer->memory_ == nullptr) { 918 HLOGE("CreateAVBuffer failed"); 919 return; 920 } 921 SetCallerToBuffer(buffer->GetFileDescriptor()); 922 HLOGI("bufferId=%u, seq=%u", nullSlot->bufferId, buffer->GetSeqNum()); 923 WrapSurfaceBufferToSlot(*nullSlot, buffer, 0, 0); 924 nullSlot->avBuffer = avBuffer; 925 nullSlot->needDealWithCache = (requestCfg_.usage & BUFFER_USAGE_MEM_MMZ_CACHE); 926 if (nullSlot == outputBufferPool_.begin()) { 927 UpdateFormatFromSurfaceBuffer(); 928 } 929 NotifyOmxToFillThisOutBuffer(*nullSlot); 930 nullSlot->omxBuffer->bufferhandle = nullptr; 931} 932 933int32_t HDecoder::NotifySurfaceToRenderOutputBuffer(BufferInfo &info) 934{ 935 SCOPED_TRACE_WITH_ID(info.omxBuffer->pts); 936 info.lastFlushTime = GetNowUs(); 937 if (std::abs(lastFlushRate_ - codecRate_) > std::numeric_limits<float>::epsilon()) { 938 sptr<BufferExtraData> extraData = new BufferExtraDataImpl(); 939 extraData->ExtraSet("VIDEO_RATE", codecRate_); 940 info.surfaceBuffer->SetExtraData(extraData); 941 lastFlushRate_ = codecRate_; 942 HLOGI("flush video rate(%d)", static_cast<int32_t>(codecRate_)); 943 } 944 BufferFlushConfig cfg { 945 .damage = {.x = 0, .y = 0, .w = info.surfaceBuffer->GetWidth(), .h = info.surfaceBuffer->GetHeight() }, 946 .timestamp = info.omxBuffer->pts, 947 .desiredPresentTimestamp = -1, 948 }; 949 if (info.avBuffer->meta_->Find(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP) != 950 info.avBuffer->meta_->end()) { 951 info.avBuffer->meta_->Get<OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP>( 952 cfg.desiredPresentTimestamp); 953 info.avBuffer->meta_->Remove(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP); 954 } 955 GSError ret = currSurface_.surface_->FlushBuffer(info.surfaceBuffer, -1, cfg); 956 if (ret != GSERROR_OK) { 957 HLOGW("surface(%" PRIu64 "), FlushBuffer(seq=%u) failed, GSError=%d", 958 currSurface_.surface_->GetUniqueId(), info.surfaceBuffer->GetSeqNum(), ret); 959 return AVCS_ERR_UNKNOWN; 960 } 961 ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE); 962 return AVCS_ERR_OK; 963} 964 965void HDecoder::OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode) 966{ 967 SCOPED_TRACE_WITH_ID(bufferId); 968 BufferInfo *info = FindBufferInfoByID(OMX_DirInput, bufferId); 969 if (info == nullptr) { 970 HLOGE("unknown buffer id %u", bufferId); 971 return; 972 } 973 if (info->owner != BufferOwner::OWNED_BY_OMX) { 974 HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info->owner)); 975 return; 976 } 977 ChangeOwner(*info, BufferOwner::OWNED_BY_US); 978 979 switch (mode) { 980 case KEEP_BUFFER: 981 return; 982 case RESUBMIT_BUFFER: { 983 if (!inputPortEos_) { 984 NotifyUserToFillThisInBuffer(*info); 985 } 986 return; 987 } 988 default: { 989 HLOGE("SHOULD NEVER BE HERE"); 990 return; 991 } 992 } 993} 994 995void HDecoder::OnReleaseOutputBuffer(const BufferInfo &info) 996{ 997 if (currSurface_.surface_) { 998 HLOGI("outBufId = %u, discard by user, pts = %" PRId64, info.bufferId, info.omxBuffer->pts); 999 } 1000} 1001 1002void HDecoder::OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode) 1003{ 1004 if (currSurface_.surface_ == nullptr) { 1005 HLOGE("can only render in surface mode"); 1006 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION); 1007 return; 1008 } 1009 uint32_t bufferId = 0; 1010 (void)msg.param->GetValue(BUFFER_ID, bufferId); 1011 SCOPED_TRACE_WITH_ID(bufferId); 1012 optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId); 1013 if (!idx.has_value()) { 1014 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1015 return; 1016 } 1017 BufferInfo& info = outputBufferPool_[idx.value()]; 1018 if (info.owner != BufferOwner::OWNED_BY_USER) { 1019 HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info.owner)); 1020 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1021 return; 1022 } 1023 info.omxBuffer->pts = info.avBuffer->pts_; 1024 ChangeOwner(info, BufferOwner::OWNED_BY_US); 1025 ReplyErrorCode(msg.id, AVCS_ERR_OK); 1026 1027 if (info.omxBuffer->filledLen != 0) { 1028 NotifySurfaceToRenderOutputBuffer(info); 1029 } 1030 if (mode == FREE_BUFFER) { 1031 EraseBufferFromPool(OMX_DirOutput, idx.value()); 1032 } else { 1033 SurfaceModeSubmitBuffer(); 1034 } 1035} 1036 1037void HDecoder::OnEnterUninitializedState() 1038{ 1039 freeList_.clear(); 1040 currSurface_.Release(); 1041} 1042 1043HDecoder::SurfaceItem::SurfaceItem(const sptr<Surface> &surface) 1044 : surface_(surface), originalTransform_(surface->GetTransform()) {} 1045 1046void HDecoder::SurfaceItem::Release() 1047{ 1048 if (surface_) { 1049 LOGI("release surface(%" PRIu64 ")", surface_->GetUniqueId()); 1050 if (originalTransform_.has_value()) { 1051 surface_->SetTransform(originalTransform_.value()); 1052 originalTransform_ = std::nullopt; 1053 } 1054 surface_ = nullptr; 1055 } 1056} 1057 1058void HDecoder::OnSetOutputSurfaceWhenRunning(const sptr<Surface> &newSurface, 1059 const MsgInfo &msg, BufferOperationMode mode) 1060{ 1061 SCOPED_TRACE(); 1062 if (currSurface_.surface_ == nullptr) { 1063 HLOGE("can only switch surface on surface mode"); 1064 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION); 1065 return; 1066 } 1067 if (newSurface == nullptr) { 1068 HLOGE("surface is null"); 1069 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1070 return; 1071 } 1072 if (newSurface->IsConsumer()) { 1073 HLOGE("expect a producer surface but got a consumer surface"); 1074 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1075 return; 1076 } 1077 uint64_t oldId = currSurface_.surface_->GetUniqueId(); 1078 uint64_t newId = newSurface->GetUniqueId(); 1079 HLOGI("surface %" PRIu64 " -> %" PRIu64, oldId, newId); 1080 if (oldId == newId) { 1081 HLOGI("same surface, no need to set again"); 1082 ReplyErrorCode(msg.id, AVCS_ERR_OK); 1083 return; 1084 } 1085 int32_t ret = RegisterListenerToSurface(newSurface); 1086 if (ret != AVCS_ERR_OK) { 1087 ReplyErrorCode(msg.id, ret); 1088 return; 1089 } 1090 ret = SetQueueSize(newSurface, outBufferCnt_); 1091 if (ret != AVCS_ERR_OK) { 1092 ReplyErrorCode(msg.id, ret); 1093 return; 1094 } 1095 SwitchBetweenSurface(newSurface, msg, mode); 1096} 1097 1098void HDecoder::ConsumeFreeList(BufferOperationMode mode) 1099{ 1100 SCOPED_TRACE(); 1101 while (!freeList_.empty()) { 1102 SurfaceBufferItem item = freeList_.front(); 1103 freeList_.pop_front(); 1104 auto iter = FindBelongTo(item.buffer); 1105 if (iter == outputBufferPool_.end()) { 1106 continue; 1107 } 1108 ChangeOwner(*iter, BufferOwner::OWNED_BY_US); 1109 if (mode == RESUBMIT_BUFFER) { 1110 WaitFence(item.fence); 1111 NotifyOmxToFillThisOutBuffer(*iter); 1112 } 1113 } 1114} 1115 1116void HDecoder::SwitchBetweenSurface(const sptr<Surface> &newSurface, 1117 const MsgInfo &msg, BufferOperationMode mode) 1118{ 1119 SCOPED_TRACE(); 1120 newSurface->Connect(); // cleancache will work only if the surface is connected by us 1121 newSurface->CleanCache(); // make sure new surface is empty 1122 uint64_t newId = newSurface->GetUniqueId(); 1123 for (size_t i = 0; i < outputBufferPool_.size(); i++) { 1124 BufferInfo& info = outputBufferPool_[i]; 1125 if (info.surfaceBuffer == nullptr) { 1126 continue; 1127 } 1128 GSError err = newSurface->AttachBufferToQueue(info.surfaceBuffer); 1129 if (err != GSERROR_OK) { 1130 HLOGE("surface(%" PRIu64 "), AttachBufferToQueue(seq=%u) failed, GSError=%d", 1131 newId, info.surfaceBuffer->GetSeqNum(), err); 1132 ReplyErrorCode(msg.id, AVCS_ERR_UNKNOWN); 1133 return; 1134 } 1135 } 1136 ReplyErrorCode(msg.id, AVCS_ERR_OK); 1137 1138 ConsumeFreeList(mode); 1139 map<int64_t, size_t> ownedBySurfaceFlushTime2BufferIndex; 1140 vector<size_t> ownedByUs; 1141 for (size_t i = 0; i < outputBufferPool_.size(); i++) { 1142 BufferInfo& info = outputBufferPool_[i]; 1143 if (info.surfaceBuffer == nullptr) { 1144 continue; 1145 } 1146 if (info.owner == OWNED_BY_SURFACE) { 1147 ownedBySurfaceFlushTime2BufferIndex[info.lastFlushTime] = i; 1148 } else if (info.owner == OWNED_BY_US) { 1149 ownedByUs.push_back(i); 1150 } 1151 } 1152 1153 SurfaceItem oldSurface = currSurface_; 1154 currSurface_ = SurfaceItem(newSurface); 1155 // if owned by old surface, we need to transfer them to new surface 1156 for (auto [flushTime, i] : ownedBySurfaceFlushTime2BufferIndex) { 1157 ChangeOwner(outputBufferPool_[i], BufferOwner::OWNED_BY_US); 1158 NotifySurfaceToRenderOutputBuffer(outputBufferPool_[i]); 1159 } 1160 // the consumer of old surface may be destroyed, so flushbuffer will fail, and they are owned by us 1161 for (size_t i : ownedByUs) { 1162 if (mode == RESUBMIT_BUFFER) { 1163 NotifyOmxToFillThisOutBuffer(outputBufferPool_[i]); 1164 } 1165 } 1166 1167 oldSurface.surface_->CleanCache(true); // make sure old surface is empty and go black 1168 oldSurface.Release(); 1169 SetTransform(); 1170 SetScaleMode(); 1171 HLOGI("set surface(%" PRIu64 ")(%s) succ", newId, newSurface->GetName().c_str()); 1172} 1173 1174#ifdef USE_VIDEO_PROCESSING_ENGINE 1175int32_t HDecoder::VrrPrediction(BufferInfo &info) 1176{ 1177 SCOPED_TRACE(); 1178 if (vrrPredictor_ == nullptr) { 1179 HLOGE("vrrPredictor_ is nullptr"); 1180 return AVCS_ERR_INVALID_OPERATION; 1181 } 1182 int vrrMvType = Media::VideoProcessingEngine::MOTIONVECTOR_TYPE_NONE; 1183 if (static_cast<int>(codingType_) == CODEC_OMX_VIDEO_CodingHEVC) { 1184 vrrMvType = Media::VideoProcessingEngine::MOTIONVECTOR_TYPE_HEVC; 1185 } else if (static_cast<int>(codingType_) == OMX_VIDEO_CodingAVC) { 1186 vrrMvType = Media::VideoProcessingEngine::MOTIONVECTOR_TYPE_AVC; 1187 } else { 1188 HLOGE("VRR only support for HEVC or AVC"); 1189 return AVCS_ERR_UNSUPPORT; 1190 } 1191 vrrPredictor_->Process(info.surfaceBuffer, static_cast<int32_t>(codecRate_), vrrMvType); 1192 return AVCS_ERR_OK; 1193} 1194#endif 1195} // namespace OHOS::MediaAVCodec