• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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