1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "V4L2ComponentStore"
7
8 #include <v4l2_codec2/components/V4L2ComponentStore.h>
9
10 #include <stdint.h>
11
12 #include <memory>
13 #include <mutex>
14
15 #include <C2.h>
16 #include <C2Config.h>
17 #include <log/log.h>
18 #include <media/stagefright/foundation/MediaDefs.h>
19
20 #include <v4l2_codec2/common/V4L2ComponentCommon.h>
21 #include <v4l2_codec2/components/V4L2ComponentFactory.h>
22
23 namespace android {
24 namespace {
25 const uint32_t kComponentRank = 0x80;
26
getMediaTypeFromComponentName(const std::string & name)27 std::string getMediaTypeFromComponentName(const std::string& name) {
28 if (name == V4L2ComponentName::kH264Decoder || name == V4L2ComponentName::kH264SecureDecoder ||
29 name == V4L2ComponentName::kH264Encoder) {
30 return MEDIA_MIMETYPE_VIDEO_AVC;
31 }
32 if (name == V4L2ComponentName::kVP8Decoder || name == V4L2ComponentName::kVP8SecureDecoder ||
33 name == V4L2ComponentName::kVP8Encoder) {
34 return MEDIA_MIMETYPE_VIDEO_VP8;
35 }
36 if (name == V4L2ComponentName::kVP9Decoder || name == V4L2ComponentName::kVP9SecureDecoder ||
37 name == V4L2ComponentName::kVP9Encoder) {
38 return MEDIA_MIMETYPE_VIDEO_VP9;
39 }
40 return "";
41 }
42
43 } // namespace
44
45 // static
Create()46 std::shared_ptr<C2ComponentStore> V4L2ComponentStore::Create() {
47 ALOGV("%s()", __func__);
48
49 static std::mutex mutex;
50 static std::weak_ptr<C2ComponentStore> platformStore;
51
52 std::lock_guard<std::mutex> lock(mutex);
53 std::shared_ptr<C2ComponentStore> store = platformStore.lock();
54 if (store != nullptr) return store;
55
56 store = std::shared_ptr<C2ComponentStore>(new V4L2ComponentStore());
57 platformStore = store;
58 return store;
59 }
60
V4L2ComponentStore()61 V4L2ComponentStore::V4L2ComponentStore() : mReflector(std::make_shared<C2ReflectorHelper>()) {
62 ALOGV("%s()", __func__);
63 }
64
~V4L2ComponentStore()65 V4L2ComponentStore::~V4L2ComponentStore() {
66 ALOGV("%s()", __func__);
67
68 std::lock_guard<std::mutex> lock(mCachedFactoriesLock);
69 mCachedFactories.clear();
70 }
71
getName() const72 C2String V4L2ComponentStore::getName() const {
73 return "android.componentStore.v4l2";
74 }
75
createComponent(C2String name,std::shared_ptr<C2Component> * const component)76 c2_status_t V4L2ComponentStore::createComponent(C2String name,
77 std::shared_ptr<C2Component>* const component) {
78 ALOGV("%s(%s)", __func__, name.c_str());
79
80 if (!V4L2ComponentName::isValid(name.c_str())) {
81 ALOGI("%s(): Invalid component name: %s", __func__, name.c_str());
82 return C2_NOT_FOUND;
83 }
84
85 auto factory = GetFactory(name);
86 if (factory == nullptr) return C2_CORRUPTED;
87
88 component->reset();
89 return factory->createComponent(0, component);
90 }
91
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)92 c2_status_t V4L2ComponentStore::createInterface(
93 C2String name, std::shared_ptr<C2ComponentInterface>* const interface) {
94 ALOGV("%s(%s)", __func__, name.c_str());
95
96 if (!V4L2ComponentName::isValid(name.c_str())) {
97 ALOGI("%s(): Invalid component name: %s", __func__, name.c_str());
98 return C2_NOT_FOUND;
99 }
100
101 auto factory = GetFactory(name);
102 if (factory == nullptr) return C2_CORRUPTED;
103
104 interface->reset();
105 return factory->createInterface(0, interface);
106 }
107
listComponents()108 std::vector<std::shared_ptr<const C2Component::Traits>> V4L2ComponentStore::listComponents() {
109 ALOGV("%s()", __func__);
110
111 std::vector<std::shared_ptr<const C2Component::Traits>> ret;
112 ret.push_back(GetTraits(V4L2ComponentName::kH264Encoder));
113 ret.push_back(GetTraits(V4L2ComponentName::kH264Decoder));
114 ret.push_back(GetTraits(V4L2ComponentName::kH264SecureDecoder));
115 ret.push_back(GetTraits(V4L2ComponentName::kVP8Encoder));
116 ret.push_back(GetTraits(V4L2ComponentName::kVP8Decoder));
117 ret.push_back(GetTraits(V4L2ComponentName::kVP8SecureDecoder));
118 ret.push_back(GetTraits(V4L2ComponentName::kVP9Encoder));
119 ret.push_back(GetTraits(V4L2ComponentName::kVP9Decoder));
120 ret.push_back(GetTraits(V4L2ComponentName::kVP9SecureDecoder));
121 return ret;
122 }
123
getParamReflector() const124 std::shared_ptr<C2ParamReflector> V4L2ComponentStore::getParamReflector() const {
125 return mReflector;
126 }
127
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)128 c2_status_t V4L2ComponentStore::copyBuffer(std::shared_ptr<C2GraphicBuffer> /* src */,
129 std::shared_ptr<C2GraphicBuffer> /* dst */) {
130 return C2_OMITTED;
131 }
132
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const) const133 c2_status_t V4L2ComponentStore::querySupportedParams_nb(
134 std::vector<std::shared_ptr<C2ParamDescriptor>>* const /* params */) const {
135 return C2_OK;
136 }
137
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const) const138 c2_status_t V4L2ComponentStore::query_sm(
139 const std::vector<C2Param*>& stackParams,
140 const std::vector<C2Param::Index>& heapParamIndices,
141 std::vector<std::unique_ptr<C2Param>>* const /* heapParams */) const {
142 // There are no supported config params.
143 return stackParams.empty() && heapParamIndices.empty() ? C2_OK : C2_BAD_INDEX;
144 }
145
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const)146 c2_status_t V4L2ComponentStore::config_sm(
147 const std::vector<C2Param*>& params,
148 std::vector<std::unique_ptr<C2SettingResult>>* const /* failures */) {
149 // There are no supported config params.
150 return params.empty() ? C2_OK : C2_BAD_INDEX;
151 }
152
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const153 c2_status_t V4L2ComponentStore::querySupportedValues_sm(
154 std::vector<C2FieldSupportedValuesQuery>& fields) const {
155 // There are no supported config params.
156 return fields.empty() ? C2_OK : C2_BAD_INDEX;
157 }
158
GetFactory(const C2String & name)159 ::C2ComponentFactory* V4L2ComponentStore::GetFactory(const C2String& name) {
160 ALOGV("%s(%s)", __func__, name.c_str());
161 ALOG_ASSERT(V4L2ComponentName::isValid(name.c_str()));
162
163 std::lock_guard<std::mutex> lock(mCachedFactoriesLock);
164 const auto it = mCachedFactories.find(name);
165 if (it != mCachedFactories.end()) return it->second.get();
166
167 std::unique_ptr<::C2ComponentFactory> factory = V4L2ComponentFactory::create(
168 name, std::static_pointer_cast<C2ReflectorHelper>(getParamReflector()));
169 if (factory == nullptr) {
170 ALOGE("Failed to create factory for %s", name.c_str());
171 return nullptr;
172 }
173
174 auto ret = factory.get();
175 mCachedFactories.emplace(name, std::move(factory));
176 return ret;
177 }
178
GetTraits(const C2String & name)179 std::shared_ptr<const C2Component::Traits> V4L2ComponentStore::GetTraits(const C2String& name) {
180 ALOGV("%s(%s)", __func__, name.c_str());
181
182 if (!V4L2ComponentName::isValid(name.c_str())) {
183 ALOGE("Invalid component name: %s", name.c_str());
184 return nullptr;
185 }
186
187 std::lock_guard<std::mutex> lock(mCachedTraitsLock);
188 auto it = mCachedTraits.find(name);
189 if (it != mCachedTraits.end()) return it->second;
190
191 auto traits = std::make_shared<C2Component::Traits>();
192 traits->name = name;
193 traits->domain = C2Component::DOMAIN_VIDEO;
194 traits->rank = kComponentRank;
195 traits->mediaType = getMediaTypeFromComponentName(name);
196 traits->kind = V4L2ComponentName::isEncoder(name.c_str()) ? C2Component::KIND_ENCODER
197 : C2Component::KIND_DECODER;
198
199 mCachedTraits.emplace(name, traits);
200 return traits;
201 }
202
203 } // namespace android
204