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