• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "hdi_buffer_mgr.h"
17 #include <hdf_base.h>
18 #include "hdi_codec_util.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 
22 namespace {
23     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "HdiBufferMgr"};
24 }
25 
26 namespace OHOS {
27 namespace Media {
HdiBufferMgr()28 HdiBufferMgr::HdiBufferMgr()
29 {
30     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
31 }
32 
~HdiBufferMgr()33 HdiBufferMgr::~HdiBufferMgr()
34 {
35     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
36     FreeBuffers();
37     ClearCodingBuffers();
38 }
39 
Start()40 int32_t HdiBufferMgr::Start()
41 {
42     MEDIA_LOGD("Enter Start");
43     std::unique_lock<std::mutex> lock(mutex_);
44     isStart_ = true;
45     isFlushed_ = false;
46     return GST_CODEC_OK;
47 }
48 
Init(CodecComponentType * handle,int32_t index,const CompVerInfo & verInfo)49 void HdiBufferMgr::Init(CodecComponentType *handle, int32_t index, const CompVerInfo &verInfo)
50 {
51     MEDIA_LOGD("Enter Init");
52     handle_ = handle;
53     verInfo_ = verInfo;
54     InitParam(mPortDef_, verInfo_);
55     mPortIndex_ = index;
56     mPortDef_.nPortIndex = (uint32_t)index;
57 }
58 
GetCodecBuffer(GstBuffer * buffer)59 std::shared_ptr<HdiBufferWrap> HdiBufferMgr::GetCodecBuffer(GstBuffer *buffer)
60 {
61     MEDIA_LOGD("Enter GetCodecBuffer");
62     std::shared_ptr<HdiBufferWrap> codecBuffer = nullptr;
63     GstBufferTypeMeta *bufferType = gst_buffer_get_buffer_type_meta(buffer);
64     CHECK_AND_RETURN_RET_LOG(bufferType != nullptr, nullptr, "bufferType is nullptr");
65     for (auto iter = availableBuffers_.begin(); iter != availableBuffers_.end(); ++iter) {
66         if (*iter != nullptr) {
67             if ((*iter)->buf == bufferType->buf) {
68                 codecBuffer = *iter;
69                 codingBuffers_.push_back(std::make_pair(codecBuffer, buffer));
70                 gst_buffer_ref(buffer);
71                 (void)availableBuffers_.erase(iter);
72                 UpdateCodecMeta(bufferType, codecBuffer);
73                 codecBuffer->hdiBuffer.pts = (int64_t)(GST_BUFFER_PTS(buffer));
74                 break;
75             }
76         }
77     }
78     return codecBuffer;
79 }
80 
UpdateCodecMeta(GstBufferTypeMeta * bufferType,std::shared_ptr<HdiBufferWrap> & codecBuffer)81 void HdiBufferMgr::UpdateCodecMeta(GstBufferTypeMeta *bufferType, std::shared_ptr<HdiBufferWrap> &codecBuffer)
82 {
83     MEDIA_LOGD("Enter UpdateCodecMeta");
84     CHECK_AND_RETURN_LOG(codecBuffer != nullptr, "bufferType is nullptr");
85     CHECK_AND_RETURN_LOG(bufferType != nullptr, "bufferType is nullptr");
86     codecBuffer->hdiBuffer.allocLen = bufferType->totalSize;
87     codecBuffer->hdiBuffer.offset = bufferType->offset;
88     codecBuffer->hdiBuffer.filledLen = bufferType->length;
89     codecBuffer->hdiBuffer.fenceFd = bufferType->fenceFd;
90     codecBuffer->hdiBuffer.type = bufferType->memFlag == FLAGS_READ_ONLY ? READ_ONLY_TYPE : READ_WRITE_TYPE;
91 }
92 
PreUseAshareMems(std::vector<GstBuffer * > & buffers)93 std::vector<std::shared_ptr<HdiBufferWrap>> HdiBufferMgr::PreUseAshareMems(std::vector<GstBuffer *> &buffers)
94 {
95     MEDIA_LOGD("Enter PreUseAshareMems");
96     std::vector<std::shared_ptr<HdiBufferWrap>> preBuffers;
97     auto ret = HdiGetParameter(handle_, OMX_IndexParamPortDefinition, mPortDef_);
98     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, preBuffers, "HdiGetParameter failed");
99     CHECK_AND_RETURN_RET_LOG(buffers.size() == mPortDef_.nBufferCountActual, preBuffers, "BufferNum error");
100     for (auto buffer : buffers) {
101         CHECK_AND_RETURN_RET_LOG(buffer != nullptr, preBuffers, "buffer is nullptr");
102         GstBufferTypeMeta *bufferType = gst_buffer_get_buffer_type_meta(buffer);
103         CHECK_AND_RETURN_RET_LOG(bufferType != nullptr, preBuffers, "bufferType is nullptr");
104         std::shared_ptr<HdiBufferWrap> codecBuffer = std::make_shared<HdiBufferWrap>();
105         codecBuffer->buf = bufferType->buf;
106         codecBuffer->hdiBuffer.size = sizeof(OmxCodecBuffer);
107         codecBuffer->hdiBuffer.version = verInfo_.compVersion;
108         codecBuffer->hdiBuffer.bufferType = CodecBufferType::CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
109         codecBuffer->hdiBuffer.bufferLen = bufferType->bufLen;
110         codecBuffer->hdiBuffer.buffer = reinterpret_cast<uint8_t *>(bufferType->buf);
111         codecBuffer->hdiBuffer.allocLen = bufferType->totalSize;
112         codecBuffer->hdiBuffer.offset = bufferType->offset;
113         codecBuffer->hdiBuffer.filledLen = bufferType->length;
114         codecBuffer->hdiBuffer.fenceFd = bufferType->fenceFd;
115         codecBuffer->hdiBuffer.flag = 0;
116         codecBuffer->hdiBuffer.type = bufferType->memFlag == FLAGS_READ_ONLY ? READ_ONLY_TYPE : READ_WRITE_TYPE;
117         preBuffers.push_back(codecBuffer);
118     }
119     return preBuffers;
120 }
121 
UseHdiBuffers(std::vector<std::shared_ptr<HdiBufferWrap>> & buffers)122 int32_t HdiBufferMgr::UseHdiBuffers(std::vector<std::shared_ptr<HdiBufferWrap>> &buffers)
123 {
124     MEDIA_LOGD("Enter UseHdiBuffers");
125     CHECK_AND_RETURN_RET_LOG(buffers.size() == mPortDef_.nBufferCountActual, GST_CODEC_ERROR, "BufferNum error");
126     for (auto buffer : buffers) {
127         CHECK_AND_RETURN_RET_LOG(buffer != nullptr, GST_CODEC_ERROR, "buffer is nullptr");
128         int32_t ret = HDF_SUCCESS;
129         LISTENER(ret = handle_->UseBuffer(handle_, (uint32_t)mPortIndex_, &buffer->hdiBuffer),
130             "Hdi::UseBuffer", PlayerXCollie::timerTimeout)
131         CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, GST_CODEC_ERROR, "UseBuffer failed");
132         MEDIA_LOGD("Enter buffer id %{public}d", buffer->hdiBuffer.bufferId);
133         availableBuffers_.push_back(buffer);
134     }
135     return GST_CODEC_OK;
136 }
137 
FreeCodecBuffers()138 void HdiBufferMgr::FreeCodecBuffers()
139 {
140     // Caller lock protection
141     MEDIA_LOGD("Enter FreeCodecBuffers");
142     for (auto codecBuffer : availableBuffers_) {
143         CHECK_AND_BREAK_LOG(!bufferReleased_, "bufferRleased!");
144         int32_t ret = HDF_SUCCESS;
145         LISTENER(ret = handle_->FreeBuffer(handle_, mPortIndex_, &codecBuffer->hdiBuffer),
146             "Hdi::FreeBuffer", PlayerXCollie::timerTimeout)
147         if (ret != HDF_SUCCESS) {
148             MEDIA_LOGE("free buffer %{public}u fail", codecBuffer->hdiBuffer.bufferId);
149         }
150     }
151     EmptyList(availableBuffers_);
152     MEDIA_LOGD("Enter FreeCodecBuffers End");
153 }
154 
Stop(bool isFormatChange)155 int32_t HdiBufferMgr::Stop(bool isFormatChange)
156 {
157     MEDIA_LOGD("Enter Stop");
158     std::unique_lock<std::mutex> lock(mutex_);
159     isStart_ = false;
160     isFormatChange_ = isFormatChange;
161     isFlushed_ = false;
162     bufferCond_.notify_all();
163     flushCond_.notify_all();
164     return GST_CODEC_OK;
165 }
166 
Flush(bool enable)167 int32_t HdiBufferMgr::Flush(bool enable)
168 {
169     MEDIA_LOGD("Enter Flush %{public}d", enable);
170     std::unique_lock<std::mutex> lock(mutex_);
171     isFlushing_ = enable;
172     if (isFlushing_) {
173         bufferCond_.notify_all();
174         isFlushed_ = true;
175     }
176     if (!isFlushing_) {
177         flushCond_.notify_all();
178     }
179     return GST_CODEC_OK;
180 }
181 
WaitFlushed()182 void HdiBufferMgr::WaitFlushed()
183 {
184     MEDIA_LOGD("Enter WaitFlushed");
185     std::unique_lock<std::mutex> lock(mutex_);
186     flushCond_.wait(lock, [this]() { return !isFlushing_ || !isStart_; });
187 }
188 
NotifyAvailable()189 void HdiBufferMgr::NotifyAvailable()
190 {
191     if (isStart_ == false && availableBuffers_.size() == mPortDef_.nBufferCountActual) {
192         freeCond_.notify_all();
193     }
194 }
195 
SetFlagToBuffer(GstBuffer * buffer,const uint32_t & flag)196 void HdiBufferMgr::SetFlagToBuffer(GstBuffer *buffer, const uint32_t &flag)
197 {
198     GstBufferTypeMeta *bufferType = gst_buffer_get_buffer_type_meta(buffer);
199     CHECK_AND_RETURN_LOG(bufferType != nullptr,
200         "bufferType is null, set flag %{public}d to gstbuffer fail", flag);
201     bufferType->bufferFlag = BUFFER_FLAG_NONE;
202     if (flag & OMX_BUFFERFLAG_EOS) {
203         bufferType->bufferFlag |= BUFFER_FLAG_EOS;
204     }
205     if (flag & OMX_BUFFERFLAG_SYNCFRAME) {
206         bufferType->bufferFlag |= BUFFER_FLAG_SYNC_FRAME;
207     }
208     if (flag & OMX_BUFFERFLAG_CODECCONFIG) {
209         bufferType->bufferFlag |= BUFFER_FLAG_CODEC_DATA;
210     }
211 }
212 
ClearCodingBuffers()213 void HdiBufferMgr::ClearCodingBuffers()
214 {
215     std::unique_lock<std::mutex> lock(mutex_);
216     MEDIA_LOGI("unref buffer %{public}zu", codingBuffers_.size());
217     for (auto iter = codingBuffers_.begin(); iter != codingBuffers_.end(); ++iter) {
218         gst_buffer_unref(iter->second);
219     }
220     codingBuffers_.clear();
221 }
222 
BufferReleased()223 void HdiBufferMgr::BufferReleased()
224 {
225     MEDIA_LOGI("Enter BufferReleased");
226     std::unique_lock<std::mutex> lock(mutex_);
227     bufferReleased_ = true;
228     isStart_ = false;
229     bufferCond_.notify_all();
230     flushCond_.notify_all();
231     freeCond_.notify_all();
232     preBufferCond_.notify_all();
233 }
234 }  // namespace Media
235 }  // namespace OHOS
236