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