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