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 const std::vector<std::string> VIDEO_MIME_VEC = {
24 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_AVC),
25 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_HEVC),
26 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_VVC),
27 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_MPEG2),
28 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_H263),
29 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_MPEG4),
30 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_RV30),
31 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_RV40),
32 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_VP8),
33 std::string(OHOS::MediaAVCodec::CodecMimeType::VIDEO_VP9)};
34 const std::vector<std::string> AUDIO_MIME_VEC = {
35 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AMR_NB),
36 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AMR_WB),
37 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_MPEG),
38 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AAC),
39 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_VORBIS),
40 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_OPUS),
41 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_FLAC),
42 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_RAW),
43 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_G711MU),
44 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_COOK),
45 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AC3),
46 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_AVS3DA),
47 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_LBVC),
48 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_APE),
49 std::string(OHOS::MediaAVCodec::CodecMimeType::AUDIO_VIVID)};
50 }
51 namespace OHOS {
52 namespace MediaAVCodec {
CreateAVCodecList()53 std::shared_ptr<AVCodecList> AVCodecListFactory::CreateAVCodecList()
54 {
55 static std::shared_ptr<AVCodecListImpl> impl = std::make_shared<AVCodecListImpl>();
56 static bool initialized = false;
57 static std::mutex initMutex;
58 std::lock_guard lock(initMutex);
59 if (!initialized || impl->IsServiceDied()) {
60 int32_t ret = impl->Init();
61 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Init AVCodecListImpl failed");
62 initialized = true;
63 }
64 return impl;
65 }
66
Init()67 int32_t AVCodecListImpl::Init()
68 {
69 codecListService_ = AVCodecServiceFactory::GetInstance().CreateCodecListService();
70 CHECK_AND_RETURN_RET_LOG(codecListService_ != nullptr, AVCS_ERR_UNKNOWN, "Create AVCodecList service failed");
71 return AVCS_ERR_OK;
72 }
73
IsServiceDied()74 bool AVCodecListImpl::IsServiceDied()
75 {
76 return codecListService_ == nullptr || codecListService_->IsServiceDied();
77 }
78
AVCodecListImpl()79 AVCodecListImpl::AVCodecListImpl()
80 {
81 AVCODEC_LOGD("Create AVCodecList instances successful");
82 }
83
~AVCodecListImpl()84 AVCodecListImpl::~AVCodecListImpl()
85 {
86 if (codecListService_ != nullptr) {
87 (void)AVCodecServiceFactory::GetInstance().DestroyCodecListService(codecListService_);
88 codecListService_ = nullptr;
89 }
90 for (auto iter = nameAddrMap_.begin(); iter != nameAddrMap_.end(); iter++) {
91 if (iter->second != nullptr) {
92 free(iter->second);
93 iter->second = nullptr;
94 }
95 }
96 nameAddrMap_.clear();
97 for (auto addr : bufAddrSet_) {
98 if (addr != nullptr) {
99 delete[] addr;
100 }
101 }
102 bufAddrSet_.clear();
103 for (auto iter = mimeCapsMap_.begin(); iter != mimeCapsMap_.end(); iter++) {
104 std::string mime = iter->first;
105 for (uint32_t i = 0; i < mimeCapsMap_[mime].size(); i++) {
106 delete mimeCapsMap_[mime][i];
107 mimeCapsMap_[mime][i] = nullptr;
108 }
109 mimeCapsMap_[mime].clear();
110 }
111 mimeCapsMap_.clear();
112 AVCODEC_LOGD("Destroy AVCodecList instances successful");
113 }
114
FindDecoder(const Format & format)115 std::string AVCodecListImpl::FindDecoder(const Format &format)
116 {
117 return codecListService_->FindDecoder(format);
118 }
119
FindEncoder(const Format & format)120 std::string AVCodecListImpl::FindEncoder(const Format &format)
121 {
122 return codecListService_->FindEncoder(format);
123 }
124
IsStrMatch(const std::string & str,const std::vector<std::string> & strVec)125 bool AVCodecListImpl::IsStrMatch(const std::string &str, const std::vector<std::string>& strVec)
126 {
127 for (const auto& s : strVec) {
128 if (s.compare(str) == 0) {
129 return true;
130 }
131 }
132 return false;
133 }
134
GetCapability(const std::string & mime,const bool isEncoder,const AVCodecCategory & category)135 CapabilityData *AVCodecListImpl::GetCapability(const std::string &mime, const bool isEncoder,
136 const AVCodecCategory &category)
137 {
138 std::lock_guard<std::mutex> lock(mutex_);
139 CHECK_AND_RETURN_RET_LOG(category >= AVCodecCategory::AVCODEC_NONE &&
140 category <= AVCodecCategory::AVCODEC_SOFTWARE, nullptr,
141 "Unsupported category %{public}d", category);
142 bool isHardward = (category == AVCodecCategory::AVCODEC_SOFTWARE) ? false : true;
143 AVCodecType codecType = AVCODEC_TYPE_NONE;
144 if (IsStrMatch(mime, VIDEO_MIME_VEC)) {
145 codecType = isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER;
146 } else if (IsStrMatch(mime, AUDIO_MIME_VEC)) {
147 codecType = isEncoder ? AVCODEC_TYPE_AUDIO_ENCODER : AVCODEC_TYPE_AUDIO_DECODER;
148 } else {
149 AVCODEC_LOGE("GetCapability failed, mime is %{public}s", mime.c_str());
150 return nullptr;
151 }
152 if (mimeCapsMap_.find(mime) == mimeCapsMap_.end()) {
153 std::vector<CapabilityData *> capsArray;
154 mimeCapsMap_.emplace(mime, capsArray);
155 }
156 for (auto cap : mimeCapsMap_[mime]) {
157 if (cap->codecType == codecType && cap->isVendor == isHardward) {
158 return cap;
159 }
160 }
161 CapabilityData capaDataIn;
162 int32_t ret = codecListService_->GetCapability(capaDataIn, mime, isEncoder, category);
163 std::string name = capaDataIn.codecName;
164 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK && !name.empty(), nullptr, "Get capability failed from service,"
165 "mime: %{public}s, isEnc: %{public}d, category: %{public}d", mime.c_str(), isEncoder, category);
166 if (category == AVCodecCategory::AVCODEC_NONE && nameAddrMap_.find(name) != nameAddrMap_.end()) {
167 for (auto cap : mimeCapsMap_[mime]) {
168 if (cap->codecType == codecType && cap->codecName == name) {
169 return cap;
170 }
171 }
172 }
173 CapabilityData *cap = new CapabilityData(capaDataIn);
174 CHECK_AND_RETURN_RET_LOG(cap != nullptr, nullptr, "New capabilityData failed");
175 mimeCapsMap_[mime].emplace_back(cap);
176 AVCODEC_LOGD("Get capabilityData successfully, mime: %{public}s, isEnc: %{public}d, category: %{public}d",
177 mime.c_str(), isEncoder, category);
178 return cap;
179 }
180
GetBuffer(const std::string & name,uint32_t sizeOfCap)181 void *AVCodecListImpl::GetBuffer(const std::string &name, uint32_t sizeOfCap)
182 {
183 std::lock_guard<std::mutex> lock(mutex_);
184 if (nameAddrMap_.find(name) != nameAddrMap_.end()) {
185 return nameAddrMap_[name];
186 }
187 CHECK_AND_RETURN_RET_LOG(sizeOfCap > 0, nullptr, "Get capability buffer failed: invalid size");
188 void *buf = static_cast<void *>(malloc(sizeOfCap));
189 if (buf != nullptr) {
190 nameAddrMap_[name] = buf;
191 return buf;
192 } else {
193 return nullptr;
194 }
195 }
196
NewBuffer(size_t bufSize)197 void *AVCodecListImpl::NewBuffer(size_t bufSize)
198 {
199 std::lock_guard<std::mutex> lock(mutex_);
200 CHECK_AND_RETURN_RET_LOG(bufSize > 0, nullptr, "new buffer failed: invalid size");
201 uint8_t *temp = new uint8_t[bufSize];
202 CHECK_AND_RETURN_RET_LOG(temp != nullptr, nullptr, "new buffer failed: no memory");
203
204 bufAddrSet_.insert(temp);
205 return static_cast<void *>(temp);
206 }
207
DeleteBuffer(void * bufAddr)208 void AVCodecListImpl::DeleteBuffer(void *bufAddr)
209 {
210 std::lock_guard<std::mutex> lock(mutex_);
211 CHECK_AND_RETURN_LOG(bufAddr != nullptr, "bufAddr is nullptr!");
212 uint8_t *temp = static_cast<uint8_t *>(bufAddr);
213 bufAddrSet_.erase(temp);
214 delete[] temp;
215 }
216 } // namespace MediaAVCodec
217 } // namespace OHOS