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/components/V4L2ComponentFactory.h>
9 
10 #include <codec2/hidl/1.0/InputBufferManager.h>
11 #include <log/log.h>
12 
13 #include <v4l2_codec2/common/V4L2ComponentCommon.h>
14 #include <v4l2_codec2/components/V4L2DecodeComponent.h>
15 #include <v4l2_codec2/components/V4L2DecodeInterface.h>
16 #include <v4l2_codec2/components/V4L2EncodeComponent.h>
17 #include <v4l2_codec2/components/V4L2EncodeInterface.h>
18 
19 namespace android {
20 
21 // static
create(const std::string & componentName,std::shared_ptr<C2ReflectorHelper> reflector)22 std::unique_ptr<V4L2ComponentFactory> V4L2ComponentFactory::create(
23         const std::string& componentName, std::shared_ptr<C2ReflectorHelper> reflector) {
24     ALOGV("%s(%s)", __func__, componentName.c_str());
25 
26     if (!android::V4L2ComponentName::isValid(componentName.c_str())) {
27         ALOGE("Invalid component name: %s", componentName.c_str());
28         return nullptr;
29     }
30     if (reflector == nullptr) {
31         ALOGE("reflector is null");
32         return nullptr;
33     }
34 
35     bool isEncoder = android::V4L2ComponentName::isEncoder(componentName.c_str());
36     return std::make_unique<V4L2ComponentFactory>(componentName, isEncoder, std::move(reflector));
37 }
38 
V4L2ComponentFactory(const std::string & componentName,bool isEncoder,std::shared_ptr<C2ReflectorHelper> reflector)39 V4L2ComponentFactory::V4L2ComponentFactory(const std::string& componentName, bool isEncoder,
40                                            std::shared_ptr<C2ReflectorHelper> reflector)
41       : mComponentName(componentName), mIsEncoder(isEncoder), mReflector(std::move(reflector)) {
42     using namespace ::android::hardware::media::c2::V1_0;
43     // To minimize IPC, we generally want the codec2 framework to release and
44     // recycle input buffers when the corresponding work item is done. However,
45     // sometimes it is necessary to provide more input to unblock a decoder.
46     //
47     // Optimally we would configure this on a per-context basis. However, the
48     // InputBufferManager is a process-wide singleton, so we need to configure it
49     // pessimistically. Basing the interval on frame timing can be suboptimal if
50     // the decoded output isn't being displayed, but that's not a primary use case
51     // and few videos will actually rely on this behavior.
52     constexpr nsecs_t kMinFrameIntervalNs = 1000000000ull / 60;
53     uint32_t delayCount = 0;
54     for (auto c : kAllCodecs) {
55         delayCount = std::max(delayCount, V4L2DecodeInterface::getOutputDelay(c));
56     }
57     utils::InputBufferManager::setNotificationInterval(delayCount * kMinFrameIntervalNs / 2);
58 }
59 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,ComponentDeleter deleter)60 c2_status_t V4L2ComponentFactory::createComponent(c2_node_id_t id,
61                                                   std::shared_ptr<C2Component>* const component,
62                                                   ComponentDeleter deleter) {
63     ALOGV("%s(%d), componentName: %s, isEncoder: %d", __func__, id, mComponentName.c_str(),
64           mIsEncoder);
65 
66     if (mReflector == nullptr) {
67         ALOGE("mReflector doesn't exist.");
68         return C2_CORRUPTED;
69     }
70 
71     if (mIsEncoder) {
72         *component = V4L2EncodeComponent::create(mComponentName, id, mReflector, deleter);
73     } else {
74         *component = V4L2DecodeComponent::create(mComponentName, id, mReflector, deleter);
75     }
76     return *component ? C2_OK : C2_NO_MEMORY;
77 }
78 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,InterfaceDeleter deleter)79 c2_status_t V4L2ComponentFactory::createInterface(
80         c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
81         InterfaceDeleter deleter) {
82     ALOGV("%s(), componentName: %s", __func__, mComponentName.c_str());
83 
84     if (mReflector == nullptr) {
85         ALOGE("mReflector doesn't exist.");
86         return C2_CORRUPTED;
87     }
88 
89     if (mIsEncoder) {
90         *interface = std::shared_ptr<C2ComponentInterface>(
91                 new SimpleInterface<V4L2EncodeInterface>(
92                         mComponentName.c_str(), id,
93                         std::make_shared<V4L2EncodeInterface>(mComponentName, mReflector)),
94                 deleter);
95         return C2_OK;
96     } else {
97         *interface = std::shared_ptr<C2ComponentInterface>(
98                 new SimpleInterface<V4L2DecodeInterface>(
99                         mComponentName.c_str(), id,
100                         std::make_shared<V4L2DecodeInterface>(mComponentName, mReflector)),
101                 deleter);
102         return C2_OK;
103     }
104 }
105 
106 }  // namespace android
107