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