• 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_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