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