xref: /aosp_15_r20/external/v4l2_codec2/v4l2/V4L2ComponentFactory.cpp (revision 0ec5a0ec62797f775085659156625e7f1bdb369f)
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