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