aboutsummaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/Android.bp4
-rw-r--r--components/V4L2ComponentFactory.cpp103
-rw-r--r--components/V4L2ComponentStore.cpp203
-rw-r--r--components/include/v4l2_codec2/components/V4L2ComponentFactory.h39
-rw-r--r--components/include/v4l2_codec2/components/V4L2ComponentStore.h61
5 files changed, 340 insertions, 70 deletions
diff --git a/components/Android.bp b/components/Android.bp
index c683cb0..9b39a22 100644
--- a/components/Android.bp
+++ b/components/Android.bp
@@ -18,8 +18,9 @@ cc_library {
srcs: [
"VideoFrame.cpp",
"VideoFramePool.cpp",
- "V4L2Decoder.cpp",
"V4L2ComponentFactory.cpp",
+ "V4L2ComponentStore.cpp",
+ "V4L2Decoder.cpp",
"V4L2DecodeComponent.cpp",
"V4L2DecodeInterface.cpp",
"V4L2EncodeComponent.cpp",
@@ -43,7 +44,6 @@ cc_library {
"libsfplugin_ccodec_utils",
"libstagefright_bufferqueue_helper",
"libstagefright_foundation",
- "libv4l2_codec2_store",
"libui",
],
static_libs: [
diff --git a/components/V4L2ComponentFactory.cpp b/components/V4L2ComponentFactory.cpp
index 049edce..a3f8837 100644
--- a/components/V4L2ComponentFactory.cpp
+++ b/components/V4L2ComponentFactory.cpp
@@ -5,71 +5,57 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "V4L2ComponentFactory"
-#include <string>
+#include <v4l2_codec2/components/V4L2ComponentFactory.h>
-#include <C2ComponentFactory.h>
-#include <SimpleC2Interface.h>
#include <codec2/hidl/1.0/InputBufferManager.h>
#include <log/log.h>
-#include <util/C2InterfaceHelper.h>
#include <v4l2_codec2/common/V4L2ComponentCommon.h>
#include <v4l2_codec2/components/V4L2DecodeComponent.h>
#include <v4l2_codec2/components/V4L2DecodeInterface.h>
#include <v4l2_codec2/components/V4L2EncodeComponent.h>
#include <v4l2_codec2/components/V4L2EncodeInterface.h>
-#include <v4l2_codec2/store/V4L2ComponentStore.h>
namespace android {
-class V4L2ComponentFactory : public C2ComponentFactory {
-public:
- V4L2ComponentFactory(const char* componentName, bool isEncoder);
- ~V4L2ComponentFactory() override;
-
- // Implementation of C2ComponentFactory.
- c2_status_t createComponent(c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- ComponentDeleter deleter) override;
- c2_status_t createInterface(c2_node_id_t id,
- std::shared_ptr<C2ComponentInterface>* const interface,
- InterfaceDeleter deleter) override;
-
-private:
- const std::string mComponentName;
- const bool mIsEncoder;
- std::shared_ptr<C2ReflectorHelper> mReflector;
-};
-
-V4L2ComponentFactory::V4L2ComponentFactory(const char* componentName, bool isEncoder)
- : mComponentName(componentName), mIsEncoder(isEncoder) {
- auto componentStore = V4L2ComponentStore::Create();
- if (componentStore == nullptr) {
- ALOGE("Could not create V4L2ComponentStore.");
- return;
+// static
+std::unique_ptr<V4L2ComponentFactory> V4L2ComponentFactory::create(
+ const std::string& componentName, std::shared_ptr<C2ReflectorHelper> reflector) {
+ ALOGV("%s(%s)", __func__, componentName.c_str());
+
+ if (!android::V4L2ComponentName::isValid(componentName.c_str())) {
+ ALOGE("Invalid component name: %s", componentName.c_str());
+ return nullptr;
}
- mReflector = std::static_pointer_cast<C2ReflectorHelper>(componentStore->getParamReflector());
-
- {
- using namespace ::android::hardware::media::c2::V1_0;
- // To minimize IPC, we generally want the codec2 framework to release and
- // recycle input buffers when the corresponding work item is done. However,
- // sometimes it is necessary to provide more input to unblock a decoder.
- //
- // Optimally we would configure this on a per-context basis. However, the
- // InputBufferManager is a process-wide singleton, so we need to configure it
- // pessimistically. Basing the interval on frame timing can be suboptimal if
- // the decoded output isn't being displayed, but that's not a primary use case
- // and few videos will actually rely on this behavior.
- constexpr nsecs_t kMinFrameIntervalNs = 1000000000ull / 60;
- uint32_t delayCount = 0;
- for (auto c : kAllCodecs) {
- delayCount = std::max(delayCount, V4L2DecodeInterface::getOutputDelay(c));
- }
- utils::InputBufferManager::setNotificationInterval(delayCount * kMinFrameIntervalNs / 2);
+ if (reflector == nullptr) {
+ ALOGE("reflector is null");
+ return nullptr;
}
+
+ bool isEncoder = android::V4L2ComponentName::isEncoder(componentName.c_str());
+ return std::make_unique<V4L2ComponentFactory>(componentName, isEncoder, std::move(reflector));
}
-V4L2ComponentFactory::~V4L2ComponentFactory() = default;
+V4L2ComponentFactory::V4L2ComponentFactory(const std::string& componentName, bool isEncoder,
+ std::shared_ptr<C2ReflectorHelper> reflector)
+ : mComponentName(componentName), mIsEncoder(isEncoder), mReflector(std::move(reflector)) {
+ using namespace ::android::hardware::media::c2::V1_0;
+ // To minimize IPC, we generally want the codec2 framework to release and
+ // recycle input buffers when the corresponding work item is done. However,
+ // sometimes it is necessary to provide more input to unblock a decoder.
+ //
+ // Optimally we would configure this on a per-context basis. However, the
+ // InputBufferManager is a process-wide singleton, so we need to configure it
+ // pessimistically. Basing the interval on frame timing can be suboptimal if
+ // the decoded output isn't being displayed, but that's not a primary use case
+ // and few videos will actually rely on this behavior.
+ constexpr nsecs_t kMinFrameIntervalNs = 1000000000ull / 60;
+ uint32_t delayCount = 0;
+ for (auto c : kAllCodecs) {
+ delayCount = std::max(delayCount, V4L2DecodeInterface::getOutputDelay(c));
+ }
+ utils::InputBufferManager::setNotificationInterval(delayCount * kMinFrameIntervalNs / 2);
+}
c2_status_t V4L2ComponentFactory::createComponent(c2_node_id_t id,
std::shared_ptr<C2Component>* const component,
@@ -118,22 +104,3 @@ c2_status_t V4L2ComponentFactory::createInterface(
}
} // namespace android
-
-__attribute__((cfi_canonical_jump_table)) extern "C" ::C2ComponentFactory* CreateCodec2Factory(
- const char* componentName) {
- ALOGV("%s(%s)", __func__, componentName);
-
- if (!android::V4L2ComponentName::isValid(componentName)) {
- ALOGE("Invalid component name: %s", componentName);
- return nullptr;
- }
-
- bool isEncoder = android::V4L2ComponentName::isEncoder(componentName);
- return new android::V4L2ComponentFactory(componentName, isEncoder);
-}
-
-__attribute__((cfi_canonical_jump_table)) extern "C" void DestroyCodec2Factory(
- ::C2ComponentFactory* factory) {
- ALOGV("%s()", __func__);
- delete factory;
-}
diff --git a/components/V4L2ComponentStore.cpp b/components/V4L2ComponentStore.cpp
new file mode 100644
index 0000000..4004ce5
--- /dev/null
+++ b/components/V4L2ComponentStore.cpp
@@ -0,0 +1,203 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "V4L2ComponentStore"
+
+#include <v4l2_codec2/components/V4L2ComponentStore.h>
+
+#include <stdint.h>
+
+#include <memory>
+#include <mutex>
+
+#include <C2.h>
+#include <C2Config.h>
+#include <log/log.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include <v4l2_codec2/common/V4L2ComponentCommon.h>
+#include <v4l2_codec2/components/V4L2ComponentFactory.h>
+
+namespace android {
+namespace {
+const uint32_t kComponentRank = 0x80;
+
+std::string getMediaTypeFromComponentName(const std::string& name) {
+ if (name == V4L2ComponentName::kH264Decoder || name == V4L2ComponentName::kH264SecureDecoder ||
+ name == V4L2ComponentName::kH264Encoder) {
+ return MEDIA_MIMETYPE_VIDEO_AVC;
+ }
+ if (name == V4L2ComponentName::kVP8Decoder || name == V4L2ComponentName::kVP8SecureDecoder ||
+ name == V4L2ComponentName::kVP8Encoder) {
+ return MEDIA_MIMETYPE_VIDEO_VP8;
+ }
+ if (name == V4L2ComponentName::kVP9Decoder || name == V4L2ComponentName::kVP9SecureDecoder ||
+ name == V4L2ComponentName::kVP9Encoder) {
+ return MEDIA_MIMETYPE_VIDEO_VP9;
+ }
+ return "";
+}
+
+} // namespace
+
+// static
+std::shared_ptr<C2ComponentStore> V4L2ComponentStore::Create() {
+ ALOGV("%s()", __func__);
+
+ static std::mutex mutex;
+ static std::weak_ptr<C2ComponentStore> platformStore;
+
+ std::lock_guard<std::mutex> lock(mutex);
+ std::shared_ptr<C2ComponentStore> store = platformStore.lock();
+ if (store != nullptr) return store;
+
+ store = std::shared_ptr<C2ComponentStore>(new V4L2ComponentStore());
+ platformStore = store;
+ return store;
+}
+
+V4L2ComponentStore::V4L2ComponentStore() : mReflector(std::make_shared<C2ReflectorHelper>()) {
+ ALOGV("%s()", __func__);
+}
+
+V4L2ComponentStore::~V4L2ComponentStore() {
+ ALOGV("%s()", __func__);
+
+ std::lock_guard<std::mutex> lock(mCachedFactoriesLock);
+ mCachedFactories.clear();
+}
+
+C2String V4L2ComponentStore::getName() const {
+ return "android.componentStore.v4l2";
+}
+
+c2_status_t V4L2ComponentStore::createComponent(C2String name,
+ std::shared_ptr<C2Component>* const component) {
+ ALOGV("%s(%s)", __func__, name.c_str());
+
+ if (!V4L2ComponentName::isValid(name.c_str())) {
+ ALOGI("%s(): Invalid component name: %s", __func__, name.c_str());
+ return C2_NOT_FOUND;
+ }
+
+ auto factory = GetFactory(name);
+ if (factory == nullptr) return C2_CORRUPTED;
+
+ component->reset();
+ return factory->createComponent(0, component);
+}
+
+c2_status_t V4L2ComponentStore::createInterface(
+ C2String name, std::shared_ptr<C2ComponentInterface>* const interface) {
+ ALOGV("%s(%s)", __func__, name.c_str());
+
+ if (!V4L2ComponentName::isValid(name.c_str())) {
+ ALOGI("%s(): Invalid component name: %s", __func__, name.c_str());
+ return C2_NOT_FOUND;
+ }
+
+ auto factory = GetFactory(name);
+ if (factory == nullptr) return C2_CORRUPTED;
+
+ interface->reset();
+ return factory->createInterface(0, interface);
+}
+
+std::vector<std::shared_ptr<const C2Component::Traits>> V4L2ComponentStore::listComponents() {
+ ALOGV("%s()", __func__);
+
+ std::vector<std::shared_ptr<const C2Component::Traits>> ret;
+ ret.push_back(GetTraits(V4L2ComponentName::kH264Encoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kH264Decoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kH264SecureDecoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kVP8Encoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kVP8Decoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kVP8SecureDecoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kVP9Encoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kVP9Decoder));
+ ret.push_back(GetTraits(V4L2ComponentName::kVP9SecureDecoder));
+ return ret;
+}
+
+std::shared_ptr<C2ParamReflector> V4L2ComponentStore::getParamReflector() const {
+ return mReflector;
+}
+
+c2_status_t V4L2ComponentStore::copyBuffer(std::shared_ptr<C2GraphicBuffer> /* src */,
+ std::shared_ptr<C2GraphicBuffer> /* dst */) {
+ return C2_OMITTED;
+}
+
+c2_status_t V4L2ComponentStore::querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const /* params */) const {
+ return C2_OK;
+}
+
+c2_status_t V4L2ComponentStore::query_sm(
+ const std::vector<C2Param*>& stackParams,
+ const std::vector<C2Param::Index>& heapParamIndices,
+ std::vector<std::unique_ptr<C2Param>>* const /* heapParams */) const {
+ // There are no supported config params.
+ return stackParams.empty() && heapParamIndices.empty() ? C2_OK : C2_BAD_INDEX;
+}
+
+c2_status_t V4L2ComponentStore::config_sm(
+ const std::vector<C2Param*>& params,
+ std::vector<std::unique_ptr<C2SettingResult>>* const /* failures */) {
+ // There are no supported config params.
+ return params.empty() ? C2_OK : C2_BAD_INDEX;
+}
+
+c2_status_t V4L2ComponentStore::querySupportedValues_sm(
+ std::vector<C2FieldSupportedValuesQuery>& fields) const {
+ // There are no supported config params.
+ return fields.empty() ? C2_OK : C2_BAD_INDEX;
+}
+
+::C2ComponentFactory* V4L2ComponentStore::GetFactory(const C2String& name) {
+ ALOGV("%s(%s)", __func__, name.c_str());
+ ALOG_ASSERT(V4L2ComponentName::isValid(name.c_str()));
+
+ std::lock_guard<std::mutex> lock(mCachedFactoriesLock);
+ const auto it = mCachedFactories.find(name);
+ if (it != mCachedFactories.end()) return it->second.get();
+
+ std::unique_ptr<::C2ComponentFactory> factory = V4L2ComponentFactory::create(
+ name, std::static_pointer_cast<C2ReflectorHelper>(getParamReflector()));
+ if (factory == nullptr) {
+ ALOGE("Failed to create factory for %s", name.c_str());
+ return nullptr;
+ }
+
+ auto ret = factory.get();
+ mCachedFactories.emplace(name, std::move(factory));
+ return ret;
+}
+
+std::shared_ptr<const C2Component::Traits> V4L2ComponentStore::GetTraits(const C2String& name) {
+ ALOGV("%s(%s)", __func__, name.c_str());
+
+ if (!V4L2ComponentName::isValid(name.c_str())) {
+ ALOGE("Invalid component name: %s", name.c_str());
+ return nullptr;
+ }
+
+ std::lock_guard<std::mutex> lock(mCachedTraitsLock);
+ auto it = mCachedTraits.find(name);
+ if (it != mCachedTraits.end()) return it->second;
+
+ auto traits = std::make_shared<C2Component::Traits>();
+ traits->name = name;
+ traits->domain = C2Component::DOMAIN_VIDEO;
+ traits->rank = kComponentRank;
+ traits->mediaType = getMediaTypeFromComponentName(name);
+ traits->kind = V4L2ComponentName::isEncoder(name.c_str()) ? C2Component::KIND_ENCODER
+ : C2Component::KIND_DECODER;
+
+ mCachedTraits.emplace(name, traits);
+ return traits;
+}
+
+} // namespace android
diff --git a/components/include/v4l2_codec2/components/V4L2ComponentFactory.h b/components/include/v4l2_codec2/components/V4L2ComponentFactory.h
new file mode 100644
index 0000000..fc6abea
--- /dev/null
+++ b/components/include/v4l2_codec2/components/V4L2ComponentFactory.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_COMPONENT_FACTORY_H
+#define ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_COMPONENT_FACTORY_H
+
+#include <memory>
+#include <string>
+
+#include <C2ComponentFactory.h>
+#include <util/C2InterfaceHelper.h>
+
+namespace android {
+
+class V4L2ComponentFactory : public C2ComponentFactory {
+public:
+ static std::unique_ptr<V4L2ComponentFactory> create(
+ const std::string& componentName, std::shared_ptr<C2ReflectorHelper> reflector);
+ V4L2ComponentFactory(const std::string& componentName, bool isEncoder,
+ std::shared_ptr<C2ReflectorHelper> reflector);
+ ~V4L2ComponentFactory() override = default;
+
+ // Implementation of C2ComponentFactory.
+ c2_status_t createComponent(c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ ComponentDeleter deleter) override;
+ c2_status_t createInterface(c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ InterfaceDeleter deleter) override;
+
+private:
+ const std::string mComponentName;
+ const bool mIsEncoder;
+ std::shared_ptr<C2ReflectorHelper> mReflector;
+};
+
+} // namespace android
+
+#endif // ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_COMPONENT_FACTORY_H
diff --git a/components/include/v4l2_codec2/components/V4L2ComponentStore.h b/components/include/v4l2_codec2/components/V4L2ComponentStore.h
new file mode 100644
index 0000000..bfec407
--- /dev/null
+++ b/components/include/v4l2_codec2/components/V4L2ComponentStore.h
@@ -0,0 +1,61 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_COMPONENT_STORE_H
+#define ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_COMPONENT_STORE_H
+
+#include <map>
+#include <mutex>
+
+#include <C2Component.h>
+#include <C2ComponentFactory.h>
+#include <android-base/thread_annotations.h>
+#include <util/C2InterfaceHelper.h>
+
+namespace android {
+
+class V4L2ComponentStore : public C2ComponentStore {
+public:
+ static std::shared_ptr<C2ComponentStore> Create();
+ ~V4L2ComponentStore();
+
+ // C2ComponentStore implementation.
+ C2String getName() const override;
+ c2_status_t createComponent(C2String name,
+ std::shared_ptr<C2Component>* const component) override;
+ c2_status_t createInterface(C2String name,
+ std::shared_ptr<C2ComponentInterface>* const interface) override;
+ std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
+ std::shared_ptr<C2ParamReflector> getParamReflector() const override;
+ c2_status_t copyBuffer(std::shared_ptr<C2GraphicBuffer> src,
+ std::shared_ptr<C2GraphicBuffer> dst) override;
+ c2_status_t querySupportedParams_nb(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override;
+ c2_status_t query_sm(const std::vector<C2Param*>& stackParams,
+ const std::vector<C2Param::Index>& heapParamIndices,
+ std::vector<std::unique_ptr<C2Param>>* const heapParams) const override;
+ c2_status_t config_sm(const std::vector<C2Param*>& params,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) override;
+ c2_status_t querySupportedValues_sm(
+ std::vector<C2FieldSupportedValuesQuery>& fields) const override;
+
+private:
+ V4L2ComponentStore();
+
+ ::C2ComponentFactory* GetFactory(const C2String& name);
+ std::shared_ptr<const C2Component::Traits> GetTraits(const C2String& name);
+
+ std::shared_ptr<C2ReflectorHelper> mReflector;
+
+ std::mutex mCachedFactoriesLock;
+ std::map<C2String, std::unique_ptr<::C2ComponentFactory>> mCachedFactories
+ GUARDED_BY(mCachedFactoriesLock);
+ std::mutex mCachedTraitsLock;
+ std::map<C2String, std::shared_ptr<const C2Component::Traits>> mCachedTraits
+ GUARDED_BY(mCachedTraitsLock);
+};
+
+} // namespace android
+
+#endif // ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_COMPONENT_STORE_H