aboutsummaryrefslogtreecommitdiff
path: root/components/V4L2ComponentFactory.cpp
blob: a3f883706ca45b897dd09f34f8cda545da1c4435 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 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 "V4L2ComponentFactory"

#include <v4l2_codec2/components/V4L2ComponentFactory.h>

#include <codec2/hidl/1.0/InputBufferManager.h>
#include <log/log.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>

namespace android {

// 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;
    }
    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(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,
                                                  ComponentDeleter deleter) {
    ALOGV("%s(%d), componentName: %s, isEncoder: %d", __func__, id, mComponentName.c_str(),
          mIsEncoder);

    if (mReflector == nullptr) {
        ALOGE("mReflector doesn't exist.");
        return C2_CORRUPTED;
    }

    if (mIsEncoder) {
        *component = V4L2EncodeComponent::create(mComponentName, id, mReflector, deleter);
    } else {
        *component = V4L2DecodeComponent::create(mComponentName, id, mReflector, deleter);
    }
    return *component ? C2_OK : C2_NO_MEMORY;
}

c2_status_t V4L2ComponentFactory::createInterface(
        c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
        InterfaceDeleter deleter) {
    ALOGV("%s(), componentName: %s", __func__, mComponentName.c_str());

    if (mReflector == nullptr) {
        ALOGE("mReflector doesn't exist.");
        return C2_CORRUPTED;
    }

    if (mIsEncoder) {
        *interface = std::shared_ptr<C2ComponentInterface>(
                new SimpleInterface<V4L2EncodeInterface>(
                        mComponentName.c_str(), id,
                        std::make_shared<V4L2EncodeInterface>(mComponentName, mReflector)),
                deleter);
        return C2_OK;
    } else {
        *interface = std::shared_ptr<C2ComponentInterface>(
                new SimpleInterface<V4L2DecodeInterface>(
                        mComponentName.c_str(), id,
                        std::make_shared<V4L2DecodeInterface>(mComponentName, mReflector)),
                deleter);
        return C2_OK;
    }
}

}  // namespace android