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