• 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 <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