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