1 /*
2 * Copyright (C) 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
16 #include "avcodeclist_impl.h"
17 #include "avcodec_errors.h"
18 #include "avcodec_log.h"
19 #include "i_avcodec_service.h"
20
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "AVCodecListImpl"};
23 }
24 namespace OHOS {
25 namespace MediaAVCodec {
CreateAVCodecList()26 std::shared_ptr<AVCodecList> AVCodecListFactory::CreateAVCodecList()
27 {
28 static std::shared_ptr<AVCodecListImpl> impl = std::make_shared<AVCodecListImpl>();
29 static bool initialized = false;
30 static std::mutex initMutex;
31 std::lock_guard lock(initMutex);
32 if (!initialized || impl->IsServiceDied()) {
33 int32_t ret = impl->Init();
34 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init AVCodecListImpl failed");
35 initialized = true;
36 }
37 return impl;
38 }
39
Init()40 int32_t AVCodecListImpl::Init()
41 {
42 codecListService_ = AVCodecServiceFactory::GetInstance().CreateCodecListService();
43 CHECK_AND_RETURN_RET_LOG(codecListService_ != nullptr, AVCS_ERR_UNKNOWN, "Create AVCodecList service failed");
44 return AVCS_ERR_OK;
45 }
46
IsServiceDied()47 bool AVCodecListImpl::IsServiceDied()
48 {
49 return codecListService_ == nullptr || codecListService_->IsServiceDied();
50 }
51
AVCodecListImpl()52 AVCodecListImpl::AVCodecListImpl()
53 {
54 AVCODEC_LOGD("Create AVCodecList instances successful");
55 }
56
~AVCodecListImpl()57 AVCodecListImpl::~AVCodecListImpl()
58 {
59 if (codecListService_ != nullptr) {
60 (void)AVCodecServiceFactory::GetInstance().DestroyCodecListService(codecListService_);
61 codecListService_ = nullptr;
62 }
63 for (auto iter = nameAddrMap_.begin(); iter != nameAddrMap_.end(); iter++) {
64 if (iter->second != nullptr) {
65 free(iter->second);
66 iter->second = nullptr;
67 }
68 }
69 nameAddrMap_.clear();
70 for (auto addr : bufAddrSet_) {
71 if (addr != nullptr) {
72 delete[] addr;
73 }
74 }
75 bufAddrSet_.clear();
76 for (auto iter = mimeCapsMap_.begin(); iter != mimeCapsMap_.end(); iter++) {
77 std::string mime = iter->first;
78 for (uint32_t i = 0; i < mimeCapsMap_[mime].size(); i++) {
79 delete mimeCapsMap_[mime][i];
80 mimeCapsMap_[mime][i] = nullptr;
81 }
82 mimeCapsMap_[mime].clear();
83 }
84 mimeCapsMap_.clear();
85 AVCODEC_LOGD("Destroy AVCodecList instances successful");
86 }
87
FindDecoder(const Format & format)88 std::string AVCodecListImpl::FindDecoder(const Format &format)
89 {
90 return codecListService_->FindDecoder(format);
91 }
92
FindEncoder(const Format & format)93 std::string AVCodecListImpl::FindEncoder(const Format &format)
94 {
95 return codecListService_->FindEncoder(format);
96 }
97
GetCapability(const std::string & mime,const bool isEncoder,const AVCodecCategory & category)98 CapabilityData *AVCodecListImpl::GetCapability(const std::string &mime, const bool isEncoder,
99 const AVCodecCategory &category)
100 {
101 std::lock_guard<std::mutex> lock(mutex_);
102 bool isVendor = (category == AVCodecCategory::AVCODEC_SOFTWARE) ? false : true;
103 AVCodecType codecType = AVCODEC_TYPE_NONE;
104 bool isVideo = mime.find("video") != std::string::npos;
105 if (isVideo) {
106 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
107 } else {
108 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
109 }
110 if (mimeCapsMap_.find(mime) != mimeCapsMap_.end()) {
111 for (uint32_t i = 0; i < mimeCapsMap_[mime].size(); i++) {
112 if (mimeCapsMap_[mime][i]->codecType == codecType && mimeCapsMap_[mime][i]->isVendor == isVendor) {
113 return mimeCapsMap_[mime][i];
114 }
115 }
116 } else {
117 std::vector<CapabilityData *> capsArray;
118 mimeCapsMap_.insert(std::make_pair(mime, capsArray));
119 }
120 CapabilityData capaDataIn;
121 int32_t ret = codecListService_->GetCapability(capaDataIn, mime, isEncoder, category);
122 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Get capability failed");
123 std::string name = capaDataIn.codecName;
124 CHECK_AND_RETURN_RET_LOG(!name.empty(), nullptr, "Get capability failed");
125 if (category == AVCodecCategory::AVCODEC_NONE && nameAddrMap_.find(name) != nameAddrMap_.end()) {
126 for (uint32_t i = 0; i < mimeCapsMap_[mime].size(); i++) {
127 if (mimeCapsMap_[mime][i]->codecType == codecType && mimeCapsMap_[mime][i]->codecName == name) {
128 return mimeCapsMap_[mime][i];
129 }
130 }
131 }
132 CapabilityData *cap = new CapabilityData(capaDataIn);
133 mimeCapsMap_.at(mime).emplace_back(cap);
134 uint32_t idx = mimeCapsMap_[mime].size() - 1;
135 return mimeCapsMap_[mime][idx];
136 }
137
GetBuffer(const std::string & name,uint32_t sizeOfCap)138 void *AVCodecListImpl::GetBuffer(const std::string &name, uint32_t sizeOfCap)
139 {
140 std::lock_guard<std::mutex> lock(mutex_);
141 if (nameAddrMap_.find(name) != nameAddrMap_.end()) {
142 return nameAddrMap_[name];
143 }
144 CHECK_AND_RETURN_RET_LOG(sizeOfCap > 0, nullptr, "Get capability buffer failed: invalid size");
145 void *buf = static_cast<void *>(malloc(sizeOfCap));
146 if (buf != nullptr) {
147 nameAddrMap_[name] = buf;
148 return buf;
149 } else {
150 return nullptr;
151 }
152 }
153
NewBuffer(size_t bufSize)154 void *AVCodecListImpl::NewBuffer(size_t bufSize)
155 {
156 std::lock_guard<std::mutex> lock(mutex_);
157 CHECK_AND_RETURN_RET_LOG(bufSize > 0, nullptr, "new buffer failed: invalid size");
158 uint8_t *temp = new uint8_t[bufSize];
159 CHECK_AND_RETURN_RET_LOG(temp != nullptr, nullptr, "new buffer failed: no memory");
160
161 bufAddrSet_.insert(temp);
162 return static_cast<void *>(temp);
163 }
164
DeleteBuffer(void * bufAddr)165 void AVCodecListImpl::DeleteBuffer(void *bufAddr)
166 {
167 std::lock_guard<std::mutex> lock(mutex_);
168 uint8_t *temp = static_cast<uint8_t *>(bufAddr);
169 bufAddrSet_.erase(temp);
170 delete[] temp;
171 }
172 } // namespace MediaAVCodec
173 } // namespace OHOS