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