You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
4.3 KiB
107 lines
4.3 KiB
4 months ago
|
// 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
|