1 /*
2  * Copyright (c) 2023-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 #if defined(VIDEO_SUPPORT)
16 
17 #define HST_LOG_TAG "CodecBufferPool"
18 
19 #include "codec_buffer_pool.h"
20 #include "codec_utils.h"
21 #include "foundation/log.h"
22 #include "hdf_base.h"
23 
24 namespace OHOS {
25 namespace Media {
26 namespace Plugin {
27 namespace CodecAdapter {
CodecBufferPool(CodecComponentType * compType,CompVerInfo & verInfo,uint32_t portIndex,uint32_t bufferCnt)28 CodecBufferPool::CodecBufferPool(CodecComponentType* compType, CompVerInfo& verInfo,
29     uint32_t portIndex, uint32_t bufferCnt)
30     : codecComp_(compType), verInfo_(verInfo), portIndex_(portIndex), freeBufferId_("hdiFreeBufferId", bufferCnt)
31 {
32 }
33 
34 // 当前实现仅仅支持异步模式,hdi的工作模式决定了仅支持异步,要求提前将所有 out buffer 配置好
UseBuffers(OHOS::Media::BlockingQueue<std::shared_ptr<Buffer>> & bufQue,MemoryType bufMemType,bool isInput,uint32_t bufferSize)35 Status CodecBufferPool::UseBuffers(OHOS::Media::BlockingQueue<std::shared_ptr<Buffer>>& bufQue, MemoryType bufMemType,
36                                    bool isInput, uint32_t bufferSize)
37 {
38     MEDIA_LOG_D("UseBuffers begin");
39     FALSE_RETURN_V_MSG_E(ConfigBufType(bufMemType, isInput) == Status::OK, Status::ERROR_INVALID_DATA,
40                          "ConfigBufType failed");
41     auto count = bufQue.Size();
42     for (uint32_t i = 0; i < count; i++) {
43         auto pluginBuffer = bufQue.Pop();
44         auto codecBuffer = std::make_shared<CodecBuffer>(pluginBuffer, verInfo_, isInput, bufferSize, bufMemType);
45         FALSE_RETURN_V_MSG(codecBuffer != nullptr, Status::ERROR_NULL_POINTER, "Create codec buffer failed");
46         auto err = codecComp_->UseBuffer(codecComp_, portIndex_, codecBuffer->GetOmxBuffer().get());
47         if (err != HDF_SUCCESS) {
48             MEDIA_LOG_E("failed to UseBuffer");
49             return Status::ERROR_INVALID_DATA;
50         }
51         MEDIA_LOG_D("UseBuffer returned bufferID: " PUBLIC_LOG_U32 ", PortIndex: " PUBLIC_LOG_U32,
52                     codecBuffer->GetBufferId(), portIndex_);
53         codecBufMap_.emplace(codecBuffer->GetBufferId(), codecBuffer);
54         freeBufferId_.Push(codecBuffer->GetBufferId());
55     }
56     MEDIA_LOG_D("UseBuffers end, freeBufId.size: " PUBLIC_LOG_ZU ", portIndex: " PUBLIC_LOG_U32,
57                 freeBufferId_.Size(), portIndex_);
58     return Status::OK;
59 }
60 
FreeBuffers()61 Status CodecBufferPool::FreeBuffers()
62 {
63     MEDIA_LOG_D("FreeBuffers begin");
64     for (auto& codecBuf : codecBufMap_) {
65         auto& codecBuffer = codecBuf.second;
66         FALSE_RETURN_V_MSG_E(codecComp_ != nullptr, Status::ERROR_NULL_POINTER, "Codec component is null.");
67         FALSE_RETURN_V_MSG_E(codecBuffer != nullptr, Status::ERROR_NULL_POINTER, "Codec buffer is null.");
68         auto omxBuffer = codecBuffer->GetOmxBuffer().get();
69         FALSE_RETURN_V_MSG_E(omxBuffer != nullptr, Status::ERROR_NULL_POINTER, "Omx buffer is null.");
70         auto ret = codecComp_->FreeBuffer(codecComp_, portIndex_, omxBuffer);
71         FALSE_RETURN_V_MSG_E(ret == HDF_SUCCESS, TransHdiRetVal2Status(ret),
72             "codec component free buffer failed, omxBufId: " PUBLIC_LOG_U32, codecBuffer->GetBufferId());
73     }
74     codecBufMap_.clear();
75     freeBufferId_.Clear();
76     MEDIA_LOG_D("FreeBuffers end");
77     return Status::OK;
78 }
79 
ConfigBufType(const MemoryType & bufMemType,bool isInput)80 Status CodecBufferPool::ConfigBufType(const MemoryType& bufMemType, bool isInput)
81 {
82     if (bufMemType == MemoryType::SHARE_MEMORY) {
83         return Status::OK;
84     }
85     UseBufferType bufType{};
86     InitHdiParam(bufType, verInfo_);
87     bufType.portIndex = portIndex_;
88     bufType.bufferType = GetOmxBufferType(bufMemType, isInput);
89     auto ret = codecComp_->SetParameter(codecComp_, OMX_IndexParamUseBufferType, (int8_t *)&bufType, sizeof(bufType));
90     FALSE_LOG_MSG(ret == HDF_SUCCESS, "isInput: " PUBLIC_LOG_D32 ", bufferTypes: " PUBLIC_LOG_D32 ", ret: "
91             PUBLIC_LOG_S, static_cast<int32_t>(isInput), bufType.bufferType, OmxErrorType2String(ret).c_str());
92     MEDIA_LOG_D("ConfigOutPortBufType end");
93     return TransHdiRetVal2Status(ret);
94 }
95 
EmptyBufferCount()96 uint32_t CodecBufferPool::EmptyBufferCount()
97 {
98     OSAL::ScopedLock lock(mutex_);
99     return freeBufferId_.Size();
100 }
101 
UseBufferDone(uint32_t bufId)102 Status CodecBufferPool::UseBufferDone(uint32_t bufId)
103 {
104     OSAL::ScopedLock lock(mutex_);
105     freeBufferId_.Push(bufId);
106     return Status::OK;
107 }
108 
GetBuffer(int32_t bufferId)109 std::shared_ptr<CodecBuffer> CodecBufferPool::GetBuffer(int32_t bufferId)
110 {
111     OSAL::ScopedLock lock(mutex_);
112     auto bufId = bufferId >= 0 ? static_cast<uint32_t>(bufferId) : freeBufferId_.Pop(1);
113     return codecBufMap_.count(bufId) ? codecBufMap_[bufId] : nullptr;
114 }
115 } // namespace CodecAdapter
116 } // namespace Plugin
117 } // namespace Media
118 } // namespace OHOS
119 #endif