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