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