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