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 "hcodec.h" 17#include <cassert> 18#include <vector> 19#include <algorithm> 20#include <thread> 21#include "syspara/parameters.h" // base/startup/init/interfaces/innerkits/include/ 22#include "qos.h" 23#include "utils/hdf_base.h" 24#include "codec_omx_ext.h" 25#include "hcodec_list.h" 26#include "hencoder.h" 27#include "hdecoder.h" 28#include "hitrace_meter.h" 29#include "hcodec_log.h" 30#include "hcodec_dfx.h" 31#include "hcodec_utils.h" 32#include "av_hardware_memory.h" 33#include "av_hardware_allocator.h" 34#include "av_shared_memory_ext.h" 35#include "av_shared_allocator.h" 36#include "av_surface_memory.h" 37#include "av_surface_allocator.h" 38 39namespace OHOS::MediaAVCodec { 40using namespace std; 41using namespace CodecHDI; 42using namespace Media; 43 44std::shared_ptr<HCodec> HCodec::Create(const std::string &name) 45{ 46 vector<CodecCompCapability> capList = GetCapList(); 47 shared_ptr<HCodec> codec; 48 for (const auto& cap : capList) { 49 if (cap.compName != name) { 50 continue; 51 } 52 optional<OMX_VIDEO_CODINGTYPE> type = TypeConverter::HdiRoleToOmxCodingType(cap.role); 53 if (!type) { 54 LOGE("unsupported role %d", cap.role); 55 return nullptr; 56 } 57 if (cap.type == VIDEO_DECODER) { 58 codec = make_shared<HDecoder>(cap, type.value()); 59 } else if (cap.type == VIDEO_ENCODER) { 60 codec = make_shared<HEncoder>(cap, type.value()); 61 } 62 break; 63 } 64 if (codec == nullptr) { 65 LOGE("cannot find %s", name.c_str()); 66 return nullptr; 67 } 68 return codec; 69} 70 71int32_t HCodec::Init(Media::Meta &callerInfo) 72{ 73 if (callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PID, playerCaller_.pid) && 74 callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PROCESS_NAME, playerCaller_.processName)) { 75 calledByAvcodec_ = false; 76 } else if (callerInfo.GetData(Tag::AV_CODEC_CALLER_PID, avcodecCaller_.pid) && 77 callerInfo.GetData(Tag::AV_CODEC_CALLER_PROCESS_NAME, avcodecCaller_.processName)) { 78 calledByAvcodec_ = true; 79 } 80 return DoSyncCall(MsgWhat::INIT, nullptr); 81} 82 83void HCodec::PrintCaller() 84{ 85 if (calledByAvcodec_) { 86 HLOGI("[pid %d][%s] -> avcodec", avcodecCaller_.pid, avcodecCaller_.processName.c_str()); 87 } else { 88 HLOGI("[pid %d][%s] -> player -> avcodec", playerCaller_.pid, playerCaller_.processName.c_str()); 89 } 90} 91 92int32_t HCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback) 93{ 94 HLOGI(">>"); 95 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 96 msg->SetValue("callback", callback); 97 }; 98 return DoSyncCall(MsgWhat::SET_CALLBACK, proc); 99} 100 101int32_t HCodec::Configure(const Format &format) 102{ 103 SCOPED_TRACE(); 104 HLOGI("%s", format.Stringify().c_str()); 105 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 106 msg->SetValue("format", format); 107 }; 108 return DoSyncCall(MsgWhat::CONFIGURE, proc); 109} 110 111int32_t HCodec::SetCustomBuffer(std::shared_ptr<AVBuffer> buffer) 112{ 113 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 114 msg->SetValue("buffer", buffer); 115 }; 116 return DoSyncCall(MsgWhat::CONFIGURE_BUFFER, proc); 117} 118 119int32_t HCodec::SetOutputSurface(sptr<Surface> surface) 120{ 121 HLOGI(">>"); 122 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 123 msg->SetValue("surface", surface); 124 }; 125 return DoSyncCall(MsgWhat::SET_OUTPUT_SURFACE, proc); 126} 127 128int32_t HCodec::Start() 129{ 130 SCOPED_TRACE(); 131 FUNC_TRACKER(); 132 return DoSyncCall(MsgWhat::START, nullptr); 133} 134 135int32_t HCodec::Stop() 136{ 137 SCOPED_TRACE(); 138 FUNC_TRACKER(); 139 return DoSyncCall(MsgWhat::STOP, nullptr); 140} 141 142int32_t HCodec::Flush() 143{ 144 SCOPED_TRACE(); 145 FUNC_TRACKER(); 146 return DoSyncCall(MsgWhat::FLUSH, nullptr); 147} 148 149int32_t HCodec::Reset() 150{ 151 SCOPED_TRACE(); 152 FUNC_TRACKER(); 153 int32_t ret = Release(); 154 if (ret == AVCS_ERR_OK) { 155 ret = DoSyncCall(MsgWhat::INIT, nullptr); 156 } 157 return ret; 158} 159 160int32_t HCodec::Release() 161{ 162 SCOPED_TRACE(); 163 FUNC_TRACKER(); 164 return DoSyncCall(MsgWhat::RELEASE, nullptr); 165} 166 167int32_t HCodec::NotifyEos() 168{ 169 HLOGI(">>"); 170 return DoSyncCall(MsgWhat::NOTIFY_EOS, nullptr); 171} 172 173int32_t HCodec::SetParameter(const Format &format) 174{ 175 HLOGI("%s", format.Stringify().c_str()); 176 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 177 msg->SetValue("params", format); 178 }; 179 return DoSyncCall(MsgWhat::SET_PARAMETERS, proc); 180} 181 182int32_t HCodec::GetInputFormat(Format& format) 183{ 184 HLOGI(">>"); 185 ParamSP reply; 186 int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_INPUT_FORMAT, nullptr, reply); 187 if (ret != AVCS_ERR_OK) { 188 HLOGE("failed to get input format"); 189 return ret; 190 } 191 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format), 192 AVCS_ERR_UNKNOWN, "input format not replied"); 193 return AVCS_ERR_OK; 194} 195 196int32_t HCodec::GetOutputFormat(Format &format) 197{ 198 ParamSP reply; 199 int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_OUTPUT_FORMAT, nullptr, reply); 200 if (ret != AVCS_ERR_OK) { 201 HLOGE("failed to get output format"); 202 return ret; 203 } 204 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format), 205 AVCS_ERR_UNKNOWN, "output format not replied"); 206 format.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, caps_.compName); 207 format.PutIntValue("IS_VENDOR", 1); 208 return AVCS_ERR_OK; 209} 210 211std::string HCodec::GetHidumperInfo() 212{ 213 HLOGI(">>"); 214 ParamSP reply; 215 int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_HIDUMPER_INFO, nullptr, reply); 216 if (ret != AVCS_ERR_OK) { 217 HLOGW("failed to get hidumper info"); 218 return ""; 219 } 220 string info; 221 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("hidumper-info", info), 222 "", "hidumper info not replied"); 223 return info; 224} 225 226sptr<Surface> HCodec::CreateInputSurface() 227{ 228 HLOGI(">>"); 229 ParamSP reply; 230 int32_t ret = DoSyncCallAndGetReply(MsgWhat::CREATE_INPUT_SURFACE, nullptr, reply); 231 if (ret != AVCS_ERR_OK) { 232 HLOGE("failed to create input surface"); 233 return nullptr; 234 } 235 sptr<Surface> inputSurface; 236 IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("surface", inputSurface), nullptr, "input surface not replied"); 237 return inputSurface; 238} 239 240int32_t HCodec::SetInputSurface(sptr<Surface> surface) 241{ 242 HLOGI(">>"); 243 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 244 msg->SetValue("surface", surface); 245 }; 246 return DoSyncCall(MsgWhat::SET_INPUT_SURFACE, proc); 247} 248 249int32_t HCodec::SignalRequestIDRFrame() 250{ 251 HLOGI(">>"); 252 return DoSyncCall(MsgWhat::REQUEST_IDR_FRAME, nullptr); 253} 254 255int32_t HCodec::QueueInputBuffer(uint32_t index) 256{ 257 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 258 msg->SetValue(BUFFER_ID, index); 259 }; 260 return DoSyncCall(MsgWhat::QUEUE_INPUT_BUFFER, proc); 261} 262 263int32_t HCodec::RenderOutputBuffer(uint32_t index) 264{ 265 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 266 msg->SetValue(BUFFER_ID, index); 267 }; 268 return DoSyncCall(MsgWhat::RENDER_OUTPUT_BUFFER, proc); 269} 270 271int32_t HCodec::ReleaseOutputBuffer(uint32_t index) 272{ 273 std::function<void(ParamSP)> proc = [&](ParamSP msg) { 274 msg->SetValue(BUFFER_ID, index); 275 }; 276 return DoSyncCall(MsgWhat::RELEASE_OUTPUT_BUFFER, proc); 277} 278/**************************** public functions end ****************************/ 279 280 281HCodec::HCodec(CodecCompCapability caps, OMX_VIDEO_CODINGTYPE codingType, bool isEncoder) 282 : caps_(caps), codingType_(codingType), isEncoder_(isEncoder) 283{ 284 debugMode_ = HiLogIsLoggable(HCODEC_DOMAIN, HCODEC_TAG, LOG_DEBUG); 285 string dumpModeStr = OHOS::system::GetParameter("hcodec.dump", "0"); 286 dumpMode_ = static_cast<DumpMode>(strtoul(dumpModeStr.c_str(), nullptr, 2)); // 2 is binary 287 LOGI(">> debug mode = %d, dump mode = %s(%lu)", 288 debugMode_, dumpModeStr.c_str(), dumpMode_); 289 290 string isEncoderStr = isEncoder ? "enc." : "dec."; 291 switch (static_cast<int>(codingType_)) { 292 case OMX_VIDEO_CodingAVC: 293 shortName_ = isEncoderStr + "avc"; 294 break; 295 case CODEC_OMX_VIDEO_CodingHEVC: 296 shortName_ = isEncoderStr + "hevc"; 297 break; 298 case CODEC_OMX_VIDEO_CodingVVC: 299 shortName_ = isEncoderStr + "vvc"; 300 break; 301 default: 302 shortName_ = isEncoderStr; 303 break; 304 }; 305 isSecure_ = IsSecureMode(caps_.compName); 306 if (isSecure_) { 307 shortName_ += ".secure"; 308 } 309 310 uninitializedState_ = make_shared<UninitializedState>(this); 311 initializedState_ = make_shared<InitializedState>(this); 312 startingState_ = make_shared<StartingState>(this); 313 runningState_ = make_shared<RunningState>(this); 314 outputPortChangedState_ = make_shared<OutputPortChangedState>(this); 315 stoppingState_ = make_shared<StoppingState>(this); 316 flushingState_ = make_shared<FlushingState>(this); 317 StateMachine::ChangeStateTo(uninitializedState_); 318} 319 320HCodec::~HCodec() 321{ 322 HLOGI(">>"); 323 MsgHandleLoop::Stop(); 324 ReleaseComponent(); 325} 326 327int32_t HCodec::HdiCallback::EventHandler(CodecEventType event, const EventInfo &info) 328{ 329 LOGI("event = %d, data1 = %u, data2 = %u", event, info.data1, info.data2); 330 ParamSP msg = make_shared<ParamBundle>(); 331 msg->SetValue("event", event); 332 msg->SetValue("data1", info.data1); 333 msg->SetValue("data2", info.data2); 334 std::shared_ptr<HCodec> codec = codec_.lock(); 335 if (codec == nullptr) { 336 LOGI("HCodec is gone"); 337 return HDF_SUCCESS; 338 } 339 codec->SendAsyncMsg(MsgWhat::CODEC_EVENT, msg); 340 return HDF_SUCCESS; 341} 342 343int32_t HCodec::HdiCallback::EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer) 344{ 345 ParamSP msg = make_shared<ParamBundle>(); 346 msg->SetValue(BUFFER_ID, buffer.bufferId); 347 std::shared_ptr<HCodec> codec = codec_.lock(); 348 if (codec == nullptr) { 349 LOGI("HCodec is gone"); 350 return HDF_SUCCESS; 351 } 352 codec->SendAsyncMsg(MsgWhat::OMX_EMPTY_BUFFER_DONE, msg); 353 return HDF_SUCCESS; 354} 355 356int32_t HCodec::HdiCallback::FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer) 357{ 358 ParamSP msg = make_shared<ParamBundle>(); 359 msg->SetValue("omxBuffer", buffer); 360 std::shared_ptr<HCodec> codec = codec_.lock(); 361 if (codec == nullptr) { 362 LOGI("HCodec is gone"); 363 return HDF_SUCCESS; 364 } 365 codec->SendAsyncMsg(MsgWhat::OMX_FILL_BUFFER_DONE, msg); 366 return HDF_SUCCESS; 367} 368 369int32_t HCodec::SetFrameRateAdaptiveMode(const Format &format) 370{ 371 if (!format.ContainKey(OHOS::Media::Tag::VIDEO_FRAME_RATE_ADAPTIVE_MODE)) { 372 return AVCS_ERR_UNKNOWN; 373 } 374 375 WorkingFrequencyParam param {}; 376 InitOMXParamExt(param); 377 if (!GetParameter(OMX_IndexParamWorkingFrequency, param)) { 378 HLOGW("get working freq param failed"); 379 return AVCS_ERR_UNKNOWN; 380 } 381 if (param.level == 0) { 382 return AVCS_ERR_UNKNOWN; 383 } 384 HLOGI("level cnt is %d, set level to %d", param.level, param.level - 1); 385 param.level = param.level - 1; 386 387 if (!SetParameter(OMX_IndexParamWorkingFrequency, param)) { 388 HLOGW("set working freq param failed"); 389 return AVCS_ERR_UNKNOWN; 390 } 391 return AVCS_ERR_OK; 392} 393 394int32_t HCodec::SetProcessName() 395{ 396 const std::string& processName = calledByAvcodec_ ? avcodecCaller_.processName : playerCaller_.processName; 397 HLOGI("processName is %s", processName.c_str()); 398 399 ProcessNameParam param {}; 400 InitOMXParamExt(param); 401 if (strcpy_s(param.processName, sizeof(param.processName), processName.c_str()) != EOK) { 402 HLOGW("strcpy failed"); 403 return AVCS_ERR_UNKNOWN; 404 } 405 if (!SetParameter(OMX_IndexParamProcessName, param)) { 406 HLOGW("set process name failed"); 407 return AVCS_ERR_UNKNOWN; 408 } 409 return AVCS_ERR_OK; 410} 411 412int32_t HCodec::SetLowLatency(const Format &format) 413{ 414 int32_t enableLowLatency; 415 if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENABLE_LOW_LATENCY, enableLowLatency)) { 416 return AVCS_ERR_OK; 417 } 418 if (!caps_.port.video.isSupportLowLatency) { 419 HLOGW("platform not support LowLatency"); 420 return AVCS_ERR_OK; 421 } 422 423 OMX_CONFIG_BOOLEANTYPE param {}; 424 InitOMXParam(param); 425 param.bEnabled = enableLowLatency ? OMX_TRUE : OMX_FALSE; 426 if (!SetParameter(OMX_IndexParamLowLatency, param)) { 427 HLOGW("set low latency failed"); 428 return AVCS_ERR_UNKNOWN; 429 } 430 HLOGI("set low latency succ %d", enableLowLatency); 431 return AVCS_ERR_OK; 432} 433 434bool HCodec::GetPixelFmtFromUser(const Format &format) 435{ 436 optional<PixelFmt> fmt; 437 VideoPixelFormat innerFmt; 438 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, *(int *)&innerFmt) && 439 innerFmt != VideoPixelFormat::SURFACE_FORMAT) { 440 fmt = TypeConverter::InnerFmtToFmt(innerFmt); 441 } else { 442 HLOGI("user don't set VideoPixelFormat, use default"); 443 for (int32_t f : caps_.port.video.supportPixFmts) { 444 fmt = TypeConverter::GraphicFmtToFmt(static_cast<GraphicPixelFormat>(f)); 445 if (fmt.has_value()) { 446 break; 447 } 448 } 449 } 450 if (!fmt) { 451 HLOGE("pixel format unspecified"); 452 return false; 453 } 454 configuredFmt_ = fmt.value(); 455 HLOGI("configured pixel format is %s", configuredFmt_.strFmt.c_str()); 456 return true; 457} 458 459std::optional<double> HCodec::GetFrameRateFromUser(const Format &format) 460{ 461 double frameRateDouble; 462 if (format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRateDouble) && frameRateDouble > 0) { 463 LOGI("user set frame rate %.2f", frameRateDouble); 464 return frameRateDouble; 465 } 466 int frameRateInt; 467 if (format.GetIntValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRateInt) && frameRateInt > 0) { 468 LOGI("user set frame rate %d", frameRateInt); 469 return static_cast<double>(frameRateInt); 470 } 471 return nullopt; 472} 473 474bool HCodec::CheckBufPixFmt(const sptr<SurfaceBuffer>& buffer) 475{ 476 int32_t dispFmt = buffer->GetFormat(); 477 const std::vector<int32_t>& supportFmts = caps_.port.video.supportPixFmts; 478 if (std::find(supportFmts.begin(), supportFmts.end(), dispFmt) == supportFmts.end()) { 479 LOGE("unsupported buffer pixel format %d", dispFmt); 480 callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR); 481 return false; 482 } 483 return true; 484} 485 486int32_t HCodec::SetVideoPortInfo(OMX_DIRTYPE portIndex, const PortInfo& info) 487{ 488 if (info.pixelFmt.has_value()) { 489 CodecVideoPortFormatParam param; 490 InitOMXParamExt(param); 491 param.portIndex = portIndex; 492 param.codecCompressFormat = info.codingType; 493 param.codecColorFormat = info.pixelFmt->graphicFmt; 494 param.framerate = info.frameRate * FRAME_RATE_COEFFICIENT; 495 if (!SetParameter(OMX_IndexCodecVideoPortFormat, param)) { 496 HLOGE("set port format failed"); 497 return AVCS_ERR_UNKNOWN; 498 } 499 } 500 { 501 OMX_PARAM_PORTDEFINITIONTYPE def; 502 InitOMXParam(def); 503 def.nPortIndex = portIndex; 504 if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 505 HLOGE("get port definition failed"); 506 return AVCS_ERR_UNKNOWN; 507 } 508 def.format.video.nFrameWidth = info.width; 509 def.format.video.nFrameHeight = info.height; 510 def.format.video.eCompressionFormat = info.codingType; 511 // we dont set eColorFormat here because it has been set by CodecVideoPortFormatParam 512 def.format.video.xFramerate = info.frameRate * FRAME_RATE_COEFFICIENT; 513 if (portIndex == OMX_DirInput && info.inputBufSize.has_value()) { 514 def.nBufferSize = info.inputBufSize.value(); 515 } 516 if (!SetParameter(OMX_IndexParamPortDefinition, def)) { 517 HLOGE("set port definition failed"); 518 return AVCS_ERR_UNKNOWN; 519 } 520 if (portIndex == OMX_DirOutput) { 521 if (outputFormat_ == nullptr) { 522 outputFormat_ = make_shared<Format>(); 523 } 524 outputFormat_->PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, info.frameRate); 525 } 526 } 527 528 return (portIndex == OMX_DirInput) ? UpdateInPortFormat() : UpdateOutPortFormat(); 529} 530 531void HCodec::PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE& def) 532{ 533 const OMX_VIDEO_PORTDEFINITIONTYPE& video = def.format.video; 534 HLOGI("----- %s port definition -----", (def.nPortIndex == OMX_DirInput) ? "INPUT" : "OUTPUT"); 535 HLOGI("bEnabled %d, bPopulated %d", def.bEnabled, def.bPopulated); 536 HLOGI("nBufferCountActual %u, nBufferSize %u", def.nBufferCountActual, def.nBufferSize); 537 HLOGI("nFrameWidth x nFrameHeight (%u x %u), framerate %u(%.2f)", 538 video.nFrameWidth, video.nFrameHeight, video.xFramerate, video.xFramerate / FRAME_RATE_COEFFICIENT); 539 HLOGI(" nStride x nSliceHeight (%u x %u)", video.nStride, video.nSliceHeight); 540 HLOGI("eCompressionFormat %d(%#x), eColorFormat %d(%#x)", 541 video.eCompressionFormat, video.eCompressionFormat, video.eColorFormat, video.eColorFormat); 542 HLOGI("----------------------------------"); 543} 544 545int32_t HCodec::GetPortDefinition(OMX_DIRTYPE portIndex, OMX_PARAM_PORTDEFINITIONTYPE& def) 546{ 547 InitOMXParam(def); 548 def.nPortIndex = portIndex; 549 if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 550 HLOGE("get %s port definition failed", (portIndex == OMX_DirInput ? "input" : "output")); 551 return AVCS_ERR_INVALID_VAL; 552 } 553 if (def.nBufferSize == 0 || def.nBufferSize > MAX_HCODEC_BUFFER_SIZE) { 554 HLOGE("invalid nBufferSize %u", def.nBufferSize); 555 return AVCS_ERR_INVALID_VAL; 556 } 557 return AVCS_ERR_OK; 558} 559 560int32_t HCodec::AllocateAvLinearBuffers(OMX_DIRTYPE portIndex) 561{ 562 SCOPED_TRACE(); 563 OMX_PARAM_PORTDEFINITIONTYPE def; 564 int32_t ret = GetPortDefinition(portIndex, def); 565 if (ret != AVCS_ERR_OK) { 566 return ret; 567 } 568 569 SupportBufferType type; 570 InitOMXParamExt(type); 571 type.portIndex = portIndex; 572 if (GetParameter(OMX_IndexParamSupportBufferType, type) && (type.bufferTypes & CODEC_BUFFER_TYPE_DMA_MEM_FD)) { 573 HLOGI("allocate hardware buffer"); 574 return AllocateAvHardwareBuffers(portIndex, def); 575 } else { 576 HLOGI("allocate shared buffer"); 577 return AllocateAvSharedBuffers(portIndex, def); 578 } 579} 580 581int32_t HCodec::AllocateAvHardwareBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def) 582{ 583 SCOPED_TRACE(); 584 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 585 pool.clear(); 586 for (uint32_t i = 0; i < def.nBufferCountActual; ++i) { 587 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 588 omxBuffer->size = sizeof(OmxCodecBuffer); 589 omxBuffer->version.version.majorVersion = 1; 590 omxBuffer->bufferType = CODEC_BUFFER_TYPE_DMA_MEM_FD; 591 omxBuffer->fd = -1; 592 omxBuffer->allocLen = def.nBufferSize; 593 omxBuffer->fenceFd = -1; 594 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 595 int32_t ret = compNode_->AllocateBuffer(portIndex, *omxBuffer, *outBuffer); 596 if (ret != HDF_SUCCESS) { 597 HLOGE("Failed to AllocateBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output")); 598 return AVCS_ERR_INVALID_VAL; 599 } 600 MemoryFlag memFlag = MEMORY_READ_WRITE; 601 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateHardwareAllocator( 602 outBuffer->fd, static_cast<int32_t>(def.nBufferSize), memFlag, isSecure_); 603 IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateHardwareAllocator failed"); 604 605 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer( 606 avAllocator, static_cast<int32_t>(def.nBufferSize)); 607 if (avBuffer == nullptr || avBuffer->memory_ == nullptr || 608 avBuffer->memory_->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) { 609 HLOGE("CreateAVBuffer failed"); 610 return AVCS_ERR_NO_MEMORY; 611 } 612 SetCallerToBuffer(outBuffer->fd); 613 BufferInfo bufInfo; 614 bufInfo.isInput = (portIndex == OMX_DirInput) ? true : false; 615 bufInfo.owner = BufferOwner::OWNED_BY_US; 616 bufInfo.surfaceBuffer = nullptr; 617 bufInfo.avBuffer = avBuffer; 618 bufInfo.omxBuffer = outBuffer; 619 bufInfo.bufferId = outBuffer->bufferId; 620 bufInfo.CleanUpUnusedInfo(); 621 pool.push_back(bufInfo); 622 } 623 return AVCS_ERR_OK; 624} 625 626int32_t HCodec::AllocateAvSharedBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def) 627{ 628 SCOPED_TRACE(); 629 MemoryFlag memFlag = MEMORY_READ_WRITE; 630 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSharedAllocator(memFlag); 631 IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateSharedAllocator failed"); 632 633 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 634 pool.clear(); 635 for (uint32_t i = 0; i < def.nBufferCountActual; ++i) { 636 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator, 637 static_cast<int32_t>(def.nBufferSize)); 638 if (avBuffer == nullptr || avBuffer->memory_ == nullptr || 639 avBuffer->memory_->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) { 640 HLOGE("CreateAVBuffer failed"); 641 return AVCS_ERR_NO_MEMORY; 642 } 643 std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 644 omxBuffer->size = sizeof(OmxCodecBuffer); 645 omxBuffer->version.version.majorVersion = 1; 646 omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD; 647 omxBuffer->fd = avBuffer->memory_->GetFileDescriptor(); 648 omxBuffer->allocLen = def.nBufferSize; 649 omxBuffer->fenceFd = -1; 650 omxBuffer->type = (portIndex == OMX_DirInput) ? READ_ONLY_TYPE : READ_WRITE_TYPE; 651 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 652 int32_t ret = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer); 653 if (ret != HDF_SUCCESS) { 654 HLOGE("Failed to UseBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output")); 655 return AVCS_ERR_INVALID_VAL; 656 } 657 BufferInfo bufInfo; 658 bufInfo.isInput = (portIndex == OMX_DirInput) ? true : false; 659 bufInfo.owner = BufferOwner::OWNED_BY_US; 660 bufInfo.surfaceBuffer = nullptr; 661 bufInfo.avBuffer = avBuffer; 662 bufInfo.omxBuffer = outBuffer; 663 bufInfo.bufferId = outBuffer->bufferId; 664 pool.push_back(bufInfo); 665 } 666 return AVCS_ERR_OK; 667} 668 669int32_t HCodec::AllocateAvSurfaceBuffers(OMX_DIRTYPE portIndex) 670{ 671 SCOPED_TRACE(); 672 OMX_PARAM_PORTDEFINITIONTYPE def; 673 int32_t ret = GetPortDefinition(portIndex, def); 674 if (ret != AVCS_ERR_OK) { 675 return ret; 676 } 677 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSurfaceAllocator(requestCfg_); 678 IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateSurfaceAllocator failed"); 679 bool needDealWithCache = (requestCfg_.usage & BUFFER_USAGE_MEM_MMZ_CACHE); 680 681 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 682 pool.clear(); 683 for (uint32_t i = 0; i < def.nBufferCountActual; ++i) { 684 std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator, 685 static_cast<int32_t>(def.nBufferSize)); 686 if (avBuffer == nullptr || avBuffer->memory_ == nullptr) { 687 HLOGE("CreateAVBuffer failed"); 688 return AVCS_ERR_NO_MEMORY; 689 } 690 sptr<SurfaceBuffer> surfaceBuffer = avBuffer->memory_->GetSurfaceBuffer(); 691 IF_TRUE_RETURN_VAL_WITH_MSG(surfaceBuffer == nullptr, AVCS_ERR_INVALID_VAL, "avbuffer has null surfacebuffer"); 692 shared_ptr<OmxCodecBuffer> omxBuffer = isEncoder_ ? 693 DynamicSurfaceBufferToOmxBuffer() : SurfaceBufferToOmxBuffer(surfaceBuffer); 694 IF_TRUE_RETURN_VAL(omxBuffer == nullptr, AVCS_ERR_INVALID_VAL); 695 shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 696 int32_t hdiRet = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer); 697 if (hdiRet != HDF_SUCCESS) { 698 HLOGE("Failed to UseBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output")); 699 return AVCS_ERR_INVALID_VAL; 700 } 701 BufferInfo bufInfo; 702 bufInfo.isInput = (portIndex == OMX_DirInput) ? true : false; 703 bufInfo.owner = BufferOwner::OWNED_BY_US; 704 bufInfo.surfaceBuffer = surfaceBuffer; 705 bufInfo.avBuffer = avBuffer; 706 bufInfo.omxBuffer = outBuffer; 707 bufInfo.bufferId = outBuffer->bufferId; 708 bufInfo.needDealWithCache = needDealWithCache; 709 pool.push_back(bufInfo); 710 } 711 712 return AVCS_ERR_OK; 713} 714 715shared_ptr<OmxCodecBuffer> HCodec::SurfaceBufferToOmxBuffer(const sptr<SurfaceBuffer>& surfaceBuffer) 716{ 717 BufferHandle* bufferHandle = surfaceBuffer->GetBufferHandle(); 718 IF_TRUE_RETURN_VAL_WITH_MSG(bufferHandle == nullptr, nullptr, "surfacebuffer has null bufferhandle"); 719 auto omxBuffer = std::make_shared<OmxCodecBuffer>(); 720 omxBuffer->size = sizeof(OmxCodecBuffer); 721 omxBuffer->version.version.majorVersion = 1; 722 omxBuffer->bufferType = CODEC_BUFFER_TYPE_HANDLE; 723 omxBuffer->bufferhandle = new NativeBuffer(bufferHandle); 724 omxBuffer->fd = -1; 725 omxBuffer->allocLen = surfaceBuffer->GetSize(); 726 omxBuffer->fenceFd = -1; 727 return omxBuffer; 728} 729 730shared_ptr<OmxCodecBuffer> HCodec::DynamicSurfaceBufferToOmxBuffer() 731{ 732 auto omxBuffer = make_shared<OmxCodecBuffer>(); 733 omxBuffer->size = sizeof(OmxCodecBuffer); 734 omxBuffer->version.version.majorVersion = 1; 735 omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE; 736 omxBuffer->fd = -1; 737 omxBuffer->allocLen = 0; 738 omxBuffer->fenceFd = -1; 739 return omxBuffer; 740} 741 742const char* HCodec::ToString(BufferOwner owner) 743{ 744 switch (owner) { 745 case BufferOwner::OWNED_BY_US: 746 return "us"; 747 case BufferOwner::OWNED_BY_USER: 748 return "user"; 749 case BufferOwner::OWNED_BY_OMX: 750 return "omx"; 751 case BufferOwner::OWNED_BY_SURFACE: 752 return "surface"; 753 default: 754 return ""; 755 } 756} 757 758void HCodec::BufferInfo::CleanUpUnusedInfo() 759{ 760 if (omxBuffer == nullptr || omxBuffer->fd < 0) { 761 return; 762 } 763 if (omxBuffer->fd == 0) { 764 LOGW("fd of omxbuffer should never be 0"); 765 } 766 close(omxBuffer->fd); 767 omxBuffer->fd = -1; 768} 769 770void HCodec::BufferInfo::BeginCpuAccess() 771{ 772 if (surfaceBuffer && needDealWithCache) { 773 GSError err = surfaceBuffer->InvalidateCache(); 774 if (err != GSERROR_OK) { 775 LOGW("InvalidateCache failed, GSError=%d", err); 776 } 777 } 778} 779 780void HCodec::BufferInfo::EndCpuAccess() 781{ 782 if (surfaceBuffer && needDealWithCache) { 783 GSError err = surfaceBuffer->Map(); 784 if (err != GSERROR_OK) { 785 LOGW("Map failed, GSError=%d", err); 786 return; 787 } 788 err = surfaceBuffer->FlushCache(); 789 if (err != GSERROR_OK) { 790 LOGW("FlushCache failed, GSError=%d", err); 791 } 792 } 793} 794 795HCodec::BufferInfo* HCodec::FindBufferInfoByID(OMX_DIRTYPE portIndex, uint32_t bufferId) 796{ 797 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 798 for (BufferInfo &info : pool) { 799 if (info.bufferId == bufferId) { 800 return &info; 801 } 802 } 803 HLOGE("unknown buffer id %u", bufferId); 804 return nullptr; 805} 806 807optional<size_t> HCodec::FindBufferIndexByID(OMX_DIRTYPE portIndex, uint32_t bufferId) 808{ 809 const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 810 for (size_t i = 0; i < pool.size(); i++) { 811 if (pool[i].bufferId == bufferId) { 812 return i; 813 } 814 } 815 HLOGE("unknown buffer id %u", bufferId); 816 return nullopt; 817} 818 819uint32_t HCodec::UserFlagToOmxFlag(AVCodecBufferFlag userFlag) 820{ 821 uint32_t flags = 0; 822 if (userFlag & AVCODEC_BUFFER_FLAG_EOS) { 823 flags |= OMX_BUFFERFLAG_EOS; 824 HLOGI("got input eos"); 825 } 826 if (userFlag & AVCODEC_BUFFER_FLAG_SYNC_FRAME) { 827 flags |= OMX_BUFFERFLAG_SYNCFRAME; 828 } 829 if (userFlag & AVCODEC_BUFFER_FLAG_CODEC_DATA) { 830 flags |= OMX_BUFFERFLAG_CODECCONFIG; 831 } 832 return flags; 833} 834 835AVCodecBufferFlag HCodec::OmxFlagToUserFlag(uint32_t omxFlag) 836{ 837 uint32_t flags = 0; 838 if (omxFlag & OMX_BUFFERFLAG_EOS) { 839 flags |= AVCODEC_BUFFER_FLAG_EOS; 840 HLOGI("got output eos"); 841 } 842 if (omxFlag & OMX_BUFFERFLAG_SYNCFRAME) { 843 flags |= AVCODEC_BUFFER_FLAG_SYNC_FRAME; 844 } 845 if (omxFlag & OMX_BUFFERFLAG_CODECCONFIG) { 846 flags |= AVCODEC_BUFFER_FLAG_CODEC_DATA; 847 } 848 return static_cast<AVCodecBufferFlag>(flags); 849} 850 851bool HCodec::WaitFence(const sptr<SyncFence>& fence) 852{ 853 if (fence == nullptr || !fence->IsValid()) { 854 return true; 855 } 856 SCOPED_TRACE(); 857 auto before = chrono::steady_clock::now(); 858 int waitRes = fence->Wait(WAIT_FENCE_MS); 859 if (waitRes == 0) { 860 int64_t costMs = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - before).count(); 861 if (costMs >= WARN_FENCE_MS) { 862 HLOGW("wait fence succ but cost %" PRId64 " ms", costMs); 863 } 864 return true; 865 } else { 866 HLOGE("wait fence time out, cost more than %u ms", WAIT_FENCE_MS); 867 return false; 868 } 869} 870 871void HCodec::NotifyUserToFillThisInBuffer(BufferInfo &info) 872{ 873 SCOPED_TRACE_WITH_ID(info.bufferId); 874 callback_->OnInputBufferAvailable(info.bufferId, info.avBuffer); 875 ChangeOwner(info, BufferOwner::OWNED_BY_USER); 876} 877 878void HCodec::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode) 879{ 880 uint32_t bufferId = 0; 881 (void)msg.param->GetValue(BUFFER_ID, bufferId); 882 SCOPED_TRACE_WITH_ID(bufferId); 883 BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId); 884 if (bufferInfo == nullptr) { 885 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 886 return; 887 } 888 if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) { 889 HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(bufferInfo->owner)); 890 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 891 return; 892 } 893 if (!gotFirstInput_) { 894 HLOGI("got first input"); 895 gotFirstInput_ = true; 896 } 897 bufferInfo->omxBuffer->filledLen = static_cast<uint32_t> 898 (bufferInfo->avBuffer->memory_->GetSize()); 899 bufferInfo->omxBuffer->offset = static_cast<uint32_t>(bufferInfo->avBuffer->memory_->GetOffset()); 900 bufferInfo->omxBuffer->pts = bufferInfo->avBuffer->pts_; 901 bufferInfo->omxBuffer->flag = UserFlagToOmxFlag(static_cast<AVCodecBufferFlag>(bufferInfo->avBuffer->flag_)); 902 ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US); 903 ReplyErrorCode(msg.id, AVCS_ERR_OK); 904 int32_t ret = OnQueueInputBuffer(mode, bufferInfo); 905 if (ret != AVCS_ERR_OK) { 906 SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN); 907 } 908} 909 910int32_t HCodec::OnQueueInputBuffer(BufferOperationMode mode, BufferInfo* info) 911{ 912 switch (mode) { 913 case KEEP_BUFFER: { 914 return AVCS_ERR_OK; 915 } 916 case RESUBMIT_BUFFER: { 917 if (inputPortEos_) { 918 HLOGI("input already eos, keep this buffer"); 919 return AVCS_ERR_OK; 920 } 921 bool eos = (info->omxBuffer->flag & OMX_BUFFERFLAG_EOS); 922 if (!eos && info->omxBuffer->filledLen == 0) { 923 HLOGI("this is not a eos buffer but not filled, ask user to re-fill it"); 924 NotifyUserToFillThisInBuffer(*info); 925 return AVCS_ERR_OK; 926 } 927 if (eos) { 928 inputPortEos_ = true; 929 } 930 return NotifyOmxToEmptyThisInBuffer(*info); 931 } 932 default: { 933 HLOGE("SHOULD NEVER BE HERE"); 934 return AVCS_ERR_UNKNOWN; 935 } 936 } 937} 938 939void HCodec::WrapSurfaceBufferToSlot(BufferInfo &info, 940 const sptr<SurfaceBuffer>& surfaceBuffer, int64_t pts, uint32_t flag) 941{ 942 info.surfaceBuffer = surfaceBuffer; 943 info.omxBuffer->bufferhandle = new NativeBuffer(surfaceBuffer->GetBufferHandle()); 944 info.omxBuffer->filledLen = surfaceBuffer->GetSize(); 945 info.omxBuffer->fd = -1; 946 info.omxBuffer->fenceFd = -1; 947 info.omxBuffer->pts = pts; 948 info.omxBuffer->flag = flag; 949} 950 951void HCodec::OnSignalEndOfInputStream(const MsgInfo &msg) 952{ 953 ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT); 954} 955 956int32_t HCodec::NotifyOmxToEmptyThisInBuffer(BufferInfo& info) 957{ 958 SCOPED_TRACE_WITH_ID(info.bufferId); 959#ifdef BUILD_ENG_VERSION 960 info.Dump(compUniqueStr_, inTotalCnt_, dumpMode_, isEncoder_); 961#endif 962 info.EndCpuAccess(); 963 int32_t ret = compNode_->EmptyThisBuffer(*(info.omxBuffer)); 964 if (ret != HDF_SUCCESS) { 965 HLOGE("EmptyThisBuffer failed"); 966 return AVCS_ERR_UNKNOWN; 967 } 968 ChangeOwner(info, BufferOwner::OWNED_BY_OMX); 969 return AVCS_ERR_OK; 970} 971 972int32_t HCodec::NotifyOmxToFillThisOutBuffer(BufferInfo& info) 973{ 974 SCOPED_TRACE_WITH_ID(info.bufferId); 975 info.omxBuffer->flag = 0; 976 int32_t ret = compNode_->FillThisBuffer(*(info.omxBuffer)); 977 if (ret != HDF_SUCCESS) { 978 HLOGE("outBufId = %u failed", info.bufferId); 979 return AVCS_ERR_UNKNOWN; 980 } 981 ChangeOwner(info, BufferOwner::OWNED_BY_OMX); 982 return AVCS_ERR_OK; 983} 984 985void HCodec::OnOMXFillBufferDone(const OmxCodecBuffer& omxBuffer, BufferOperationMode mode) 986{ 987 SCOPED_TRACE_WITH_ID(omxBuffer.bufferId); 988 optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, omxBuffer.bufferId); 989 if (!idx.has_value()) { 990 return; 991 } 992 BufferInfo& info = outputBufferPool_[idx.value()]; 993 if (info.owner != BufferOwner::OWNED_BY_OMX) { 994 HLOGE("wrong ownership: buffer id=%d, owner=%s", info.bufferId, ToString(info.owner)); 995 return; 996 } 997 info.omxBuffer->offset = omxBuffer.offset; 998 info.omxBuffer->filledLen = omxBuffer.filledLen; 999 info.omxBuffer->pts = omxBuffer.pts; 1000 info.omxBuffer->flag = omxBuffer.flag; 1001 info.omxBuffer->alongParam = std::move(omxBuffer.alongParam); 1002 ChangeOwner(info, BufferOwner::OWNED_BY_US); 1003 OnOMXFillBufferDone(mode, info, idx.value()); 1004} 1005 1006void HCodec::OnOMXFillBufferDone(BufferOperationMode mode, BufferInfo& info, size_t bufferIdx) 1007{ 1008 switch (mode) { 1009 case KEEP_BUFFER: 1010 return; 1011 case RESUBMIT_BUFFER: { 1012 if (outputPortEos_) { 1013 HLOGI("output eos, keep this buffer"); 1014 return; 1015 } 1016 bool eos = (info.omxBuffer->flag & OMX_BUFFERFLAG_EOS); 1017 if (!eos && info.omxBuffer->filledLen == 0) { 1018 HLOGW("it's not a eos buffer but not filled, ask omx to re-fill it"); 1019 NotifyOmxToFillThisOutBuffer(info); 1020 return; 1021 } 1022#ifdef USE_VIDEO_PROCESSING_ENGINE 1023 if (!isEncoder_ && isVrrEnable_) { 1024 (void)VrrPrediction(info); 1025 } 1026#endif 1027 NotifyUserOutBufferAvaliable(info); 1028 if (eos) { 1029 outputPortEos_ = true; 1030 } 1031 return; 1032 } 1033 case FREE_BUFFER: 1034 EraseBufferFromPool(OMX_DirOutput, bufferIdx); 1035 return; 1036 default: 1037 HLOGE("SHOULD NEVER BE HERE"); 1038 return; 1039 } 1040} 1041 1042void HCodec::NotifyUserOutBufferAvaliable(BufferInfo &info) 1043{ 1044 SCOPED_TRACE_WITH_ID(info.bufferId); 1045 if (!gotFirstOutput_) { 1046 HLOGI("got first output"); 1047 OHOS::QOS::ResetThreadQos(); 1048 gotFirstOutput_ = true; 1049 } 1050 info.BeginCpuAccess(); 1051#ifdef BUILD_ENG_VERSION 1052 info.Dump(compUniqueStr_, outRecord_.totalCnt, dumpMode_, isEncoder_); 1053#endif 1054 shared_ptr<OmxCodecBuffer> omxBuffer = info.omxBuffer; 1055 info.avBuffer->pts_ = omxBuffer->pts; 1056 info.avBuffer->flag_ = OmxFlagToUserFlag(omxBuffer->flag); 1057 if (info.avBuffer->memory_) { 1058 info.avBuffer->memory_->SetSize(static_cast<int32_t>(omxBuffer->filledLen)); 1059 info.avBuffer->memory_->SetOffset(static_cast<int32_t>(omxBuffer->offset)); 1060 } 1061 ExtractPerFrameParamFromOmxBuffer(omxBuffer, info.avBuffer->meta_); 1062 callback_->OnOutputBufferAvailable(info.bufferId, info.avBuffer); 1063 ChangeOwner(info, BufferOwner::OWNED_BY_USER); 1064} 1065 1066void HCodec::OnReleaseOutputBuffer(const MsgInfo &msg, BufferOperationMode mode) 1067{ 1068 uint32_t bufferId = 0; 1069 (void)msg.param->GetValue(BUFFER_ID, bufferId); 1070 SCOPED_TRACE_WITH_ID(bufferId); 1071 optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId); 1072 if (!idx.has_value()) { 1073 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1074 return; 1075 } 1076 BufferInfo& info = outputBufferPool_[idx.value()]; 1077 if (info.owner != BufferOwner::OWNED_BY_USER) { 1078 HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info.owner)); 1079 ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1080 return; 1081 } 1082 OnReleaseOutputBuffer(info); 1083 ChangeOwner(info, BufferOwner::OWNED_BY_US); 1084 ReplyErrorCode(msg.id, AVCS_ERR_OK); 1085 1086 switch (mode) { 1087 case KEEP_BUFFER: { 1088 return; 1089 } 1090 case RESUBMIT_BUFFER: { 1091 if (outputPortEos_) { 1092 HLOGI("output eos, keep this buffer"); 1093 return; 1094 } 1095 int32_t ret = NotifyOmxToFillThisOutBuffer(info); 1096 if (ret != AVCS_ERR_OK) { 1097 SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN); 1098 } 1099 return; 1100 } 1101 case FREE_BUFFER: { 1102 EraseBufferFromPool(OMX_DirOutput, idx.value()); 1103 return; 1104 } 1105 default: { 1106 HLOGE("SHOULD NEVER BE HERE"); 1107 return; 1108 } 1109 } 1110} 1111 1112void HCodec::OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode) 1113{ 1114 ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT); 1115} 1116 1117void HCodec::ReclaimBuffer(OMX_DIRTYPE portIndex, BufferOwner owner, bool erase) 1118{ 1119 vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1120 for (size_t i = pool.size(); i > 0;) { 1121 i--; 1122 BufferInfo& info = pool[i]; 1123 if (info.owner == owner) { 1124 ChangeOwner(info, BufferOwner::OWNED_BY_US); 1125 if (erase) { 1126 EraseBufferFromPool(portIndex, i); 1127 } 1128 } 1129 } 1130} 1131 1132bool HCodec::IsAllBufferOwnedByUsOrSurface(OMX_DIRTYPE portIndex) 1133{ 1134 const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1135 for (const BufferInfo& info : pool) { 1136 if (info.owner != BufferOwner::OWNED_BY_US && 1137 info.owner != BufferOwner::OWNED_BY_SURFACE) { 1138 return false; 1139 } 1140 } 1141 return true; 1142} 1143 1144bool HCodec::IsAllBufferOwnedByUsOrSurface() 1145{ 1146 return IsAllBufferOwnedByUsOrSurface(OMX_DirInput) && 1147 IsAllBufferOwnedByUsOrSurface(OMX_DirOutput); 1148} 1149 1150void HCodec::ClearBufferPool(OMX_DIRTYPE portIndex) 1151{ 1152 const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1153 for (size_t i = pool.size(); i > 0;) { 1154 i--; 1155 EraseBufferFromPool(portIndex, i); 1156 } 1157 OnClearBufferPool(portIndex); 1158} 1159 1160void HCodec::FreeOmxBuffer(OMX_DIRTYPE portIndex, const BufferInfo& info) 1161{ 1162 if (compNode_ && info.omxBuffer) { 1163 int32_t omxRet = compNode_->FreeBuffer(portIndex, *(info.omxBuffer)); 1164 if (omxRet != HDF_SUCCESS) { 1165 HLOGW("notify omx to free buffer failed"); 1166 } 1167 } 1168} 1169 1170void HCodec::EraseOutBuffersOwnedByUsOrSurface() 1171{ 1172 // traverse index in reverse order because we need to erase index from vector 1173 for (size_t i = outputBufferPool_.size(); i > 0;) { 1174 i--; 1175 const BufferInfo& info = outputBufferPool_[i]; 1176 if (info.owner == BufferOwner::OWNED_BY_US || info.owner == BufferOwner::OWNED_BY_SURFACE) { 1177 EraseBufferFromPool(OMX_DirOutput, i); 1178 } 1179 } 1180} 1181 1182void HCodec::OnSetOutputSurface(const MsgInfo &msg, BufferOperationMode mode) 1183{ 1184 (void)msg; 1185 (void)mode; 1186 ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT); 1187} 1188 1189int32_t HCodec::ForceShutdown(int32_t generation, bool isNeedNotifyCaller) 1190{ 1191 if (generation != stateGeneration_) { 1192 HLOGE("ignoring stale force shutdown message: #%d (now #%d)", 1193 generation, stateGeneration_); 1194 return AVCS_ERR_OK; 1195 } 1196 HLOGI("force to shutdown"); 1197 isShutDownFromRunning_ = true; 1198 notifyCallerAfterShutdownComplete_ = isNeedNotifyCaller; 1199 keepComponentAllocated_ = false; 1200 auto err = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {}); 1201 if (err == HDF_SUCCESS) { 1202 ChangeStateTo(stoppingState_); 1203 } 1204 return AVCS_ERR_OK; 1205} 1206 1207void HCodec::SignalError(AVCodecErrorType errorType, int32_t errorCode) 1208{ 1209 HLOGE("fatal error happened: errType=%d, errCode=%d", errorType, errorCode); 1210 hasFatalError_ = true; 1211 callback_->OnError(errorType, errorCode); 1212} 1213 1214int32_t HCodec::DoSyncCall(MsgWhat msgType, std::function<void(ParamSP)> oper) 1215{ 1216 ParamSP reply; 1217 return DoSyncCallAndGetReply(msgType, oper, reply); 1218} 1219 1220int32_t HCodec::DoSyncCallAndGetReply(MsgWhat msgType, std::function<void(ParamSP)> oper, ParamSP &reply) 1221{ 1222 ParamSP msg = make_shared<ParamBundle>(); 1223 IF_TRUE_RETURN_VAL_WITH_MSG(msg == nullptr, AVCS_ERR_NO_MEMORY, "out of memory"); 1224 if (oper) { 1225 oper(msg); 1226 } 1227 bool ret = MsgHandleLoop::SendSyncMsg(msgType, msg, reply, FIVE_SECONDS_IN_MS); 1228 if (!ret) { 1229 HLOGE("wait msg %d(%s) time out", msgType, ToString(msgType)); 1230 return AVCS_ERR_UNKNOWN; 1231 } 1232 int32_t err; 1233 IF_TRUE_RETURN_VAL_WITH_MSG(reply == nullptr || !reply->GetValue("err", err), 1234 AVCS_ERR_UNKNOWN, "error code of msg %d not replied", msgType); 1235 return err; 1236} 1237 1238void HCodec::DeferMessage(const MsgInfo &info) 1239{ 1240 deferredQueue_.push_back(info); 1241} 1242 1243void HCodec::ProcessDeferredMessages() 1244{ 1245 for (const MsgInfo &info : deferredQueue_) { 1246 StateMachine::OnMsgReceived(info); 1247 } 1248 deferredQueue_.clear(); 1249} 1250 1251void HCodec::ReplyToSyncMsgLater(const MsgInfo& msg) 1252{ 1253 syncMsgToReply_[msg.type].push(std::make_pair(msg.id, msg.param)); 1254} 1255 1256bool HCodec::GetFirstSyncMsgToReply(MsgInfo& msg) 1257{ 1258 auto iter = syncMsgToReply_.find(msg.type); 1259 if (iter == syncMsgToReply_.end()) { 1260 return false; 1261 } 1262 std::tie(msg.id, msg.param) = iter->second.front(); 1263 iter->second.pop(); 1264 return true; 1265} 1266 1267void HCodec::ReplyErrorCode(MsgId id, int32_t err) 1268{ 1269 if (id == ASYNC_MSG_ID) { 1270 return; 1271 } 1272 ParamSP reply = make_shared<ParamBundle>(); 1273 reply->SetValue("err", err); 1274 PostReply(id, reply); 1275} 1276 1277void HCodec::ChangeOmxToTargetState(CodecStateType &state, CodecStateType targetState) 1278{ 1279 int32_t ret = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, targetState, {}); 1280 if (ret != HDF_SUCCESS) { 1281 HLOGE("failed to change omx state, ret=%d", ret); 1282 return; 1283 } 1284 1285 int tryCnt = 0; 1286 do { 1287 if (tryCnt++ > 10) { // try up to 10 times 1288 HLOGE("failed to change to state(%d), abort", targetState); 1289 state = CODEC_STATE_INVALID; 1290 break; 1291 } 1292 this_thread::sleep_for(10ms); // wait 10ms 1293 ret = compNode_->GetState(state); 1294 if (ret != HDF_SUCCESS) { 1295 HLOGE("failed to get omx state, ret=%d", ret); 1296 } 1297 } while (ret == HDF_SUCCESS && state != targetState && state != CODEC_STATE_INVALID); 1298} 1299 1300bool HCodec::RollOmxBackToLoaded() 1301{ 1302 CodecStateType state; 1303 int32_t ret = compNode_->GetState(state); 1304 if (ret != HDF_SUCCESS) { 1305 HLOGE("failed to get omx node status(ret=%d), can not perform state rollback", ret); 1306 return false; 1307 } 1308 HLOGI("current omx state (%d)", state); 1309 switch (state) { 1310 case CODEC_STATE_EXECUTING: { 1311 ChangeOmxToTargetState(state, CODEC_STATE_IDLE); 1312 [[fallthrough]]; 1313 } 1314 case CODEC_STATE_IDLE: { 1315 ChangeOmxToTargetState(state, CODEC_STATE_LOADED); 1316 [[fallthrough]]; 1317 } 1318 case CODEC_STATE_LOADED: 1319 case CODEC_STATE_INVALID: { 1320 return true; 1321 } 1322 default: { 1323 HLOGE("invalid omx state: %d", state); 1324 return false; 1325 } 1326 } 1327} 1328 1329void HCodec::CleanUpOmxNode() 1330{ 1331 if (compNode_ == nullptr) { 1332 return; 1333 } 1334 1335 if (RollOmxBackToLoaded()) { 1336 for (const BufferInfo& info : inputBufferPool_) { 1337 FreeOmxBuffer(OMX_DirInput, info); 1338 } 1339 for (const BufferInfo& info : outputBufferPool_) { 1340 FreeOmxBuffer(OMX_DirOutput, info); 1341 } 1342 } 1343} 1344 1345int32_t HCodec::OnAllocateComponent() 1346{ 1347 HitraceScoped trace(HITRACE_TAG_ZMEDIA, "hcodec_AllocateComponent_" + caps_.compName); 1348 compMgr_ = GetManager(false, caps_.port.video.isSupportPassthrough, isSecure_); 1349 if (compMgr_ == nullptr) { 1350 HLOGE("GetCodecComponentManager failed"); 1351 return AVCS_ERR_UNKNOWN; 1352 } 1353 compCb_ = new HdiCallback(weak_from_this()); 1354 int32_t ret = compMgr_->CreateComponent(compNode_, componentId_, caps_.compName, 0, compCb_); 1355 if (ret != HDF_SUCCESS || compNode_ == nullptr) { 1356 compCb_ = nullptr; 1357 compMgr_ = nullptr; 1358 HLOGE("CreateComponent failed, ret=%d", ret); 1359 return AVCS_ERR_UNKNOWN; 1360 } 1361 compUniqueStr_ = "[" + to_string(componentId_) + "][" + shortName_ + "]"; 1362 inputOwnerStr_ = { compUniqueStr_ + "in_us", compUniqueStr_ + "in_user", 1363 compUniqueStr_ + "in_omx", compUniqueStr_ + "in_surface"}; 1364 outputOwnerStr_ = { compUniqueStr_ + "out_us", compUniqueStr_ + "out_user", 1365 compUniqueStr_ + "out_omx", compUniqueStr_ + "out_surface"}; 1366 HLOGI("create omx node %s succ", caps_.compName.c_str()); 1367 PrintCaller(); 1368 return AVCS_ERR_OK; 1369} 1370 1371void HCodec::ReleaseComponent() 1372{ 1373 CleanUpOmxNode(); 1374 if (compMgr_ != nullptr) { 1375 compMgr_->DestroyComponent(componentId_); 1376 } 1377 compNode_ = nullptr; 1378 compCb_ = nullptr; 1379 compMgr_ = nullptr; 1380 componentId_ = 0; 1381} 1382 1383const char* HCodec::ToString(MsgWhat what) 1384{ 1385 static const map<MsgWhat, const char*> m = { 1386 { INIT, "INIT" }, { SET_CALLBACK, "SET_CALLBACK" }, { CONFIGURE, "CONFIGURE" }, 1387 { CREATE_INPUT_SURFACE, "CREATE_INPUT_SURFACE" }, { SET_INPUT_SURFACE, "SET_INPUT_SURFACE" }, 1388 { SET_OUTPUT_SURFACE, "SET_OUTPUT_SURFACE" }, { START, "START" }, 1389 { GET_INPUT_FORMAT, "GET_INPUT_FORMAT" }, { GET_OUTPUT_FORMAT, "GET_OUTPUT_FORMAT" }, 1390 { SET_PARAMETERS, "SET_PARAMETERS" }, { REQUEST_IDR_FRAME, "REQUEST_IDR_FRAME" }, 1391 { FLUSH, "FLUSH" }, { QUEUE_INPUT_BUFFER, "QUEUE_INPUT_BUFFER" }, 1392 { NOTIFY_EOS, "NOTIFY_EOS" }, { RELEASE_OUTPUT_BUFFER, "RELEASE_OUTPUT_BUFFER" }, 1393 { RENDER_OUTPUT_BUFFER, "RENDER_OUTPUT_BUFFER" }, { STOP, "STOP" }, { RELEASE, "RELEASE" }, 1394 { CODEC_EVENT, "CODEC_EVENT" }, { OMX_EMPTY_BUFFER_DONE, "OMX_EMPTY_BUFFER_DONE" }, 1395 { OMX_FILL_BUFFER_DONE, "OMX_FILL_BUFFER_DONE" }, { GET_BUFFER_FROM_SURFACE, "GET_BUFFER_FROM_SURFACE" }, 1396 { CHECK_IF_STUCK, "CHECK_IF_STUCK" }, { FORCE_SHUTDOWN, "FORCE_SHUTDOWN" }, 1397 }; 1398 auto it = m.find(what); 1399 if (it != m.end()) { 1400 return it->second; 1401 } 1402 return "UNKNOWN"; 1403} 1404} // namespace OHOS::MediaAVCodec