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 "V4L2ComponentFactory"
7
8 #include <v4l2_codec2/v4l2/V4L2ComponentFactory.h>
9
10 #include <codec2/hidl/1.0/InputBufferManager.h>
11 #include <log/log.h>
12
13 #include <v4l2_codec2/common/Common.h>
14 #include <v4l2_codec2/components/DecodeInterface.h>
15 #include <v4l2_codec2/components/EncodeInterface.h>
16 #include <v4l2_codec2/v4l2/V4L2ComponentCommon.h>
17 #include <v4l2_codec2/v4l2/V4L2DecodeComponent.h>
18 #include <v4l2_codec2/v4l2/V4L2Device.h>
19 #include <v4l2_codec2/v4l2/V4L2EncodeComponent.h>
20
21 namespace android {
22
23 // static
create(const std::string & componentName,std::shared_ptr<C2ReflectorHelper> reflector)24 std::unique_ptr<V4L2ComponentFactory> V4L2ComponentFactory::create(
25 const std::string& componentName, std::shared_ptr<C2ReflectorHelper> reflector) {
26 ALOGV("%s(%s)", __func__, componentName.c_str());
27
28 if (!android::V4L2ComponentName::isValid(componentName.c_str())) {
29 ALOGE("Invalid component name: %s", componentName.c_str());
30 return nullptr;
31 }
32 if (reflector == nullptr) {
33 ALOGE("reflector is null");
34 return nullptr;
35 }
36
37 bool isEncoder = android::V4L2ComponentName::isEncoder(componentName.c_str());
38 return std::make_unique<V4L2ComponentFactory>(componentName, isEncoder, std::move(reflector));
39 }
40
V4L2ComponentFactory(const std::string & componentName,bool isEncoder,std::shared_ptr<C2ReflectorHelper> reflector)41 V4L2ComponentFactory::V4L2ComponentFactory(const std::string& componentName, bool isEncoder,
42 std::shared_ptr<C2ReflectorHelper> reflector)
43 : mComponentName(componentName), mIsEncoder(isEncoder), mReflector(std::move(reflector)) {
44 using namespace ::android::hardware::media::c2::V1_0;
45 // To minimize IPC, we generally want the codec2 framework to release and
46 // recycle input buffers when the corresponding work item is done. However,
47 // sometimes it is necessary to provide more input to unblock a decoder.
48 //
49 // Optimally we would configure this on a per-context basis. However, the
50 // InputBufferManager is a process-wide singleton, so we need to configure it
51 // pessimistically. Basing the interval on frame timing can be suboptimal if
52 // the decoded output isn't being displayed, but that's not a primary use case
53 // and few videos will actually rely on this behavior.
54 constexpr nsecs_t kMinFrameIntervalNs = 1000000000ull / 60;
55 uint32_t delayCount = 0;
56 for (auto c : kAllCodecs) {
57 delayCount = std::max(delayCount, DecodeInterface::getOutputDelay(c));
58 }
59 utils::InputBufferManager::setNotificationInterval(delayCount * kMinFrameIntervalNs / 2);
60 }
61
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,ComponentDeleter deleter)62 c2_status_t V4L2ComponentFactory::createComponent(c2_node_id_t id,
63 std::shared_ptr<C2Component>* const component,
64 ComponentDeleter deleter) {
65 ALOGV("%s(%d), componentName: %s, isEncoder: %d", __func__, id, mComponentName.c_str(),
66 mIsEncoder);
67
68 if (mReflector == nullptr) {
69 ALOGE("mReflector doesn't exist.");
70 return C2_CORRUPTED;
71 }
72
73 if (mIsEncoder) {
74 std::shared_ptr<EncodeInterface> intfImpl;
75 c2_status_t status = createEncodeInterface(&intfImpl);
76 if (status != C2_OK) {
77 return status;
78 }
79
80 *component = V4L2EncodeComponent::create(mComponentName, id, std::move(intfImpl), deleter);
81 } else {
82 std::shared_ptr<DecodeInterface> intfImpl;
83 c2_status_t status = createDecodeInterface(&intfImpl);
84 if (status != C2_OK) {
85 return status;
86 }
87
88 *component = V4L2DecodeComponent::create(mComponentName, id, std::move(intfImpl), deleter);
89 }
90 return *component ? C2_OK : C2_NO_MEMORY;
91 }
92
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,InterfaceDeleter deleter)93 c2_status_t V4L2ComponentFactory::createInterface(
94 c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
95 InterfaceDeleter deleter) {
96 ALOGV("%s(), componentName: %s", __func__, mComponentName.c_str());
97
98 if (mReflector == nullptr) {
99 ALOGE("mReflector doesn't exist.");
100 return C2_CORRUPTED;
101 }
102
103 if (mIsEncoder) {
104 std::shared_ptr<EncodeInterface> intfImpl;
105 c2_status_t status = createEncodeInterface(&intfImpl);
106 if (status != C2_OK) {
107 return status;
108 }
109
110 *interface = std::shared_ptr<C2ComponentInterface>(
111 new SimpleInterface<EncodeInterface>(mComponentName.c_str(), id,
112 std::move(intfImpl)),
113 deleter);
114 return C2_OK;
115 } else {
116 std::shared_ptr<DecodeInterface> intfImpl;
117 c2_status_t status = createDecodeInterface(&intfImpl);
118 if (status != C2_OK) {
119 return status;
120 }
121
122 *interface = std::shared_ptr<C2ComponentInterface>(
123 new SimpleInterface<DecodeInterface>(mComponentName.c_str(), id,
124 std::move(intfImpl)),
125 deleter);
126 return C2_OK;
127 }
128 }
129
createEncodeInterface(std::shared_ptr<EncodeInterface> * intfImpl)130 c2_status_t V4L2ComponentFactory::createEncodeInterface(
131 std::shared_ptr<EncodeInterface>* intfImpl) {
132 if (!mCapabilites) {
133 auto codec = V4L2ComponentName::getCodec(mComponentName);
134 if (!codec) {
135 return C2_CORRUPTED;
136 }
137 mCapabilites = std::make_unique<SupportedCapabilities>(
138 V4L2Device::queryEncodingCapabilities(*codec));
139 }
140
141 *intfImpl = std::make_shared<EncodeInterface>(mComponentName, mReflector, *mCapabilites);
142 if (*intfImpl == nullptr) {
143 return C2_NO_MEMORY;
144 }
145
146 return (*intfImpl)->status();
147 }
148
createDecodeInterface(std::shared_ptr<DecodeInterface> * intfImpl)149 c2_status_t V4L2ComponentFactory::createDecodeInterface(
150 std::shared_ptr<DecodeInterface>* intfImpl) {
151 if (!mCapabilites) {
152 auto codec = V4L2ComponentName::getCodec(mComponentName);
153 if (!codec) {
154 return C2_CORRUPTED;
155 }
156 mCapabilites = std::make_unique<SupportedCapabilities>(
157 V4L2Device::queryDecodingCapabilities(*codec));
158 }
159
160 *intfImpl = std::make_shared<DecodeInterface>(mComponentName, mReflector, *mCapabilites);
161 if (*intfImpl == nullptr) {
162 return C2_NO_MEMORY;
163 }
164
165 return (*intfImpl)->status();
166 }
167
168 } // namespace android
169