• 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 "utils/hdf_base.h"
19 #include "codec_omx_ext.h"
20 #include "media_description.h"  // foundation/multimedia/av_codec/interfaces/inner_api/native/
21 #include "sync_fence.h"  // foundation/graphic/graphic_2d/utils/sync_fence/export/
22 #include "OMX_VideoExt.h"
23 #include "hcodec_log.h"
24 #include "type_converter.h"
25 #include "surface_buffer.h"
26 
27 namespace OHOS::MediaAVCodec {
28 using namespace std;
29 using namespace OHOS::HDI::Codec::V2_0;
30 
OnConfigure(const Format & format)31 int32_t HDecoder::OnConfigure(const Format &format)
32 {
33     configFormat_ = make_shared<Format>(format);
34 
35     UseBufferType useBufferTypes;
36     InitOMXParamExt(useBufferTypes);
37     useBufferTypes.portIndex = OMX_DirOutput;
38     useBufferTypes.bufferType = CODEC_BUFFER_TYPE_HANDLE;
39     if (!SetParameter(OMX_IndexParamUseBufferType, useBufferTypes)) {
40         HLOGE("component don't support CODEC_BUFFER_TYPE_HANDLE");
41         return AVCS_ERR_INVALID_VAL;
42     }
43 
44     SaveTransform(format);
45     SaveScaleMode(format);
46     (void)SetProcessName(format);
47     (void)SetFrameRateAdaptiveMode(format);
48     return SetupPort(format);
49 }
50 
SetupPort(const Format & format)51 int32_t HDecoder::SetupPort(const Format &format)
52 {
53     int32_t width;
54     if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width) || width <= 0) {
55         HLOGE("format should contain width");
56         return AVCS_ERR_INVALID_VAL;
57     }
58     int32_t height;
59     if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height) || height <= 0) {
60         HLOGE("format should contain height");
61         return AVCS_ERR_INVALID_VAL;
62     }
63     HLOGI("user set width %{public}d, height %{public}d", width, height);
64     if (!GetPixelFmtFromUser(format)) {
65         return AVCS_ERR_INVALID_VAL;
66     }
67 
68     optional<double> frameRate = GetFrameRateFromUser(format);
69     if (!frameRate.has_value()) {
70         HLOGI("user don't set valid frame rate, use default 30.0");
71         frameRate = 30.0;  // default frame rate 30.0
72     }
73 
74     PortInfo inputPortInfo {static_cast<uint32_t>(width), static_cast<uint32_t>(height),
75                             codingType_, std::nullopt, frameRate.value()};
76     int32_t maxInputSize = 0;
77     (void)format.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize);
78     if (maxInputSize > 0) {
79         inputPortInfo.inputBufSize = static_cast<uint32_t>(maxInputSize);
80     }
81     int32_t ret = SetVideoPortInfo(OMX_DirInput, inputPortInfo);
82     if (ret != AVCS_ERR_OK) {
83         return ret;
84     }
85 
86     PortInfo outputPortInfo = {static_cast<uint32_t>(width), static_cast<uint32_t>(height),
87                                OMX_VIDEO_CodingUnused, configuredFmt_, frameRate.value()};
88     ret = SetVideoPortInfo(OMX_DirOutput, outputPortInfo);
89     if (ret != AVCS_ERR_OK) {
90         return ret;
91     }
92 
93     return AVCS_ERR_OK;
94 }
95 
UpdateInPortFormat()96 int32_t HDecoder::UpdateInPortFormat()
97 {
98     OMX_PARAM_PORTDEFINITIONTYPE def;
99     InitOMXParam(def);
100     def.nPortIndex = OMX_DirInput;
101     if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
102         HLOGE("get input port definition failed");
103         return AVCS_ERR_UNKNOWN;
104     }
105     PrintPortDefinition(def);
106     if (inputFormat_ == nullptr) {
107         inputFormat_ = make_shared<Format>();
108     }
109     inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, def.format.video.nFrameWidth);
110     inputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, def.format.video.nFrameHeight);
111     return AVCS_ERR_OK;
112 }
113 
UpdateConfiguredFmt(OMX_COLOR_FORMATTYPE portFmt)114 bool HDecoder::UpdateConfiguredFmt(OMX_COLOR_FORMATTYPE portFmt)
115 {
116     auto graphicFmt = static_cast<GraphicPixelFormat>(portFmt);
117     if (graphicFmt != configuredFmt_.graphicFmt) {
118         optional<PixelFmt> fmt = TypeConverter::GraphicFmtToFmt(graphicFmt);
119         if (!fmt.has_value()) {
120             return false;
121         }
122         HLOGI("GraphicPixelFormat need update: configured(%{public}s) -> portdefinition(%{public}s)",
123             configuredFmt_.strFmt.c_str(), fmt->strFmt.c_str());
124         configuredFmt_ = fmt.value();
125     }
126     return true;
127 }
128 
UpdateOutPortFormat()129 int32_t HDecoder::UpdateOutPortFormat()
130 {
131     OMX_PARAM_PORTDEFINITIONTYPE def;
132     InitOMXParam(def);
133     def.nPortIndex = OMX_DirOutput;
134     if (!GetParameter(OMX_IndexParamPortDefinition, def)) {
135         HLOGE("get output port definition failed");
136         return AVCS_ERR_UNKNOWN;
137     }
138     PrintPortDefinition(def);
139     if (def.nBufferCountActual == 0) {
140         HLOGE("invalid bufferCount");
141         return AVCS_ERR_UNKNOWN;
142     }
143     (void)UpdateConfiguredFmt(def.format.video.eColorFormat);
144 
145     uint32_t w = def.format.video.nFrameWidth;
146     uint32_t h = def.format.video.nFrameHeight;
147 
148     // save into member variable
149     GetCropFromOmx(w, h);
150     outBufferCnt_ = def.nBufferCountActual;
151     requestCfg_.timeout = 0;
152     requestCfg_.width = flushCfg_.damage.w;
153     requestCfg_.height = flushCfg_.damage.h;
154     requestCfg_.strideAlignment = STRIDE_ALIGNMENT;
155     requestCfg_.format = configuredFmt_.graphicFmt;
156     requestCfg_.usage = GetProducerUsage();
157 
158     // save into format
159     if (outputFormat_ == nullptr) {
160         outputFormat_ = make_shared<Format>();
161     }
162     if (!outputFormat_->ContainKey(MediaDescriptionKey::MD_KEY_WIDTH)) {
163         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, w);
164     }
165     if (!outputFormat_->ContainKey(MediaDescriptionKey::MD_KEY_HEIGHT)) {
166         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, h);
167     }
168     outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_WIDTH, flushCfg_.damage.w);
169     outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_HEIGHT, flushCfg_.damage.h);
170     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT,
171         static_cast<int32_t>(configuredFmt_.innerFmt));
172     HLOGI("output format: %{public}s", outputFormat_->Stringify().c_str());
173     return AVCS_ERR_OK;
174 }
175 
UpdateColorAspects()176 void HDecoder::UpdateColorAspects()
177 {
178     CodecVideoColorspace param;
179     InitOMXParamExt(param);
180     param.portIndex = OMX_DirOutput;
181     if (!GetParameter(OMX_IndexColorAspects, param, true)) {
182         return;
183     }
184     HLOGI("range:%{public}d, primary:%{public}d, transfer:%{public}d, matrix:%{public}d)",
185         param.aspects.range, param.aspects.primaries, param.aspects.transfer, param.aspects.matrixCoeffs);
186     if (outputFormat_) {
187         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, param.aspects.range);
188         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, param.aspects.primaries);
189         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, param.aspects.transfer);
190         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, param.aspects.matrixCoeffs);
191         HLOGI("output format changed: %{public}s", outputFormat_->Stringify().c_str());
192         callback_->OnOutputFormatChanged(*(outputFormat_.get()));
193     }
194 }
195 
GetCropFromOmx(uint32_t w,uint32_t h)196 void HDecoder::GetCropFromOmx(uint32_t w, uint32_t h)
197 {
198     flushCfg_.damage.x = 0;
199     flushCfg_.damage.y = 0;
200     flushCfg_.damage.w = w;
201     flushCfg_.damage.h = h;
202 
203     OMX_CONFIG_RECTTYPE rect;
204     InitOMXParam(rect);
205     rect.nPortIndex = OMX_DirOutput;
206     if (!GetParameter(OMX_IndexConfigCommonOutputCrop, rect, true)) {
207         HLOGW("get crop failed, use default");
208         return;
209     }
210     if (rect.nLeft < 0 || rect.nTop < 0 ||
211         rect.nWidth == 0 || rect.nHeight == 0 ||
212         rect.nLeft + rect.nWidth > w ||
213         rect.nTop + rect.nHeight > h) {
214         HLOGW("wrong crop rect (%{public}d, %{public}d, %{public}u, %{public}u) vs. frame (%{public}u," \
215               "%{public}u), use default", rect.nLeft, rect.nTop, rect.nWidth, rect.nHeight, w, h);
216         return;
217     }
218     HLOGI("crop rect (%{public}d, %{public}d, %{public}u, %{public}u)",
219           rect.nLeft, rect.nTop, rect.nWidth, rect.nHeight);
220     flushCfg_.damage.x = rect.nLeft;
221     flushCfg_.damage.y = rect.nTop;
222     flushCfg_.damage.w = rect.nWidth;
223     flushCfg_.damage.h = rect.nHeight;
224 }
225 
OnSetOutputSurface(const sptr<Surface> & surface)226 int32_t HDecoder::OnSetOutputSurface(const sptr<Surface> &surface)
227 {
228     if (surface == nullptr) {
229         HLOGE("surface is null");
230         return AVCS_ERR_INVALID_VAL;
231     }
232     if (surface->IsConsumer()) {
233         HLOGE("expect a producer surface but got a consumer surface");
234         return AVCS_ERR_INVALID_VAL;
235     }
236     std::weak_ptr<HDecoder> weakThis = weak_from_this();
237     GSError err = surface->RegisterReleaseListener([weakThis](sptr<SurfaceBuffer> &buffer) {
238         std::shared_ptr<HDecoder> decoder = weakThis.lock();
239         if (decoder == nullptr) {
240             LOGI("decoder is gone");
241             return GSERROR_OK;
242         }
243         return decoder->OnBufferReleasedByConsumer(buffer);
244     });
245     if (err != GSERROR_OK) {
246         HLOGE("RegisterReleaseListener failed, GSError=%{public}d", err);
247         return AVCS_ERR_UNKNOWN;
248     }
249     outputSurface_ = surface;
250     originalTransform_ = surface->GetTransform();
251     HLOGI("set surface (%{public}s) succ", surface->GetName().c_str());
252     return AVCS_ERR_OK;
253 }
254 
OnSetParameters(const Format & format)255 int32_t HDecoder::OnSetParameters(const Format &format)
256 {
257     int32_t ret = SaveTransform(format, true);
258     if (ret != AVCS_ERR_OK) {
259         return ret;
260     }
261     ret = SaveScaleMode(format, true);
262     if (ret != AVCS_ERR_OK) {
263         return ret;
264     }
265     return AVCS_ERR_OK;
266 }
267 
SaveTransform(const Format & format,bool set)268 int32_t HDecoder::SaveTransform(const Format &format, bool set)
269 {
270     int32_t rotate;
271     if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, rotate)) {
272         return AVCS_ERR_OK;
273     }
274     optional<GraphicTransformType> transform = TypeConverter::InnerRotateToDisplayRotate(
275         static_cast<VideoRotation>(rotate));
276     if (!transform.has_value()) {
277         return AVCS_ERR_INVALID_VAL;
278     }
279     HLOGI("VideoRotation = %{public}d, GraphicTransformType = %{public}d", rotate, transform.value());
280     transform_ = transform.value();
281     if (set) {
282         return SetTransform();
283     }
284     return AVCS_ERR_OK;
285 }
286 
SetTransform()287 int32_t HDecoder::SetTransform()
288 {
289     if (outputSurface_ == nullptr) {
290         return AVCS_ERR_INVALID_VAL;
291     }
292     GSError err = outputSurface_->SetTransform(transform_);
293     if (err != GSERROR_OK) {
294         HLOGW("set GraphicTransformType %{public}d to surface failed", transform_);
295         return AVCS_ERR_UNKNOWN;
296     }
297     HLOGI("set GraphicTransformType %{public}d to surface succ", transform_);
298     return AVCS_ERR_OK;
299 }
300 
SaveScaleMode(const Format & format,bool set)301 int32_t HDecoder::SaveScaleMode(const Format &format, bool set)
302 {
303     int scaleType;
304     if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, scaleType)) {
305         return AVCS_ERR_OK;
306     }
307     optional<ScalingMode> scaleMode = TypeConverter::InnerScaleToSurfaceScale(
308         static_cast<OHOS::Media::Plugins::VideoScaleType>(scaleType));
309     if (!scaleMode.has_value()) {
310         return AVCS_ERR_INVALID_VAL;
311     }
312     HLOGI("VideoScaleType = %{public}d, ScalingMode = %{public}d", scaleType, scaleMode.value());
313     scaleMode_ = scaleMode.value();
314     if (set) {
315         return SetScaleMode();
316     }
317     return AVCS_ERR_OK;
318 }
319 
SetScaleMode()320 int32_t HDecoder::SetScaleMode()
321 {
322     if (outputSurface_ == nullptr || !scaleMode_.has_value()) {
323         return AVCS_ERR_INVALID_VAL;
324     }
325     for (const BufferInfo& info : outputBufferPool_) {
326         if (info.surfaceBuffer == nullptr) {
327             continue;
328         }
329         GSError err = outputSurface_->SetScalingMode(info.surfaceBuffer->GetSeqNum(), scaleMode_.value());
330         if (err != GSERROR_OK) {
331             HLOGW("set ScalingMode %{public}d to surface failed", scaleMode_.value());
332             return AVCS_ERR_UNKNOWN;
333         }
334     }
335     return AVCS_ERR_OK;
336 }
337 
OnBufferReleasedByConsumer(sptr<SurfaceBuffer> & buffer)338 GSError HDecoder::OnBufferReleasedByConsumer(sptr<SurfaceBuffer> &buffer)
339 {
340     SendAsyncMsg(MsgWhat::GET_BUFFER_FROM_SURFACE, nullptr);
341     return GSERROR_OK;
342 }
343 
SubmitOutputBuffersToOmxNode()344 int32_t HDecoder::SubmitOutputBuffersToOmxNode()
345 {
346     for (BufferInfo& info : outputBufferPool_) {
347         switch (info.owner) {
348             case BufferOwner::OWNED_BY_US: {
349                 int32_t ret = NotifyOmxToFillThisOutBuffer(info);
350                 if (ret != AVCS_ERR_OK) {
351                     return ret;
352                 }
353                 continue;
354             }
355             case BufferOwner::OWNED_BY_SURFACE: {
356                 continue;
357             }
358             case BufferOwner::OWNED_BY_OMX: {
359                 continue;
360             }
361             default: {
362                 HLOGE("buffer id %{public}u has invalid owner %{public}d", info.bufferId, info.owner);
363                 return AVCS_ERR_UNKNOWN;
364             }
365         }
366     }
367     return AVCS_ERR_OK;
368 }
369 
ReadyToStart()370 bool HDecoder::ReadyToStart()
371 {
372     if (callback_ == nullptr || outputFormat_ == nullptr || inputFormat_ == nullptr) {
373         return false;
374     }
375     if (outputSurface_) {
376         HLOGI("surface mode");
377     } else {
378         HLOGI("buffer mode");
379     }
380     return true;
381 }
382 
AllocateBuffersOnPort(OMX_DIRTYPE portIndex)383 int32_t HDecoder::AllocateBuffersOnPort(OMX_DIRTYPE portIndex)
384 {
385     if (portIndex == OMX_DirInput) {
386         return AllocateAvLinearBuffers(portIndex);
387     }
388     int32_t ret = outputSurface_ ? AllocateOutputBuffersFromSurface() : AllocateAvSurfaceBuffers(portIndex);
389     if (ret == AVCS_ERR_OK) {
390         UpdateFormatFromSurfaceBuffer();
391     }
392     return ret;
393 }
394 
UpdateFormatFromSurfaceBuffer()395 void HDecoder::UpdateFormatFromSurfaceBuffer()
396 {
397     if (outputBufferPool_.empty()) {
398         return;
399     }
400     sptr<SurfaceBuffer> surfaceBuffer = outputBufferPool_.front().surfaceBuffer;
401     if (surfaceBuffer == nullptr) {
402         return;
403     }
404     outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_WIDTH, surfaceBuffer->GetWidth());
405     outputFormat_->PutIntValue(OHOS::Media::Tag::VIDEO_DISPLAY_HEIGHT, surfaceBuffer->GetHeight());
406     outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, surfaceBuffer->GetStride());
407 
408     OMX_PARAM_PORTDEFINITIONTYPE def;
409     int32_t ret = GetPortDefinition(OMX_DirOutput, def);
410     int32_t sliceHeight = static_cast<int32_t>(def.format.video.nSliceHeight);
411     if (ret == AVCS_ERR_OK && sliceHeight >= surfaceBuffer->GetHeight()) {
412         outputFormat_->PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, sliceHeight);
413     }
414 }
415 
SubmitAllBuffersOwnedByUs()416 int32_t HDecoder::SubmitAllBuffersOwnedByUs()
417 {
418     HLOGI(">>");
419     if (isBufferCirculating_) {
420         HLOGI("buffer is already circulating, no need to do again");
421         return AVCS_ERR_OK;
422     }
423     int32_t ret = SubmitOutputBuffersToOmxNode();
424     if (ret != AVCS_ERR_OK) {
425         return ret;
426     }
427     for (BufferInfo& info : inputBufferPool_) {
428         if (info.owner == BufferOwner::OWNED_BY_US) {
429             NotifyUserToFillThisInBuffer(info);
430         }
431     }
432     isBufferCirculating_ = true;
433     return AVCS_ERR_OK;
434 }
435 
EraseBufferFromPool(OMX_DIRTYPE portIndex,size_t i)436 void HDecoder::EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i)
437 {
438     vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_;
439     if (i >= pool.size()) {
440         return;
441     }
442     BufferInfo& info = pool[i];
443     if (portIndex == OMX_DirOutput && outputSurface_ &&
444         info.owner != BufferOwner::OWNED_BY_SURFACE) {
445         CancelBufferToSurface(info);
446     }
447     FreeOmxBuffer(portIndex, info);
448     pool.erase(pool.begin() + i);
449 }
450 
GetProducerUsage()451 uint64_t HDecoder::GetProducerUsage()
452 {
453     uint64_t producerUsage = outputSurface_ ? SURFACE_MODE_PRODUCER_USAGE : BUFFER_MODE_REQUEST_USAGE;
454 
455     GetBufferHandleUsageParams vendorUsage;
456     InitOMXParamExt(vendorUsage);
457     vendorUsage.portIndex = static_cast<uint32_t>(OMX_DirOutput);
458     if (GetParameter(OMX_IndexParamGetBufferHandleUsage, vendorUsage)) {
459         HLOGI("vendor producer usage = 0x%" PRIx64 "", vendorUsage.usage);
460         producerUsage |= vendorUsage.usage;
461     } else {
462         HLOGW("get vendor producer usage failed, add CPU_READ");
463         producerUsage |= BUFFER_USAGE_CPU_READ;
464     }
465     HLOGI("decoder producer usage = 0x%" PRIx64 "", producerUsage);
466     return producerUsage;
467 }
468 
CombineConsumerUsage()469 void HDecoder::CombineConsumerUsage()
470 {
471     uint32_t consumerUsage = outputSurface_->GetDefaultUsage();
472     uint64_t finalUsage = requestCfg_.usage | consumerUsage;
473     HLOGI("producer usage 0x%{public}" PRIx64 " | consumer usage 0x%{public}x -> 0x%{public}" PRIx64 "",
474         requestCfg_.usage, consumerUsage, finalUsage);
475     requestCfg_.usage = finalUsage;
476 }
477 
AllocateOutputBuffersFromSurface()478 int32_t HDecoder::AllocateOutputBuffersFromSurface()
479 {
480     GSError err = outputSurface_->CleanCache();
481     if (err != GSERROR_OK) {
482         HLOGW("clean cache failed");
483     }
484     err = outputSurface_->SetQueueSize(outBufferCnt_);
485     if (err != GSERROR_OK) {
486         HLOGE("set surface queue size failed");
487         return AVCS_ERR_INVALID_VAL;
488     }
489     if (!outputBufferPool_.empty()) {
490         HLOGW("output buffer pool should be empty");
491     }
492     outputBufferPool_.clear();
493     CombineConsumerUsage();
494     for (uint32_t i = 0; i < outBufferCnt_; ++i) {
495         sptr<SurfaceBuffer> surfaceBuffer;
496         sptr<SyncFence> fence;
497         err = outputSurface_->RequestBuffer(surfaceBuffer, fence, requestCfg_);
498         if (err != GSERROR_OK || surfaceBuffer == nullptr) {
499             HLOGE("RequestBuffer %{public}u failed, GSError=%{public}d", i, err);
500             return AVCS_ERR_UNKNOWN;
501         }
502         shared_ptr<OmxCodecBuffer> omxBuffer = SurfaceBufferToOmxBuffer(surfaceBuffer);
503         if (omxBuffer == nullptr) {
504             outputSurface_->CancelBuffer(surfaceBuffer);
505             return AVCS_ERR_UNKNOWN;
506         }
507         shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>();
508         int32_t ret = compNode_->UseBuffer(OMX_DirOutput, *omxBuffer, *outBuffer);
509         if (ret != HDF_SUCCESS) {
510             outputSurface_->CancelBuffer(surfaceBuffer);
511             HLOGE("Failed to UseBuffer with output port");
512             return AVCS_ERR_NO_MEMORY;
513         }
514         outBuffer->fenceFd = -1;
515         BufferInfo info {};
516         info.isInput = false;
517         info.owner = BufferOwner::OWNED_BY_US;
518         info.surfaceBuffer = surfaceBuffer;
519         info.avBuffer = AVBuffer::CreateAVBuffer();
520         info.omxBuffer = outBuffer;
521         info.bufferId = outBuffer->bufferId;
522         outputBufferPool_.push_back(info);
523     }
524     SetTransform();
525     SetScaleMode();
526     return AVCS_ERR_OK;
527 }
528 
CancelBufferToSurface(BufferInfo & info)529 void HDecoder::CancelBufferToSurface(BufferInfo& info)
530 {
531     HLOGD("outBufId = %{public}u", info.bufferId);
532     GSError ret = outputSurface_->CancelBuffer(info.surfaceBuffer);
533     if (ret != OHOS::GSERROR_OK) {
534         HLOGW("bufferId=%{public}u cancel failed, GSError=%{public}d", info.bufferId, ret);
535     }
536     ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE); // change owner even if cancel failed
537 }
538 
OnGetBufferFromSurface()539 void HDecoder::OnGetBufferFromSurface()
540 {
541     while (true) {
542         if (!GetOneBufferFromSurface()) {
543             break;
544         }
545     }
546 }
547 
GetOneBufferFromSurface()548 bool HDecoder::GetOneBufferFromSurface()
549 {
550     sptr<SurfaceBuffer> buffer;
551     sptr<SyncFence> fence;
552     GSError ret = outputSurface_->RequestBuffer(buffer, fence, requestCfg_);
553     if (ret != GSERROR_OK || buffer == nullptr) {
554         return false;
555     }
556     if (fence != nullptr && fence->IsValid()) {
557         int waitRes = fence->Wait(WAIT_FENCE_MS);
558         if (waitRes != 0) {
559             HLOGW("wait fence time out, cancel it");
560             outputSurface_->CancelBuffer(buffer);
561             return false;
562         }
563     }
564     for (BufferInfo& info : outputBufferPool_) {
565         if (info.owner == BufferOwner::OWNED_BY_SURFACE &&
566             info.surfaceBuffer->GetBufferHandle() == buffer->GetBufferHandle()) {
567             int32_t err = NotifyOmxToFillThisOutBuffer(info);
568             if (err == AVCS_ERR_OK) {
569                 return true;
570             }
571             break;
572         }
573     }
574     HLOGW("cannot find slot or submit to omx failed, cancel it");
575     outputSurface_->CancelBuffer(buffer);
576     return false;
577 }
578 
NotifySurfaceToRenderOutputBuffer(BufferInfo & info)579 int32_t HDecoder::NotifySurfaceToRenderOutputBuffer(BufferInfo &info)
580 {
581     flushCfg_.timestamp = info.omxBuffer->pts;
582     GSError ret = outputSurface_->FlushBuffer(info.surfaceBuffer, -1, flushCfg_);
583     if (ret != GSERROR_OK) {
584         HLOGE("FlushBuffer failed, GSError=%{public}d", ret);
585         return AVCS_ERR_UNKNOWN;
586     }
587     HLOGD("outBufId = %{public}u, render succ, pts = %{public}" PRId64 ", "
588         "[%{public}d %{public}d %{public}d %{public}d]", info.bufferId, flushCfg_.timestamp,
589         flushCfg_.damage.x, flushCfg_.damage.y, flushCfg_.damage.w, flushCfg_.damage.h);
590     ChangeOwner(info, BufferOwner::OWNED_BY_SURFACE);
591     return AVCS_ERR_OK;
592 }
593 
OnOMXEmptyBufferDone(uint32_t bufferId,BufferOperationMode mode)594 void HDecoder::OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode)
595 {
596     BufferInfo *info = FindBufferInfoByID(OMX_DirInput, bufferId);
597     if (info == nullptr) {
598         HLOGE("unknown buffer id %{public}u", bufferId);
599         return;
600     }
601     if (info->owner != BufferOwner::OWNED_BY_OMX) {
602         HLOGE("wrong ownership: buffer id=%{public}d, owner=%{public}s", bufferId, ToString(info->owner));
603         return;
604     }
605     ChangeOwner(*info, BufferOwner::OWNED_BY_US);
606 
607     switch (mode) {
608         case KEEP_BUFFER:
609             return;
610         case RESUBMIT_BUFFER: {
611             if (!inputPortEos_) {
612                 NotifyUserToFillThisInBuffer(*info);
613             }
614             return;
615         }
616         default: {
617             HLOGE("SHOULD NEVER BE HERE");
618             return;
619         }
620     }
621 }
622 
OnRenderOutputBuffer(const MsgInfo & msg,BufferOperationMode mode)623 void HDecoder::OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode)
624 {
625     if (outputSurface_ == nullptr) {
626         HLOGE("can only render in surface mode");
627         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_OPERATION);
628         return;
629     }
630     uint32_t bufferId;
631     (void)msg.param->GetValue(BUFFER_ID, bufferId);
632     optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId);
633     if (!idx.has_value()) {
634         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
635         return;
636     }
637     BufferInfo& info = outputBufferPool_[idx.value()];
638     if (info.owner != BufferOwner::OWNED_BY_USER) {
639         HLOGE("wrong ownership: buffer id=%{public}d, owner=%{public}s", bufferId, ToString(info.owner));
640         ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL);
641         return;
642     }
643     HLOGD("outBufId = %{public}u", info.bufferId);
644     ChangeOwner(info, BufferOwner::OWNED_BY_US);
645     ReplyErrorCode(msg.id, AVCS_ERR_OK);
646 
647     NotifySurfaceToRenderOutputBuffer(info);
648     if (mode == FREE_BUFFER) {
649         EraseBufferFromPool(OMX_DirOutput, idx.value());
650     }
651 }
652 
OnEnterUninitializedState()653 void HDecoder::OnEnterUninitializedState()
654 {
655     if (outputSurface_) {
656         outputSurface_->SetTransform(originalTransform_);
657         outputSurface_->UnRegisterReleaseListener();
658     }
659 }
660 } // namespace OHOS::MediaAVCodec