• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include "hdi_codec.h"
16 #include "avcodec_log.h"
17 #include <unistd.h>
18 
19 namespace {
20 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO, "AvCodec-HdiCodec"};
21 constexpr int TIMEOUT_MS = 1000;
22 using namespace OHOS::HDI::Codec::V4_0;
23 } // namespace
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Plugins {
28 namespace Hdi {
HdiCodec()29 HdiCodec::HdiCodec()
30     : componentId_(0),
31       componentName_(""),
32       compCb_(nullptr),
33       compNode_(nullptr),
34       compMgr_(nullptr),
35       outputOmxBuffer_(nullptr),
36       omxInBufferInfo_(std::make_shared<OmxBufferInfo>()),
37       omxOutBufferInfo_(std::make_shared<OmxBufferInfo>()),
38       event_(CODEC_EVENT_ERROR)
39 {
40 }
41 
InitComponent(const std::string & name)42 Status HdiCodec::InitComponent(const std::string &name)
43 {
44     compMgr_ = GetComponentManager();
45     CHECK_AND_RETURN_RET_LOG(compMgr_ != nullptr, Status::ERROR_NULL_POINTER, "GetCodecComponentManager failed!");
46 
47     componentName_ = name;
48     compCb_ = new HdiCodec::HdiCallback(shared_from_this());
49     int32_t ret = compMgr_->CreateComponent(compNode_, componentId_, componentName_, 0, compCb_);
50     if (ret != HDF_SUCCESS || compNode_ == nullptr) {
51         if (compCb_ != nullptr) {
52             compCb_ = nullptr;
53         }
54         compMgr_ = nullptr;
55         AVCODEC_LOGE("CreateComponent failed, ret=%{public}d", ret);
56         return Status::ERROR_NULL_POINTER;
57     }
58     return Status::OK;
59 }
60 
GetComponentManager()61 sptr<ICodecComponentManager> HdiCodec::GetComponentManager()
62 {
63     sptr<ICodecComponentManager> compMgr = ICodecComponentManager::Get(false); // false: ipc
64     return compMgr;
65 }
66 
GetCapabilityList()67 std::vector<CodecCompCapability> HdiCodec::GetCapabilityList()
68 {
69     CHECK_AND_RETURN_RET_LOG(compMgr_ != nullptr, {}, "compMgr is nullptr!");
70     int32_t compCount = 0;
71     int32_t ret = compMgr_->GetComponentNum(compCount);
72     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, {}, "GetComponentNum failed, ret=%{public}d", ret);
73     CHECK_AND_RETURN_RET_LOG(compCount > 0, {}, "GetComponentNum failed, compCount=%{public}d", compCount);
74 
75     std::vector<CodecCompCapability> capabilityList(compCount);
76     ret = compMgr_->GetComponentCapabilityList(capabilityList, compCount);
77     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, {}, "GetComponentCapabilityList failed, ret=%{public}d", ret);
78 
79     return capabilityList;
80 }
81 
IsSupportCodecType(const std::string & name,MediaAVCodec::CapabilityData * audioCapability)82 bool HdiCodec::IsSupportCodecType(const std::string &name, MediaAVCodec::CapabilityData *audioCapability)
83 {
84     if (compMgr_ == nullptr) {
85         compMgr_ = GetComponentManager();
86         CHECK_AND_RETURN_RET_LOG(compMgr_ != nullptr, false, "compMgr_ is null");
87     }
88 
89     std::vector<CodecCompCapability> capabilityList = GetCapabilityList();
90     CHECK_AND_RETURN_RET_LOG(!capabilityList.empty(), false, "Hdi capabilityList is empty!");
91 
92     bool checkName = std::any_of(std::begin(capabilityList),
93         std::end(capabilityList), [name, audioCapability](CodecCompCapability capability) {
94             if (capability.compName == name) {
95                 audioCapability->bitrate = MediaAVCodec::Range(capability.bitRate.min, capability.bitRate.max);
96                 audioCapability->sampleRate.push_back(capability.port.audio.sampleRate[0]); //set first number so far
97                 audioCapability->maxInstance = capability.maxInst;
98                 audioCapability->profiles.push_back(capability.supportProfiles[0]);
99                 audioCapability->channels = MediaAVCodec::Range(1, capability.port.audio.channelCount[0]);
100             }
101 
102         return capability.compName == name;
103     });
104     return checkName;
105 }
106 
InitParameter(AudioCodecOmxParam & param)107 void HdiCodec::InitParameter(AudioCodecOmxParam &param)
108 {
109     (void)memset_s(&param, sizeof(param), 0x0, sizeof(param));
110     param.size = sizeof(param);
111     param.version.s.nVersionMajor = 1;
112 }
113 
GetParameter(uint32_t index,AudioCodecOmxParam & param)114 Status HdiCodec::GetParameter(uint32_t index, AudioCodecOmxParam &param)
115 {
116     CHECK_AND_RETURN_RET_LOG(compNode_ != nullptr, Status::ERROR_NULL_POINTER, "compNode is nullptr!");
117     int8_t *p = reinterpret_cast<int8_t *>(&param);
118     std::vector<int8_t> inParamVec(p, p + sizeof(param));
119     std::vector<int8_t> outParamVec;
120     int32_t ret = compNode_->GetParameter(index, inParamVec, outParamVec);
121     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_INVALID_PARAMETER, "GetParameter failed!");
122     CHECK_AND_RETURN_RET_LOG(outParamVec.size() == sizeof(param), Status::ERROR_INVALID_PARAMETER,
123         "param size is invalid!");
124 
125     errno_t rc = memcpy_s(&param, sizeof(param), outParamVec.data(), outParamVec.size());
126     CHECK_AND_RETURN_RET_LOG(rc == EOK, Status::ERROR_INVALID_DATA, "memory copy failed!");
127     return Status::OK;
128 }
129 
SetParameter(uint32_t index,const std::vector<int8_t> & paramVec)130 Status HdiCodec::SetParameter(uint32_t index, const std::vector<int8_t> &paramVec)
131 {
132     CHECK_AND_RETURN_RET_LOG(compNode_ != nullptr, Status::ERROR_NULL_POINTER, "compNode is nullptr!");
133     int32_t ret = compNode_->SetParameter(index, paramVec);
134     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_INVALID_PARAMETER, "SetParameter failed!");
135     return Status::OK;
136 }
137 
InitBuffers(uint32_t bufferSize)138 Status HdiCodec::InitBuffers(uint32_t bufferSize)
139 {
140     Status ret;
141 
142     ret = InitBuffersByPort(PortIndex::INPUT_PORT, bufferSize);
143     CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret, "Init Input Buffers failed, ret=%{public}d", ret);
144     ret = InitBuffersByPort(PortIndex::OUTPUT_PORT, bufferSize);
145     CHECK_AND_RETURN_RET_LOG(ret == Status::OK, ret, "Init Output Buffers failed, ret=%{public}d", ret);
146 
147     return Status::OK;
148 }
149 
InitBuffersByPort(PortIndex portIndex,uint32_t bufferSize)150 Status HdiCodec::InitBuffersByPort(PortIndex portIndex, uint32_t bufferSize)
151 {
152     CHECK_AND_RETURN_RET_LOG(compNode_ != nullptr, Status::ERROR_NULL_POINTER, "compNode is nullptr!");
153     auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
154     std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator, bufferSize);
155     if (avBuffer == nullptr) {
156         AVCODEC_LOGE("Create avBuffer failed!");
157         return Status::ERROR_NO_MEMORY;
158     }
159     std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>();
160     omxBuffer->size = sizeof(OmxCodecBuffer);
161     omxBuffer->version.version.majorVersion = 1;
162     omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD;
163     omxBuffer->fd = avBuffer->memory_->GetFileDescriptor();
164     omxBuffer->bufferhandle = nullptr;
165     omxBuffer->allocLen = bufferSize;
166     omxBuffer->fenceFd = -1;
167     omxBuffer->pts = 0;
168     omxBuffer->flag = 0;
169 
170     if (portIndex == PortIndex::INPUT_PORT) {
171         omxBuffer->type = READ_ONLY_TYPE;
172     } else {
173         omxBuffer->type = READ_WRITE_TYPE;
174     }
175 
176     OmxCodecBuffer outBuffer;
177     int32_t ret = compNode_->UseBuffer(static_cast<uint32_t>(portIndex), *omxBuffer.get(), outBuffer);
178     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_NO_MEMORY,
179         "InitBuffers failed, ret=%{public}d", ret);
180 
181     omxBuffer->bufferId = outBuffer.bufferId;
182     if (portIndex == PortIndex::INPUT_PORT) {
183         std::unique_lock lock(inMutex_);
184         omxInBufferInfo_->omxBuffer = omxBuffer;
185         omxInBufferInfo_->avBuffer = avBuffer;
186     } else if (portIndex == PortIndex::OUTPUT_PORT) {
187         std::unique_lock lock(outMutex_);
188         omxOutBufferInfo_->omxBuffer = omxBuffer;
189         omxOutBufferInfo_->avBuffer = avBuffer;
190     }
191 
192     return Status::OK;
193 }
194 
SendCommand(CodecCommandType cmd,uint32_t param)195 Status HdiCodec::SendCommand(CodecCommandType cmd, uint32_t param)
196 {
197     std::unique_lock lock(inMutex_);
198     CHECK_AND_RETURN_RET_LOG(compNode_ != nullptr, Status::ERROR_NULL_POINTER, "compNode is nullptr!");
199     event_ = CODEC_EVENT_ERROR;
200     int32_t ret = compNode_->SendCommand(cmd, param, {});
201     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_INVALID_DATA, "SendCommand failed");
202 
203     condition_.wait_for(lock, std::chrono::milliseconds(TIMEOUT_MS),
204                         [this] { return event_ == CODEC_EVENT_CMD_COMPLETE; });
205     CHECK_AND_RETURN_RET_LOG(event_ == CODEC_EVENT_CMD_COMPLETE, Status::ERROR_INVALID_PARAMETER,
206         "SendCommand timeout!");
207 
208     return Status::OK;
209 }
210 
EmptyThisBuffer(const std::shared_ptr<AVBuffer> & buffer)211 Status HdiCodec::EmptyThisBuffer(const std::shared_ptr<AVBuffer> &buffer)
212 {
213     std::unique_lock lock(inMutex_);
214     CHECK_AND_RETURN_RET_LOG(compNode_ != nullptr, Status::ERROR_NULL_POINTER, "compNode is nullptr!");
215     omxInBufferInfo_->omxBuffer->filledLen = static_cast<uint32_t>(buffer->memory_->GetSize());
216     omxInBufferInfo_->omxBuffer->offset = static_cast<uint32_t>(buffer->memory_->GetOffset());
217     omxInBufferInfo_->omxBuffer->pts = buffer->pts_;
218     omxInBufferInfo_->omxBuffer->flag = buffer->flag_;
219 
220     errno_t rc = memcpy_s(omxInBufferInfo_->avBuffer->memory_->GetAddr(), omxInBufferInfo_->omxBuffer->filledLen,
221                           buffer->memory_->GetAddr(), omxInBufferInfo_->omxBuffer->filledLen);
222     CHECK_AND_RETURN_RET_LOG(rc == EOK, Status::ERROR_INVALID_DATA, "memory copy failed!");
223 
224     int32_t ret = compNode_->EmptyThisBuffer(*omxInBufferInfo_->omxBuffer.get());
225     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_INVALID_DATA,
226         "EmptyThisBuffer failed, ret=%{public}d", ret);
227 
228     AVCODEC_LOGD("EmptyThisBuffer OK");
229     return Status::OK;
230 }
231 
FillThisBuffer(std::shared_ptr<AVBuffer> & buffer)232 Status HdiCodec::FillThisBuffer(std::shared_ptr<AVBuffer> &buffer)
233 {
234     std::unique_lock lock(outMutex_);
235     CHECK_AND_RETURN_RET_LOG(compNode_ != nullptr, Status::ERROR_NULL_POINTER, "compNode is nullptr!");
236     outputOmxBuffer_ = nullptr;
237     int32_t ret = compNode_->FillThisBuffer(*omxOutBufferInfo_->omxBuffer.get());
238     CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_INVALID_DATA, "FillThisBuffer failed!");
239 
240     condition_.wait_for(lock, std::chrono::milliseconds(TIMEOUT_MS), [this] { return outputOmxBuffer_ != nullptr; });
241     CHECK_AND_RETURN_RET_LOG(outputOmxBuffer_ != nullptr, Status::ERROR_INVALID_PARAMETER, "FillThisBuffer timeout!");
242 
243     errno_t rc = memcpy_s(buffer->memory_->GetAddr(), outputOmxBuffer_->filledLen,
244                           omxOutBufferInfo_->avBuffer->memory_->GetAddr(), outputOmxBuffer_->filledLen);
245     CHECK_AND_RETURN_RET_LOG(rc == EOK, Status::ERROR_INVALID_DATA, "memory copy failed!");
246 
247     buffer->memory_->SetSize(outputOmxBuffer_->filledLen);
248     buffer->memory_->SetOffset(outputOmxBuffer_->offset);
249     buffer->pts_ = outputOmxBuffer_->pts;
250     buffer->flag_ = outputOmxBuffer_->flag;
251 
252     AVCODEC_LOGD("FillThisBuffer OK");
253     return Status::OK;
254 }
255 
FreeBuffer(PortIndex portIndex,const std::shared_ptr<OmxCodecBuffer> & omxBuffer)256 Status HdiCodec::FreeBuffer(PortIndex portIndex, const std::shared_ptr<OmxCodecBuffer> &omxBuffer)
257 {
258     if (omxBuffer != nullptr) {
259         int32_t ret = compNode_->FreeBuffer(static_cast<uint32_t>(portIndex), *omxBuffer.get());
260         CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, Status::ERROR_INVALID_DATA,
261             "Free buffer fail, portIndex=%{public}d, ret=%{public}d", portIndex, ret);
262     }
263 
264     AVCODEC_LOGD("FreeBuffer OK");
265     return Status::OK;
266 }
267 
OnEventHandler(CodecEventType event,const EventInfo & info)268 Status HdiCodec::OnEventHandler(CodecEventType event, const EventInfo &info)
269 {
270     std::unique_lock lock(inMutex_);
271     event_ = event;
272     condition_.notify_all();
273     return Status::OK;
274 }
275 
OnEmptyBufferDone(const OmxCodecBuffer & buffer)276 Status HdiCodec::OnEmptyBufferDone(const OmxCodecBuffer &buffer)
277 {
278     return Status::OK;
279 }
280 
OnFillBufferDone(const OmxCodecBuffer & buffer)281 Status HdiCodec::OnFillBufferDone(const OmxCodecBuffer &buffer)
282 {
283     std::unique_lock lock(outMutex_);
284     outputOmxBuffer_ = std::make_shared<OmxCodecBuffer>(buffer);
285     condition_.notify_all();
286     return Status::OK;
287 }
288 
Reset()289 Status HdiCodec::Reset()
290 {
291     {
292         std::unique_lock lock(inMutex_);
293         FreeBuffer(PortIndex::INPUT_PORT, omxInBufferInfo_->omxBuffer);
294         omxInBufferInfo_->Reset();
295     }
296     {
297         std::unique_lock lock(outMutex_);
298         FreeBuffer(PortIndex::OUTPUT_PORT, omxOutBufferInfo_->omxBuffer);
299         omxOutBufferInfo_->Reset();
300     }
301     return Status::OK;
302 }
303 
Release()304 void HdiCodec::Release()
305 {
306     {
307         std::unique_lock lock(inMutex_);
308         FreeBuffer(PortIndex::INPUT_PORT, omxInBufferInfo_->omxBuffer);
309         omxInBufferInfo_->Reset();
310     }
311     {
312         std::unique_lock lock(outMutex_);
313         FreeBuffer(PortIndex::OUTPUT_PORT, omxOutBufferInfo_->omxBuffer);
314         omxOutBufferInfo_->Reset();
315     }
316 
317     if (compMgr_ != nullptr && componentId_ > 0) {
318         compMgr_->DestroyComponent(componentId_);
319     }
320     compNode_ = nullptr;
321     if (compCb_ != nullptr) {
322         compCb_ = nullptr;
323     }
324     compMgr_ = nullptr;
325 }
326 
HdiCallback(std::shared_ptr<HdiCodec> hdiCodec)327 HdiCodec::HdiCallback::HdiCallback(std::shared_ptr<HdiCodec> hdiCodec) : hdiCodec_(hdiCodec)
328 {
329 }
330 
EventHandler(CodecEventType event,const EventInfo & info)331 int32_t HdiCodec::HdiCallback::EventHandler(CodecEventType event, const EventInfo &info)
332 {
333     AVCODEC_LOGD("OnEventHandler");
334     if (hdiCodec_) {
335         hdiCodec_->OnEventHandler(event, info);
336     }
337     return HDF_SUCCESS;
338 }
339 
EmptyBufferDone(int64_t appData,const OmxCodecBuffer & buffer)340 int32_t HdiCodec::HdiCallback::EmptyBufferDone(int64_t appData, const OmxCodecBuffer &buffer)
341 {
342     if (hdiCodec_) {
343         hdiCodec_->OnEmptyBufferDone(buffer);
344     }
345     if (buffer.fd >= 0) {
346         close(buffer.fd);
347     }
348     return HDF_SUCCESS;
349 }
350 
FillBufferDone(int64_t appData,const OmxCodecBuffer & buffer)351 int32_t HdiCodec::HdiCallback::FillBufferDone(int64_t appData, const OmxCodecBuffer &buffer)
352 {
353     AVCODEC_LOGD("FillBufferDone");
354     if (hdiCodec_) {
355         hdiCodec_->OnFillBufferDone(buffer);
356     }
357     if (buffer.fd >= 0) {
358         close(buffer.fd);
359     }
360     return HDF_SUCCESS;
361 }
362 } // namespace Hdi
363 } // namespace Plugins
364 } // namespace Media
365 } // namespace OHOS
366