Initial commit for the Codec2.0 HAL
Test: make cts -j123 && cts-tradefed run cts-dev -m \
CtsMediaTestCases --compatibility:module-arg \
CtsMediaTestCases:include-annotation:\
android.platform.test.annotations.RequiresDevice
Bug: 112362730
Change-Id: I26b99ba4b83c527c1caed7492d6d57b7056361e3
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index c5ad6a0..d0296a5 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -8,8 +8,10 @@
srcs: [
"Component.cpp",
+ "ComponentInterface.cpp",
"ComponentStore.cpp",
"Configurable.cpp",
+ "InputBufferManager.cpp",
"InputSurface.cpp",
"InputSurfaceConnection.cpp",
"types.cpp",
diff --git a/media/codec2/hidl/1.0/utils/Component.cpp b/media/codec2/hidl/1.0/utils/Component.cpp
index 5ae1972..0473b57 100644
--- a/media/codec2/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hidl/1.0/utils/Component.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,11 +18,11 @@
#define LOG_TAG "Codec2-Component"
#include <android-base/logging.h>
-#include <C2PlatformSupport.h>
#include <codec2/hidl/1.0/Component.h>
#include <codec2/hidl/1.0/ComponentStore.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
#include <hidl/HidlBinderSupport.h>
#include <utils/Timers.h>
@@ -42,281 +42,6 @@
using namespace ::android;
-namespace /* unnamed */ {
-
-// Implementation of ConfigurableC2Intf based on C2ComponentInterface
-struct CompIntf : public ConfigurableC2Intf {
- CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
- ConfigurableC2Intf(intf->getName()),
- mIntf(intf) {
- }
-
- virtual c2_status_t config(
- const std::vector<C2Param*>& params,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures
- ) override {
- ALOGV("config");
- return mIntf->config_vb(params, mayBlock, failures);
- }
-
- virtual c2_status_t query(
- const std::vector<C2Param::Index>& indices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>>* const params
- ) const override {
- ALOGV("query");
- return mIntf->query_vb({}, indices, mayBlock, params);
- }
-
- virtual c2_status_t querySupportedParams(
- std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
- ) const override {
- ALOGV("querySupportedParams");
- return mIntf->querySupportedParams_nb(params);
- }
-
- virtual c2_status_t querySupportedValues(
- std::vector<C2FieldSupportedValuesQuery>& fields,
- c2_blocking_t mayBlock) const override {
- ALOGV("querySupportedValues");
- return mIntf->querySupportedValues_vb(fields, mayBlock);
- }
-
-protected:
- std::shared_ptr<C2ComponentInterface> mIntf;
-};
-
-} // unnamed namespace
-
-// InputBufferManager
-// ==================
-//
-// InputBufferManager presents a way to track and untrack input buffers in this
-// (codec) process and send a notification to a listener, possibly in a
-// different process, when a tracked buffer no longer has any references in this
-// process. (In fact, this class would work for listeners in the same process
-// too, but the optimization discussed below will not be beneficial.)
-//
-// InputBufferManager holds a collection of records representing tracked buffers
-// and their callback listeners. Conceptually, one record is a triple (listener,
-// frameIndex, bufferIndex) where
-//
-// - (frameIndex, bufferIndex) is a pair of indices used to identify the buffer.
-// - listener is of type IComponentListener. Its onFramesRendered() function
-// will be called after the associated buffer dies. The argument of
-// onFramesRendered() is a list of RenderedFrame objects, each of which has
-// the following members:
-//
-// uint64_t bufferQueueId
-// int32_t slotId
-// int64_t timestampNs
-//
-// When a tracked buffer associated to the triple (listener, frameIndex,
-// bufferIndex) goes out of scope, listener->onFramesRendered() will be called
-// with a RenderedFrame object whose members are set as follows:
-//
-// bufferQueueId = frameIndex
-// slotId = ~bufferIndex
-// timestampNs = systemTime() at the time of notification
-//
-// The reason for the bitwise negation of bufferIndex is that onFramesRendered()
-// may be used for a different purpose when slotId is non-negative (which is a
-// more general use case).
-//
-// IPC Optimization
-// ----------------
-//
-// Since onFramesRendered() generally is an IPC call, InputBufferManager tries
-// not to call it too often. There is a mechanism to guarantee that any two
-// calls to the same listener are at least kNotificationPeriodNs nanoseconds
-// apart.
-//
-struct InputBufferManager {
- // The minimum time period between IPC calls to notify the client about the
- // destruction of input buffers.
- static constexpr nsecs_t kNotificationPeriodNs = 1000000;
-
- // Track all buffers in a C2FrameData object.
- //
- // input (C2FrameData) has the following two members that are of interest:
- //
- // C2WorkOrdinal ordinal
- // vector<shared_ptr<C2Buffer>> buffers
- //
- // Calling registerFrameData(listener, input) will register multiple
- // triples (, frameIndex, bufferIndex) where frameIndex is equal to
- // input.ordinal.frameIndex and bufferIndex runs through the indices of
- // input.buffers such that input.buffers[bufferIndex] is not null.
- //
- // This should be called from queue().
- static void registerFrameData(
- const sp<IComponentListener>& listener,
- const C2FrameData& input);
-
- // Untrack all buffers in a C2FrameData object.
- //
- // Calling unregisterFrameData(listener, input) will unregister and remove
- // pending notifications for all triples (l, fi, bufferIndex) such that
- // l = listener and fi = input.ordinal.frameIndex.
- //
- // This should be called from onWorkDone() and flush().
- static void unregisterFrameData(
- const wp<IComponentListener>& listener,
- const C2FrameData& input);
-
- // Untrack all buffers associated to a given listener.
- //
- // Calling unregisterFrameData(listener) will unregister and remove
- // pending notifications for all triples (l, frameIndex, bufferIndex) such
- // that l = listener.
- //
- // This should be called when the component cleans up all input buffers,
- // i.e., when reset(), release(), stop() or ~Component() is called.
- static void unregisterFrameData(
- const wp<IComponentListener>& listener);
-
-private:
- void _registerFrameData(
- const sp<IComponentListener>& listener,
- const C2FrameData& input);
- void _unregisterFrameData(
- const wp<IComponentListener>& listener,
- const C2FrameData& input);
- void _unregisterFrameData(
- const wp<IComponentListener>& listener);
-
- // The callback function tied to C2Buffer objects.
- //
- // Note: This function assumes that sInstance is the only instance of this
- // class.
- static void onBufferDestroyed(const C2Buffer* buf, void* arg);
- void _onBufferDestroyed(const C2Buffer* buf, void* arg);
-
- // Comparison operator for weak pointers.
- struct CompareWeakComponentListener {
- constexpr bool operator()(
- const wp<IComponentListener>& x,
- const wp<IComponentListener>& y) const {
- return x.get_refs() < y.get_refs();
- }
- };
-
- // Persistent data to be passed as "arg" in onBufferDestroyed().
- // This is essentially the triple (listener, frameIndex, bufferIndex) plus a
- // weak pointer to the C2Buffer object.
- //
- // Note that the "key" is bufferIndex according to operator<(). This is
- // designed to work with TrackedBuffersMap defined below.
- struct TrackedBuffer {
- wp<IComponentListener> listener;
- uint64_t frameIndex;
- size_t bufferIndex;
- std::weak_ptr<C2Buffer> buffer;
- TrackedBuffer(const wp<IComponentListener>& listener,
- uint64_t frameIndex,
- size_t bufferIndex,
- const std::shared_ptr<C2Buffer>& buffer)
- : listener(listener),
- frameIndex(frameIndex),
- bufferIndex(bufferIndex),
- buffer(buffer) {}
- TrackedBuffer(const TrackedBuffer&) = default;
- bool operator<(const TrackedBuffer& other) const {
- return bufferIndex < other.bufferIndex;
- }
- };
-
- // Map: listener -> frameIndex -> set<TrackedBuffer>.
- // Essentially, this is used to store triples (listener, frameIndex,
- // bufferIndex) that's searchable by listener and (listener, frameIndex).
- // However, the value of the innermost map is TrackedBuffer, which also
- // contains an extra copy of listener and frameIndex. This is needed
- // because onBufferDestroyed() needs to know listener and frameIndex too.
- typedef std::map<wp<IComponentListener>,
- std::map<uint64_t,
- std::set<TrackedBuffer>>,
- CompareWeakComponentListener> TrackedBuffersMap;
-
- // Storage for pending (unsent) death notifications for one listener.
- // Each pair in member named "indices" are (frameIndex, bufferIndex) from
- // the (listener, frameIndex, bufferIndex) triple.
- struct DeathNotifications {
-
- // The number of pending notifications for this listener.
- // count may be 0, in which case the DeathNotifications object will
- // remain valid for only a small period (kNotificationPeriodNs
- // nanoseconds).
- size_t count;
-
- // The timestamp of the most recent callback on this listener. This is
- // used to guarantee that callbacks do not occur too frequently, and
- // also to trigger expiration of a DeathNotifications object that has
- // count = 0.
- nsecs_t lastSentNs;
-
- // Map: frameIndex -> vector of bufferIndices
- // This is essentially a collection of (framdeIndex, bufferIndex).
- std::map<uint64_t, std::vector<size_t>> indices;
-
- DeathNotifications()
- : count(0),
- lastSentNs(systemTime() - kNotificationPeriodNs),
- indices() {}
- };
-
- // Mutex for the management of all input buffers.
- std::mutex mMutex;
-
- // Tracked input buffers.
- TrackedBuffersMap mTrackedBuffersMap;
-
- // Death notifications to be sent.
- //
- // A DeathNotifications object is associated to each listener. An entry in
- // this map will be removed if its associated DeathNotifications has count =
- // 0 and lastSentNs < systemTime() - kNotificationPeriodNs.
- std::map<wp<IComponentListener>, DeathNotifications> mDeathNotifications;
-
- // Condition variable signaled when an entry is added to mDeathNotifications.
- std::condition_variable mOnBufferDestroyed;
-
- // Notify the clients about buffer destructions.
- // Return false if all destructions have been notified.
- // Return true and set timeToRetry to the duration to wait for before
- // retrying if some destructions have not been notified.
- bool processNotifications(nsecs_t* timeToRetryNs);
-
- // Main function for the input buffer manager thread.
- void main();
-
- // The thread that manages notifications.
- //
- // Note: This variable is declared last so its initialization will happen
- // after all other member variables have been initialized.
- std::thread mMainThread;
-
- // Private constructor.
- InputBufferManager();
-
- // The only instance of this class.
- static InputBufferManager& getInstance();
-
-};
-
-// ComponentInterface
-ComponentInterface::ComponentInterface(
- const std::shared_ptr<C2ComponentInterface>& intf,
- const sp<ComponentStore>& store) :
- Configurable(new CachedConfigurable(std::make_unique<CompIntf>(intf))),
- mInterface(intf) {
- mInit = init(store.get());
-}
-
-c2_status_t ComponentInterface::status() const {
- return mInit;
-}
-
// ComponentListener wrapper
struct Component::Listener : public C2Component::Listener {
@@ -328,12 +53,12 @@
virtual void onError_nb(
std::weak_ptr<C2Component> /* c2component */,
uint32_t errorCode) override {
- ALOGV("onError");
sp<IComponentListener> listener = mListener.promote();
if (listener) {
Return<void> transStatus = listener->onError(Status::OK, errorCode);
if (!transStatus.isOk()) {
- ALOGE("onError -- transaction failed.");
+ LOG(ERROR) << "Component::Listener::onError_nb -- "
+ << "transaction failed.";
}
}
}
@@ -342,7 +67,6 @@
std::weak_ptr<C2Component> /* c2component */,
std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
) override {
- ALOGV("onTripped");
sp<IComponentListener> listener = mListener.promote();
if (listener) {
hidl_vec<SettingResult> settingResults(c2settingResult.size());
@@ -350,8 +74,7 @@
for (const std::shared_ptr<C2SettingResult> &c2result :
c2settingResult) {
if (c2result) {
- if (objcpy(&settingResults[ix++], *c2result) !=
- Status::OK) {
+ if (!objcpy(&settingResults[ix++], *c2result)) {
break;
}
}
@@ -359,7 +82,8 @@
settingResults.resize(ix);
Return<void> transStatus = listener->onTripped(settingResults);
if (!transStatus.isOk()) {
- ALOGE("onTripped -- transaction failed.");
+ LOG(ERROR) << "Component::Listener::onTripped_nb -- "
+ << "transaction failed.";
}
}
}
@@ -367,7 +91,6 @@
virtual void onWorkDone_nb(
std::weak_ptr<C2Component> /* c2component */,
std::list<std::unique_ptr<C2Work>> c2workItems) override {
- ALOGV("onWorkDone");
for (const std::unique_ptr<C2Work>& work : c2workItems) {
if (work) {
if (work->worklets.empty()
@@ -385,15 +108,16 @@
WorkBundle workBundle;
sp<Component> strongComponent = mComponent.promote();
- if (objcpy(&workBundle, c2workItems, strongComponent ?
- &strongComponent->mBufferPoolSender : nullptr)
- != Status::OK) {
- ALOGE("onWorkDone() received corrupted work items.");
+ if (!objcpy(&workBundle, c2workItems, strongComponent ?
+ &strongComponent->mBufferPoolSender : nullptr)) {
+ LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+ << "received corrupted work items.";
return;
}
Return<void> transStatus = listener->onWorkDone(workBundle);
if (!transStatus.isOk()) {
- ALOGE("onWorkDone -- transaction failed.");
+ LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+ << "transaction failed.";
return;
}
yieldBufferQueueBlocks(c2workItems, true);
@@ -405,23 +129,86 @@
wp<IComponentListener> mListener;
};
+// Component::Sink
+struct Component::Sink : public IInputSink {
+ std::shared_ptr<Component> mComponent;
+ sp<IConfigurable> mConfigurable;
+
+ virtual Return<Status> queue(const WorkBundle& workBundle) override {
+ return mComponent->queue(workBundle);
+ }
+
+ virtual Return<sp<IConfigurable>> getConfigurable() override {
+ return mConfigurable;
+ }
+
+ Sink(const std::shared_ptr<Component>& component);
+ virtual ~Sink() override;
+
+ // Process-wide map: Component::Sink -> C2Component.
+ static std::mutex sSink2ComponentMutex;
+ static std::map<IInputSink*, std::weak_ptr<C2Component>> sSink2Component;
+
+ static std::shared_ptr<C2Component> findLocalComponent(
+ const sp<IInputSink>& sink);
+};
+
+std::mutex
+ Component::Sink::sSink2ComponentMutex{};
+std::map<IInputSink*, std::weak_ptr<C2Component>>
+ Component::Sink::sSink2Component{};
+
+Component::Sink::Sink(const std::shared_ptr<Component>& component)
+ : mComponent{component},
+ mConfigurable{[&component]() -> sp<IConfigurable> {
+ Return<sp<IComponentInterface>> ret1 = component->getInterface();
+ if (!ret1.isOk()) {
+ LOG(ERROR) << "Sink::Sink -- component's transaction failed.";
+ return nullptr;
+ }
+ Return<sp<IConfigurable>> ret2 =
+ static_cast<sp<IComponentInterface>>(ret1)->
+ getConfigurable();
+ if (!ret2.isOk()) {
+ LOG(ERROR) << "Sink::Sink -- interface's transaction failed.";
+ return nullptr;
+ }
+ return static_cast<sp<IConfigurable>>(ret2);
+ }()} {
+ std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+ sSink2Component.emplace(this, component->mComponent);
+}
+
+Component::Sink::~Sink() {
+ std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+ sSink2Component.erase(this);
+}
+
+std::shared_ptr<C2Component> Component::Sink::findLocalComponent(
+ const sp<IInputSink>& sink) {
+ std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+ auto i = sSink2Component.find(sink.get());
+ if (i == sSink2Component.end()) {
+ return nullptr;
+ }
+ return i->second.lock();
+}
+
// Component
Component::Component(
const std::shared_ptr<C2Component>& component,
const sp<IComponentListener>& listener,
const sp<ComponentStore>& store,
const sp<::android::hardware::media::bufferpool::V2_0::
- IClientManager>& clientPoolManager) :
- Configurable(new CachedConfigurable(
- std::make_unique<CompIntf>(component->intf()))),
- mComponent(component),
- mInterface(component->intf()),
- mListener(listener),
- mStore(store),
- mBufferPoolSender(clientPoolManager) {
+ IClientManager>& clientPoolManager)
+ : mComponent{component},
+ mInterface{new ComponentInterface(component->intf(), store.get())},
+ mListener{listener},
+ mStore{store},
+ mBufferPoolSender{clientPoolManager} {
// Retrieve supported parameters from store
// TODO: We could cache this per component/interface type
- mInit = init(store.get());
+ mInit = mInterface->status();
}
c2_status_t Component::status() const {
@@ -430,11 +217,9 @@
// Methods from ::android::hardware::media::c2::V1_0::IComponent
Return<Status> Component::queue(const WorkBundle& workBundle) {
- ALOGV("queue -- converting input");
std::list<std::unique_ptr<C2Work>> c2works;
- if (objcpy(&c2works, workBundle) != C2_OK) {
- ALOGV("queue -- corrupted");
+ if (!objcpy(&c2works, workBundle)) {
return Status::CORRUPTED;
}
@@ -446,13 +231,11 @@
}
}
- ALOGV("queue -- calling");
return static_cast<Status>(mComponent->queue_nb(&c2works));
}
Return<void> Component::flush(flush_cb _hidl_cb) {
std::list<std::unique_ptr<C2Work>> c2flushedWorks;
- ALOGV("flush -- calling");
c2_status_t c2res = mComponent->flush_sm(
C2Component::FLUSH_COMPONENT,
&c2flushedWorks);
@@ -473,8 +256,9 @@
WorkBundle flushedWorkBundle;
Status res = static_cast<Status>(c2res);
if (c2res == C2_OK) {
- ALOGV("flush -- converting output");
- res = objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender);
+ if (!objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+ res = Status::CORRUPTED;
+ }
}
_hidl_cb(res, flushedWorkBundle);
yieldBufferQueueBlocks(c2flushedWorks, true);
@@ -482,7 +266,6 @@
}
Return<Status> Component::drain(bool withEos) {
- ALOGV("drain");
return static_cast<Status>(mComponent->drain_nb(withEos ?
C2Component::DRAIN_COMPONENT_WITH_EOS :
C2Component::DRAIN_COMPONENT_NO_EOS));
@@ -512,14 +295,39 @@
return Status::OK;
}
-Return<Status> Component::connectToOmxInputSurface(
+Return<void> Component::connectToInputSurface(
+ const sp<IInputSurface>& inputSurface,
+ connectToInputSurface_cb _hidl_cb) {
+ sp<Sink> sink;
+ {
+ std::lock_guard<std::mutex> lock(mSinkMutex);
+ if (!mSink) {
+ mSink = new Sink(shared_from_this());
+ }
+ sink = mSink;
+ }
+ Status status;
+ sp<IInputSurfaceConnection> connection;
+ auto transStatus = inputSurface->connect(sink,
+ [&status, &connection](Status s,
+ const sp<IInputSurfaceConnection>& c) {
+ status = s;
+ connection = c;
+ }
+ );
+ _hidl_cb(status, connection);
+ return Void();
+}
+
+Return<void> Component::connectToOmxInputSurface(
const sp<HGraphicBufferProducer>& producer,
const sp<::android::hardware::media::omx::V1_0::
- IGraphicBufferSource>& source) {
- // TODO implement
+ IGraphicBufferSource>& source,
+ connectToOmxInputSurface_cb _hidl_cb) {
(void)producer;
(void)source;
- return Status::OMITTED;
+ (void)_hidl_cb;
+ return Void();
}
Return<Status> Component::disconnectFromInputSurface() {
@@ -530,11 +338,12 @@
namespace /* unnamed */ {
struct BlockPoolIntf : public ConfigurableC2Intf {
- BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool) :
- ConfigurableC2Intf("C2BlockPool:" +
- (pool ? std::to_string(pool->getLocalId()) :
- "null")),
- mPool(pool) {
+ BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
+ : ConfigurableC2Intf{
+ "C2BlockPool:" +
+ (pool ? std::to_string(pool->getLocalId()) : "null"),
+ 0},
+ mPool{pool} {
}
virtual c2_status_t config(
@@ -613,18 +422,15 @@
}
Return<Status> Component::start() {
- ALOGV("start");
return static_cast<Status>(mComponent->start());
}
Return<Status> Component::stop() {
- ALOGV("stop");
InputBufferManager::unregisterFrameData(mListener);
return static_cast<Status>(mComponent->stop());
}
Return<Status> Component::reset() {
- ALOGV("reset");
Status status = static_cast<Status>(mComponent->reset());
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
@@ -635,7 +441,6 @@
}
Return<Status> Component::release() {
- ALOGV("release");
Status status = static_cast<Status>(mComponent->release());
{
std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
@@ -645,8 +450,13 @@
return status;
}
-void Component::setLocalId(const Component::LocalId& localId) {
- mLocalId = localId;
+Return<sp<IComponentInterface>> Component::getInterface() {
+ return sp<IComponentInterface>(mInterface);
+}
+
+std::shared_ptr<C2Component> Component::findLocalComponent(
+ const sp<IInputSink>& sink) {
+ return Component::Sink::findLocalComponent(sink);
}
void Component::initListener(const sp<Component>& self) {
@@ -660,395 +470,7 @@
Component::~Component() {
InputBufferManager::unregisterFrameData(mListener);
- mStore->reportComponentDeath(mLocalId);
-}
-
-Component::InterfaceKey::InterfaceKey(const sp<IComponent>& component) {
- isRemote = component->isRemote();
- if (isRemote) {
- remote = ::android::hardware::toBinder(component);
- } else {
- local = component;
- }
-}
-
-// InputBufferManager implementation
-
-constexpr nsecs_t InputBufferManager::kNotificationPeriodNs;
-
-void InputBufferManager::registerFrameData(
- const sp<IComponentListener>& listener,
- const C2FrameData& input) {
- getInstance()._registerFrameData(listener, input);
-}
-
-void InputBufferManager::unregisterFrameData(
- const wp<IComponentListener>& listener,
- const C2FrameData& input) {
- getInstance()._unregisterFrameData(listener, input);
-}
-
-void InputBufferManager::unregisterFrameData(
- const wp<IComponentListener>& listener) {
- getInstance()._unregisterFrameData(listener);
-}
-
-void InputBufferManager::_registerFrameData(
- const sp<IComponentListener>& listener,
- const C2FrameData& input) {
- uint64_t frameIndex = input.ordinal.frameIndex.peeku();
- ALOGV("InputBufferManager::_registerFrameData called "
- "(listener @ %p, frameIndex = %llu)",
- listener.get(),
- static_cast<long long unsigned>(frameIndex));
- std::lock_guard<std::mutex> lock(mMutex);
-
- std::set<TrackedBuffer> &bufferIds =
- mTrackedBuffersMap[listener][frameIndex];
-
- for (size_t i = 0; i < input.buffers.size(); ++i) {
- if (!input.buffers[i]) {
- ALOGV("InputBufferManager::_registerFrameData: "
- "Input buffer at index %zu is null", i);
- continue;
- }
- const TrackedBuffer &bufferId =
- *bufferIds.emplace(listener, frameIndex, i, input.buffers[i]).
- first;
-
- c2_status_t status = input.buffers[i]->registerOnDestroyNotify(
- onBufferDestroyed,
- const_cast<void*>(reinterpret_cast<const void*>(&bufferId)));
- if (status != C2_OK) {
- ALOGD("InputBufferManager: registerOnDestroyNotify failed "
- "(listener @ %p, frameIndex = %llu, bufferIndex = %zu) "
- "=> %s (%d)",
- listener.get(),
- static_cast<unsigned long long>(frameIndex),
- i,
- asString(status), static_cast<int>(status));
- }
- }
-
- mDeathNotifications.emplace(listener, DeathNotifications());
-}
-
-// Remove a pair (listener, frameIndex) from mTrackedBuffersMap and
-// mDeathNotifications. This implies all bufferIndices are removed.
-//
-// This is called from onWorkDone() and flush().
-void InputBufferManager::_unregisterFrameData(
- const wp<IComponentListener>& listener,
- const C2FrameData& input) {
- uint64_t frameIndex = input.ordinal.frameIndex.peeku();
- ALOGV("InputBufferManager::_unregisterFrameData called "
- "(listener @ %p, frameIndex = %llu)",
- listener.unsafe_get(),
- static_cast<long long unsigned>(frameIndex));
- std::lock_guard<std::mutex> lock(mMutex);
-
- auto findListener = mTrackedBuffersMap.find(listener);
- if (findListener != mTrackedBuffersMap.end()) {
- std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds
- = findListener->second;
- auto findFrameIndex = frameIndex2BufferIds.find(frameIndex);
- if (findFrameIndex != frameIndex2BufferIds.end()) {
- std::set<TrackedBuffer> &bufferIds = findFrameIndex->second;
- for (const TrackedBuffer& bufferId : bufferIds) {
- std::shared_ptr<C2Buffer> buffer = bufferId.buffer.lock();
- if (buffer) {
- c2_status_t status = buffer->unregisterOnDestroyNotify(
- onBufferDestroyed,
- const_cast<void*>(
- reinterpret_cast<const void*>(&bufferId)));
- if (status != C2_OK) {
- ALOGD("InputBufferManager: "
- "unregisterOnDestroyNotify failed "
- "(listener @ %p, "
- "frameIndex = %llu, "
- "bufferIndex = %zu) "
- "=> %s (%d)",
- bufferId.listener.unsafe_get(),
- static_cast<unsigned long long>(
- bufferId.frameIndex),
- bufferId.bufferIndex,
- asString(status), static_cast<int>(status));
- }
- }
- }
-
- frameIndex2BufferIds.erase(findFrameIndex);
- if (frameIndex2BufferIds.empty()) {
- mTrackedBuffersMap.erase(findListener);
- }
- }
- }
-
- auto findListenerD = mDeathNotifications.find(listener);
- if (findListenerD != mDeathNotifications.end()) {
- DeathNotifications &deathNotifications = findListenerD->second;
- auto findFrameIndex = deathNotifications.indices.find(frameIndex);
- if (findFrameIndex != deathNotifications.indices.end()) {
- std::vector<size_t> &bufferIndices = findFrameIndex->second;
- deathNotifications.count -= bufferIndices.size();
- deathNotifications.indices.erase(findFrameIndex);
- }
- }
-}
-
-// Remove listener from mTrackedBuffersMap and mDeathNotifications. This implies
-// all frameIndices and bufferIndices are removed.
-//
-// This is called when the component cleans up all input buffers, i.e., when
-// reset(), release(), stop() or ~Component() is called.
-void InputBufferManager::_unregisterFrameData(
- const wp<IComponentListener>& listener) {
- ALOGV("InputBufferManager::_unregisterFrameData called (listener @ %p)",
- listener.unsafe_get());
- std::lock_guard<std::mutex> lock(mMutex);
-
- auto findListener = mTrackedBuffersMap.find(listener);
- if (findListener != mTrackedBuffersMap.end()) {
- std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds =
- findListener->second;
- for (auto findFrameIndex = frameIndex2BufferIds.begin();
- findFrameIndex != frameIndex2BufferIds.end();
- ++findFrameIndex) {
- std::set<TrackedBuffer> &bufferIds = findFrameIndex->second;
- for (const TrackedBuffer& bufferId : bufferIds) {
- std::shared_ptr<C2Buffer> buffer = bufferId.buffer.lock();
- if (buffer) {
- c2_status_t status = buffer->unregisterOnDestroyNotify(
- onBufferDestroyed,
- const_cast<void*>(
- reinterpret_cast<const void*>(&bufferId)));
- if (status != C2_OK) {
- ALOGD("InputBufferManager: "
- "unregisterOnDestroyNotify failed "
- "(listener @ %p, "
- "frameIndex = %llu, "
- "bufferIndex = %zu) "
- "=> %s (%d)",
- bufferId.listener.unsafe_get(),
- static_cast<unsigned long long>(bufferId.frameIndex),
- bufferId.bufferIndex,
- asString(status), static_cast<int>(status));
- }
- }
- }
- }
- mTrackedBuffersMap.erase(findListener);
- }
-
- mDeathNotifications.erase(listener);
-}
-
-// Move a buffer from mTrackedBuffersMap to mDeathNotifications.
-// This is called when a registered C2Buffer object is destroyed.
-void InputBufferManager::onBufferDestroyed(const C2Buffer* buf, void* arg) {
- getInstance()._onBufferDestroyed(buf, arg);
-}
-
-void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) {
- if (!buf || !arg) {
- ALOGW("InputBufferManager::_onBufferDestroyed called "
- "with null argument(s) (buf @ %p, arg @ %p)",
- buf, arg);
- return;
- }
- TrackedBuffer id(*reinterpret_cast<TrackedBuffer*>(arg));
- ALOGV("InputBufferManager::_onBufferDestroyed called "
- "(listener @ %p, frameIndex = %llu, bufferIndex = %zu)",
- id.listener.unsafe_get(),
- static_cast<unsigned long long>(id.frameIndex),
- id.bufferIndex);
-
- std::lock_guard<std::mutex> lock(mMutex);
-
- auto findListener = mTrackedBuffersMap.find(id.listener);
- if (findListener == mTrackedBuffersMap.end()) {
- ALOGD("InputBufferManager::_onBufferDestroyed received "
- "invalid listener "
- "(listener @ %p, frameIndex = %llu, bufferIndex = %zu)",
- id.listener.unsafe_get(),
- static_cast<unsigned long long>(id.frameIndex),
- id.bufferIndex);
- return;
- }
-
- std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds
- = findListener->second;
- auto findFrameIndex = frameIndex2BufferIds.find(id.frameIndex);
- if (findFrameIndex == frameIndex2BufferIds.end()) {
- ALOGD("InputBufferManager::_onBufferDestroyed received "
- "invalid frame index "
- "(listener @ %p, frameIndex = %llu, bufferIndex = %zu)",
- id.listener.unsafe_get(),
- static_cast<unsigned long long>(id.frameIndex),
- id.bufferIndex);
- return;
- }
-
- std::set<TrackedBuffer> &bufferIds = findFrameIndex->second;
- auto findBufferId = bufferIds.find(id);
- if (findBufferId == bufferIds.end()) {
- ALOGD("InputBufferManager::_onBufferDestroyed received "
- "invalid buffer index: "
- "(listener @ %p, frameIndex = %llu, bufferIndex = %zu)",
- id.listener.unsafe_get(),
- static_cast<unsigned long long>(id.frameIndex),
- id.bufferIndex);
- }
-
- bufferIds.erase(findBufferId);
- if (bufferIds.empty()) {
- frameIndex2BufferIds.erase(findFrameIndex);
- if (frameIndex2BufferIds.empty()) {
- mTrackedBuffersMap.erase(findListener);
- }
- }
-
- DeathNotifications &deathNotifications = mDeathNotifications[id.listener];
- deathNotifications.indices[id.frameIndex].emplace_back(id.bufferIndex);
- ++deathNotifications.count;
- mOnBufferDestroyed.notify_one();
-}
-
-// Notify the clients about buffer destructions.
-// Return false if all destructions have been notified.
-// Return true and set timeToRetry to the time point to wait for before
-// retrying if some destructions have not been notified.
-bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
-
- struct Notification {
- sp<IComponentListener> listener;
- hidl_vec<IComponentListener::RenderedFrame> renderedFrames;
- Notification(const sp<IComponentListener>& l, size_t s)
- : listener(l), renderedFrames(s) {}
- };
- std::list<Notification> notifications;
-
- bool retry = false;
- {
- std::lock_guard<std::mutex> lock(mMutex);
- *timeToRetryNs = kNotificationPeriodNs;
- nsecs_t timeNowNs = systemTime();
- for (auto it = mDeathNotifications.begin();
- it != mDeathNotifications.end(); ) {
- sp<IComponentListener> listener = it->first.promote();
- if (!listener) {
- ++it;
- continue;
- }
- DeathNotifications &deathNotifications = it->second;
-
- nsecs_t timeSinceLastNotifiedNs =
- timeNowNs - deathNotifications.lastSentNs;
- // If not enough time has passed since the last callback, leave the
- // notifications for this listener untouched for now and retry
- // later.
- if (timeSinceLastNotifiedNs < kNotificationPeriodNs) {
- retry = true;
- *timeToRetryNs = std::min(*timeToRetryNs,
- kNotificationPeriodNs - timeSinceLastNotifiedNs);
- ALOGV("InputBufferManager: Notifications for "
- "listener @ %p will be postponed.",
- listener.get());
- ++it;
- continue;
- }
-
- // If enough time has passed since the last notification to this
- // listener but there are currently no pending notifications, the
- // listener can be removed from mDeathNotifications---there is no
- // need to keep track of the last notification time anymore.
- if (deathNotifications.count == 0) {
- it = mDeathNotifications.erase(it);
- continue;
- }
-
- // Create the argument for the callback.
- notifications.emplace_back(listener, deathNotifications.count);
- hidl_vec<IComponentListener::RenderedFrame>& renderedFrames =
- notifications.back().renderedFrames;
- size_t i = 0;
- for (std::pair<const uint64_t, std::vector<size_t>>& p :
- deathNotifications.indices) {
- uint64_t frameIndex = p.first;
- const std::vector<size_t> &bufferIndices = p.second;
- for (const size_t& bufferIndex : bufferIndices) {
- IComponentListener::RenderedFrame &renderedFrame
- = renderedFrames[i++];
- renderedFrame.slotId = ~bufferIndex;
- renderedFrame.bufferQueueId = frameIndex;
- renderedFrame.timestampNs = timeNowNs;
- ALOGV("InputBufferManager: "
- "Sending death notification (listener @ %p, "
- "frameIndex = %llu, bufferIndex = %zu)",
- listener.get(),
- static_cast<long long unsigned>(frameIndex),
- bufferIndex);
- }
- }
-
- // Clear deathNotifications for this listener and set retry to true
- // so processNotifications will be called again. This will
- // guarantee that a listener with no pending notifications will
- // eventually be removed from mDeathNotifications after
- // kNotificationPeriodNs nanoseconds has passed.
- retry = true;
- deathNotifications.indices.clear();
- deathNotifications.count = 0;
- deathNotifications.lastSentNs = timeNowNs;
- ++it;
- }
- }
-
- // Call onFramesRendered outside the lock to avoid deadlock.
- for (const Notification& notification : notifications) {
- if (!notification.listener->onFramesRendered(
- notification.renderedFrames).isOk()) {
- // This may trigger if the client has died.
- ALOGD("InputBufferManager: onFramesRendered transaction failed "
- "(listener @ %p)",
- notification.listener.get());
- }
- }
- if (retry) {
- ALOGV("InputBufferManager: Pending death notifications"
- "will be sent in %lldns.",
- static_cast<long long>(*timeToRetryNs));
- }
- return retry;
-}
-
-void InputBufferManager::main() {
- ALOGV("InputBufferManager: Starting main thread");
- nsecs_t timeToRetryNs;
- while (true) {
- std::unique_lock<std::mutex> lock(mMutex);
- while (mDeathNotifications.empty()) {
- ALOGV("InputBufferManager: Waiting for buffer deaths");
- mOnBufferDestroyed.wait(lock);
- }
- lock.unlock();
- ALOGV("InputBufferManager: Sending buffer death notifications");
- while (processNotifications(&timeToRetryNs)) {
- std::this_thread::sleep_for(
- std::chrono::nanoseconds(timeToRetryNs));
- ALOGV("InputBufferManager: Sending pending death notifications");
- }
- ALOGV("InputBufferManager: No pending death notifications");
- }
-}
-
-InputBufferManager::InputBufferManager()
- : mMainThread(&InputBufferManager::main, this) {
-}
-
-InputBufferManager& InputBufferManager::getInstance() {
- static InputBufferManager instance{};
- return instance;
+ mStore->reportComponentDeath(this);
}
} // namespace utils
diff --git a/media/codec2/hidl/1.0/utils/ComponentInterface.cpp b/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
new file mode 100644
index 0000000..39e5357
--- /dev/null
+++ b/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentInterface"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/ComponentStore.h>
+
+#include <hidl/HidlBinderSupport.h>
+#include <utils/Timers.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+namespace /* unnamed */ {
+
+// Implementation of ConfigurableC2Intf based on C2ComponentInterface
+struct CompIntf : public ConfigurableC2Intf {
+ CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
+ ConfigurableC2Intf{intf->getName(), intf->getId()},
+ mIntf{intf} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*>& params,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ return mIntf->config_vb(params, mayBlock, failures);
+ }
+
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index>& indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params
+ ) const override {
+ return mIntf->query_vb({}, indices, mayBlock, params);
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ return mIntf->querySupportedParams_nb(params);
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields,
+ c2_blocking_t mayBlock) const override {
+ return mIntf->querySupportedValues_vb(fields, mayBlock);
+ }
+
+protected:
+ std::shared_ptr<C2ComponentInterface> mIntf;
+};
+
+} // unnamed namespace
+
+// ComponentInterface
+ComponentInterface::ComponentInterface(
+ const std::shared_ptr<C2ComponentInterface>& intf,
+ ComponentStore* store)
+ : mInterface{intf},
+ mConfigurable{new CachedConfigurable(std::make_unique<CompIntf>(intf))} {
+ mInit = mConfigurable->init(store);
+}
+
+c2_status_t ComponentInterface::status() const {
+ return mInit;
+}
+
+Return<sp<IConfigurable>> ComponentInterface::getConfigurable() {
+ return mConfigurable;
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index 9c05014..bb5faa5 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,37 +16,25 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-ComponentStore"
-#include <log/log.h>
+#include <android-base/logging.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/InputSurface.h>
-#include <codec2/hidl/1.0/Component.h>
-#include <codec2/hidl/1.0/ConfigurableC2Intf.h>
#include <codec2/hidl/1.0/types.h>
+#include <android-base/file.h>
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <utils/Errors.h>
#include <C2PlatformSupport.h>
#include <util/C2InterfaceHelper.h>
-#include <utils/Errors.h>
-
-#include <android-base/file.h>
-
-#ifdef LOG
-#undef LOG
-#endif
-
-#ifdef PLOG
-#undef PLOG
-#endif
-
-#include <android-base/logging.h>
-
+#include <chrono>
+#include <ctime>
+#include <iomanip>
#include <ostream>
#include <sstream>
-#include <iomanip>
namespace android {
namespace hardware {
@@ -62,12 +50,12 @@
namespace /* unnamed */ {
struct StoreIntf : public ConfigurableC2Intf {
- StoreIntf(const std::shared_ptr<C2ComponentStore>& store) :
- ConfigurableC2Intf(store ? store->getName() : ""),
- mStore(store) {
+ StoreIntf(const std::shared_ptr<C2ComponentStore>& store)
+ : ConfigurableC2Intf{store ? store->getName() : "", 0},
+ mStore{store} {
}
- c2_status_t config(
+ virtual c2_status_t config(
const std::vector<C2Param*> ¶ms,
c2_blocking_t mayBlock,
std::vector<std::unique_ptr<C2SettingResult>> *const failures
@@ -80,7 +68,7 @@
return mStore->config_sm(params, failures);
}
- c2_status_t query(
+ virtual c2_status_t query(
const std::vector<C2Param::Index> &indices,
c2_blocking_t mayBlock,
std::vector<std::unique_ptr<C2Param>> *const params) const override {
@@ -92,13 +80,13 @@
return mStore->query_sm({}, indices, params);
}
- c2_status_t querySupportedParams(
+ virtual c2_status_t querySupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
) const override {
return mStore->querySupportedParams_nb(params);
}
- c2_status_t querySupportedValues(
+ virtual c2_status_t querySupportedValues(
std::vector<C2FieldSupportedValuesQuery> &fields,
c2_blocking_t mayBlock) const override {
// Assume all params are blocking
@@ -115,9 +103,9 @@
} // unnamed namespace
-ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store) :
- Configurable(new CachedConfigurable(std::make_unique<StoreIntf>(store))),
- mStore(store) {
+ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
+ : mConfigurable{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
+ mStore{store} {
std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
SetPreferredCodec2ComponentStore(store);
@@ -126,7 +114,11 @@
mParamReflector = mStore->getParamReflector();
// Retrieve supported parameters from store
- mInit = init(this);
+ mInit = mConfigurable->init(this);
+}
+
+c2_status_t ComponentStore::status() const {
+ return mInit;
}
c2_status_t ComponentStore::validateSupportedParams(
@@ -172,19 +164,15 @@
component = new Component(c2component, listener, this, pool);
if (!component) {
status = Status::CORRUPTED;
- } else if (component->status() != C2_OK) {
- status = static_cast<Status>(component->status());
} else {
- component->initListener(component);
+ reportComponentBirth(component.get());
if (component->status() != C2_OK) {
status = static_cast<Status>(component->status());
} else {
- std::lock_guard<std::mutex> lock(mComponentRosterMutex);
- component->setLocalId(
- mComponentRoster.emplace(
- Component::InterfaceKey(component),
- c2component)
- .first);
+ component->initListener(component);
+ if (component->status() != C2_OK) {
+ status = static_cast<Status>(component->status());
+ }
}
}
}
@@ -202,7 +190,7 @@
onInterfaceLoaded(c2interface);
interface = new ComponentInterface(c2interface, this);
}
- _hidl_cb((Status)res, interface);
+ _hidl_cb(static_cast<Status>(res), interface);
return Void();
}
@@ -213,27 +201,35 @@
size_t ix = 0;
for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
if (c2trait) {
- objcpy(&traits[ix++], *c2trait);
+ if (objcpy(&traits[ix], *c2trait)) {
+ ++ix;
+ } else {
+ break;
+ }
}
}
traits.resize(ix);
- _hidl_cb(traits);
+ _hidl_cb(Status::OK, traits);
return Void();
}
-Return<sp<IInputSurface>> ComponentStore::createInputSurface() {
+Return<void> ComponentStore::createInputSurface(createInputSurface_cb _hidl_cb) {
sp<GraphicBufferSource> source = new GraphicBufferSource();
if (source->initCheck() != OK) {
- return nullptr;
+ _hidl_cb(Status::CORRUPTED, nullptr);
+ return Void();
}
typedef ::android::hardware::graphics::bufferqueue::V1_0::
IGraphicBufferProducer HGbp;
typedef ::android::TWGraphicBufferProducer<HGbp> B2HGbp;
- return new InputSurface(
+ sp<InputSurface> inputSurface = new InputSurface(
this,
std::make_shared<C2ReflectorHelper>(),
new B2HGbp(source->getIGraphicBufferProducer()),
source);
+ _hidl_cb(inputSurface ? Status::OK : Status::NO_MEMORY,
+ inputSurface);
+ return Void();
}
void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
@@ -265,15 +261,25 @@
mUnsupportedStructDescriptors.emplace(coreIndex);
} else {
mStructDescriptors.insert({ coreIndex, structDesc });
- objcpy(&descriptors[dstIx++], *structDesc);
- continue;
+ if (objcpy(&descriptors[dstIx], *structDesc)) {
+ ++dstIx;
+ continue;
+ }
+ res = Status::CORRUPTED;
+ break;
}
}
res = Status::NOT_FOUND;
} else if (item->second) {
- objcpy(&descriptors[dstIx++], *item->second);
+ if (objcpy(&descriptors[dstIx], *item->second)) {
+ ++dstIx;
+ continue;
+ }
+ res = Status::CORRUPTED;
+ break;
} else {
res = Status::NO_MEMORY;
+ break;
}
}
descriptors.resize(dstIx);
@@ -292,29 +298,29 @@
return Status::OMITTED;
}
-void ComponentStore::reportComponentDeath(
- const Component::LocalId& componentLocalId) {
- std::lock_guard<std::mutex> lock(mComponentRosterMutex);
- mComponentRoster.erase(componentLocalId);
+Return<sp<IConfigurable>> ComponentStore::getConfigurable() {
+ return mConfigurable;
}
-std::shared_ptr<C2Component> ComponentStore::findC2Component(
- const sp<IComponent>& component) const {
+// Called from createComponent() after a successful creation of `component`.
+void ComponentStore::reportComponentBirth(Component* component) {
+ ComponentStatus componentStatus;
+ componentStatus.c2Component = component->mComponent;
+ componentStatus.birthTime = std::chrono::system_clock::now();
+
std::lock_guard<std::mutex> lock(mComponentRosterMutex);
- Component::LocalId it = mComponentRoster.find(
- Component::InterfaceKey(component));
- if (it == mComponentRoster.end()) {
- return std::shared_ptr<C2Component>();
- }
- return it->second.lock();
+ mComponentRoster.emplace(component, componentStatus);
}
-// Debug dump
+// Called from within the destructor of `component`. No virtual function calls
+// are made on `component` here.
+void ComponentStore::reportComponentDeath(Component* component) {
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ mComponentRoster.erase(component);
+}
-namespace /* unnamed */ {
-
-// Dump component traits
-std::ostream& dump(
+// Dumps component traits.
+std::ostream& ComponentStore::dump(
std::ostream& out,
const std::shared_ptr<const C2Component::Traits>& comp) {
@@ -334,25 +340,38 @@
return out;
}
-// Dump component
-std::ostream& dump(
+// Dumps component status.
+std::ostream& ComponentStore::dump(
std::ostream& out,
- const std::shared_ptr<C2Component>& comp) {
+ ComponentStatus& compStatus) {
constexpr const char indent[] = " ";
- std::shared_ptr<C2ComponentInterface> intf = comp->intf();
+ // Print birth time.
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ compStatus.birthTime.time_since_epoch());
+ std::time_t birthTime = std::chrono::system_clock::to_time_t(
+ compStatus.birthTime);
+ std::tm tm = *std::localtime(&birthTime);
+ out << indent << "Creation time: "
+ << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
+ << '.' << std::setfill('0') << std::setw(3) << ms.count() % 1000
+ << std::endl;
+
+ // Print name and id.
+ std::shared_ptr<C2ComponentInterface> intf = compStatus.c2Component->intf();
if (!intf) {
- out << indent << "Unknown -- null interface" << std::endl;
+ out << indent << "Unknown component -- null interface" << std::endl;
return out;
}
- out << indent << "name: " << intf->getName() << std::endl;
- out << indent << "id: " << intf->getId() << std::endl;
+ out << indent << "Name: " << intf->getName() << std::endl;
+ out << indent << "Id: " << intf->getId() << std::endl;
+
return out;
}
-} // unnamed namespace
-
+// Dumps information when lshal is called.
Return<void> ComponentStore::debug(
const hidl_handle& handle,
const hidl_vec<hidl_string>& /* args */) {
@@ -387,31 +406,16 @@
}
}
- // Retrieve the list of active components.
- std::list<std::shared_ptr<C2Component>> activeComps;
- {
- std::lock_guard<std::mutex> lock(mComponentRosterMutex);
- auto i = mComponentRoster.begin();
- while (i != mComponentRoster.end()) {
- std::shared_ptr<C2Component> c2comp = i->second.lock();
- if (!c2comp) {
- auto j = i;
- ++i;
- mComponentRoster.erase(j);
- } else {
- ++i;
- activeComps.emplace_back(c2comp);
- }
- }
- }
-
// Dump active components.
- out << indent << "Active components:" << std::endl << std::endl;
- if (activeComps.size() == 0) {
- out << indent << indent << "NONE" << std::endl << std::endl;
- } else {
- for (const std::shared_ptr<C2Component>& c2comp : activeComps) {
- dump(out, c2comp) << std::endl;
+ {
+ out << indent << "Active components:" << std::endl << std::endl;
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ if (mComponentRoster.size() == 0) {
+ out << indent << indent << "NONE" << std::endl << std::endl;
+ } else {
+ for (auto& pair : mComponentRoster) {
+ dump(out, pair.second) << std::endl;
+ }
}
}
diff --git a/media/codec2/hidl/1.0/utils/Configurable.cpp b/media/codec2/hidl/1.0/utils/Configurable.cpp
index d023ba8..a35b74c 100644
--- a/media/codec2/hidl/1.0/utils/Configurable.cpp
+++ b/media/codec2/hidl/1.0/utils/Configurable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,12 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-Configurable"
-#include <log/log.h>
+#include <android-base/logging.h>
#include <codec2/hidl/1.0/Configurable.h>
#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.0/types.h>
+
#include <C2ParamInternal.h>
namespace android {
@@ -33,8 +34,8 @@
using namespace ::android;
CachedConfigurable::CachedConfigurable(
- std::unique_ptr<ConfigurableC2Intf>&& intf) :
- mIntf(std::move(intf)) {
+ std::unique_ptr<ConfigurableC2Intf>&& intf)
+ : mIntf{std::move(intf)} {
}
c2_status_t CachedConfigurable::init(ComponentStore* store) {
@@ -45,6 +46,10 @@
}
// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
+Return<uint32_t> CachedConfigurable::getId() {
+ return mIntf->getId();
+}
+
Return<void> CachedConfigurable::getName(getName_cb _hidl_cb) {
_hidl_cb(mIntf->getName());
return Void();
@@ -65,9 +70,10 @@
&c2heapParams);
hidl_vec<uint8_t> params;
- createParamsBlob(¶ms, c2heapParams);
+ if (!createParamsBlob(¶ms, c2heapParams)) {
+ LOG(WARNING) << "query -- invalid output params.";
+ }
_hidl_cb(static_cast<Status>(c2res), params);
-
return Void();
}
@@ -78,7 +84,8 @@
// inParams is not writable, so create a copy as config modifies the parameters
hidl_vec<uint8_t> inParamsCopy = inParams;
std::vector<C2Param*> c2params;
- if (parseParamsBlob(&c2params, inParamsCopy) != C2_OK) {
+ if (!parseParamsBlob(&c2params, inParamsCopy)) {
+ LOG(WARNING) << "config -- invalid input params.";
_hidl_cb(Status::CORRUPTED,
hidl_vec<SettingResult>(),
hidl_vec<uint8_t>());
@@ -95,13 +102,20 @@
size_t ix = 0;
for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
if (c2result) {
- objcpy(&failures[ix++], *c2result);
+ if (objcpy(&failures[ix], *c2result)) {
+ ++ix;
+ } else {
+ LOG(DEBUG) << "config -- invalid setting results.";
+ break;
+ }
}
}
failures.resize(ix);
}
hidl_vec<uint8_t> outParams;
- createParamsBlob(&outParams, c2params);
+ if (!createParamsBlob(&outParams, c2params)) {
+ LOG(DEBUG) << "config -- invalid output params.";
+ }
_hidl_cb((Status)c2res, failures, outParams);
return Void();
}
@@ -117,7 +131,13 @@
size_t dstIx = 0;
for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
if (mSupportedParams[srcIx]) {
- objcpy(¶ms[dstIx++], *mSupportedParams[srcIx]);
+ if (objcpy(¶ms[dstIx], *mSupportedParams[srcIx])) {
+ ++dstIx;
+ } else {
+ res = Status::CORRUPTED;
+ LOG(WARNING) << "querySupportedParams -- invalid output params.";
+ break;
+ }
} else {
res = Status::BAD_INDEX;
}
@@ -154,7 +174,14 @@
{
size_t ix = 0;
for (const C2FieldSupportedValuesQuery &result : c2fields) {
- objcpy(&outFields[ix++], result);
+ if (!objcpy(&outFields[ix], result)) {
+ ++ix;
+ } else {
+ outFields.resize(ix);
+ c2res = C2_CORRUPTED;
+ LOG(WARNING) << "querySupportedValues -- invalid output params.";
+ break;
+ }
}
}
_hidl_cb((Status)c2res, outFields);
diff --git a/media/codec2/hidl/1.0/utils/InputBufferManager.cpp b/media/codec2/hidl/1.0/utils/InputBufferManager.cpp
new file mode 100644
index 0000000..a023a05
--- /dev/null
+++ b/media/codec2/hidl/1.0/utils/InputBufferManager.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-InputBufferManager"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android-base/logging.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <chrono>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+void InputBufferManager::registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ getInstance()._registerFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ getInstance()._unregisterFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+ const wp<IComponentListener>& listener) {
+ getInstance()._unregisterFrameData(listener);
+}
+
+void InputBufferManager::setNotificationInterval(
+ nsecs_t notificationIntervalNs) {
+ getInstance()._setNotificationInterval(notificationIntervalNs);
+}
+
+void InputBufferManager::_registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+ LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ std::set<TrackedBuffer> &bufferIds =
+ mTrackedBuffersMap[listener][frameIndex];
+
+ for (size_t i = 0; i < input.buffers.size(); ++i) {
+ if (!input.buffers[i]) {
+ LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- "
+ << "Input buffer at index " << i << " is null.";
+ continue;
+ }
+ const TrackedBuffer &bufferId =
+ *bufferIds.emplace(listener, frameIndex, i, input.buffers[i]).
+ first;
+
+ c2_status_t status = input.buffers[i]->registerOnDestroyNotify(
+ onBufferDestroyed,
+ const_cast<void*>(reinterpret_cast<const void*>(&bufferId)));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_registerFrameData -- "
+ << "registerOnDestroyNotify() failed "
+ << "(listener @ 0x" << std::hex << listener.get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ", bufferIndex = " << i
+ << ") => status = " << status
+ << ".";
+ }
+ }
+
+ mDeathNotifications.emplace(
+ listener,
+ DeathNotifications(
+ mNotificationIntervalNs.load(std::memory_order_relaxed)));
+}
+
+// Remove a pair (listener, frameIndex) from mTrackedBuffersMap and
+// mDeathNotifications. This implies all bufferIndices are removed.
+//
+// This is called from onWorkDone() and flush().
+void InputBufferManager::_unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.unsafe_get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(listener);
+ if (findListener != mTrackedBuffersMap.end()) {
+ std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds
+ = findListener->second;
+ auto findFrameIndex = frameIndex2BufferIds.find(frameIndex);
+ if (findFrameIndex != frameIndex2BufferIds.end()) {
+ std::set<TrackedBuffer> &bufferIds = findFrameIndex->second;
+ for (const TrackedBuffer& bufferId : bufferIds) {
+ std::shared_ptr<C2Buffer> buffer = bufferId.buffer.lock();
+ if (buffer) {
+ c2_status_t status = buffer->unregisterOnDestroyNotify(
+ onBufferDestroyed,
+ const_cast<void*>(
+ reinterpret_cast<const void*>(&bufferId)));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+ << "-- unregisterOnDestroyNotify() failed "
+ << "(listener @ 0x"
+ << std::hex
+ << bufferId.listener.unsafe_get()
+ << ", frameIndex = "
+ << std::dec << bufferId.frameIndex
+ << ", bufferIndex = " << bufferId.bufferIndex
+ << ") => status = " << status
+ << ".";
+ }
+ }
+ }
+
+ frameIndex2BufferIds.erase(findFrameIndex);
+ if (frameIndex2BufferIds.empty()) {
+ mTrackedBuffersMap.erase(findListener);
+ }
+ }
+ }
+
+ auto findListenerD = mDeathNotifications.find(listener);
+ if (findListenerD != mDeathNotifications.end()) {
+ DeathNotifications &deathNotifications = findListenerD->second;
+ auto findFrameIndex = deathNotifications.indices.find(frameIndex);
+ if (findFrameIndex != deathNotifications.indices.end()) {
+ std::vector<size_t> &bufferIndices = findFrameIndex->second;
+ deathNotifications.count -= bufferIndices.size();
+ deathNotifications.indices.erase(findFrameIndex);
+ }
+ }
+}
+
+// Remove listener from mTrackedBuffersMap and mDeathNotifications. This implies
+// all frameIndices and bufferIndices are removed.
+//
+// This is called when the component cleans up all input buffers, i.e., when
+// reset(), release(), stop() or ~Component() is called.
+void InputBufferManager::_unregisterFrameData(
+ const wp<IComponentListener>& listener) {
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.unsafe_get()
+ << std::dec << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(listener);
+ if (findListener != mTrackedBuffersMap.end()) {
+ std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds =
+ findListener->second;
+ for (auto findFrameIndex = frameIndex2BufferIds.begin();
+ findFrameIndex != frameIndex2BufferIds.end();
+ ++findFrameIndex) {
+ std::set<TrackedBuffer> &bufferIds = findFrameIndex->second;
+ for (const TrackedBuffer& bufferId : bufferIds) {
+ std::shared_ptr<C2Buffer> buffer = bufferId.buffer.lock();
+ if (buffer) {
+ c2_status_t status = buffer->unregisterOnDestroyNotify(
+ onBufferDestroyed,
+ const_cast<void*>(
+ reinterpret_cast<const void*>(&bufferId)));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+ << "-- unregisterOnDestroyNotify() failed "
+ << "(listener @ 0x"
+ << std::hex
+ << bufferId.listener.unsafe_get()
+ << ", frameIndex = "
+ << std::dec << bufferId.frameIndex
+ << ", bufferIndex = " << bufferId.bufferIndex
+ << ") => status = " << status
+ << ".";
+ }
+ }
+ }
+ }
+ mTrackedBuffersMap.erase(findListener);
+ }
+
+ mDeathNotifications.erase(listener);
+}
+
+// Set mNotificationIntervalNs.
+void InputBufferManager::_setNotificationInterval(
+ nsecs_t notificationIntervalNs) {
+ mNotificationIntervalNs.store(
+ notificationIntervalNs,
+ std::memory_order_relaxed);
+}
+
+// Move a buffer from mTrackedBuffersMap to mDeathNotifications.
+// This is called when a registered C2Buffer object is destroyed.
+void InputBufferManager::onBufferDestroyed(const C2Buffer* buf, void* arg) {
+ getInstance()._onBufferDestroyed(buf, arg);
+}
+
+void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) {
+ if (!buf || !arg) {
+ LOG(WARNING) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "null argument (s): "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << ".";
+ return;
+ }
+ TrackedBuffer id(*reinterpret_cast<TrackedBuffer*>(arg));
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << " -- "
+ << "listener @ 0x" << std::hex << id.listener.unsafe_get()
+ << ", frameIndex = " << std::dec << id.frameIndex
+ << ", bufferIndex = " << id.bufferIndex
+ << ".";
+
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(id.listener);
+ if (findListener == mTrackedBuffersMap.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid listener: "
+ << "listener @ 0x" << std::hex << id.listener.unsafe_get()
+ << " (frameIndex = " << std::dec << id.frameIndex
+ << ", bufferIndex = " << id.bufferIndex
+ << ").";
+ return;
+ }
+
+ std::map<uint64_t, std::set<TrackedBuffer>> &frameIndex2BufferIds
+ = findListener->second;
+ auto findFrameIndex = frameIndex2BufferIds.find(id.frameIndex);
+ if (findFrameIndex == frameIndex2BufferIds.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid frame index: "
+ << "frameIndex = " << id.frameIndex
+ << " (listener @ 0x" << std::hex << id.listener.unsafe_get()
+ << ", bufferIndex = " << std::dec << id.bufferIndex
+ << ").";
+ return;
+ }
+
+ std::set<TrackedBuffer> &bufferIds = findFrameIndex->second;
+ auto findBufferId = bufferIds.find(id);
+ if (findBufferId == bufferIds.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid buffer index: "
+ << "bufferIndex = " << id.bufferIndex
+ << " (frameIndex = " << id.frameIndex
+ << ", listener @ 0x" << std::hex << id.listener.unsafe_get()
+ << std::dec << ").";
+ return;
+ }
+
+ bufferIds.erase(findBufferId);
+ if (bufferIds.empty()) {
+ frameIndex2BufferIds.erase(findFrameIndex);
+ if (frameIndex2BufferIds.empty()) {
+ mTrackedBuffersMap.erase(findListener);
+ }
+ }
+
+ DeathNotifications &deathNotifications = mDeathNotifications[id.listener];
+ deathNotifications.indices[id.frameIndex].emplace_back(id.bufferIndex);
+ ++deathNotifications.count;
+ mOnBufferDestroyed.notify_one();
+}
+
+// Notify the clients about buffer destructions.
+// Return false if all destructions have been notified.
+// Return true and set timeToRetry to the time point to wait for before
+// retrying if some destructions have not been notified.
+bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
+
+ struct Notification {
+ sp<IComponentListener> listener;
+ hidl_vec<IComponentListener::InputBuffer> inputBuffers;
+ Notification(const sp<IComponentListener>& l, size_t s)
+ : listener(l), inputBuffers(s) {}
+ };
+ std::list<Notification> notifications;
+ nsecs_t notificationIntervalNs =
+ mNotificationIntervalNs.load(std::memory_order_relaxed);
+
+ bool retry = false;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ *timeToRetryNs = notificationIntervalNs;
+ nsecs_t timeNowNs = systemTime();
+ for (auto it = mDeathNotifications.begin();
+ it != mDeathNotifications.end(); ) {
+ sp<IComponentListener> listener = it->first.promote();
+ if (!listener) {
+ ++it;
+ continue;
+ }
+ DeathNotifications &deathNotifications = it->second;
+
+ nsecs_t timeSinceLastNotifiedNs =
+ timeNowNs - deathNotifications.lastSentNs;
+ // If not enough time has passed since the last callback, leave the
+ // notifications for this listener untouched for now and retry
+ // later.
+ if (timeSinceLastNotifiedNs < notificationIntervalNs) {
+ retry = true;
+ *timeToRetryNs = std::min(*timeToRetryNs,
+ notificationIntervalNs - timeSinceLastNotifiedNs);
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "Notifications for listener @ "
+ << std::hex << listener.get()
+ << " will be postponed.";
+ ++it;
+ continue;
+ }
+
+ // If enough time has passed since the last notification to this
+ // listener but there are currently no pending notifications, the
+ // listener can be removed from mDeathNotifications---there is no
+ // need to keep track of the last notification time anymore.
+ if (deathNotifications.count == 0) {
+ it = mDeathNotifications.erase(it);
+ continue;
+ }
+
+ // Create the argument for the callback.
+ notifications.emplace_back(listener, deathNotifications.count);
+ hidl_vec<IComponentListener::InputBuffer> &inputBuffers =
+ notifications.back().inputBuffers;
+ size_t i = 0;
+ for (std::pair<const uint64_t, std::vector<size_t>>& p :
+ deathNotifications.indices) {
+ uint64_t frameIndex = p.first;
+ const std::vector<size_t> &bufferIndices = p.second;
+ for (const size_t& bufferIndex : bufferIndices) {
+ IComponentListener::InputBuffer &inputBuffer
+ = inputBuffers[i++];
+ inputBuffer.arrayIndex = bufferIndex;
+ inputBuffer.frameIndex = frameIndex;
+ }
+ }
+
+ // Clear deathNotifications for this listener and set retry to true
+ // so processNotifications will be called again. This will
+ // guarantee that a listener with no pending notifications will
+ // eventually be removed from mDeathNotifications after
+ // mNotificationIntervalNs nanoseconds has passed.
+ retry = true;
+ deathNotifications.indices.clear();
+ deathNotifications.count = 0;
+ deathNotifications.lastSentNs = timeNowNs;
+ ++it;
+ }
+ }
+
+ // Call onInputBuffersReleased() outside the lock to avoid deadlock.
+ for (const Notification& notification : notifications) {
+ if (!notification.listener->onInputBuffersReleased(
+ notification.inputBuffers).isOk()) {
+ // This may trigger if the client has died.
+ LOG(DEBUG) << "InputBufferManager::processNotifications -- "
+ << "failed to send death notifications to "
+ << "listener @ 0x" << std::hex
+ << notification.listener.get()
+ << std::dec << ".";
+ } else {
+#if LOG_NDEBUG == 0
+ std::stringstream inputBufferLog;
+ for (const IComponentListener::InputBuffer& inputBuffer :
+ notification.inputBuffers) {
+ inputBufferLog << " (" << inputBuffer.frameIndex
+ << ", " << inputBuffer.arrayIndex
+ << ")";
+ }
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "death notifications sent to "
+ << "listener @ 0x" << std::hex
+ << notification.listener.get()
+ << std::dec
+ << " with these (frameIndex, bufferIndex) pairs:"
+ << inputBufferLog.str();
+#endif
+ }
+ }
+#if LOG_NDEBUG == 0
+ if (retry) {
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "will retry again in " << *timeToRetryNs << "ns.";
+ } else {
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "no pending death notifications.";
+ }
+#endif
+ return retry;
+}
+
+void InputBufferManager::main() {
+ LOG(VERBOSE) << "InputBufferManager main -- started.";
+ nsecs_t timeToRetryNs;
+ while (true) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mDeathNotifications.empty()) {
+ mOnBufferDestroyed.wait(lock);
+ }
+ lock.unlock();
+ while (processNotifications(&timeToRetryNs)) {
+ std::this_thread::sleep_for(
+ std::chrono::nanoseconds(timeToRetryNs));
+ }
+ }
+}
+
+InputBufferManager::InputBufferManager()
+ : mMainThread{&InputBufferManager::main, this} {
+}
+
+InputBufferManager& InputBufferManager::getInstance() {
+ static InputBufferManager instance{};
+ return instance;
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+
+
diff --git a/media/codec2/hidl/1.0/utils/InputSurface.cpp b/media/codec2/hidl/1.0/utils/InputSurface.cpp
index b669460..2cbe64b 100644
--- a/media/codec2/hidl/1.0/utils/InputSurface.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurface.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,11 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-InputSurface"
-#include <log/log.h>
+#include <android-base/logging.h>
#include <codec2/hidl/1.0/InputSurface.h>
#include <codec2/hidl/1.0/InputSurfaceConnection.h>
-#include <util/C2InterfaceHelper.h>
#include <C2Component.h>
#include <C2Config.h>
@@ -36,9 +35,10 @@
using namespace ::android;
-class InputSurface::ConfigurableImpl : public C2InterfaceHelper {
+// Derived class of C2InterfaceHelper
+class InputSurface::Interface : public C2InterfaceHelper {
public:
- explicit ConfigurableImpl(
+ explicit Interface(
const std::shared_ptr<C2ReflectorHelper> &helper)
: C2InterfaceHelper(helper) {
@@ -63,33 +63,34 @@
std::shared_ptr<C2InputSurfaceEosTuning> mEos;
};
-namespace {
-
-class ConfigurableWrapper : public ConfigurableC2Intf {
+// Derived class of ConfigurableC2Intf
+class InputSurface::ConfigurableIntf : public ConfigurableC2Intf {
public:
- ConfigurableWrapper(
- const std::shared_ptr<InputSurface::ConfigurableImpl> &impl,
+ ConfigurableIntf(
+ const std::shared_ptr<InputSurface::Interface> &intf,
const sp<GraphicBufferSource> &source)
- : ConfigurableC2Intf("input-surface"),
- mImpl(impl),
+ : ConfigurableC2Intf("input-surface", 0),
+ mIntf(intf),
mSource(source) {
}
- ~ConfigurableWrapper() override = default;
+ virtual ~ConfigurableIntf() override = default;
- c2_status_t query(
+ virtual c2_status_t query(
const std::vector<C2Param::Index> &indices,
c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>>* const params) const override {
- return mImpl->query({}, indices, mayBlock, params);
+ std::vector<std::unique_ptr<C2Param>>* const params
+ ) const override {
+ return mIntf->query({}, indices, mayBlock, params);
}
- c2_status_t config(
+ virtual c2_status_t config(
const std::vector<C2Param*> ¶ms,
c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
- c2_status_t err = mImpl->config(params, mayBlock, failures);
- if (mImpl->eos()) {
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ c2_status_t err = mIntf->config(params, mayBlock, failures);
+ if (mIntf->eos()) {
sp<GraphicBufferSource> source = mSource.promote();
if (source == nullptr || source->signalEndOfInputStream() != OK) {
// TODO: put something in |failures|
@@ -100,202 +101,71 @@
return err;
}
- c2_status_t querySupportedParams(
- std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const override {
- return mImpl->querySupportedParams(params);
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ return mIntf->querySupportedParams(params);
}
- c2_status_t querySupportedValues(
+ virtual c2_status_t querySupportedValues(
std::vector<C2FieldSupportedValuesQuery>& fields,
c2_blocking_t mayBlock) const override {
- return mImpl->querySupportedValues(fields, mayBlock);
+ return mIntf->querySupportedValues(fields, mayBlock);
}
private:
- const std::shared_ptr<InputSurface::ConfigurableImpl> mImpl;
+ const std::shared_ptr<InputSurface::Interface> mIntf;
wp<GraphicBufferSource> mSource;
};
-} // namespace
-
-
-Return<void> InputSurface::connectToComponent(
- const sp<IComponent>& component,
- connectToComponent_cb _hidl_cb) {
- Status status;
- sp<InputSurfaceConnection> conn;
- if (!component) {
- status = Status::BAD_VALUE;
- } else {
- std::shared_ptr<C2Component> comp = mStore->findC2Component(component);
- if (!comp) {
- conn = new InputSurfaceConnection(mSource, component);
- } else {
- conn = new InputSurfaceConnection(mSource, comp);
- }
- if (!conn->init()) {
- conn = nullptr;
- status = Status::BAD_VALUE;
- } else {
- status = Status::OK;
- }
- }
- _hidl_cb(status, conn);
- return Void();
+Return<sp<InputSurface::HGraphicBufferProducer>> InputSurface::getGraphicBufferProducer() {
+ return mProducer;
}
Return<sp<IConfigurable>> InputSurface::getConfigurable() {
return mConfigurable;
}
-// Derived methods from IGraphicBufferProducer
-
-Return<void> InputSurface::requestBuffer(
- int32_t slot,
- requestBuffer_cb _hidl_cb) {
- return mBase->requestBuffer(slot, _hidl_cb);
-}
-
-Return<int32_t> InputSurface::setMaxDequeuedBufferCount(
- int32_t maxDequeuedBuffers) {
- return mBase->setMaxDequeuedBufferCount(maxDequeuedBuffers);
-}
-
-Return<int32_t> InputSurface::setAsyncMode(
- bool async) {
- return mBase->setAsyncMode(async);
-}
-
-Return<void> InputSurface::dequeueBuffer(
- uint32_t width,
- uint32_t height,
- PixelFormat format,
- uint32_t usage,
- bool getFrameTimestamps,
- dequeueBuffer_cb _hidl_cb) {
- return mBase->dequeueBuffer(
- width, height, format, usage, getFrameTimestamps, _hidl_cb);
-}
-
-Return<int32_t> InputSurface::detachBuffer(
- int32_t slot) {
- return mBase->detachBuffer(slot);
-}
-
-Return<void> InputSurface::detachNextBuffer(
- detachNextBuffer_cb _hidl_cb) {
- return mBase->detachNextBuffer(_hidl_cb);
-}
-
-Return<void> InputSurface::attachBuffer(
- const AnwBuffer& buffer,
- attachBuffer_cb _hidl_cb) {
- return mBase->attachBuffer(buffer, _hidl_cb);
-}
-
-Return<void> InputSurface::queueBuffer(
- int32_t slot,
- const QueueBufferInput& input,
- queueBuffer_cb _hidl_cb) {
- return mBase->queueBuffer(slot, input, _hidl_cb);
-}
-
-Return<int32_t> InputSurface::cancelBuffer(
- int32_t slot,
- const hidl_handle& fence) {
- return mBase->cancelBuffer(slot, fence);
-}
-
-Return<void> InputSurface::query(
- int32_t what,
- query_cb _hidl_cb) {
- return mBase->query(what, _hidl_cb);
-}
-
Return<void> InputSurface::connect(
- const sp<HProducerListener>& listener,
- int32_t api,
- bool producerControlledByApp,
+ const sp<IInputSink>& sink,
connect_cb _hidl_cb) {
- return mBase->connect(listener, api, producerControlledByApp, _hidl_cb);
+ Status status;
+ sp<InputSurfaceConnection> connection;
+ if (!sink) {
+ _hidl_cb(Status::BAD_VALUE, nullptr);
+ return Void();
+ }
+ std::shared_ptr<C2Component> comp = Component::findLocalComponent(sink);
+ if (comp) {
+ connection = new InputSurfaceConnection(mSource, comp, mStore);
+ } else {
+ connection = new InputSurfaceConnection(mSource, sink, mStore);
+ }
+ if (!connection->init()) {
+ connection = nullptr;
+ status = Status::BAD_VALUE;
+ } else {
+ status = Status::OK;
+ }
+ _hidl_cb(status, connection);
+ return Void();
}
-Return<int32_t> InputSurface::disconnect(
- int32_t api,
- DisconnectMode mode) {
- return mBase->disconnect(api, mode);
-}
-
-Return<int32_t> InputSurface::setSidebandStream(
- const hidl_handle& stream) {
- return mBase->setSidebandStream(stream);
-}
-
-Return<void> InputSurface::allocateBuffers(
- uint32_t width,
- uint32_t height,
- PixelFormat format,
- uint32_t usage) {
- return mBase->allocateBuffers(width, height, format, usage);
-}
-
-Return<int32_t> InputSurface::allowAllocation(
- bool allow) {
- return mBase->allowAllocation(allow);
-}
-
-Return<int32_t> InputSurface::setGenerationNumber(
- uint32_t generationNumber) {
- return mBase->setGenerationNumber(generationNumber);
-}
-
-Return<void> InputSurface::getConsumerName(
- getConsumerName_cb _hidl_cb) {
- return mBase->getConsumerName(_hidl_cb);
-}
-
-Return<int32_t> InputSurface::setSharedBufferMode(
- bool sharedBufferMode) {
- return mBase->setSharedBufferMode(sharedBufferMode);
-}
-
-Return<int32_t> InputSurface::setAutoRefresh(
- bool autoRefresh) {
- return mBase->setAutoRefresh(autoRefresh);
-}
-
-Return<int32_t> InputSurface::setDequeueTimeout(
- int64_t timeoutNs) {
- return mBase->setDequeueTimeout(timeoutNs);
-}
-
-Return<void> InputSurface::getLastQueuedBuffer(
- getLastQueuedBuffer_cb _hidl_cb) {
- return mBase->getLastQueuedBuffer(_hidl_cb);
-}
-
-Return<void> InputSurface::getFrameTimestamps(
- getFrameTimestamps_cb _hidl_cb) {
- return mBase->getFrameTimestamps(_hidl_cb);
-}
-
-Return<void> InputSurface::getUniqueId(
- getUniqueId_cb _hidl_cb) {
- return mBase->getUniqueId(_hidl_cb);
-}
+// Derived methods from IGraphicBufferProducer
// Constructor is exclusive to ComponentStore.
InputSurface::InputSurface(
const sp<ComponentStore>& store,
const std::shared_ptr<C2ReflectorHelper>& reflector,
- const sp<HGraphicBufferProducer>& base,
- const sp<GraphicBufferSource>& source) :
- mStore(store),
- mBase(base),
- mSource(source),
- mHelper(std::make_shared<ConfigurableImpl>(reflector)),
- mConfigurable(new CachedConfigurable(
- std::make_unique<ConfigurableWrapper>(mHelper, source))) {
+ const sp<HGraphicBufferProducer>& producer,
+ const sp<GraphicBufferSource>& source)
+ : mStore{store},
+ mProducer{producer},
+ mSource{source},
+ mIntf{std::make_shared<Interface>(reflector)},
+ mConfigurable{new CachedConfigurable(
+ std::make_unique<ConfigurableIntf>(
+ mIntf, source))} {
mConfigurable->init(store.get());
}
diff --git a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
index 8b1ece3..1024f50 100644
--- a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,10 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-InputSurfaceConnection"
-#include <log/log.h>
+#include <android-base/logging.h>
#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
#include <memory>
#include <list>
@@ -65,51 +66,74 @@
} // unnamed namespace
+// Derived class of ComponentWrapper for use with
+// GraphicBufferSource::configure().
+//
struct InputSurfaceConnection::Impl : public ComponentWrapper {
+
Impl(const sp<GraphicBufferSource>& source,
- const std::shared_ptr<C2Component>& comp) :
- mSource(source), mComp(comp), mRemoteComp(),
- mFrameIndex(0) {
- std::shared_ptr<C2ComponentInterface> intf = comp->intf();
- mCompName = intf ? intf->getName() : "";
+ const std::shared_ptr<C2Component>& localComp)
+ : mSource{source}, mLocalComp{localComp}, mSink{}, mFrameIndex{0} {
+ std::shared_ptr<C2ComponentInterface> intf = localComp->intf();
+ mSinkName = intf ? intf->getName() : "";
}
Impl(const sp<GraphicBufferSource>& source,
- const sp<IComponent>& comp) :
- mSource(source), mComp(), mRemoteComp(comp),
- mFrameIndex(0) {
- Return<void> transStatus = comp->getName(
- [this](const hidl_string& name) {
- mCompName = name.c_str();
+ const sp<IInputSink>& sink)
+ : mSource{source}, mLocalComp{}, mSink{sink}, mFrameIndex{0} {
+ Return<sp<IConfigurable>> transResult = sink->getConfigurable();
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "Remote sink is dead.";
+ return;
+ }
+ mSinkConfigurable =
+ static_cast<sp<IConfigurable>>(transResult);
+ if (!mSinkConfigurable) {
+ LOG(ERROR) << "Remote sink is not configurable.";
+ mSinkName = "";
+ return;
+ }
+
+ hidl_string name;
+ Return<void> transStatus = mSinkConfigurable->getName(
+ [&name](const hidl_string& n) {
+ name = n;
});
if (!transStatus.isOk()) {
- ALOGD("getName -- Cannot obtain remote component name.");
+ LOG(ERROR) << "Remote sink's configurable is dead.";
+ mSinkName = "";
+ return;
}
+ mSinkName = name.c_str();
}
- virtual ~Impl() = default;
+ virtual ~Impl() {
+ mSource->stop();
+ mSource->release();
+ }
bool init() {
- sp<GraphicBufferSource> source = mSource.promote();
- if (source == nullptr) {
+ if (mSource == nullptr) {
return false;
}
- status_t err = source->initCheck();
+ status_t err = mSource->initCheck();
if (err != OK) {
- ALOGD("Impl::init -- GBS init failed: %d", err);
+ LOG(WARNING) << "Impl::init -- GraphicBufferSource init failed: "
+ << "status = " << err << ".";
return false;
}
// TODO: read settings properly from the interface
C2VideoSizeStreamTuning::input inputSize;
C2StreamUsageTuning::input usage;
- c2_status_t c2Status = compQuery({ &inputSize, &usage },
+ c2_status_t c2Status = queryFromSink({ &inputSize, &usage },
{},
C2_MAY_BLOCK,
nullptr);
if (c2Status != C2_OK) {
- ALOGD("Impl::init -- cannot query information from "
- "the component interface: %s.", asString(c2Status));
+ LOG(WARNING) << "Impl::init -- cannot query information from "
+ "the component interface: "
+ << "status = " << asString(c2Status) << ".";
return false;
}
@@ -122,26 +146,27 @@
// asGrallocUsage();
uint32_t grallocUsage =
- mCompName.compare(0, 11, "c2.android.") == 0 ?
+ mSinkName.compare(0, 11, "c2.android.") == 0 ?
GRALLOC_USAGE_SW_READ_OFTEN :
GRALLOC_USAGE_HW_VIDEO_ENCODER;
- err = source->configure(
+ err = mSource->configure(
this, dataSpace, kBufferCount,
inputSize.width, inputSize.height,
grallocUsage);
if (err != OK) {
- ALOGD("Impl::init -- GBS configure failed: %d", err);
+ LOG(WARNING) << "Impl::init -- GBS configure failed: "
+ << "status = " << err << ".";
return false;
}
for (int32_t i = 0; i < kBufferCount; ++i) {
- if (!source->onInputBufferAdded(i).isOk()) {
- ALOGD("Impl::init: populating GBS slots failed");
+ if (!mSource->onInputBufferAdded(i).isOk()) {
+ LOG(WARNING) << "Impl::init: failed to populate GBS slots.";
return false;
}
}
- if (!source->start().isOk()) {
- ALOGD("Impl::init -- GBS start failed");
+ if (!mSource->start().isOk()) {
+ LOG(WARNING) << "Impl::init -- GBS failed to start.";
return false;
}
mAllocatorMutex.lock();
@@ -150,7 +175,8 @@
&mAllocator);
mAllocatorMutex.unlock();
if (c2err != OK) {
- ALOGD("Impl::init -- failed to fetch gralloc allocator: %d", c2err);
+ LOG(WARNING) << "Impl::init -- failed to fetch gralloc allocator: "
+ << "status = " << asString(c2err) << ".";
return false;
}
return true;
@@ -162,7 +188,7 @@
const sp<GraphicBuffer>& buffer,
int64_t timestamp,
int fenceFd) override {
- ALOGV("Impl::submitBuffer -- bufferId = %d", bufferId);
+ LOG(VERBOSE) << "Impl::submitBuffer -- bufferId = " << bufferId << ".";
// TODO: Use fd to construct fence
(void)fenceFd;
@@ -190,9 +216,8 @@
// TODO: fence
new Buffer2D(block->share(
C2Rect(block->width(), block->height()), ::C2Fence())),
- [bufferId, src = mSource](C2Buffer* ptr) {
+ [bufferId, source = mSource](C2Buffer* ptr) {
delete ptr;
- sp<GraphicBufferSource> source = src.promote();
if (source != nullptr) {
// TODO: fence
(void)source->onInputBufferEmptied(bufferId, -1);
@@ -204,12 +229,13 @@
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
- err = compQueue(&items);
+ err = queueToSink(&items);
return (err == C2_OK) ? OK : UNKNOWN_ERROR;
}
- virtual status_t submitEos(int32_t /* bufferId */) override {
- ALOGV("Impl::submitEos");
+ virtual status_t submitEos(int32_t bufferId) override {
+ LOG(VERBOSE) << "Impl::submitEos -- bufferId = " << bufferId << ".";
+ (void)bufferId;
std::unique_ptr<C2Work> work(new C2Work);
work->input.flags = (C2FrameData::flags_t)0;
@@ -221,11 +247,11 @@
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
- c2_status_t err = compQueue(&items);
+ c2_status_t err = queueToSink(&items);
return (err == C2_OK) ? OK : UNKNOWN_ERROR;
}
- void dispatchDataSpaceChanged(
+ virtual void dispatchDataSpaceChanged(
int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
// TODO
(void)dataSpace;
@@ -233,36 +259,63 @@
(void)pixelFormat;
}
+ // Configurable interface for InputSurfaceConnection::Impl.
+ //
+ // This class is declared as an inner class so that it will have access to
+ // all Impl's members.
+ struct ConfigurableIntf : public ConfigurableC2Intf {
+ sp<Impl> mConnection;
+ ConfigurableIntf(const sp<Impl>& connection)
+ : ConfigurableC2Intf{"input-surface-connection", 0},
+ mConnection{connection} {}
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>> *const failures
+ ) override;
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>> *const params) const override;
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+ ) const override;
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const override;
+ };
+
private:
- c2_status_t compQuery(
+ c2_status_t queryFromSink(
const std::vector<C2Param*> &stackParams,
const std::vector<C2Param::Index> &heapParamIndices,
c2_blocking_t mayBlock,
std::vector<std::unique_ptr<C2Param>>* const heapParams) {
- std::shared_ptr<C2Component> comp = mComp.lock();
- if (comp) {
- std::shared_ptr<C2ComponentInterface> intf = comp->intf();
+ if (mLocalComp) {
+ std::shared_ptr<C2ComponentInterface> intf = mLocalComp->intf();
if (intf) {
return intf->query_vb(stackParams,
heapParamIndices,
mayBlock,
heapParams);
} else {
- ALOGD("compQuery -- component does not have an interface.");
+ LOG(ERROR) << "queryFromSink -- "
+ << "component does not have an interface.";
return C2_BAD_STATE;
}
}
- if (!mRemoteComp) {
- ALOGD("compQuery -- component no longer exists.");
- return C2_BAD_STATE;
- }
+
+ CHECK(mSink) << "-- queryFromSink "
+ << "-- connection has no sink.";
+ CHECK(mSinkConfigurable) << "-- queryFromSink "
+ << "-- sink has no configurable.";
hidl_vec<ParamIndex> indices(
stackParams.size() + heapParamIndices.size());
size_t numIndices = 0;
for (C2Param* const& stackParam : stackParams) {
if (!stackParam) {
- ALOGD("compQuery -- null stack param encountered.");
+ LOG(DEBUG) << "queryFromSink -- null stack param encountered.";
continue;
}
indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
@@ -277,22 +330,22 @@
heapParams->reserve(heapParams->size() + numIndices);
}
c2_status_t status;
- Return<void> transStatus = mRemoteComp->query(
+ Return<void> transStatus = mSinkConfigurable->query(
indices,
mayBlock == C2_MAY_BLOCK,
[&status, &numStackIndices, &stackParams, heapParams](
Status s, const Params& p) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK && status != C2_BAD_INDEX) {
- ALOGD("compQuery -- call failed: %s.", asString(status));
+ LOG(DEBUG) << "queryFromSink -- call failed: "
+ << "status = " << asString(status) << ".";
return;
}
std::vector<C2Param*> paramPointers;
- c2_status_t parseStatus = parseParamsBlob(¶mPointers, p);
- if (parseStatus != C2_OK) {
- ALOGD("compQuery -- error while parsing params: %s.",
- asString(parseStatus));
- status = parseStatus;
+ if (!parseParamsBlob(¶mPointers, p)) {
+ LOG(DEBUG) << "queryFromSink -- error while "
+ << "parsing params.";
+ status = C2_CORRUPTED;
return;
}
size_t i = 0;
@@ -302,7 +355,8 @@
if (numStackIndices > 0) {
--numStackIndices;
if (!paramPointer) {
- ALOGD("compQuery -- null stack param.");
+ LOG(DEBUG) << "queryFromSink -- "
+ "null stack param.";
++it;
continue;
}
@@ -313,25 +367,27 @@
CHECK(i < stackParams.size());
if (stackParams[i]->index() !=
paramPointer->index()) {
- ALOGD("compQuery -- param skipped. index = %d",
- static_cast<int>(
- stackParams[i]->index()));
+ LOG(DEBUG) << "queryFromSink -- "
+ "param skipped (index = "
+ << stackParams[i]->index() << ").";
stackParams[i++]->invalidate();
continue;
}
if (!stackParams[i++]->updateFrom(*paramPointer)) {
- ALOGD("compQuery -- param update failed: "
- "index = %d.",
- static_cast<int>(paramPointer->index()));
+ LOG(DEBUG) << "queryFromSink -- "
+ "param update failed (index = "
+ << paramPointer->index() << ").";
}
} else {
if (!paramPointer) {
- ALOGD("compQuery -- null heap param.");
+ LOG(DEBUG) << "queryFromSink -- "
+ "null heap param.";
++it;
continue;
}
if (!heapParams) {
- ALOGD("compQuery -- too many stack params.");
+ LOG(WARNING) << "queryFromSink -- "
+ "too many stack params.";
break;
}
heapParams->emplace_back(C2Param::Copy(*paramPointer));
@@ -340,96 +396,130 @@
}
});
if (!transStatus.isOk()) {
- ALOGD("compQuery -- transaction failed.");
+ LOG(ERROR) << "queryFromSink -- transaction failed.";
return C2_CORRUPTED;
}
return status;
}
- c2_status_t compQueue(std::list<std::unique_ptr<C2Work>>* const items) {
- std::shared_ptr<C2Component> comp = mComp.lock();
- if (comp) {
- return comp->queue_nb(items);
+ c2_status_t queueToSink(std::list<std::unique_ptr<C2Work>>* const items) {
+ if (mLocalComp) {
+ return mLocalComp->queue_nb(items);
}
+ CHECK(mSink) << "-- queueToSink "
+ << "-- connection has no sink.";
+
WorkBundle workBundle;
- Status hidlStatus = objcpy(&workBundle, *items, nullptr);
- if (hidlStatus != Status::OK) {
- ALOGD("compQueue -- bad input.");
+ if (!objcpy(&workBundle, *items, nullptr)) {
+ LOG(ERROR) << "queueToSink -- bad input.";
return C2_CORRUPTED;
}
- Return<Status> transStatus = mRemoteComp->queue(workBundle);
+ Return<Status> transStatus = mSink->queue(workBundle);
if (!transStatus.isOk()) {
- ALOGD("compQueue -- transaction failed.");
+ LOG(ERROR) << "queueToSink -- transaction failed.";
return C2_CORRUPTED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGV("compQueue -- call failed: %s.", asString(status));
+ LOG(DEBUG) << "queueToSink -- call failed: "
+ << asString(status);
}
return status;
}
- wp<GraphicBufferSource> mSource;
- std::weak_ptr<C2Component> mComp;
- sp<IComponent> mRemoteComp;
- std::string mCompName;
+ sp<GraphicBufferSource> mSource;
+ std::shared_ptr<C2Component> mLocalComp;
+ sp<IInputSink> mSink;
+ sp<IConfigurable> mSinkConfigurable;
+ std::string mSinkName;
// Needed for ComponentWrapper implementation
std::mutex mAllocatorMutex;
std::shared_ptr<C2Allocator> mAllocator;
std::atomic_uint64_t mFrameIndex;
+
};
InputSurfaceConnection::InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
- const std::shared_ptr<C2Component>& comp) :
- mSource(source),
- mImpl(new Impl(source, comp)) {
+ const std::shared_ptr<C2Component>& comp,
+ const sp<ComponentStore>& store)
+ : mImpl{new Impl(source, comp)},
+ mConfigurable{new CachedConfigurable(
+ std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
+ mConfigurable->init(store.get());
}
InputSurfaceConnection::InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
- const sp<IComponent>& comp) :
- mSource(source),
- mImpl(new Impl(source, comp)) {
-}
-
-InputSurfaceConnection::~InputSurfaceConnection() {
- if (mSource) {
- (void)mSource->stop();
- (void)mSource->release();
- mSource.clear();
- }
- mImpl.clear();
-}
-
-bool InputSurfaceConnection::init() {
- mMutex.lock();
- sp<Impl> impl = mImpl;
- mMutex.unlock();
-
- if (!impl) {
- return false;
- }
- return impl->init();
+ const sp<IInputSink>& sink,
+ const sp<ComponentStore>& store)
+ : mImpl{new Impl(source, sink)},
+ mConfigurable{new CachedConfigurable(
+ std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
+ mConfigurable->init(store.get());
}
Return<Status> InputSurfaceConnection::disconnect() {
- ALOGV("disconnect");
- mMutex.lock();
- if (mSource) {
- (void)mSource->stop();
- (void)mSource->release();
- mSource.clear();
- }
- mImpl.clear();
- mMutex.unlock();
- ALOGV("disconnected");
+ std::lock_guard<std::mutex> lock(mImplMutex);
+ mImpl = nullptr;
return Status::OK;
}
+InputSurfaceConnection::~InputSurfaceConnection() {
+ mImpl = nullptr;
+}
+
+bool InputSurfaceConnection::init() {
+ std::lock_guard<std::mutex> lock(mImplMutex);
+ return mImpl->init();
+}
+
+Return<sp<IConfigurable>> InputSurfaceConnection::getConfigurable() {
+ return mConfigurable;
+}
+
+// Configurable interface for InputSurfaceConnection::Impl
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
+ // TODO: implement
+ (void)params;
+ (void)mayBlock;
+ (void)failures;
+ return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>> *const params) const {
+ // TODO: implement
+ (void)indices;
+ (void)mayBlock;
+ (void)params;
+ return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+ // TODO: implement
+ (void)params;
+ return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const {
+ // TODO: implement
+ (void)fields;
+ (void)mayBlock;
+ return C2_OK;
+}
+
} // namespace utils
} // namespace V1_0
} // namespace c2
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
index 0908226..4ac95c5 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,13 +17,15 @@
#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
+#include <codec2/hidl/1.0/ComponentInterface.h>
#include <codec2/hidl/1.0/Configurable.h>
#include <codec2/hidl/1.0/types.h>
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.0/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
#include <android/hardware/media/c2/1.0/IComponentListener.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <android/hardware/media/c2/1.0/IComponent.h>
#include <hidl/Status.h>
#include <hwbinder/IBinder.h>
@@ -31,9 +33,9 @@
#include <C2Buffer.h>
#include <C2.h>
-#include <list>
#include <map>
#include <memory>
+#include <mutex>
namespace android {
namespace hardware {
@@ -54,19 +56,8 @@
struct ComponentStore;
-struct ComponentInterface : public Configurable<IComponentInterface> {
- ComponentInterface(
- const std::shared_ptr<C2ComponentInterface>& interface,
- const sp<ComponentStore>& store);
- c2_status_t status() const;
-
-protected:
- c2_status_t mInit;
- std::shared_ptr<C2ComponentInterface> mInterface;
- sp<ComponentStore> mStore;
-};
-
-struct Component : public Configurable<IComponent> {
+struct Component : public IComponent,
+ public std::enable_shared_from_this<Component> {
Component(
const std::shared_ptr<C2Component>&,
const sp<IComponentListener>& listener,
@@ -85,10 +76,14 @@
virtual Return<Status> setOutputSurface(
uint64_t blockPoolId,
const sp<HGraphicBufferProducer>& surface) override;
- virtual Return<Status> connectToOmxInputSurface(
+ virtual Return<void> connectToInputSurface(
+ const sp<IInputSurface>& inputSurface,
+ connectToInputSurface_cb _hidl_cb) override;
+ virtual Return<void> connectToOmxInputSurface(
const sp<HGraphicBufferProducer>& producer,
const sp<::android::hardware::media::omx::V1_0::
- IGraphicBufferSource>& source) override;
+ IGraphicBufferSource>& source,
+ connectToOmxInputSurface_cb _hidl_cb) override;
virtual Return<Status> disconnectFromInputSurface() override;
virtual Return<void> createBlockPool(
uint32_t allocatorId,
@@ -98,63 +93,34 @@
virtual Return<Status> stop() override;
virtual Return<Status> reset() override;
virtual Return<Status> release() override;
+ virtual Return<sp<IComponentInterface>> getInterface() override;
+
+ // Returns a C2Component associated to the given sink if the sink is indeed
+ // a local component. Returns nullptr otherwise.
+ //
+ // This function is used by InputSurface::connect().
+ static std::shared_ptr<C2Component> findLocalComponent(
+ const sp<IInputSink>& sink);
protected:
c2_status_t mInit;
std::shared_ptr<C2Component> mComponent;
- std::shared_ptr<C2ComponentInterface> mInterface;
+ sp<ComponentInterface> mInterface;
sp<IComponentListener> mListener;
sp<ComponentStore> mStore;
::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
mBufferPoolSender;
+ struct Sink;
+ std::mutex mSinkMutex;
+ sp<Sink> mSink;
+
std::mutex mBlockPoolsMutex;
// This map keeps C2BlockPool objects that are created by createBlockPool()
// alive. These C2BlockPool objects can be deleted by calling
// destroyBlockPool(), reset() or release(), or by destroying the component.
std::map<uint64_t, std::shared_ptr<C2BlockPool>> mBlockPools;
- // This struct is a comparable wrapper for IComponent.
- //
- // An IComponent object is either local or remote. If it is local, we can
- // use the underlying pointer as a key. If it is remote, we have to use the
- // underlying pointer of the associated binder object as a key.
- //
- // See interfacesEqual() for more detail.
- struct InterfaceKey {
- // An InterfaceKey is constructed from IComponent.
- InterfaceKey(const sp<IComponent>& component);
- // operator< is defined here to control the default definition of
- // std::less<InterfaceKey>, which will be used in type Roster defined
- // below.
- bool operator<(const InterfaceKey& other) const {
- return isRemote ?
- (other.isRemote ?
- // remote & remote
- std::less<IBinder*>()(
- remote.unsafe_get(),
- other.remote.unsafe_get()) :
- // remote & local
- false) :
- (other.isRemote ?
- // local & remote
- true :
- // local & local
- std::less<IComponent*>()(
- local.unsafe_get(),
- other.local.unsafe_get()));
- }
- private:
- bool isRemote;
- wp<IBinder> remote;
- wp<IComponent> local;
- };
-
- typedef std::map<InterfaceKey, std::weak_ptr<C2Component>> Roster;
- typedef Roster::const_iterator LocalId;
- LocalId mLocalId;
- void setLocalId(const LocalId& localId);
-
void initListener(const sp<Component>& self);
virtual ~Component() override;
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
new file mode 100644
index 0000000..a5d235e
--- /dev/null
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore;
+
+struct ComponentInterface : public IComponentInterface {
+ ComponentInterface(
+ const std::shared_ptr<C2ComponentInterface>& interface,
+ ComponentStore* store);
+ c2_status_t status() const;
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+protected:
+ std::shared_ptr<C2ComponentInterface> mInterface;
+ sp<CachedConfigurable> mConfigurable;
+ c2_status_t mInit;
+};
+
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index 41e1416..be80c62 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,15 +18,18 @@
#define CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/ComponentInterface.h>
#include <codec2/hidl/1.0/Configurable.h>
-#include <android/hardware/media/c2/1.0/IComponentStore.h>
+
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <hidl/Status.h>
#include <C2Component.h>
#include <C2Param.h>
#include <C2.h>
+#include <chrono>
#include <map>
#include <memory>
#include <mutex>
@@ -42,53 +45,61 @@
using ::android::hardware::media::bufferpool::V2_0::IClientManager;
-using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
-using ::android::wp;
-struct ComponentStore : public Configurable<IComponentStore> {
+struct ComponentStore : public IComponentStore {
ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
virtual ~ComponentStore() = default;
- c2_status_t status() const {
- return mInit;
- }
+ /**
+ * Returns the status of the construction of this object.
+ */
+ c2_status_t status() const;
+ /**
+ * This function is called by CachedConfigurable::init() to validate
+ * supported parameters.
+ */
c2_status_t validateSupportedParams(
const std::vector<std::shared_ptr<C2ParamDescriptor>>& params);
- // Methods from ::android::hardware::media::c2::V1_0::IComponentStore
- Return<void> createComponent(
+ // Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
+ virtual Return<void> createComponent(
const hidl_string& name,
const sp<IComponentListener>& listener,
const sp<IClientManager>& pool,
createComponent_cb _hidl_cb) override;
- Return<void> createInterface(
+ virtual Return<void> createInterface(
const hidl_string& name,
createInterface_cb _hidl_cb) override;
- Return<void> listComponents(listComponents_cb _hidl_cb) override;
- Return<sp<IInputSurface>> createInputSurface() override;
- Return<void> getStructDescriptors(
+ virtual Return<void> listComponents(listComponents_cb _hidl_cb) override;
+ virtual Return<void> createInputSurface(
+ createInputSurface_cb _hidl_cb) override;
+ virtual Return<void> getStructDescriptors(
const hidl_vec<uint32_t>& indices,
getStructDescriptors_cb _hidl_cb) override;
- Return<sp<IClientManager>> getPoolClientManager() override;
- Return<Status> copyBuffer(
+ virtual Return<sp<IClientManager>> getPoolClientManager() override;
+ virtual Return<Status> copyBuffer(
const Buffer& src,
const Buffer& dst) override;
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
- // Debug dump
- Return<void> debug(
+ /**
+ * Dumps information when lshal is called.
+ */
+ virtual Return<void> debug(
const hidl_handle& handle,
const hidl_vec<hidl_string>& args) override;
protected:
- // does bookkeeping for an interface that has been loaded
+ sp<CachedConfigurable> mConfigurable;
+
+ // Does bookkeeping for an interface that has been loaded.
void onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf);
c2_status_t mInit;
@@ -100,18 +111,33 @@
std::set<C2String> mLoadedInterfaces;
mutable std::mutex mStructDescriptorsMutex;
- // Component lifetime management
- Component::Roster mComponentRoster;
+ // ComponentStore keeps track of live Components.
+
+ struct ComponentStatus {
+ std::shared_ptr<C2Component> c2Component;
+ std::chrono::system_clock::time_point birthTime;
+ };
+
mutable std::mutex mComponentRosterMutex;
- void reportComponentDeath(const Component::LocalId& componentLocalId);
+ std::map<Component*, ComponentStatus> mComponentRoster;
+
+ // Called whenever Component is created.
+ void reportComponentBirth(Component* component);
+ // Called only from the destructor of Component.
+ void reportComponentDeath(Component* component);
friend Component;
- // C2Component lookup
- std::shared_ptr<C2Component> findC2Component(
- const sp<IComponent>& component) const;
+ // Helper functions for dumping.
- friend struct InputSurface;
+ std::ostream& dump(
+ std::ostream& out,
+ const std::shared_ptr<const C2Component::Traits>& comp);
+
+ std::ostream& dump(
+ std::ostream& out,
+ ComponentStatus& compStatus);
+
};
} // namespace utils
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
index 2e33a6f..8095185 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,15 +17,13 @@
#ifndef CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
#define CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
-#include <codec2/hidl/1.0/ConfigurableC2Intf.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <hidl/Status.h>
#include <C2Component.h>
#include <C2Param.h>
#include <C2.h>
-#include <android/hardware/media/c2/1.0/IConfigurable.h>
-#include <hidl/Status.h>
-
#include <memory>
namespace android {
@@ -35,9 +33,6 @@
namespace V1_0 {
namespace utils {
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
@@ -46,12 +41,52 @@
struct ComponentStore;
/**
+ * Codec2 objects of different types may have different querying and configuring
+ * functions, but across the Treble boundary, they share the same HIDL
+ * interface, IConfigurable.
+ *
+ * ConfigurableC2Intf is an abstract class that a Codec2 object can implement to
+ * easily expose an IConfigurable instance. See CachedConfigurable below.
+ */
+struct ConfigurableC2Intf {
+ C2String getName() const { return mName; }
+ uint32_t getId() const { return mId; }
+ /** C2ComponentInterface::query_vb sans stack params */
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params) const = 0;
+ /** C2ComponentInterface::config_vb */
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+ /** C2ComponentInterface::querySupportedParams_nb */
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const = 0;
+ /** C2ComponentInterface::querySupportedParams_nb */
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0;
+
+ virtual ~ConfigurableC2Intf() = default;
+
+ ConfigurableC2Intf(const C2String& name, uint32_t id)
+ : mName{name}, mId{id} {}
+
+protected:
+ C2String mName; /* cached component name */
+ uint32_t mId;
+};
+
+/**
* Implementation of the IConfigurable interface that supports caching of
* supported parameters from a supplied ComponentStore.
*
- * This is mainly the same for all of the configurable C2 interfaces though
- * there are slight differences in the blocking behavior. This is handled in the
- * ConfigurableC2Intf implementations.
+ * CachedConfigurable essentially converts a ConfigurableC2Intf into HIDL's
+ * IConfigurable. A Codec2 object generally implements ConfigurableC2Intf and
+ * passes the implementation to the constructor of CachedConfigurable.
+ *
+ * Note that caching happens
*/
struct CachedConfigurable : public IConfigurable {
CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
@@ -60,6 +95,8 @@
// Methods from ::android::hardware::media::c2::V1_0::IConfigurable
+ virtual Return<uint32_t> getId() override;
+
virtual Return<void> getName(getName_cb _hidl_cb) override;
virtual Return<void> query(
@@ -90,63 +127,6 @@
std::vector<std::shared_ptr<C2ParamDescriptor>> mSupportedParams;
};
-/**
- * Template that implements the `IConfigurable` interface for an inherited
- * interface. Classes that implement a child interface `I` of `IConfigurable`
- * can derive from `Configurable<I>`.
- */
-template <typename I>
-struct Configurable : public I {
- Configurable(const sp<CachedConfigurable>& intf): mIntf(intf) {
- }
-
- c2_status_t init(ComponentStore* store) {
- return mIntf->init(store);
- }
-
- // Methods from ::android::hardware::media::c2::V1_0::IConfigurable
-
- using getName_cb = typename I::getName_cb;
- virtual Return<void> getName(getName_cb _hidl_cb) override {
- return mIntf->getName(_hidl_cb);
- }
-
- using query_cb = typename I::query_cb;
- virtual Return<void> query(
- const hidl_vec<uint32_t>& indices,
- bool mayBlock,
- query_cb _hidl_cb) override {
- return mIntf->query(indices, mayBlock, _hidl_cb);
- }
-
- using config_cb = typename I::config_cb;
- virtual Return<void> config(
- const hidl_vec<uint8_t>& inParams,
- bool mayBlock,
- config_cb _hidl_cb) override {
- return mIntf->config(inParams, mayBlock, _hidl_cb);
- }
-
- using querySupportedParams_cb = typename I::querySupportedParams_cb;
- virtual Return<void> querySupportedParams(
- uint32_t start,
- uint32_t count,
- querySupportedParams_cb _hidl_cb) override {
- return mIntf->querySupportedParams(start, count, _hidl_cb);
- }
-
- using querySupportedValues_cb = typename I::querySupportedValues_cb;
- virtual Return<void> querySupportedValues(
- const hidl_vec<FieldSupportedValuesQuery>& inFields,
- bool mayBlock,
- querySupportedValues_cb _hidl_cb) override {
- return mIntf->querySupportedValues(inFields, mayBlock, _hidl_cb);
- }
-
-protected:
- sp<CachedConfigurable> mIntf;
-};
-
} // namespace utils
} // namespace V1_0
} // namespace c2
@@ -155,3 +135,4 @@
} // namespace android
#endif // CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ConfigurableC2Intf.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ConfigurableC2Intf.h
deleted file mode 100644
index b8801bb..0000000
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ConfigurableC2Intf.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CODEC2_HIDL_V1_0_UTILS_CONFIGURABLEC2INTF_H
-#define CODEC2_HIDL_V1_0_UTILS_CONFIGURABLEC2INTF_H
-
-#include <C2Work.h>
-#include <C2Component.h>
-#include <C2Param.h>
-#include <C2.h>
-
-#include <hidl/HidlSupport.h>
-#include <utils/StrongPointer.h>
-#include <vector>
-#include <memory>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-
-using ::android::sp;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-/**
- * Common Codec 2.0 interface wrapper.
- */
-struct ConfigurableC2Intf {
- C2String getName() const { return mName; }
- /** C2ComponentInterface::query_vb sans stack params */
- virtual c2_status_t query(
- const std::vector<C2Param::Index> &indices,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2Param>>* const params) const = 0;
- /** C2ComponentInterface::config_vb */
- virtual c2_status_t config(
- const std::vector<C2Param*> ¶ms,
- c2_blocking_t mayBlock,
- std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
- /** C2ComponentInterface::querySupportedParams_nb */
- virtual c2_status_t querySupportedParams(
- std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const = 0;
- /** C2ComponentInterface::querySupportedParams_nb */
- virtual c2_status_t querySupportedValues(
- std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0;
-
- virtual ~ConfigurableC2Intf() = default;
-
- ConfigurableC2Intf(const C2String& name) : mName(name) {}
-
-protected:
- C2String mName; /* cache component name */
-};
-
-} // namespace utils
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // CODEC2_HIDL_V1_0_UTILS_CONFIGURABLEC2INTF_H
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h
new file mode 100644
index 0000000..b6857d5
--- /dev/null
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputBufferManager.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <utils/Timers.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <set>
+#include <map>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+/**
+ * InputBufferManager
+ * ==================
+ *
+ * InputBufferManager presents a way to track and untrack input buffers in this
+ * (codec) process and send a notification to a listener, possibly in a
+ * different process, when a tracked buffer no longer has any references in this
+ * process.
+ *
+ * InputBufferManager holds a collection of records representing tracked buffers
+ * and their callback listeners. Conceptually, one record is a triple (listener,
+ * frameIndex, bufferIndex) where
+ *
+ * - (frameIndex, bufferIndex) is a pair of indices used to identify the buffer.
+ * - listener is of type IComponentListener. Its onInputBuffersReleased()
+ * function will be called after the associated buffer dies. The argument of
+ * onInputBuffersReleased() is a list of InputBuffer objects, each of which
+ * has the following members:
+ *
+ * uint64_t frameIndex
+ * uint32_t arrayIndex
+ *
+ * When a tracked buffer associated to the triple (listener, frameIndex,
+ * bufferIndex) goes out of scope, listener->onInputBuffersReleased() will be
+ * called with an InputBuffer object whose members are set as follows:
+ *
+ * inputBuffer.frameIndex = frameIndex
+ * inputBuffer.arrayIndex = bufferIndex
+ *
+ * IPC Optimization
+ * ----------------
+ *
+ * Since onInputBuffersReleased() is an IPC call, InputBufferManager tries not
+ * to call it too often. Any two calls to the same listener are at least
+ * mNotificationIntervalNs nanoseconds apart, where mNotificationIntervalNs is
+ * configurable via calling setNotificationInterval(). The default value of
+ * mNotificationIntervalNs is kDefaultNotificationInternalNs.
+ *
+ * Public Member Functions
+ * -----------------------
+ *
+ * InputBufferManager is a singleton class. Its only instance is accessible via
+ * the following public functions:
+ *
+ * - registerFrameData(const sp<IComponentListener>& listener,
+ * const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener,
+ * const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener)
+ *
+ * - setNotificationInterval(nsecs_t notificationIntervalNs)
+ *
+ */
+
+struct InputBufferManager {
+
+ /**
+ * The default value for the time interval between 2 subsequent IPCs.
+ */
+ static constexpr nsecs_t kDefaultNotificationIntervalNs = 1000000; /* 1ms */
+
+ /**
+ * Track all buffers in a C2FrameData object.
+ *
+ * input (C2FrameData) has the following two members that are of interest:
+ *
+ * C2WorkOrdinal ordinal
+ * vector<shared_ptr<C2Buffer>> buffers
+ *
+ * Calling registerFrameData(listener, input) will register multiple
+ * triples (listener, frameIndex, bufferIndex) where frameIndex is equal to
+ * input.ordinal.frameIndex and bufferIndex runs through the indices of
+ * input.buffers such that input.buffers[bufferIndex] is not null.
+ *
+ * This should be called from queue().
+ *
+ * \param listener Listener of death notifications.
+ * \param input Input frame data whose input buffers are to be tracked.
+ */
+ static void registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input);
+
+ /**
+ * Untrack all buffers in a C2FrameData object.
+ *
+ * Calling unregisterFrameData(listener, input) will unregister and remove
+ * pending notifications for all triples (l, fi, bufferIndex) such that
+ * l = listener and fi = input.ordinal.frameIndex.
+ *
+ * This should be called from onWorkDone() and flush().
+ *
+ * \param listener Previously registered listener.
+ * \param input Previously registered frame data.
+ */
+ static void unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input);
+
+ /**
+ * Untrack all buffers associated to a given listener.
+ *
+ * Calling unregisterFrameData(listener) will unregister and remove
+ * pending notifications for all triples (l, frameIndex, bufferIndex) such
+ * that l = listener.
+ *
+ * This should be called when the component cleans up all input buffers,
+ * i.e., when reset(), release(), stop() or ~Component() is called.
+ *
+ * \param listener Previously registered listener.
+ */
+ static void unregisterFrameData(
+ const wp<IComponentListener>& listener);
+
+ /**
+ * Set the notification interval.
+ *
+ * \param notificationIntervalNs New notification interval, in nanoseconds.
+ */
+ static void setNotificationInterval(nsecs_t notificationIntervalNs);
+
+private:
+ void _registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input);
+ void _unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input);
+ void _unregisterFrameData(
+ const wp<IComponentListener>& listener);
+ void _setNotificationInterval(nsecs_t notificationIntervalNs);
+
+ // The callback function tied to C2Buffer objects.
+ //
+ // Note: This function assumes that sInstance is the only instance of this
+ // class.
+ static void onBufferDestroyed(const C2Buffer* buf, void* arg);
+ void _onBufferDestroyed(const C2Buffer* buf, void* arg);
+
+ // Persistent data to be passed as "arg" in onBufferDestroyed().
+ // This is essentially the triple (listener, frameIndex, bufferIndex) plus a
+ // weak pointer to the C2Buffer object.
+ //
+ // Note that the "key" is bufferIndex according to operator<(). This is
+ // designed to work with TrackedBuffersMap defined below.
+ struct TrackedBuffer {
+ wp<IComponentListener> listener;
+ uint64_t frameIndex;
+ size_t bufferIndex;
+ std::weak_ptr<C2Buffer> buffer;
+ TrackedBuffer(const wp<IComponentListener>& listener,
+ uint64_t frameIndex,
+ size_t bufferIndex,
+ const std::shared_ptr<C2Buffer>& buffer)
+ : listener(listener),
+ frameIndex(frameIndex),
+ bufferIndex(bufferIndex),
+ buffer(buffer) {}
+ TrackedBuffer(const TrackedBuffer&) = default;
+ bool operator<(const TrackedBuffer& other) const {
+ return bufferIndex < other.bufferIndex;
+ }
+ };
+
+ // Map: listener -> frameIndex -> set<TrackedBuffer>.
+ // Essentially, this is used to store triples (listener, frameIndex,
+ // bufferIndex) that's searchable by listener and (listener, frameIndex).
+ // However, the value of the innermost map is TrackedBuffer, which also
+ // contains an extra copy of listener and frameIndex. This is needed
+ // because onBufferDestroyed() needs to know listener and frameIndex too.
+ typedef std::map<wp<IComponentListener>,
+ std::map<uint64_t,
+ std::set<TrackedBuffer>>> TrackedBuffersMap;
+
+ // Storage for pending (unsent) death notifications for one listener.
+ // Each pair in member named "indices" are (frameIndex, bufferIndex) from
+ // the (listener, frameIndex, bufferIndex) triple.
+ struct DeathNotifications {
+
+ // The number of pending notifications for this listener.
+ // count may be 0, in which case the DeathNotifications object will
+ // remain valid for only a small period (specified
+ // nanoseconds).
+ size_t count;
+
+ // The timestamp of the most recent callback on this listener. This is
+ // used to guarantee that callbacks do not occur too frequently, and
+ // also to trigger expiration of a DeathNotifications object that has
+ // count = 0.
+ nsecs_t lastSentNs;
+
+ // Map: frameIndex -> vector of bufferIndices
+ // This is essentially a collection of (framdeIndex, bufferIndex).
+ std::map<uint64_t, std::vector<size_t>> indices;
+
+ DeathNotifications(
+ nsecs_t notificationIntervalNs = kDefaultNotificationIntervalNs)
+ : count(0),
+ lastSentNs(systemTime() - notificationIntervalNs),
+ indices() {}
+ };
+
+ // The minimum time period between IPC calls to notify the client about the
+ // destruction of input buffers.
+ std::atomic<nsecs_t> mNotificationIntervalNs{kDefaultNotificationIntervalNs};
+
+ // Mutex for the management of all input buffers.
+ std::mutex mMutex;
+
+ // Tracked input buffers.
+ TrackedBuffersMap mTrackedBuffersMap;
+
+ // Death notifications to be sent.
+ //
+ // A DeathNotifications object is associated to each listener. An entry in
+ // this map will be removed if its associated DeathNotifications has count =
+ // 0 and lastSentNs < systemTime() - mNotificationIntervalNs.
+ std::map<wp<IComponentListener>, DeathNotifications> mDeathNotifications;
+
+ // Condition variable signaled when an entry is added to mDeathNotifications.
+ std::condition_variable mOnBufferDestroyed;
+
+ // Notify the clients about buffer destructions.
+ // Return false if all destructions have been notified.
+ // Return true and set timeToRetry to the duration to wait for before
+ // retrying if some destructions have not been notified.
+ bool processNotifications(nsecs_t* timeToRetryNs);
+
+ // Main function for the input buffer manager thread.
+ void main();
+
+ // The thread that manages notifications.
+ //
+ // Note: This variable is declared last so its initialization will happen
+ // after all other member variables have been initialized.
+ std::thread mMainThread;
+
+ // Private constructor.
+ InputBufferManager();
+
+ // The only instance of this class.
+ static InputBufferManager& getInstance();
+
+};
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
index cef258e..2682c13 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,21 +19,14 @@
#include <codec2/hidl/1.0/ComponentStore.h>
-#include <android/hardware/media/c2/1.0/IInputSurface.h>
-#include <android/hardware/media/c2/1.0/IComponent.h>
-
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
-#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <android/hardware/media/1.0/types.h>
-
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
#include <gui/IGraphicBufferProducer.h>
+#include <hidl/Status.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
-#include <hidl/HidlSupport.h>
-#include <hidl/Status.h>
-
-class C2ReflectorHelper;
+#include <util/C2InterfaceHelper.h>
namespace android {
namespace hardware {
@@ -49,133 +42,31 @@
using ::android::hardware::Void;
using ::android::sp;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::media::V1_0::AnwBuffer;
-
struct InputSurface : public IInputSurface {
- typedef ::android::hidl::base::V1_0::IBase IBase;
-
- typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IProducerListener HProducerListener;
-
- typedef ::android::
- IGraphicBufferProducer BGraphicBufferProducer;
-
typedef ::android::hardware::graphics::bufferqueue::V1_0::
IGraphicBufferProducer HGraphicBufferProducer;
typedef ::android::
GraphicBufferSource GraphicBufferSource;
-// Type disambiguation
-
- typedef ::android::hardware::media::c2::V1_0::Status Status;
-
-// New methods from IInputSurface
-
- virtual Return<void> connectToComponent(
- const sp<IComponent>& component,
- connectToComponent_cb _hidl_cb) override;
+ virtual Return<sp<HGraphicBufferProducer>> getGraphicBufferProducer() override;
virtual Return<sp<IConfigurable>> getConfigurable() override;
-// Methods derived from IGraphicBufferProducer
-
- virtual Return<void> requestBuffer(
- int32_t slot,
- requestBuffer_cb _hidl_cb) override;
-
- virtual Return<int32_t> setMaxDequeuedBufferCount(
- int32_t maxDequeuedBuffers) override;
-
- virtual Return<int32_t> setAsyncMode(
- bool async) override;
-
- virtual Return<void> dequeueBuffer(
- uint32_t width,
- uint32_t height,
- PixelFormat format,
- uint32_t usage,
- bool getFrameTimestamps,
- dequeueBuffer_cb _hidl_cb) override;
-
- virtual Return<int32_t> detachBuffer(
- int32_t slot) override;
-
- virtual Return<void> detachNextBuffer(
- detachNextBuffer_cb _hidl_cb) override;
-
- virtual Return<void> attachBuffer(
- const AnwBuffer& buffer,
- attachBuffer_cb _hidl_cb) override;
-
- virtual Return<void> queueBuffer(
- int32_t slot,
- const QueueBufferInput& input,
- queueBuffer_cb _hidl_cb) override;
-
- virtual Return<int32_t> cancelBuffer(
- int32_t slot,
- const hidl_handle& fence) override;
-
- virtual Return<void> query(
- int32_t what,
- query_cb _hidl_cb) override;
-
virtual Return<void> connect(
- const sp<HProducerListener>& listener,
- int32_t api,
- bool producerControlledByApp,
+ const sp<IInputSink>& sink,
connect_cb _hidl_cb) override;
- virtual Return<int32_t> disconnect(
- int32_t api,
- DisconnectMode mode) override;
-
- virtual Return<int32_t> setSidebandStream(
- const hidl_handle& stream) override;
-
- virtual Return<void> allocateBuffers(
- uint32_t width,
- uint32_t height,
- PixelFormat format,
- uint32_t usage) override;
-
- virtual Return<int32_t> allowAllocation(
- bool allow) override;
-
- virtual Return<int32_t> setGenerationNumber(
- uint32_t generationNumber) override;
-
- virtual Return<void> getConsumerName(
- getConsumerName_cb _hidl_cb) override;
-
- virtual Return<int32_t> setSharedBufferMode(
- bool sharedBufferMode) override;
-
- virtual Return<int32_t> setAutoRefresh(
- bool autoRefresh) override;
-
- virtual Return<int32_t> setDequeueTimeout(
- int64_t timeoutNs) override;
-
- virtual Return<void> getLastQueuedBuffer(
- getLastQueuedBuffer_cb _hidl_cb) override;
-
- virtual Return<void> getFrameTimestamps(
- getFrameTimestamps_cb _hidl_cb) override;
-
- virtual Return<void> getUniqueId(
- getUniqueId_cb _hidl_cb) override;
-
- class ConfigurableImpl;
-
protected:
+
+ class Interface;
+ class ConfigurableIntf;
+
sp<ComponentStore> mStore;
- sp<HGraphicBufferProducer> mBase;
+ sp<HGraphicBufferProducer> mProducer;
sp<GraphicBufferSource> mSource;
- std::shared_ptr<ConfigurableImpl> mHelper;
+ std::shared_ptr<Interface> mIntf;
sp<CachedConfigurable> mConfigurable;
InputSurface(
@@ -187,6 +78,7 @@
virtual ~InputSurface() override = default;
friend struct ComponentStore;
+
};
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
index 904fa9e..758b6b2 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,8 +18,10 @@
#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/Configurable.h>
#include <android/hardware/media/c2/1.0/IComponent.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
@@ -44,19 +46,28 @@
using ::android::sp;
using ::android::GraphicBufferSource;
+// An InputSurfaceConnection connects an InputSurface to a sink, which may be an
+// IInputSink or a local C2Component. This can be specified by choosing the
+// corresponding constructor. The reason for distinguishing these two cases is
+// that when an InputSurfaceConnection lives in the same process as the
+// component that processes the buffers, data parceling is not needed.
struct InputSurfaceConnection : public IInputSurfaceConnection {
virtual Return<Status> disconnect() override;
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
+
protected:
InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
- const std::shared_ptr<C2Component>& component);
+ const std::shared_ptr<C2Component>& comp,
+ const sp<ComponentStore>& store);
InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
- const sp<IComponent>& component);
+ const sp<IInputSink>& sink,
+ const sp<ComponentStore>& store);
bool init();
@@ -68,9 +79,9 @@
struct Impl;
- std::mutex mMutex;
- sp<GraphicBufferSource> mSource;
+ std::mutex mImplMutex;
sp<Impl> mImpl;
+ sp<CachedConfigurable> mConfigurable;
virtual ~InputSurfaceConnection() override;
};
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index d8a50b6..c38e674 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
#ifndef CODEC2_HIDL_V1_0_UTILS_TYPES_H
#define CODEC2_HIDL_V1_0_UTILS_TYPES_H
-#include <chrono>
-
#include <bufferpool/ClientManager.h>
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <android/hardware/media/bufferpool/2.0/types.h>
@@ -30,6 +28,9 @@
#include <C2Param.h>
#include <C2ParamDef.h>
#include <C2Work.h>
+#include <util/C2Debug-base.h>
+
+#include <chrono>
using namespace std::chrono_literals;
@@ -65,66 +66,74 @@
};
typedef C2GlobalParam<C2Info, C2Hidl_Rect, 1> C2Hidl_RectInfo;
+// Make asString() and operator<< work with Status as well as c2_status_t.
+C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
+
+/**
+ * All objcpy() functions will return a boolean value indicating whether the
+ * conversion succeeds or not.
+ */
+
// C2SettingResult -> SettingResult
-Status objcpy(
+bool objcpy(
SettingResult* d,
const C2SettingResult& s);
// SettingResult -> std::unique_ptr<C2SettingResult>
-c2_status_t objcpy(
+bool objcpy(
std::unique_ptr<C2SettingResult>* d,
const SettingResult& s);
// C2ParamDescriptor -> ParamDescriptor
-Status objcpy(
+bool objcpy(
ParamDescriptor* d,
const C2ParamDescriptor& s);
// ParamDescriptor -> std::shared_ptr<C2ParamDescriptor>
-c2_status_t objcpy(
+bool objcpy(
std::shared_ptr<C2ParamDescriptor>* d,
const ParamDescriptor& s);
// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-Status objcpy(
+bool objcpy(
FieldSupportedValuesQuery* d,
const C2FieldSupportedValuesQuery& s);
// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-c2_status_t objcpy(
+bool objcpy(
C2FieldSupportedValuesQuery* d,
const FieldSupportedValuesQuery& s);
// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-Status objcpy(
+bool objcpy(
FieldSupportedValuesQueryResult* d,
const C2FieldSupportedValuesQuery& s);
// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult -> C2FieldSupportedValuesQuery
-c2_status_t objcpy(
+bool objcpy(
C2FieldSupportedValuesQuery* d,
const FieldSupportedValuesQuery& sq,
const FieldSupportedValuesQueryResult& sr);
// C2Component::Traits -> ComponentTraits
-Status objcpy(
+bool objcpy(
IComponentStore::ComponentTraits* d,
const C2Component::Traits& s);
// ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
// Note: The output d is only valid as long as aliasesBuffer remains alive.
-c2_status_t objcpy(
+bool objcpy(
C2Component::Traits* d,
std::unique_ptr<std::vector<std::string>>* aliasesBuffer,
const IComponentStore::ComponentTraits& s);
// C2StructDescriptor -> StructDescriptor
-Status objcpy(
+bool objcpy(
StructDescriptor* d,
const C2StructDescriptor& s);
// StructDescriptor -> C2StructDescriptor
-c2_status_t objcpy(
+bool objcpy(
std::unique_ptr<C2StructDescriptor>* d,
const StructDescriptor& s);
@@ -208,68 +217,77 @@
// std::list<std::unique_ptr<C2Work>> -> WorkBundle
// Note: If bufferpool will be used, bpSender must not be null.
-Status objcpy(
+bool objcpy(
WorkBundle* d,
const std::list<std::unique_ptr<C2Work>>& s,
BufferPoolSender* bpSender = nullptr);
// WorkBundle -> std::list<std::unique_ptr<C2Work>>
-c2_status_t objcpy(
+bool objcpy(
std::list<std::unique_ptr<C2Work>>* d,
const WorkBundle& s);
/**
- * Parses a params blob and returns C2Param pointers to its params.
+ * Parses a params blob and returns C2Param pointers to its params. The pointers
+ * point to locations inside the underlying buffer of \p blob. If \p blob is
+ * destroyed, the pointers become invalid.
+ *
* \param[out] params target vector of C2Param pointers
* \param[in] blob parameter blob to parse
- * \retval C2_OK if the full blob was parsed
- * \retval C2_BAD_VALUE otherwise
+ * \retval true if the full blob was parsed
+ * \retval false otherwise
*/
-c2_status_t parseParamsBlob(
+bool parseParamsBlob(
std::vector<C2Param*> *params,
const hidl_vec<uint8_t> &blob);
/**
* Concatenates a list of C2Params into a params blob.
+ *
* \param[out] blob target blob
* \param[in] params parameters to concatenate
- * \retval C2_OK if the blob was successfully created
- * \retval C2_BAD_VALUE if the blob was not successful (this only happens if the parameters were
- * not const)
+ * \retval true if the blob was successfully created
+ * \retval false if the blob was not successful (this only happens if the
+ * parameters were not const)
*/
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<C2Param*> ¶ms);
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<std::unique_ptr<C2Param>> ¶ms);
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<std::shared_ptr<const C2Info>> ¶ms);
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<std::unique_ptr<C2Tuning>> ¶ms);
/**
* Parses a params blob and create a vector of C2Params whose members are copies
* of the params in the blob.
+ *
* \param[out] params the resulting vector
* \param[in] blob parameter blob to parse
- * \retval C2_OK if the full blob was parsed and params was constructed
- * \retval C2_BAD_VALUE otherwise
+ * \retval true if the full blob was parsed and params was constructed
+ * \retval false otherwise
*/
-c2_status_t copyParamsFromBlob(
+bool copyParamsFromBlob(
std::vector<std::unique_ptr<C2Param>>* params,
Params blob);
+bool copyParamsFromBlob(
+ std::vector<std::unique_ptr<C2Tuning>>* params,
+ Params blob);
/**
- * Parses a params blob and applies updates to params
+ * Parses a params blob and applies updates to params.
+ *
* \param[in,out] params params to be updated
* \param[in] blob parameter blob containing updates
- * \retval C2_OK if the full blob was parsed and params was updated
- * \retval C2_BAD_VALUE otherwise
+ * \retval true if the full blob was parsed and params was updated
+ * \retval false otherwise
*/
-c2_status_t updateParamsFromBlob(
+bool updateParamsFromBlob(
const std::vector<C2Param*>& params,
const Params& blob);
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index a128a9d..caed839 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,12 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2-types"
-#include <log/log.h>
+#include <android-base/logging.h>
#include <codec2/hidl/1.0/types.h>
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <C2AllocatorIon.h>
#include <C2AllocatorGralloc.h>
@@ -35,10 +36,9 @@
#include <algorithm>
#include <functional>
+#include <iomanip>
#include <unordered_map>
-#include <media/stagefright/foundation/AUtils.h>
-
namespace android {
namespace hardware {
namespace media {
@@ -57,8 +57,18 @@
TransactionId;
using ::android::TWGraphicBufferProducer;
+const char* asString(Status status, const char* def) {
+ return asString(static_cast<c2_status_t>(status), def);
+}
+
namespace /* unnamed */ {
+template <typename EnumClass>
+typename std::underlying_type<EnumClass>::type underlying_value(
+ EnumClass x) {
+ return static_cast<typename std::underlying_type<EnumClass>::type>(x);
+}
+
template <typename Common, typename DstVector, typename SrcVector>
void copyVector(DstVector* d, const SrcVector& s) {
static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
@@ -73,10 +83,11 @@
}
// C2ParamField -> ParamField
-void objcpy(ParamField *d, const C2ParamField &s) {
+bool objcpy(ParamField *d, const C2ParamField &s) {
d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
+ return true;
}
struct C2ParamFieldBuilder : public C2ParamField {
@@ -92,21 +103,23 @@
};
// C2WorkOrdinalStruct -> WorkOrdinal
-void objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
+bool objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
+ return true;
}
// WorkOrdinal -> C2WorkOrdinalStruct
-void objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
+bool objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
d->frameIndex = c2_cntr64_t(s.frameIndex);
d->timestamp = c2_cntr64_t(s.timestampUs);
d->customOrdinal = c2_cntr64_t(s.customOrdinal);
+ return true;
}
// C2FieldSupportedValues::range's type -> FieldSupportedValues::Range
-void objcpy(
+bool objcpy(
FieldSupportedValues::Range* d,
const decltype(C2FieldSupportedValues::range)& s) {
d->min = static_cast<PrimitiveValue>(s.min.u64);
@@ -114,21 +127,24 @@
d->step = static_cast<PrimitiveValue>(s.step.u64);
d->num = static_cast<PrimitiveValue>(s.num.u64);
d->denom = static_cast<PrimitiveValue>(s.denom.u64);
+ return true;
}
// C2FieldSupportedValues -> FieldSupportedValues
-Status objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
- d->typeOther = static_cast<int32_t>(s.type);
+bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
switch (s.type) {
case C2FieldSupportedValues::EMPTY:
d->type = FieldSupportedValues::Type::EMPTY;
d->values.resize(0);
- return Status::OK;
+ break;
case C2FieldSupportedValues::RANGE:
d->type = FieldSupportedValues::Type::RANGE;
- objcpy(&d->range, s.range);
+ if (!objcpy(&d->range, s.range)) {
+ LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
+ return false;
+ }
d->values.resize(0);
- return Status::OK;
+ break;
default:
switch (s.type) {
case C2FieldSupportedValues::VALUES:
@@ -138,18 +154,22 @@
d->type = FieldSupportedValues::Type::FLAGS;
break;
default:
- d->type = FieldSupportedValues::Type::OTHER;
- // Copy all fields in this case
- objcpy(&d->range, s.range);
+ LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
+ << "with underlying value " << underlying_value(s.type)
+ << ".";
+ d->type = static_cast<FieldSupportedValues::Type>(s.type);
+ if (!objcpy(&d->range, s.range)) {
+ LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
+ return false;
+ }
}
- d->values.resize(s.values.size());
copyVector<uint64_t>(&d->values, s.values);
- return Status::OK;
}
+ return true;
}
// FieldSupportedValues::Range -> C2FieldSupportedValues::range's type
-void objcpy(
+bool objcpy(
decltype(C2FieldSupportedValues::range)* d,
const FieldSupportedValues::Range& s) {
d->min.u64 = static_cast<uint64_t>(s.min);
@@ -157,19 +177,23 @@
d->step.u64 = static_cast<uint64_t>(s.step);
d->num.u64 = static_cast<uint64_t>(s.num);
d->denom.u64 = static_cast<uint64_t>(s.denom);
+ return true;
}
// FieldSupportedValues -> C2FieldSupportedValues
-c2_status_t objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
+bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
switch (s.type) {
case FieldSupportedValues::Type::EMPTY:
d->type = C2FieldSupportedValues::EMPTY;
- return C2_OK;
+ break;
case FieldSupportedValues::Type::RANGE:
d->type = C2FieldSupportedValues::RANGE;
- objcpy(&d->range, s.range);
+ if (!objcpy(&d->range, s.range)) {
+ LOG(ERROR) << "Invalid FieldSupportedValues::range.";
+ return false;
+ }
d->values.resize(0);
- return C2_OK;
+ break;
default:
switch (s.type) {
case FieldSupportedValues::Type::VALUES:
@@ -179,22 +203,30 @@
d->type = C2FieldSupportedValues::FLAGS;
break;
default:
- d->type = static_cast<C2FieldSupportedValues::type_t>(s.typeOther);
- // Copy all fields in this case
- objcpy(&d->range, s.range);
+ LOG(DEBUG) << "Unrecognized FieldSupportedValues::Type "
+ << "with underlying value " << underlying_value(s.type)
+ << ".";
+ d->type = static_cast<C2FieldSupportedValues::type_t>(s.type);
+ if (!objcpy(&d->range, s.range)) {
+ LOG(ERROR) << "Invalid FieldSupportedValues::range.";
+ return false;
+ }
}
copyVector<uint64_t>(&d->values, s.values);
- return C2_OK;
}
+ return true;
}
} // unnamed namespace
// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-Status objcpy(
+bool objcpy(
FieldSupportedValuesQuery* d,
const C2FieldSupportedValuesQuery& s) {
- objcpy(&d->field, s.field());
+ if (!objcpy(&d->field, s.field())) {
+ LOG(ERROR) << "Invalid C2FieldSupportedValuesQuery::field.";
+ return false;
+ }
switch (s.type()) {
case C2FieldSupportedValuesQuery::POSSIBLE:
d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
@@ -203,15 +235,16 @@
d->type = FieldSupportedValuesQuery::Type::CURRENT;
break;
default:
- ALOGE("Unknown type of C2FieldSupportedValuesQuery: %u",
- static_cast<unsigned>(s.type()));
- return Status::BAD_VALUE;
+ LOG(DEBUG) << "Unrecognized C2FieldSupportedValuesQuery::type_t "
+ << "with underlying value " << underlying_value(s.type())
+ << ".";
+ d->type = static_cast<FieldSupportedValuesQuery::Type>(s.type());
}
- return Status::OK;
+ return true;
}
// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-c2_status_t objcpy(
+bool objcpy(
C2FieldSupportedValuesQuery* d,
const FieldSupportedValuesQuery& s) {
C2FieldSupportedValuesQuery::type_t dType;
@@ -223,16 +256,17 @@
dType = C2FieldSupportedValuesQuery::CURRENT;
break;
default:
- ALOGE("Unknown type of FieldSupportedValuesQuery: %u",
- static_cast<unsigned>(s.type));
- return C2_BAD_VALUE;
+ LOG(DEBUG) << "Unrecognized FieldSupportedValuesQuery::Type "
+ << "with underlying value " << underlying_value(s.type)
+ << ".";
+ dType = static_cast<C2FieldSupportedValuesQuery::type_t>(s.type);
}
*d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
- return C2_OK;
+ return true;
}
// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-Status objcpy(
+bool objcpy(
FieldSupportedValuesQueryResult* d,
const C2FieldSupportedValuesQuery& s) {
d->status = static_cast<Status>(s.status);
@@ -241,20 +275,24 @@
// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
// C2FieldSupportedValuesQuery
-c2_status_t objcpy(
+bool objcpy(
C2FieldSupportedValuesQuery* d,
const FieldSupportedValuesQuery& sq,
const FieldSupportedValuesQueryResult& sr) {
- c2_status_t status = objcpy(d, sq);
- if (status != C2_OK) {
- return status;
+ if (!objcpy(d, sq)) {
+ LOG(ERROR) << "Invalid FieldSupportedValuesQuery.";
+ return false;
}
d->status = static_cast<c2_status_t>(sr.status);
- return objcpy(&d->values, sr.values);
+ if (!objcpy(&d->values, sr.values)) {
+ LOG(ERROR) << "Invalid FieldSupportedValuesQueryResult::values.";
+ return false;
+ }
+ return true;
}
// C2Component::Traits -> IComponentStore::ComponentTraits
-Status objcpy(
+bool objcpy(
IComponentStore::ComponentTraits *d,
const C2Component::Traits &s) {
d->name = s.name;
@@ -266,10 +304,19 @@
case C2Component::DOMAIN_AUDIO:
d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
break;
- default:
+ case C2Component::DOMAIN_IMAGE:
+ d->domain = IComponentStore::ComponentTraits::Domain::IMAGE;
+ break;
+ case C2Component::DOMAIN_OTHER:
d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
+ break;
+ default:
+ LOG(DEBUG) << "Unrecognized C2Component::domain_t "
+ << "with underlying value " << underlying_value(s.domain)
+ << ".";
+ d->domain = static_cast<IComponentStore::ComponentTraits::Domain>(
+ s.domain);
}
- d->domainOther = static_cast<uint32_t>(s.domain);
switch (s.kind) {
case C2Component::KIND_DECODER:
@@ -278,10 +325,16 @@
case C2Component::KIND_ENCODER:
d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
break;
- default:
+ case C2Component::KIND_OTHER:
d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
+ break;
+ default:
+ LOG(DEBUG) << "Unrecognized C2Component::kind_t "
+ << "with underlying value " << underlying_value(s.kind)
+ << ".";
+ d->kind = static_cast<IComponentStore::ComponentTraits::Kind>(
+ s.kind);
}
- d->kindOther = static_cast<uint32_t>(s.kind);
d->rank = static_cast<uint32_t>(s.rank);
@@ -292,11 +345,11 @@
--ix;
d->aliases[ix] = s.aliases[ix];
}
- return Status::OK;
+ return true;
}
// ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
-c2_status_t objcpy(
+bool objcpy(
C2Component::Traits* d,
std::unique_ptr<std::vector<std::string>>* aliasesBuffer,
const IComponentStore::ComponentTraits& s) {
@@ -309,8 +362,17 @@
case IComponentStore::ComponentTraits::Domain::AUDIO:
d->domain = C2Component::DOMAIN_AUDIO;
break;
+ case IComponentStore::ComponentTraits::Domain::IMAGE:
+ d->domain = C2Component::DOMAIN_IMAGE;
+ break;
+ case IComponentStore::ComponentTraits::Domain::OTHER:
+ d->domain = C2Component::DOMAIN_OTHER;
+ break;
default:
- d->domain = static_cast<C2Component::domain_t>(s.domainOther);
+ LOG(DEBUG) << "Unrecognized ComponentTraits::Domain "
+ << "with underlying value " << underlying_value(s.domain)
+ << ".";
+ d->domain = static_cast<C2Component::domain_t>(s.domain);
}
switch (s.kind) {
@@ -320,8 +382,14 @@
case IComponentStore::ComponentTraits::Kind::ENCODER:
d->kind = C2Component::KIND_ENCODER;
break;
+ case IComponentStore::ComponentTraits::Kind::OTHER:
+ d->kind = C2Component::KIND_OTHER;
+ break;
default:
- d->kind = static_cast<C2Component::kind_t>(s.kindOther);
+ LOG(DEBUG) << "Unrecognized ComponentTraits::Kind "
+ << "with underlying value " << underlying_value(s.kind)
+ << ".";
+ d->kind = static_cast<C2Component::kind_t>(s.kind);
}
d->rank = static_cast<C2Component::rank_t>(s.rank);
@@ -336,52 +404,55 @@
(**aliasesBuffer)[i] = s.aliases[i].c_str();
d->aliases[i] = (**aliasesBuffer)[i].c_str();
}
- return C2_OK;
+ return true;
}
namespace /* unnamed */ {
// C2ParamFieldValues -> ParamFieldValues
-Status objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
- objcpy(&d->paramOrField, s.paramOrField);
+bool objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
+ if (!objcpy(&d->paramOrField, s.paramOrField)) {
+ LOG(ERROR) << "Invalid C2ParamFieldValues::paramOrField.";
+ return false;
+ }
if (s.values) {
d->values.resize(1);
- return objcpy(&d->values[0], *s.values);
+ if (!objcpy(&d->values[0], *s.values)) {
+ LOG(ERROR) << "Invalid C2ParamFieldValues::values.";
+ return false;
+ }
+ return true;
}
d->values.resize(0);
- return Status::OK;
+ return true;
}
// ParamFieldValues -> C2ParamFieldValues
-c2_status_t objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
+bool objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
if (s.values.size() == 1) {
d->values = std::make_unique<C2FieldSupportedValues>();
- return objcpy(d->values.get(), s.values[0]);
+ if (!objcpy(d->values.get(), s.values[0])) {
+ LOG(ERROR) << "Invalid ParamFieldValues::values.";
+ return false;
+ }
+ return true;
} else if (s.values.size() == 0) {
d->values.reset();
- return C2_OK;
+ return true;
}
- ALOGE("Multiple FieldSupportedValues objects. "
- "(Only one is allowed.)");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid ParamFieldValues: "
+ "Two or more FieldSupportedValues objects exist in "
+ "ParamFieldValues. "
+ "Only zero or one is allowed.";
+ return false;
}
} // unnamed namespace
// C2SettingResult -> SettingResult
-Status objcpy(SettingResult *d, const C2SettingResult &s) {
- d->failureOther = static_cast<uint32_t>(s.failure);
+bool objcpy(SettingResult *d, const C2SettingResult &s) {
switch (s.failure) {
- case C2SettingResult::READ_ONLY:
- d->failure = SettingResult::Failure::READ_ONLY;
- break;
- case C2SettingResult::MISMATCH:
- d->failure = SettingResult::Failure::MISMATCH;
- break;
- case C2SettingResult::BAD_VALUE:
- d->failure = SettingResult::Failure::BAD_VALUE;
- break;
case C2SettingResult::BAD_TYPE:
d->failure = SettingResult::Failure::BAD_TYPE;
break;
@@ -391,53 +462,61 @@
case C2SettingResult::BAD_INDEX:
d->failure = SettingResult::Failure::BAD_INDEX;
break;
+ case C2SettingResult::READ_ONLY:
+ d->failure = SettingResult::Failure::READ_ONLY;
+ break;
+ case C2SettingResult::MISMATCH:
+ d->failure = SettingResult::Failure::MISMATCH;
+ break;
+ case C2SettingResult::BAD_VALUE:
+ d->failure = SettingResult::Failure::BAD_VALUE;
+ break;
case C2SettingResult::CONFLICT:
d->failure = SettingResult::Failure::CONFLICT;
break;
case C2SettingResult::UNSUPPORTED:
d->failure = SettingResult::Failure::UNSUPPORTED;
break;
+ case C2SettingResult::INFO_BAD_VALUE:
+ d->failure = SettingResult::Failure::INFO_BAD_VALUE;
+ break;
case C2SettingResult::INFO_CONFLICT:
d->failure = SettingResult::Failure::INFO_CONFLICT;
break;
default:
- d->failure = SettingResult::Failure::OTHER;
+ LOG(DEBUG) << "Unrecognized C2SettingResult::Failure "
+ << "with underlying value " << underlying_value(s.failure)
+ << ".";
+ d->failure = static_cast<SettingResult::Failure>(s.failure);
}
- Status status = objcpy(&d->field, s.field);
- if (status != Status::OK) {
- return status;
+ if (!objcpy(&d->field, s.field)) {
+ LOG(ERROR) << "Invalid C2SettingResult::field.";
+ return false;
}
d->conflicts.resize(s.conflicts.size());
size_t i = 0;
for (const C2ParamFieldValues& sConflict : s.conflicts) {
ParamFieldValues &dConflict = d->conflicts[i++];
- status = objcpy(&dConflict, sConflict);
- if (status != Status::OK) {
- return status;
+ if (!objcpy(&dConflict, sConflict)) {
+ LOG(ERROR) << "Invalid C2SettingResult::conflicts["
+ << i - 1 << "].";
+ return false;
}
}
- return Status::OK;
+ return true;
}
// SettingResult -> std::unique_ptr<C2SettingResult>
-c2_status_t objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
+bool objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
*d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
.field = C2ParamFieldValues(C2ParamFieldBuilder()) });
if (!*d) {
- return C2_NO_MEMORY;
+ LOG(ERROR) << "No memory for C2SettingResult.";
+ return false;
}
// failure
switch (s.failure) {
- case SettingResult::Failure::READ_ONLY:
- (*d)->failure = C2SettingResult::READ_ONLY;
- break;
- case SettingResult::Failure::MISMATCH:
- (*d)->failure = C2SettingResult::MISMATCH;
- break;
- case SettingResult::Failure::BAD_VALUE:
- (*d)->failure = C2SettingResult::BAD_VALUE;
- break;
case SettingResult::Failure::BAD_TYPE:
(*d)->failure = C2SettingResult::BAD_TYPE;
break;
@@ -447,23 +526,38 @@
case SettingResult::Failure::BAD_INDEX:
(*d)->failure = C2SettingResult::BAD_INDEX;
break;
+ case SettingResult::Failure::READ_ONLY:
+ (*d)->failure = C2SettingResult::READ_ONLY;
+ break;
+ case SettingResult::Failure::MISMATCH:
+ (*d)->failure = C2SettingResult::MISMATCH;
+ break;
+ case SettingResult::Failure::BAD_VALUE:
+ (*d)->failure = C2SettingResult::BAD_VALUE;
+ break;
case SettingResult::Failure::CONFLICT:
(*d)->failure = C2SettingResult::CONFLICT;
break;
case SettingResult::Failure::UNSUPPORTED:
(*d)->failure = C2SettingResult::UNSUPPORTED;
break;
+ case SettingResult::Failure::INFO_BAD_VALUE:
+ (*d)->failure = C2SettingResult::INFO_BAD_VALUE;
+ break;
case SettingResult::Failure::INFO_CONFLICT:
(*d)->failure = C2SettingResult::INFO_CONFLICT;
break;
default:
- (*d)->failure = static_cast<C2SettingResult::Failure>(s.failureOther);
+ LOG(DEBUG) << "Unrecognized SettingResult::Failure "
+ << "with underlying value " << underlying_value(s.failure)
+ << ".";
+ (*d)->failure = static_cast<C2SettingResult::Failure>(s.failure);
}
// field
- c2_status_t status = objcpy(&(*d)->field, s.field);
- if (status != C2_OK) {
- return status;
+ if (!objcpy(&(*d)->field, s.field)) {
+ LOG(ERROR) << "Invalid SettingResult::field.";
+ return false;
}
// conflicts
@@ -472,26 +566,26 @@
for (const ParamFieldValues& sConflict : s.conflicts) {
(*d)->conflicts.emplace_back(
C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
- status = objcpy(&(*d)->conflicts.back(), sConflict);
- if (status != C2_OK) {
- return status;
+ if (!objcpy(&(*d)->conflicts.back(), sConflict)) {
+ LOG(ERROR) << "Invalid SettingResult::conflicts.";
+ return false;
}
}
- return C2_OK;
+ return true;
}
// C2ParamDescriptor -> ParamDescriptor
-Status objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
+bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
d->index = static_cast<ParamIndex>(s.index());
d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
_C2ParamInspector::GetAttrib(s));
d->name = s.name();
copyVector<uint32_t>(&d->dependencies, s.dependencies());
- return Status::OK;
+ return true;
}
// ParamDescriptor -> C2ParamDescriptor
-c2_status_t objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
+bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
std::vector<C2Param::Index> dDependencies;
dDependencies.reserve(s.dependencies.size());
for (const ParamIndex& sDependency : s.dependencies) {
@@ -502,11 +596,11 @@
static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
C2String(s.name.c_str()),
std::move(dDependencies));
- return C2_OK;
+ return true;
}
// C2StructDescriptor -> StructDescriptor
-Status objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
+bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
d->fields.resize(s.numFields());
size_t i = 0;
@@ -518,7 +612,7 @@
_C2ParamInspector::GetSize(sField));
dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
sField.type());
- dField.length = static_cast<uint32_t>(sField.extent());
+ dField.extent = static_cast<uint32_t>(sField.extent());
dField.name = static_cast<hidl_string>(sField.name());
const auto& sNamedValues = sField.namedValues();
dField.namedValues.resize(sNamedValues.size());
@@ -530,18 +624,18 @@
sNamedValue.second.u64);
}
}
- return Status::OK;
+ return true;
}
// StructDescriptor -> C2StructDescriptor
-c2_status_t objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
+bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
std::vector<C2FieldDescriptor> dFields;
dFields.reserve(s.fields.size());
for (const auto &sField : s.fields) {
C2FieldDescriptor dField = {
static_cast<uint32_t>(sField.type),
- sField.length,
+ sField.extent,
sField.name,
sField.fieldId.offset,
sField.fieldId.size };
@@ -557,7 +651,7 @@
}
*d = std::make_unique<C2StructDescriptor>(
_C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
- return C2_OK;
+ return true;
}
namespace /* unnamed */ {
@@ -565,14 +659,14 @@
// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
// associated map.
// Note: The handle is not cloned.
-Status _addBaseBlock(
+bool _addBaseBlock(
uint32_t* index,
const C2Handle* handle,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
if (!handle) {
- ALOGE("addBaseBlock called on a null C2Handle.");
- return Status::BAD_VALUE;
+ LOG(ERROR) << "addBaseBlock called on a null C2Handle.";
+ return false;
}
auto it = baseBlockIndices->find(handle);
if (it != baseBlockIndices->end()) {
@@ -583,26 +677,25 @@
baseBlocks->emplace_back();
BaseBlock &dBaseBlock = baseBlocks->back();
- dBaseBlock.type = BaseBlock::Type::NATIVE;
// This does not clone the handle.
- dBaseBlock.nativeBlock =
- reinterpret_cast<const native_handle_t*>(handle);
+ dBaseBlock.nativeBlock(
+ reinterpret_cast<const native_handle_t*>(handle));
}
- return Status::OK;
+ return true;
}
// Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
// an associated map.
-Status _addBaseBlock(
+bool _addBaseBlock(
uint32_t* index,
const std::shared_ptr<BufferPoolData> bpData,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
if (!bpData) {
- ALOGE("addBaseBlock called on a null BufferPoolData.");
- return Status::BAD_VALUE;
+ LOG(ERROR) << "addBaseBlock called on a null BufferPoolData.";
+ return false;
}
auto it = baseBlockIndices->find(bpData.get());
if (it != baseBlockIndices->end()) {
@@ -613,24 +706,26 @@
baseBlocks->emplace_back();
BaseBlock &dBaseBlock = baseBlocks->back();
- dBaseBlock.type = BaseBlock::Type::POOLED;
if (bufferPoolSender) {
+ BufferStatusMessage pooledBlock;
ResultStatus bpStatus = bufferPoolSender->send(
bpData,
- &dBaseBlock.pooledBlock);
+ &pooledBlock);
if (bpStatus != ResultStatus::OK) {
- ALOGE("Failed to send buffer with BufferPool. Error: %d.",
- static_cast<int>(bpStatus));
- return Status::BAD_VALUE;
+ LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
+ << static_cast<int32_t>(bpStatus)
+ << ".";
+ return false;
}
+ dBaseBlock.pooledBlock(pooledBlock);
}
}
- return Status::OK;
+ return true;
}
-Status addBaseBlock(
+bool addBaseBlock(
uint32_t* index,
const C2Handle* handle,
const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
@@ -649,8 +744,8 @@
std::shared_ptr<BufferPoolData> bpData;
if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
|| !bpData) {
- ALOGE("BufferPoolData unavailable in a block.");
- return Status::BAD_VALUE;
+ LOG(ERROR) << "BufferPoolData unavailable in a block.";
+ return false;
}
return _addBaseBlock(
index, bpData,
@@ -662,69 +757,76 @@
index, handle,
baseBlocks, baseBlockIndices);
default:
- ALOGE("Unknown C2BlockPoolData type.");
- return Status::BAD_VALUE;
+ LOG(ERROR) << "Unknown C2BlockPoolData type.";
+ return false;
}
}
// C2Fence -> hidl_handle
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
-Status objcpy(hidl_handle* d, const C2Fence& s) {
+bool objcpy(hidl_handle* d, const C2Fence& s) {
(void)s; // TODO: implement s.fd()
int fenceFd = -1;
d->setTo(nullptr);
if (fenceFd >= 0) {
native_handle_t *handle = native_handle_create(1, 0);
if (!handle) {
- return Status::NO_MEMORY;
+ LOG(ERROR) << "Failed to create a native handle.";
+ return false;
}
handle->data[0] = fenceFd;
d->setTo(handle, true /* owns */);
}
- return Status::OK;
+ return true;
}
// C2ConstLinearBlock -> Block
// Note: Native handles are not duplicated. The original handles must not be
// closed before the transaction is complete.
-Status objcpy(Block* d, const C2ConstLinearBlock& s,
+bool objcpy(Block* d, const C2ConstLinearBlock& s,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
std::shared_ptr<const _C2BlockPoolData> bpData =
_C2BlockFactory::GetLinearBlockPoolData(s);
- Status status = addBaseBlock(&d->index, s.handle(), bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- if (status != Status::OK) {
- return status;
+ if (!addBaseBlock(&d->index, s.handle(), bpData,
+ bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
+ return false;
}
// Create the metadata.
C2Hidl_RangeInfo dRangeInfo;
dRangeInfo.offset = static_cast<uint32_t>(s.offset());
dRangeInfo.length = static_cast<uint32_t>(s.size());
- status = createParamsBlob(&d->meta,
- std::vector<C2Param*>{ &dRangeInfo });
- if (status != Status::OK) {
- return Status::BAD_VALUE;
+ if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
+ LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
+ return false;
}
// Copy the fence
- return objcpy(&d->fence, s.fence());
+ if (!objcpy(&d->fence, s.fence())) {
+ LOG(ERROR) << "Invalid C2ConstLinearBlock::fence.";
+ return false;
+ }
+ return true;
}
// C2ConstGraphicBlock -> Block
// Note: Native handles are not duplicated. The original handles must not be
// closed before the transaction is complete.
-Status objcpy(Block* d, const C2ConstGraphicBlock& s,
+bool objcpy(Block* d, const C2ConstGraphicBlock& s,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
std::shared_ptr<const _C2BlockPoolData> bpData =
_C2BlockFactory::GetGraphicBlockPoolData(s);
- Status status = addBaseBlock(&d->index, s.handle(), bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices);
+ if (!addBaseBlock(&d->index, s.handle(), bpData,
+ bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
+ return false;
+ }
// Create the metadata.
C2Hidl_RectInfo dRectInfo;
@@ -733,62 +835,70 @@
dRectInfo.top = static_cast<uint32_t>(sRect.top);
dRectInfo.width = static_cast<uint32_t>(sRect.width);
dRectInfo.height = static_cast<uint32_t>(sRect.height);
- status = createParamsBlob(&d->meta,
- std::vector<C2Param*>{ &dRectInfo });
- if (status != Status::OK) {
- return Status::BAD_VALUE;
+ if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
+ LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
+ return false;
}
// Copy the fence
- return objcpy(&d->fence, s.fence());
+ if (!objcpy(&d->fence, s.fence())) {
+ LOG(ERROR) << "Invalid C2ConstGraphicBlock::fence.";
+ return false;
+ }
+ return true;
}
// C2BufferData -> Buffer
// This function only fills in d->blocks.
-Status objcpy(Buffer* d, const C2BufferData& s,
+bool objcpy(Buffer* d, const C2BufferData& s,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- Status status;
d->blocks.resize(
s.linearBlocks().size() +
s.graphicBlocks().size());
size_t i = 0;
for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
Block& dBlock = d->blocks[i++];
- status = objcpy(
+ if (!objcpy(
&dBlock, linearBlock,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- if (status != Status::OK) {
- return status;
+ bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2BufferData::linearBlocks. "
+ << "(Destination index = " << i - 1 << ".)";
+ return false;
}
}
for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
Block& dBlock = d->blocks[i++];
- status = objcpy(
+ if (!objcpy(
&dBlock, graphicBlock,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- if (status != Status::OK) {
- return status;
+ bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2BufferData::graphicBlocks. "
+ << "(Destination index = " << i - 1 << ".)";
+ return false;
}
}
- return Status::OK;
+ return true;
}
// C2Buffer -> Buffer
-Status objcpy(Buffer* d, const C2Buffer& s,
+bool objcpy(Buffer* d, const C2Buffer& s,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- Status status = createParamsBlob(&d->info, s.info());
- if (status != Status::OK) {
- return status;
+ if (!createParamsBlob(&d->info, s.info())) {
+ LOG(ERROR) << "Invalid C2Buffer::info.";
+ return false;
}
- return objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices);
+ if (!objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2Buffer::data.";
+ return false;
+ }
+ return true;
}
// C2InfoBuffer -> InfoBuffer
-Status objcpy(InfoBuffer* d, const C2InfoBuffer& s,
+bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
@@ -798,24 +908,21 @@
(void)bufferPoolSender;
(void)baseBlocks;
(void)baseBlockIndices;
- return Status::OK;
- /*
- // Stub implementation that may work in the future.
- d->index = static_cast<uint32_t>(s.index());
- d->buffer.info.resize(0);
- return objcpy(&d->buffer, s.data(), baseBlocks, baseBlockIndices);
- */
+ LOG(INFO) << "InfoBuffer not implemented.";
+ return true;
}
// C2FrameData -> FrameData
-Status objcpy(FrameData* d, const C2FrameData& s,
+bool objcpy(FrameData* d, const C2FrameData& s,
BufferPoolSender* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
- objcpy(&d->ordinal, s.ordinal);
+ if (!objcpy(&d->ordinal, s.ordinal)) {
+ LOG(ERROR) << "Invalid C2FrameData::ordinal.";
+ return false;
+ }
- Status status;
d->buffers.resize(s.buffers.size());
size_t i = 0;
for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
@@ -827,17 +934,18 @@
dBuffer.blocks.resize(0);
continue;
}
- status = objcpy(
+ if (!objcpy(
&dBuffer, *sBuffer,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- if (status != Status::OK) {
- return status;
+ bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2FrameData::buffers["
+ << i - 1 << "].";
+ return false;
}
}
- status = createParamsBlob(&d->configUpdate, s.configUpdate);
- if (status != Status::OK) {
- return status;
+ if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
+ LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
+ return false;
}
d->infoBuffers.resize(s.infoBuffers.size());
@@ -845,17 +953,19 @@
for (const std::shared_ptr<C2InfoBuffer>& sInfoBuffer : s.infoBuffers) {
InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
if (!sInfoBuffer) {
- ALOGE("Null C2InfoBuffer");
- return Status::BAD_VALUE;
+ LOG(ERROR) << "Null C2FrameData::infoBuffers["
+ << i - 1 << "].";
+ return false;
}
- status = objcpy(&dInfoBuffer, *sInfoBuffer,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- if (status != Status::OK) {
- return status;
+ if (!objcpy(&dInfoBuffer, *sInfoBuffer,
+ bufferPoolSender, baseBlocks, baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
+ << i - 1 << "].";
+ return false;
}
}
- return status;
+ return true;
}
} // unnamed namespace
@@ -885,7 +995,7 @@
const std::shared_ptr<BufferPoolData>& bpData,
BufferStatusMessage* bpMessage) {
if (!mReceiverManager) {
- ALOGE("No access to receiver's BufferPool.");
+ LOG(ERROR) << "No access to receiver's BufferPool.";
return ResultStatus::NOT_FOUND;
}
ResultStatus rs;
@@ -893,7 +1003,7 @@
if (!mSenderManager) {
mSenderManager = ClientManager::getInstance();
if (!mSenderManager) {
- ALOGE("Failed to retrieve local BufferPool ClientManager.");
+ LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
return ResultStatus::CRITICAL_ERROR;
}
}
@@ -915,11 +1025,11 @@
connectionId,
&receiverConnectionId);
if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
- ALOGW("registerSender -- returned error: %d.",
- static_cast<int>(rs));
+ LOG(WARNING) << "registerSender -- returned error: "
+ << static_cast<int32_t>(rs)
+ << ".";
return rs;
} else {
- ALOGV("registerSender -- succeeded.");
mReceiverConnectionId = receiverConnectionId;
}
}
@@ -929,12 +1039,13 @@
rs = mSenderManager->postSend(
mReceiverConnectionId, bpData, &transactionId, ×tampUs);
if (rs != ResultStatus::OK) {
- ALOGE("ClientManager::postSend -- returned error: %d.",
- static_cast<int>(rs));
+ LOG(ERROR) << "ClientManager::postSend -- returned error: "
+ << static_cast<int32_t>(rs)
+ << ".";
return rs;
}
if (!bpMessage) {
- ALOGE("Null output parameter for BufferStatusMessage.");
+ LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
return ResultStatus::CRITICAL_ERROR;
}
bpMessage->connectionId = mReceiverConnectionId;
@@ -946,12 +1057,10 @@
}
// std::list<std::unique_ptr<C2Work>> -> WorkBundle
-Status objcpy(
+bool objcpy(
WorkBundle* d,
const std::list<std::unique_ptr<C2Work>>& s,
BufferPoolSender* bufferPoolSender) {
- Status status = Status::OK;
-
// baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
std::list<BaseBlock> baseBlocks;
@@ -971,63 +1080,80 @@
for (const std::unique_ptr<C2Work>& sWork : s) {
Work &dWork = d->works[i++];
if (!sWork) {
- ALOGW("Null C2Work encountered.");
+ LOG(WARNING) << "Null C2Work encountered.";
continue;
}
- status = objcpy(&dWork.input, sWork->input,
- bufferPoolSender, &baseBlocks, &baseBlockIndices);
- if (status != Status::OK) {
- return status;
+
+ // chain info is not in use currently.
+
+ // input
+ if (!objcpy(&dWork.input, sWork->input,
+ bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2Work::input.";
+ return false;
}
+
+ // worklets
if (sWork->worklets.size() == 0) {
- ALOGW("Work with no worklets.");
+ LOG(DEBUG) << "Work with no worklets.";
} else {
- if (sWork->worklets.size() > 1) {
- ALOGW("Work with multiple worklets. "
- "Only the first worklet will be marshalled.");
- }
- if (!sWork->worklets.front()) {
- ALOGE("Null worklet encountered.");
- return Status::BAD_VALUE;
- }
-
- // Parcel the first worklet.
- const C2Worklet &sWorklet = *sWork->worklets.front();
- Worklet &dWorklet = dWork.worklet;
-
- dWorklet.tunings.resize(sWorklet.tunings.size());
+ // Parcel the worklets.
+ hidl_vec<Worklet> &dWorklets = dWork.worklets;
+ dWorklets.resize(sWork->worklets.size());
size_t j = 0;
- for (const std::unique_ptr<C2Tuning>& sTuning : sWorklet.tunings) {
- status = createParamsBlob(
- &dWorklet.tunings[j++],
- std::vector<C2Param*>
- { reinterpret_cast<C2Param*>(sTuning.get()) });
- if (status != Status::OK) {
- return status;
+ for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
+ {
+ if (!sWorklet) {
+ LOG(WARNING) << "Null C2Work::worklets["
+ << j << "].";
+ continue;
}
- }
+ Worklet &dWorklet = dWorklets[j++];
- dWorklet.failures.resize(sWorklet.failures.size());
- j = 0;
- for (const std::unique_ptr<C2SettingResult>& sFailure :
- sWorklet.failures) {
- if (!sFailure) {
- ALOGE("Null C2SettingResult");
- return Status::BAD_VALUE;
- }
- status = objcpy(&dWorklet.failures[j++], *sFailure);
- if (status != Status::OK) {
- return status;
- }
- }
+ // component id
+ dWorklet.componentId = static_cast<uint32_t>(
+ sWorklet->component);
- status = objcpy(&dWorklet.output, sWorklet.output,
- bufferPoolSender, &baseBlocks, &baseBlockIndices);
- if (status != Status::OK) {
- return status;
+ // tunings
+ if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
+ LOG(ERROR) << "Invalid C2Work::worklets["
+ << j - 1 << "]->tunings.";
+ return false;
+ }
+
+ // failures
+ dWorklet.failures.resize(sWorklet->failures.size());
+ size_t k = 0;
+ for (const std::unique_ptr<C2SettingResult>& sFailure :
+ sWorklet->failures) {
+ if (!sFailure) {
+ LOG(WARNING) << "Null C2Work::worklets["
+ << j - 1 << "]->failures["
+ << k << "].";
+ continue;
+ }
+ if (!objcpy(&dWorklet.failures[k++], *sFailure)) {
+ LOG(ERROR) << "Invalid C2Work::worklets["
+ << j - 1 << "]->failures["
+ << k - 1 << "].";
+ return false;
+ }
+ }
+
+ // output
+ if (!objcpy(&dWorklet.output, sWorklet->output,
+ bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
+ LOG(ERROR) << "Invalid C2Work::worklets["
+ << j - 1 << "]->output.";
+ return false;
+ }
}
}
- dWork.workletProcessed = sWork->workletsProcessed > 0;
+
+ // worklets processed
+ dWork.workletsProcessed = sWork->workletsProcessed;
+
+ // result
dWork.result = static_cast<Status>(sWork->result);
}
@@ -1040,7 +1166,7 @@
}
}
- return Status::OK;
+ return true;
}
namespace /* unnamed */ {
@@ -1058,15 +1184,15 @@
// hidl_handle -> C2Fence
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
-c2_status_t objcpy(C2Fence* d, const hidl_handle& s) {
+bool objcpy(C2Fence* d, const hidl_handle& s) {
// TODO: Implement.
(void)s;
*d = C2Fence();
- return C2_OK;
+ return true;
}
// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
-c2_status_t createLinearBuffer(
+bool createLinearBuffer(
std::shared_ptr<C2Buffer>* buffer,
const std::shared_ptr<C2LinearBlock>& block,
const std::vector<C2Param*>& meta,
@@ -1074,12 +1200,12 @@
// Check the block meta. It should have exactly 1 C2Info:
// C2Hidl_RangeInfo.
if ((meta.size() != 1) || !meta[0]) {
- ALOGE("Invalid block metadata for ion block.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid C2LinearBlock::meta.";
+ return false;
}
if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
- ALOGE("Invalid block metadata for ion block: range.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid range info in C2LinearBlock.";
+ return false;
}
C2Hidl_RangeInfo *rangeInfo =
reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
@@ -1089,14 +1215,14 @@
rangeInfo->offset, rangeInfo->length,
fence));
if (!(*buffer)) {
- ALOGE("Cannot create a linear buffer.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "CreateLinearBuffer failed.";
+ return false;
}
- return C2_OK;
+ return true;
}
// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
-c2_status_t createGraphicBuffer(
+bool createGraphicBuffer(
std::shared_ptr<C2Buffer>* buffer,
const std::shared_ptr<C2GraphicBlock>& block,
const std::vector<C2Param*>& meta,
@@ -1104,12 +1230,12 @@
// Check the block meta. It should have exactly 1 C2Info:
// C2Hidl_RectInfo.
if ((meta.size() != 1) || !meta[0]) {
- ALOGE("Invalid block metadata for graphic block.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
+ return false;
}
if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
- ALOGE("Invalid block metadata for graphic block: crop rect.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
+ return false;
}
C2Hidl_RectInfo *rectInfo =
reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
@@ -1120,136 +1246,144 @@
at(rectInfo->left, rectInfo->top),
fence));
if (!(*buffer)) {
- ALOGE("Cannot create a graphic buffer.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "CreateGraphicBuffer failed.";
+ return false;
}
- return C2_OK;
+ return true;
}
// Buffer -> C2Buffer
// Note: The native handles will be cloned.
-c2_status_t objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
+bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
const std::vector<C2BaseBlock>& baseBlocks) {
- c2_status_t status;
*d = nullptr;
// Currently, a non-null C2Buffer must contain exactly 1 block.
if (s.blocks.size() == 0) {
- return C2_OK;
+ return true;
} else if (s.blocks.size() != 1) {
- ALOGE("Currently, a C2Buffer must contain exactly 1 block.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid Buffer: "
+ "Currently, a C2Buffer must contain exactly 1 block.";
+ return false;
}
const Block &sBlock = s.blocks[0];
if (sBlock.index >= baseBlocks.size()) {
- ALOGE("Index into baseBlocks is out of range.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
+ "Array index out of range.";
+ return false;
}
const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
// Parse meta.
std::vector<C2Param*> sBlockMeta;
- status = parseParamsBlob(&sBlockMeta, sBlock.meta);
- if (status != C2_OK) {
- ALOGE("Invalid block params blob.");
- return C2_BAD_VALUE;
+ if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
+ LOG(ERROR) << "Invalid Buffer::blocks[0].meta.";
+ return false;
}
// Copy fence.
C2Fence dFence;
- status = objcpy(&dFence, sBlock.fence);
+ if (!objcpy(&dFence, sBlock.fence)) {
+ LOG(ERROR) << "Invalid Buffer::blocks[0].fence.";
+ return false;
+ }
// Construct a block.
switch (baseBlock.type) {
case C2BaseBlock::LINEAR:
- status = createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence);
+ if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
+ LOG(ERROR) << "Invalid C2BaseBlock::linear.";
+ return false;
+ }
break;
case C2BaseBlock::GRAPHIC:
- status = createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence);
+ if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
+ LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
+ return false;
+ }
break;
default:
- ALOGE("Invalid BaseBlock type.");
- return C2_BAD_VALUE;
- }
- if (status != C2_OK) {
- return status;
+ LOG(ERROR) << "Invalid C2BaseBlock::type.";
+ return false;
}
// Parse info
std::vector<C2Param*> params;
- status = parseParamsBlob(¶ms, s.info);
- if (status != C2_OK) {
- ALOGE("Invalid buffer params blob.");
- return status;
+ if (!parseParamsBlob(¶ms, s.info)) {
+ LOG(ERROR) << "Invalid Buffer::info.";
+ return false;
}
for (C2Param* param : params) {
if (param == nullptr) {
- ALOGE("Null buffer param encountered.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Null param in Buffer::info.";
+ return false;
}
- std::shared_ptr<C2Param> c2param(
- C2Param::Copy(*param).release());
+ std::shared_ptr<C2Param> c2param{
+ C2Param::Copy(*param).release()};
if (!c2param) {
- ALOGE("Invalid buffer param inside a blob.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Invalid param in Buffer::info.";
+ return false;
}
- status = (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
+ c2_status_t status =
+ (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
if (status != C2_OK) {
- ALOGE("C2Buffer::setInfo failed().");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "C2Buffer::setInfo failed.";
+ return false;
}
}
- return C2_OK;
+ return true;
}
// FrameData -> C2FrameData
-c2_status_t objcpy(C2FrameData* d, const FrameData& s,
+bool objcpy(C2FrameData* d, const FrameData& s,
const std::vector<C2BaseBlock>& baseBlocks) {
- c2_status_t status;
d->flags = static_cast<C2FrameData::flags_t>(s.flags);
- objcpy(&d->ordinal, s.ordinal);
+ if (!objcpy(&d->ordinal, s.ordinal)) {
+ LOG(ERROR) << "Invalid FrameData::ordinal.";
+ return false;
+ }
d->buffers.clear();
d->buffers.reserve(s.buffers.size());
for (const Buffer& sBuffer : s.buffers) {
std::shared_ptr<C2Buffer> dBuffer;
- status = objcpy(&dBuffer, sBuffer, baseBlocks);
- if (status != C2_OK) {
- return status;
+ if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
+ LOG(ERROR) << "Invalid FrameData::buffers.";
+ return false;
}
d->buffers.emplace_back(dBuffer);
}
std::vector<C2Param*> params;
- status = parseParamsBlob(¶ms, s.configUpdate);
- if (status != C2_OK) {
- ALOGE("Failed to parse frame data params.");
- return status;
+ if (!parseParamsBlob(¶ms, s.configUpdate)) {
+ LOG(ERROR) << "Invalid FrameData::configUpdate.";
+ return false;
}
d->configUpdate.clear();
for (C2Param* param : params) {
d->configUpdate.emplace_back(C2Param::Copy(*param));
if (!d->configUpdate.back()) {
- ALOGE("Unexpected error while parsing frame data params.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Unexpected error while parsing "
+ "FrameData::configUpdate.";
+ return false;
}
}
// TODO: Implement this once C2InfoBuffer has constructors.
d->infoBuffers.clear();
- return C2_OK;
+ return true;
}
// BaseBlock -> C2BaseBlock
-c2_status_t objcpy(C2BaseBlock* d, const BaseBlock& s) {
- switch (s.type) {
- case BaseBlock::Type::NATIVE: {
+bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
+ switch (s.getDiscriminator()) {
+ case BaseBlock::hidl_discriminator::nativeBlock: {
native_handle_t* sHandle =
- native_handle_clone(s.nativeBlock);
+ native_handle_clone(s.nativeBlock());
if (sHandle == nullptr) {
- ALOGE("Null native handle in a block.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Null BaseBlock::nativeBlock.";
+ return false;
}
const C2Handle *sC2Handle =
reinterpret_cast<const C2Handle*>(sHandle);
@@ -1257,25 +1391,25 @@
d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
if (d->linear) {
d->type = C2BaseBlock::LINEAR;
- return C2_OK;
+ return true;
}
d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
if (d->graphic) {
d->type = C2BaseBlock::GRAPHIC;
- return C2_OK;
+ return true;
}
- ALOGE("Unknown handle type in native BaseBlock.");
+ LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
if (sHandle) {
native_handle_close(sHandle);
native_handle_delete(sHandle);
}
- return C2_BAD_VALUE;
+ return false;
}
- case BaseBlock::Type::POOLED: {
+ case BaseBlock::hidl_discriminator::pooledBlock: {
const BufferStatusMessage &bpMessage =
- s.pooledBlock;
+ s.pooledBlock();
sp<ClientManager> bp = ClientManager::getInstance();
std::shared_ptr<BufferPoolData> bpData;
native_handle_t *cHandle;
@@ -1287,48 +1421,49 @@
&cHandle,
&bpData);
if (bpStatus != ResultStatus::OK) {
- ALOGE("Failed to receive buffer from bufferpool -- "
- "resultStatus = %d",
- static_cast<int>(bpStatus));
- return toC2Status(bpStatus);
+ LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
+ << "resultStatus = " << underlying_value(bpStatus)
+ << ".";
+ return false;
} else if (!bpData) {
- ALOGE("No data in bufferpool transaction.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "No data in bufferpool transaction.";
+ return false;
}
d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
if (d->linear) {
d->type = C2BaseBlock::LINEAR;
- return C2_OK;
+ return true;
}
d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
if (d->graphic) {
d->type = C2BaseBlock::GRAPHIC;
- return C2_OK;
+ return true;
}
- ALOGE("Unknown handle type in pooled BaseBlock.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
+ return false;
}
default:
- ALOGE("Corrupted BaseBlock type: %d", static_cast<int>(s.type));
- return C2_BAD_VALUE;
+ LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
+ << "underlying value "
+ << underlying_value(s.getDiscriminator()) << ".";
+ return false;
}
}
} // unnamed namespace
// WorkBundle -> std::list<std::unique_ptr<C2Work>>
-c2_status_t objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
- c2_status_t status;
-
+bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
// Convert BaseBlocks to C2BaseBlocks.
std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
- status = objcpy(&dBaseBlocks[i], s.baseBlocks[i]);
- if (status != C2_OK) {
- return status;
+ if (!objcpy(&dBaseBlocks[i], s.baseBlocks[i])) {
+ LOG(ERROR) << "Invalid WorkBundle::baseBlocks["
+ << i << "].";
+ return false;
}
}
@@ -1337,74 +1472,58 @@
d->emplace_back(std::make_unique<C2Work>());
C2Work& dWork = *d->back();
+ // chain info is not in use currently.
+
// input
- status = objcpy(&dWork.input, sWork.input, dBaseBlocks);
- if (status != C2_OK) {
- ALOGE("Error constructing C2Work's input.");
- return C2_BAD_VALUE;
+ if (!objcpy(&dWork.input, sWork.input, dBaseBlocks)) {
+ LOG(ERROR) << "Invalid Work::input.";
+ return false;
}
// worklet(s)
dWork.worklets.clear();
- // TODO: Currently, tunneling is not supported.
- if (sWork.workletProcessed) {
- dWork.workletsProcessed = 1;
-
- const Worklet &sWorklet = sWork.worklet;
+ for (const Worklet& sWorklet : sWork.worklets) {
std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
+ // component id
+ dWorklet->component = static_cast<c2_node_id_t>(
+ sWorklet.componentId);
+
// tunings
- dWorklet->tunings.clear();
- dWorklet->tunings.reserve(sWorklet.tunings.size());
- for (const Params& sTuning : sWorklet.tunings) {
- std::vector<C2Param*> dParams;
- status = parseParamsBlob(&dParams, sTuning);
- if (status != C2_OK) {
- ALOGE("Failed to parse C2Tuning in C2Worklet.");
- return C2_BAD_VALUE;
- }
- for (C2Param* param : dParams) {
- std::unique_ptr<C2Param> dParam = C2Param::Copy(*param);
- if (!dParam) {
- ALOGE("Null C2Tuning encountered while "
- "parsing C2Worklet.");
- return C2_BAD_VALUE;
- }
- dWorklet->tunings.emplace_back(
- std::unique_ptr<C2Tuning>(
- reinterpret_cast<C2Tuning*>(
- dParam.release())));
- }
+ if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
+ LOG(ERROR) << "Invalid Worklet::tunings";
+ return false;
}
+
// failures
dWorklet->failures.clear();
dWorklet->failures.reserve(sWorklet.failures.size());
for (const SettingResult& sFailure : sWorklet.failures) {
std::unique_ptr<C2SettingResult> dFailure;
- status = objcpy(&dFailure, sFailure);
- if (status != C2_OK) {
- ALOGE("Failed to create C2SettingResult in C2Worklet.");
- return C2_BAD_VALUE;
+ if (!objcpy(&dFailure, sFailure)) {
+ LOG(ERROR) << "Invalid Worklet::failures.";
+ return false;
}
dWorklet->failures.emplace_back(std::move(dFailure));
}
+
// output
- status = objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks);
- if (status != C2_OK) {
- ALOGE("Failed to create output C2FrameData.");
- return C2_BAD_VALUE;
+ if (!objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks)) {
+ LOG(ERROR) << "Invalid Worklet::output.";
+ return false;
}
+
dWork.worklets.emplace_back(std::move(dWorklet));
- } else {
- dWork.worklets.emplace_back(std::make_unique<C2Worklet>());
- dWork.workletsProcessed = 0;
}
+ // workletsProcessed
+ dWork.workletsProcessed = sWork.workletsProcessed;
+
// result
dWork.result = static_cast<c2_status_t>(sWork.result);
}
- return C2_OK;
+ return true;
}
constexpr size_t PARAMS_ALIGNMENT = 8; // 64-bit alignment
@@ -1413,7 +1532,7 @@
static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
// Params -> std::vector<C2Param*>
-c2_status_t parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
+bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
// assuming blob is const here
size_t size = blob.size();
size_t ix = 0;
@@ -1429,21 +1548,27 @@
}
} while (p);
- return ix == size ? C2_OK : C2_BAD_VALUE;
+ if (ix != size) {
+ LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
+ return false;
+ }
+ return true;
}
namespace /* unnamed */ {
/**
- * Concatenates a list of C2Params into a params blob.
+ * Concatenates a list of C2Params into a params blob. T is a container type
+ * whose member type is compatible with C2Param*.
+ *
* \param[out] blob target blob
* \param[in] params parameters to concatenate
* \retval C2_OK if the blob was successfully created
- * \retval C2_BAD_VALUE if the blob was not successful (this only happens if the parameters were
- * not const)
+ * \retval C2_BAD_VALUE if the blob was not successful created (this only
+ * happens if the parameters were not const)
*/
-template<typename T>
-Status _createParamsBlob(hidl_vec<uint8_t> *blob, const T ¶ms) {
+template <typename T>
+bool _createParamsBlob(hidl_vec<uint8_t> *blob, const T ¶ms) {
// assuming the parameter values are const
size_t size = 0;
for (const auto &p : params) {
@@ -1469,77 +1594,106 @@
ix = align(ix, PARAMS_ALIGNMENT);
}
blob->resize(ix);
- return ix == size ? Status::OK : Status::CORRUPTED;
+ if (ix != size) {
+ LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Parses a params blob and create a vector of new T objects that contain copies
+ * of the params in the blob. T is C2Param or its compatible derived class.
+ *
+ * \param[out] params the resulting vector
+ * \param[in] blob parameter blob to parse
+ * \retval C2_OK if the full blob was parsed and params was constructed
+ * \retval C2_BAD_VALUE otherwise
+ */
+template <typename T>
+bool _copyParamsFromBlob(
+ std::vector<std::unique_ptr<T>>* params,
+ Params blob) {
+
+ std::vector<C2Param*> paramPointers;
+ if (!parseParamsBlob(¶mPointers, blob)) {
+ LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
+ return false;
+ }
+
+ params->resize(paramPointers.size());
+ size_t i = 0;
+ for (C2Param* const& paramPointer : paramPointers) {
+ if (!paramPointer) {
+ LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
+ return false;
+ }
+ (*params)[i++].reset(reinterpret_cast<T*>(
+ C2Param::Copy(*paramPointer).release()));
+ }
+ return true;
}
} // unnamed namespace
// std::vector<const C2Param*> -> Params
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<const C2Param*> ¶ms) {
return _createParamsBlob(blob, params);
}
// std::vector<C2Param*> -> Params
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<C2Param*> ¶ms) {
return _createParamsBlob(blob, params);
}
// std::vector<std::unique_ptr<C2Param>> -> Params
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<std::unique_ptr<C2Param>> ¶ms) {
return _createParamsBlob(blob, params);
}
// std::vector<std::unique_ptr<C2Tuning>> -> Params
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<std::unique_ptr<C2Tuning>> ¶ms) {
return _createParamsBlob(blob, params);
}
// std::vector<std::shared_ptr<const C2Info>> -> Params
-Status createParamsBlob(
+bool createParamsBlob(
hidl_vec<uint8_t> *blob,
const std::vector<std::shared_ptr<const C2Info>> ¶ms) {
return _createParamsBlob(blob, params);
}
// Params -> std::vector<std::unique_ptr<C2Param>>
-c2_status_t copyParamsFromBlob(
+bool copyParamsFromBlob(
std::vector<std::unique_ptr<C2Param>>* params,
Params blob) {
- std::vector<C2Param*> paramPointers;
- c2_status_t status = parseParamsBlob(¶mPointers, blob);
- if (status != C2_OK) {
- ALOGE("copyParamsFromBlob -- blob parsing failed.");
- return status;
- }
- params->resize(paramPointers.size());
- size_t i = 0;
- for (C2Param* const& paramPointer : paramPointers) {
- if (!paramPointer) {
- ALOGE("copyParamsFromBlob -- corrupted params blob.");
- return C2_BAD_VALUE;
- }
- (*params)[i++] = C2Param::Copy(*paramPointer);
- }
- return C2_OK;
+ return _copyParamsFromBlob(params, blob);
+}
+
+// Params -> std::vector<std::unique_ptr<C2Tuning>>
+bool copyParamsFromBlob(
+ std::vector<std::unique_ptr<C2Tuning>>* params,
+ Params blob) {
+ return _copyParamsFromBlob(params, blob);
}
// Params -> update std::vector<std::unique_ptr<C2Param>>
-c2_status_t updateParamsFromBlob(
+bool updateParamsFromBlob(
const std::vector<C2Param*>& params,
const Params& blob) {
std::unordered_map<uint32_t, C2Param*> index2param;
for (C2Param* const& param : params) {
if (!param) {
- ALOGE("updateParamsFromBlob -- corrupted input params.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "updateParamsFromBlob -- null output param.";
+ return false;
}
if (index2param.find(param->index()) == index2param.end()) {
index2param.emplace(param->index(), param);
@@ -1547,33 +1701,31 @@
}
std::vector<C2Param*> paramPointers;
- c2_status_t status = parseParamsBlob(¶mPointers, blob);
- if (status != C2_OK) {
- ALOGE("updateParamsFromBlob -- blob parsing failed.");
- return status;
+ if (!parseParamsBlob(¶mPointers, blob)) {
+ LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
+ return false;
}
for (C2Param* const& paramPointer : paramPointers) {
if (!paramPointer) {
- ALOGE("updateParamsFromBlob -- corrupted param in blob.");
- return C2_BAD_VALUE;
+ LOG(ERROR) << "updateParamsFromBlob -- null input param.";
+ return false;
}
decltype(index2param)::iterator i = index2param.find(
paramPointer->index());
if (i == index2param.end()) {
- ALOGW("updateParamsFromBlob -- unseen param index.");
+ LOG(DEBUG) << "updateParamsFromBlob -- index "
+ << paramPointer->index() << " not found. Skipping...";
continue;
}
if (!i->second->updateFrom(*paramPointer)) {
- ALOGE("updateParamsFromBlob -- mismatching sizes: "
- "%u vs %u (index = %u).",
- static_cast<unsigned>(params.size()),
- static_cast<unsigned>(paramPointer->size()),
- static_cast<unsigned>(i->first));
- return C2_BAD_VALUE;
+ LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
+ << params.size() << " vs " << paramPointer->size()
+ << " (index = " << i->first << ").";
+ return false;
}
}
- return C2_OK;
+ return true;
}
// Convert BufferPool ResultStatus to c2_status_t.
@@ -1590,7 +1742,8 @@
case ResultStatus::CRITICAL_ERROR:
return C2_CORRUPTED;
default:
- ALOGW("Unrecognized BufferPool ResultStatus: %d", static_cast<int>(rs));
+ LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
+ << static_cast<int32_t>(rs) << ".";
return C2_CORRUPTED;
}
}
@@ -1669,34 +1822,33 @@
uint32_t generation,
int32_t* bqSlot) {
if (!igbp) {
- ALOGW("attachToBufferQueue -- null producer.");
+ LOG(WARNING) << "attachToBufferQueue -- null producer.";
return NO_INIT;
}
sp<GraphicBuffer> graphicBuffer = createGraphicBuffer(block);
graphicBuffer->setGenerationNumber(generation);
- ALOGV("attachToBufferQueue -- attaching buffer: "
- "block dimension %ux%u, "
- "graphicBuffer dimension %ux%u, "
- "format %#x, usage %#llx, stride %u, generation %u.",
- static_cast<unsigned>(block.width()),
- static_cast<unsigned>(block.height()),
- static_cast<unsigned>(graphicBuffer->getWidth()),
- static_cast<unsigned>(graphicBuffer->getHeight()),
- static_cast<unsigned>(graphicBuffer->getPixelFormat()),
- static_cast<unsigned long long>(graphicBuffer->getUsage()),
- static_cast<unsigned>(graphicBuffer->getStride()),
- static_cast<unsigned>(graphicBuffer->getGenerationNumber()));
+ LOG(VERBOSE) << "attachToBufferQueue -- attaching buffer:"
+ << " block dimension " << block.width() << "x"
+ << block.height()
+ << ", graphicBuffer dimension " << graphicBuffer->getWidth() << "x"
+ << graphicBuffer->getHeight()
+ << std::hex << std::setfill('0')
+ << ", format 0x" << std::setw(8) << graphicBuffer->getPixelFormat()
+ << ", usage 0x" << std::setw(16) << graphicBuffer->getUsage()
+ << std::dec << std::setfill(' ')
+ << ", stride " << graphicBuffer->getStride()
+ << ", generation " << graphicBuffer->getGenerationNumber();
status_t result = igbp->attachBuffer(bqSlot, graphicBuffer);
if (result != OK) {
- ALOGW("attachToBufferQueue -- attachBuffer failed. Error code = %d",
- static_cast<int>(result));
+ LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: "
+ "status = " << result << ".";
return result;
}
- ALOGV("attachToBufferQueue -- attachBuffer returned slot %d",
- static_cast<int>(*bqSlot));
+ LOG(VERBOSE) << "attachToBufferQueue -- attachBuffer returned slot #"
+ << *bqSlot << ".";
return OK;
}
@@ -1747,11 +1899,11 @@
// If the block's bqId is the same as the desired bqId, just hold.
if ((oldId == bqId) && (oldGeneration == generation)) {
- ALOGV("holdBufferQueueBlock -- import without attaching: "
- "bqId %llu, bqSlot %d, generation %u.",
- static_cast<long long unsigned>(oldId),
- static_cast<int>(oldSlot),
- static_cast<unsigned>(generation));
+ LOG(VERBOSE) << "holdBufferQueueBlock -- import without attaching:"
+ << " bqId " << oldId
+ << ", bqSlot " << oldSlot
+ << ", generation " << generation
+ << ".";
_C2BlockFactory::HoldBlockFromBufferQueue(data, getHgbp(igbp));
return true;
}
@@ -1765,19 +1917,18 @@
status_t result = attachToBufferQueue(block, igbp, generation, &bqSlot);
if (result != OK) {
- ALOGE("holdBufferQueueBlock -- fail to attach: "
- "target bqId %llu, generation %u.",
- static_cast<long long unsigned>(bqId),
- static_cast<unsigned>(generation));
-
+ LOG(ERROR) << "holdBufferQueueBlock -- fail to attach:"
+ << " target bqId " << bqId
+ << ", generation " << generation
+ << ".";
return false;
}
- ALOGV("holdBufferQueueBlock -- attached: "
- "bqId %llu, bqSlot %d, generation %u.",
- static_cast<long long unsigned>(bqId),
- static_cast<int>(bqSlot),
- static_cast<unsigned>(generation));
+ LOG(VERBOSE) << "holdBufferQueueBlock -- attached:"
+ << " bqId " << bqId
+ << ", bqSlot " << bqSlot
+ << ", generation " << generation
+ << ".";
_C2BlockFactory::AssignBlockToBufferQueue(
data, getHgbp(igbp), generation, bqId, bqSlot, true);
return true;
diff --git a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
index a688530..d1557cb 100644
--- a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
@@ -94,10 +94,14 @@
(void)buffer;
}
- virtual void onFramesRendered(
- const std::vector<RenderedFrame>& renderedFrames) override {
+ virtual void onFrameRendered(
+ uint64_t bufferQueueId,
+ int32_t slotId,
+ int64_t timestampNs) override {
/* TODO */
- (void)renderedFrames;
+ (void)bufferQueueId;
+ (void)slotId;
+ (void)timestampNs;
}
// std::mutex mQueueLock;
// std::condition_variable mQueueCondition;
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index cd374b0..5b52fcd 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "Codec2Client"
-#include <log/log.h>
+#include <android-base/logging.h>
#include <codec2/hidl/client.h>
@@ -32,7 +32,6 @@
#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
#include <hidl/HidlSupport.h>
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
-#undef LOG
#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <android/hardware/media/c2/1.0/IComponent.h>
@@ -99,19 +98,17 @@
return mName;
}
-Codec2ConfigurableClient::Base* Codec2ConfigurableClient::base() const {
- return static_cast<Base*>(mBase.get());
-}
-
Codec2ConfigurableClient::Codec2ConfigurableClient(
- const sp<Codec2ConfigurableClient::Base>& base) : mBase(base) {
- Return<void> transStatus = base->getName(
- [this](const hidl_string& name) {
- mName = name.c_str();
- });
- if (!transStatus.isOk()) {
- ALOGE("Cannot obtain name from IConfigurable.");
- }
+ const sp<IConfigurable>& base)
+ : mBase{base},
+ mName{[base]() -> C2String {
+ C2String outName;
+ Return<void> transStatus = base->getName(
+ [&outName](const hidl_string& name) {
+ outName = name.c_str();
+ });
+ return transStatus.isOk() ? outName : "";
+ }()} {
}
c2_status_t Codec2ConfigurableClient::query(
@@ -124,7 +121,7 @@
size_t numIndices = 0;
for (C2Param* const& stackParam : stackParams) {
if (!stackParam) {
- ALOGW("query -- null stack param encountered.");
+ LOG(WARNING) << "query -- null stack param encountered.";
continue;
}
indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
@@ -139,32 +136,31 @@
heapParams->reserve(heapParams->size() + numIndices);
}
c2_status_t status;
- Return<void> transStatus = base()->query(
+ Return<void> transStatus = mBase->query(
indices,
mayBlock == C2_MAY_BLOCK,
[&status, &numStackIndices, &stackParams, heapParams](
Status s, const Params& p) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK && status != C2_BAD_INDEX) {
- ALOGE("query -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "query -- call failed: "
+ << status << ".";
return;
}
std::vector<C2Param*> paramPointers;
- c2_status_t parseStatus = parseParamsBlob(¶mPointers, p);
- if (parseStatus != C2_OK) {
- ALOGE("query -- error while parsing params. "
- "Error code = %d", static_cast<int>(status));
- status = parseStatus;
+ if (!parseParamsBlob(¶mPointers, p)) {
+ LOG(ERROR) << "query -- error while parsing params.";
+ status = C2_CORRUPTED;
return;
}
size_t i = 0;
- for (auto it = paramPointers.begin(); it != paramPointers.end(); ) {
+ for (auto it = paramPointers.begin();
+ it != paramPointers.end(); ) {
C2Param* paramPointer = *it;
if (numStackIndices > 0) {
--numStackIndices;
if (!paramPointer) {
- ALOGW("query -- null stack param.");
+ LOG(WARNING) << "query -- null stack param.";
++it;
continue;
}
@@ -172,37 +168,41 @@
++i;
}
if (i >= stackParams.size()) {
- ALOGE("query -- unexpected error.");
+ LOG(ERROR) << "query -- unexpected error.";
status = C2_CORRUPTED;
return;
}
if (stackParams[i]->index() != paramPointer->index()) {
- ALOGW("query -- param skipped. index = %d",
- static_cast<int>(stackParams[i]->index()));
+ LOG(WARNING) << "query -- param skipped: "
+ "index = "
+ << stackParams[i]->index() << ".";
stackParams[i++]->invalidate();
continue;
}
if (!stackParams[i++]->updateFrom(*paramPointer)) {
- ALOGW("query -- param update failed. index = %d",
- static_cast<int>(paramPointer->index()));
+ LOG(WARNING) << "query -- param update failed: "
+ "index = "
+ << paramPointer->index() << ".";
}
} else {
if (!paramPointer) {
- ALOGW("query -- null heap param.");
+ LOG(WARNING) << "query -- null heap param.";
++it;
continue;
}
if (!heapParams) {
- ALOGW("query -- unexpected extra stack param.");
+ LOG(WARNING) << "query -- "
+ "unexpected extra stack param.";
} else {
- heapParams->emplace_back(C2Param::Copy(*paramPointer));
+ heapParams->emplace_back(
+ C2Param::Copy(*paramPointer));
}
}
++it;
}
});
if (!transStatus.isOk()) {
- ALOGE("query -- transaction failed.");
+ LOG(ERROR) << "query -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
return status;
@@ -213,13 +213,12 @@
c2_blocking_t mayBlock,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
Params hidlParams;
- Status hidlStatus = createParamsBlob(&hidlParams, params);
- if (hidlStatus != Status::OK) {
- ALOGE("config -- bad input.");
+ if (!createParamsBlob(&hidlParams, params)) {
+ LOG(ERROR) << "config -- bad input.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status;
- Return<void> transStatus = base()->config(
+ Return<void> transStatus = mBase->config(
hidlParams,
mayBlock == C2_MAY_BLOCK,
[&status, ¶ms, failures](
@@ -227,24 +226,27 @@
const hidl_vec<SettingResult> f,
const Params& o) {
status = static_cast<c2_status_t>(s);
- if (status != C2_OK) {
- ALOGD("config -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ if (status != C2_OK && status != C2_BAD_INDEX) {
+ LOG(DEBUG) << "config -- call failed: "
+ << status << ".";
}
size_t i = failures->size();
failures->resize(i + f.size());
for (const SettingResult& sf : f) {
- status = objcpy(&(*failures)[i++], sf);
- if (status != C2_OK) {
- ALOGE("config -- invalid returned SettingResult. "
- "Error code = %d", static_cast<int>(status));
+ if (!objcpy(&(*failures)[i++], sf)) {
+ LOG(ERROR) << "config -- "
+ << "invalid SettingResult returned.";
return;
}
}
- status = updateParamsFromBlob(params, o);
+ if (!updateParamsFromBlob(params, o)) {
+ LOG(ERROR) << "config -- "
+ << "failed to parse returned params.";
+ status = C2_CORRUPTED;
+ }
});
if (!transStatus.isOk()) {
- ALOGE("config -- transaction failed.");
+ LOG(ERROR) << "config -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
return status;
@@ -254,7 +256,7 @@
std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
// TODO: Cache and query properly!
c2_status_t status;
- Return<void> transStatus = base()->querySupportedParams(
+ Return<void> transStatus = mBase->querySupportedParams(
std::numeric_limits<uint32_t>::min(),
std::numeric_limits<uint32_t>::max(),
[&status, params](
@@ -262,24 +264,22 @@
const hidl_vec<ParamDescriptor>& p) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
- ALOGE("querySupportedParams -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "querySupportedParams -- call failed: "
+ << status << ".";
return;
}
size_t i = params->size();
params->resize(i + p.size());
for (const ParamDescriptor& sp : p) {
- status = objcpy(&(*params)[i++], sp);
- if (status != C2_OK) {
- ALOGE("querySupportedParams -- "
- "invalid returned ParamDescriptor. "
- "Error code = %d", static_cast<int>(status));
+ if (!objcpy(&(*params)[i++], sp)) {
+ LOG(ERROR) << "querySupportedParams -- "
+ << "invalid returned ParamDescriptor.";
return;
}
}
});
if (!transStatus.isOk()) {
- ALOGE("querySupportedParams -- transaction failed.");
+ LOG(ERROR) << "querySupportedParams -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
return status;
@@ -290,15 +290,14 @@
c2_blocking_t mayBlock) const {
hidl_vec<FieldSupportedValuesQuery> inFields(fields.size());
for (size_t i = 0; i < fields.size(); ++i) {
- Status hidlStatus = objcpy(&inFields[i], fields[i]);
- if (hidlStatus != Status::OK) {
- ALOGE("querySupportedValues -- bad input");
+ if (!objcpy(&inFields[i], fields[i])) {
+ LOG(ERROR) << "querySupportedValues -- bad input";
return C2_TRANSACTION_FAILED;
}
}
c2_status_t status;
- Return<void> transStatus = base()->querySupportedValues(
+ Return<void> transStatus = mBase->querySupportedValues(
inFields,
mayBlock == C2_MAY_BLOCK,
[&status, &inFields, &fields](
@@ -306,27 +305,28 @@
const hidl_vec<FieldSupportedValuesQueryResult>& r) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
- ALOGE("querySupportedValues -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "querySupportedValues -- call failed: "
+ << status << ".";
return;
}
if (r.size() != fields.size()) {
- ALOGE("querySupportedValues -- input and output lists "
- "have different sizes.");
+ LOG(ERROR) << "querySupportedValues -- "
+ "input and output lists "
+ "have different sizes.";
status = C2_CORRUPTED;
return;
}
for (size_t i = 0; i < fields.size(); ++i) {
- status = objcpy(&fields[i], inFields[i], r[i]);
- if (status != C2_OK) {
- ALOGE("querySupportedValues -- invalid returned value. "
- "Error code = %d", static_cast<int>(status));
+ if (!objcpy(&fields[i], inFields[i], r[i])) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "invalid returned value.";
+ status = C2_CORRUPTED;
return;
}
}
});
if (!transStatus.isOk()) {
- ALOGE("querySupportedValues -- transaction failed.");
+ LOG(ERROR) << "querySupportedValues -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
return status;
@@ -339,22 +339,24 @@
virtual Return<void> onWorkDone(const WorkBundle& workBundle) override {
std::list<std::unique_ptr<C2Work>> workItems;
- c2_status_t status = objcpy(&workItems, workBundle);
- if (status != C2_OK) {
- ALOGI("onWorkDone -- received corrupted WorkBundle. "
- "status = %d.", static_cast<int>(status));
+ if (!objcpy(&workItems, workBundle)) {
+ LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
return Void();
}
// release input buffers potentially held by the component from queue
size_t numDiscardedInputBuffers = 0;
- std::shared_ptr<Codec2Client::Component> strongComponent = component.lock();
+ std::shared_ptr<Codec2Client::Component> strongComponent =
+ component.lock();
if (strongComponent) {
- numDiscardedInputBuffers = strongComponent->handleOnWorkDone(workItems);
+ numDiscardedInputBuffers =
+ strongComponent->handleOnWorkDone(workItems);
}
if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
- listener->onWorkDone(component, workItems, numDiscardedInputBuffers);
+ listener->onWorkDone(component,
+ workItems,
+ numDiscardedInputBuffers);
} else {
- ALOGD("onWorkDone -- listener died.");
+ LOG(DEBUG) << "onWorkDone -- listener died.";
}
return Void();
}
@@ -363,13 +365,10 @@
const hidl_vec<SettingResult>& settingResults) override {
std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
settingResults.size());
- c2_status_t status;
for (size_t i = 0; i < settingResults.size(); ++i) {
std::unique_ptr<C2SettingResult> c2SettingResult;
- status = objcpy(&c2SettingResult, settingResults[i]);
- if (status != C2_OK) {
- ALOGI("onTripped -- received corrupted SettingResult. "
- "status = %d.", static_cast<int>(status));
+ if (!objcpy(&c2SettingResult, settingResults[i])) {
+ LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
return Void();
}
c2SettingResults[i] = std::move(c2SettingResult);
@@ -377,20 +376,21 @@
if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
listener->onTripped(component, c2SettingResults);
} else {
- ALOGD("onTripped -- listener died.");
+ LOG(DEBUG) << "onTripped -- listener died.";
}
return Void();
}
virtual Return<void> onError(Status s, uint32_t errorCode) override {
- ALOGD("onError -- status = %d, errorCode = %u.",
- static_cast<int>(s),
- static_cast<unsigned>(errorCode));
+ LOG(DEBUG) << "onError --"
+ << " status = " << s
+ << ", errorCode = " << errorCode
+ << ".";
if (std::shared_ptr<Listener> listener = base.lock()) {
listener->onError(component, s == Status::OK ?
errorCode : static_cast<c2_status_t>(s));
} else {
- ALOGD("onError -- listener died.");
+ LOG(DEBUG) << "onError -- listener died.";
}
return Void();
}
@@ -398,55 +398,70 @@
virtual Return<void> onFramesRendered(
const hidl_vec<RenderedFrame>& renderedFrames) override {
std::shared_ptr<Listener> listener = base.lock();
- std::vector<Codec2Client::Listener::RenderedFrame> rfs;
- rfs.reserve(renderedFrames.size());
- for (const RenderedFrame& rf : renderedFrames) {
- if (rf.slotId >= 0) {
- if (listener) {
- rfs.emplace_back(rf.bufferQueueId,
- rf.slotId,
- rf.timestampNs);
- }
- } else {
- std::shared_ptr<Codec2Client::Component> strongComponent =
- component.lock();
- if (strongComponent) {
- uint64_t frameIndex = rf.bufferQueueId;
- size_t bufferIndex = static_cast<size_t>(~rf.slotId);
- ALOGV("Received death notification of input buffer: "
- "frameIndex = %llu, bufferIndex = %zu.",
- static_cast<long long unsigned>(frameIndex),
- bufferIndex);
- std::shared_ptr<C2Buffer> buffer =
- strongComponent->freeInputBuffer(
- frameIndex, bufferIndex);
- if (buffer) {
- listener->onInputBufferDone(buffer);
- }
- }
- }
+ if (!listener) {
+ LOG(DEBUG) << "onFramesRendered -- listener died.";
+ return Void();
}
- if (!rfs.empty()) {
- if (listener) {
- listener->onFramesRendered(rfs);
- } else {
- ALOGD("onFramesRendered -- listener died.");
+ for (const RenderedFrame& renderedFrame : renderedFrames) {
+ listener->onFrameRendered(
+ renderedFrame.bufferQueueId,
+ renderedFrame.slotId,
+ renderedFrame.timestampNs);
+ }
+ return Void();
+ }
+
+ virtual Return<void> onInputBuffersReleased(
+ const hidl_vec<InputBuffer>& inputBuffers) override {
+ std::shared_ptr<Listener> listener = base.lock();
+ if (!listener) {
+ LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
+ return Void();
+ }
+ std::shared_ptr<Codec2Client::Component> strongComponent =
+ component.lock();
+ if (!strongComponent) {
+ LOG(DEBUG) << "onInputBuffersReleased -- component died.";
+ return Void();
+ }
+ for (const InputBuffer& inputBuffer : inputBuffers) {
+ std::shared_ptr<C2Buffer> buffer =
+ strongComponent->freeInputBuffer(
+ inputBuffer.frameIndex,
+ inputBuffer.arrayIndex);
+ LOG(VERBOSE) << "onInputBuffersReleased --"
+ " received death notification of"
+ " input buffer:"
+ " frameIndex = " << inputBuffer.frameIndex
+ << ", bufferIndex = " << inputBuffer.arrayIndex
+ << ".";
+ if (buffer) {
+ listener->onInputBufferDone(buffer);
}
}
return Void();
}
+
};
// Codec2Client
-Codec2Client::Base* Codec2Client::base() const {
- return static_cast<Base*>(mBase.get());
-}
-
-Codec2Client::Codec2Client(const sp<Codec2Client::Base>& base, std::string instanceName) :
- Codec2ConfigurableClient(base), mListed(false), mInstanceName(instanceName) {
+Codec2Client::Codec2Client(const sp<IComponentStore>& base,
+ std::string serviceName)
+ : Configurable{
+ [base]() -> sp<IConfigurable> {
+ Return<sp<IConfigurable>> transResult =
+ base->getConfigurable();
+ return transResult.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult) :
+ nullptr;
+ }()
+ },
+ mBase{base},
+ mListed{false},
+ mServiceName{serviceName} {
Return<sp<IClientManager>> transResult = base->getPoolClientManager();
if (!transResult.isOk()) {
- ALOGE("getPoolClientManager -- failed transaction.");
+ LOG(ERROR) << "getPoolClientManager -- transaction failed.";
} else {
mHostPoolManager = static_cast<sp<IClientManager>>(transResult);
}
@@ -457,13 +472,10 @@
const std::shared_ptr<Codec2Client::Listener>& listener,
std::shared_ptr<Codec2Client::Component>* const component) {
- // TODO: Add support for Bufferpool
-
-
c2_status_t status;
- sp<Component::HidlListener> hidlListener = new Component::HidlListener();
+ sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
hidlListener->base = listener;
- Return<void> transStatus = base()->createComponent(
+ Return<void> transStatus = mBase->createComponent(
name,
hidlListener,
ClientManager::getInstance(),
@@ -478,23 +490,24 @@
hidlListener->component = *component;
});
if (!transStatus.isOk()) {
- ALOGE("createComponent -- failed transaction.");
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- transaction failed.";
return C2_TRANSACTION_FAILED;
- }
-
- if (status != C2_OK) {
+ } else if (status != C2_OK) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- call failed: " << status << ".";
return status;
- }
-
- if (!*component) {
- ALOGE("createComponent -- null component.");
+ } else if (!*component) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- null component.";
return C2_CORRUPTED;
}
status = (*component)->setDeathListener(*component, listener);
if (status != C2_OK) {
- ALOGE("createComponent -- setDeathListener returned error: %d.",
- static_cast<int>(status));
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- failed to set up death listener: "
+ << status << ".";
}
(*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
@@ -505,44 +518,51 @@
const C2String& name,
std::shared_ptr<Codec2Client::Interface>* const interface) {
c2_status_t status;
- Return<void> transStatus = base()->createInterface(
+ Return<void> transStatus = mBase->createInterface(
name,
[&status, interface](
Status s,
const sp<IComponentInterface>& i) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
- ALOGE("createInterface -- call failed. "
- "Error code = %d", static_cast<int>(status));
return;
}
- *interface = std::make_shared<Codec2Client::Interface>(i);
+ *interface = std::make_shared<Interface>(i);
});
if (!transStatus.isOk()) {
- ALOGE("createInterface -- failed transaction.");
+ LOG(ERROR) << "createInterface(" << name.c_str()
+ << ") -- transaction failed.";
return C2_TRANSACTION_FAILED;
+ } else if (status != C2_OK) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- call failed: " << status << ".";
+ return status;
}
+
return status;
}
c2_status_t Codec2Client::createInputSurface(
- std::shared_ptr<Codec2Client::InputSurface>* const inputSurface) {
- Return<sp<IInputSurface>> transResult = base()->createInputSurface();
- if (!transResult.isOk()) {
- ALOGE("createInputSurface -- failed transaction.");
+ std::shared_ptr<InputSurface>* const inputSurface) {
+ c2_status_t status;
+ Return<void> transStatus = mBase->createInputSurface(
+ [&status, inputSurface](
+ Status s,
+ const sp<IInputSurface>& i) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ return;
+ }
+ *inputSurface = std::make_shared<InputSurface>(i);
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "createInputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
+ } else if (status != C2_OK) {
+ LOG(DEBUG) << "createInputSurface -- call failed: "
+ << status << ".";
}
- sp<IInputSurface> result = static_cast<sp<IInputSurface>>(transResult);
- if (!result) {
- *inputSurface = nullptr;
- return C2_OK;
- }
- *inputSurface = std::make_shared<InputSurface>(result);
- if (!*inputSurface) {
- ALOGE("createInputSurface -- unknown error.");
- return C2_CORRUPTED;
- }
- return C2_OK;
+ return status;
}
const std::vector<C2Component::Traits>& Codec2Client::listComponents() const {
@@ -550,22 +570,26 @@
if (mListed) {
return mTraitsList;
}
- Return<void> transStatus = base()->listComponents(
- [this](const hidl_vec<IComponentStore::ComponentTraits>& t) {
+ Return<void> transStatus = mBase->listComponents(
+ [this](Status s,
+ const hidl_vec<IComponentStore::ComponentTraits>& t) {
+ if (s != Status::OK) {
+ LOG(DEBUG) << "listComponents -- call failed: "
+ << static_cast<c2_status_t>(s) << ".";
+ return;
+ }
mTraitsList.resize(t.size());
mAliasesBuffer.resize(t.size());
for (size_t i = 0; i < t.size(); ++i) {
- c2_status_t status = objcpy(
- &mTraitsList[i], &mAliasesBuffer[i], t[i]);
- mTraitsList[i].owner = mInstanceName;
- if (status != C2_OK) {
- ALOGE("listComponents -- corrupted output.");
+ if (!objcpy(&mTraitsList[i], &mAliasesBuffer[i], t[i])) {
+ LOG(ERROR) << "listComponents -- corrupted output.";
return;
}
+ mTraitsList[i].owner = mServiceName;
}
});
if (!transStatus.isOk()) {
- ALOGE("listComponents -- failed transaction.");
+ LOG(ERROR) << "listComponents -- transaction failed.";
}
mListed = true;
return mTraitsList;
@@ -577,7 +601,7 @@
// TODO: Implement?
(void)src;
(void)dst;
- ALOGE("copyBuffer not implemented");
+ LOG(ERROR) << "copyBuffer not implemented";
return C2_OMITTED;
}
@@ -597,21 +621,25 @@
const hidl_vec<StructDescriptor>& sd) {
c2_status_t status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
- ALOGE("getStructDescriptors -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() failed: "
+ << status << ".";
descriptor.reset();
return;
}
if (sd.size() != 1) {
- ALOGD("getStructDescriptors -- returned vector of size %zu.",
- sd.size());
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() "
+ "returned vector of size "
+ << sd.size() << ". "
+ "It should be 1.";
descriptor.reset();
return;
}
- status = objcpy(&descriptor, sd[0]);
- if (status != C2_OK) {
- ALOGD("getStructDescriptors -- failed to convert. "
- "Error code = %d", static_cast<int>(status));
+ if (!objcpy(&descriptor, sd[0])) {
+ LOG(DEBUG) << "SimpleParamReflector -- "
+ "getStructDescriptors() returned "
+ "corrupted data.";
descriptor.reset();
return;
}
@@ -625,44 +653,44 @@
sp<Base> mBase;
};
- return std::make_shared<SimpleParamReflector>(base());
+ return std::make_shared<SimpleParamReflector>(mBase);
};
std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
- const char* instanceName, bool waitForService) {
- if (!instanceName) {
+ const char* serviceName, bool waitForService) {
+ if (!serviceName) {
return nullptr;
}
sp<Base> baseStore = waitForService ?
- Base::getService(instanceName) :
- Base::tryGetService(instanceName);
+ Base::getService(serviceName) :
+ Base::tryGetService(serviceName);
if (!baseStore) {
if (waitForService) {
- ALOGW("Codec2.0 service \"%s\" inaccessible. "
- "Check the device manifest.",
- instanceName);
+ LOG(WARNING) << "Codec2.0 service \"" << serviceName << "\""
+ " inaccessible. Check the device manifest.";
} else {
- ALOGD("Codec2.0 service \"%s\" unavailable right now. "
- "Try again later.",
- instanceName);
+ LOG(DEBUG) << "Codec2.0 service \"" << serviceName << "\""
+ " unavailable at the moment. "
+ " Wait or check the device manifest.";
}
return nullptr;
}
- return std::make_shared<Codec2Client>(baseStore, instanceName);
+ return std::make_shared<Codec2Client>(baseStore, serviceName);
}
c2_status_t Codec2Client::ForAllStores(
const std::string &key,
- std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)> predicate) {
+ std::function<c2_status_t(const std::shared_ptr<Codec2Client>&)>
+ predicate) {
c2_status_t status = C2_NO_INIT; // no IComponentStores present
// Cache the mapping key -> index of Codec2Client in getClient().
static std::mutex key2IndexMutex;
static std::map<std::string, size_t> key2Index;
- // By default try all stores. However, try the last known client first. If the last known
- // client fails, retry once. We do this by pushing the last known client in front of the
- // list of all clients.
+ // By default try all stores. However, try the last known client first. If
+ // the last known client fails, retry once. We do this by pushing the last
+ // known client in front of the list of all clients.
std::deque<size_t> indices;
for (size_t index = kNumClients; index > 0; ) {
indices.push_front(--index);
@@ -688,7 +716,8 @@
}
}
if (wasMapped) {
- ALOGI("Could not find '%s' in last instance. Retrying...", key.c_str());
+ LOG(INFO) << "Could not find \"" << key << "\""
+ " in the last instance. Retrying...";
wasMapped = false;
}
}
@@ -704,20 +733,27 @@
c2_status_t status = ForAllStores(
componentName,
[owner, &component, componentName, &listener](
- const std::shared_ptr<Codec2Client> &client) -> c2_status_t {
- c2_status_t status = client->createComponent(componentName, listener, &component);
+ const std::shared_ptr<Codec2Client> &client)
+ -> c2_status_t {
+ c2_status_t status = client->createComponent(componentName,
+ listener,
+ &component);
if (status == C2_OK) {
if (owner) {
*owner = client;
}
} else if (status != C2_NOT_FOUND) {
- ALOGD("IComponentStore(%s)::createComponent('%s') returned %s",
- client->getInstanceName().c_str(), componentName, asString(status));
+ LOG(DEBUG) << "IComponentStore("
+ << client->getServiceName()
+ << ")::createComponent(\"" << componentName
+ << "\") returned status = "
+ << status << ".";
}
return status;
});
if (status != C2_OK) {
- ALOGI("Could not create component '%s' (%s)", componentName, asString(status));
+ LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
+ "Status = " << status << ".";
}
return component;
}
@@ -730,20 +766,26 @@
c2_status_t status = ForAllStores(
interfaceName,
[owner, &interface, interfaceName](
- const std::shared_ptr<Codec2Client> &client) -> c2_status_t {
- c2_status_t status = client->createInterface(interfaceName, &interface);
+ const std::shared_ptr<Codec2Client> &client)
+ -> c2_status_t {
+ c2_status_t status = client->createInterface(interfaceName,
+ &interface);
if (status == C2_OK) {
if (owner) {
*owner = client;
}
} else if (status != C2_NOT_FOUND) {
- ALOGD("IComponentStore(%s)::createInterface('%s') returned %s",
- client->getInstanceName().c_str(), interfaceName, asString(status));
+ LOG(DEBUG) << "IComponentStore("
+ << client->getServiceName()
+ << ")::createInterface(\"" << interfaceName
+ << "\") returned status = "
+ << status << ".";
}
return status;
});
if (status != C2_OK) {
- ALOGI("Could not create interface '%s' (%s)", interfaceName, asString(status));
+ LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
+ "Status = " << status << ".";
}
return interface;
}
@@ -762,7 +804,8 @@
}
}
}
- ALOGW("Could not create an input surface from any Codec2.0 services.");
+ LOG(INFO) << "Could not create an input surface "
+ "from any Codec2.0 services.";
return nullptr;
}
@@ -798,15 +841,39 @@
Codec2Client::Listener::~Listener() {
}
-// Codec2Client::Component
-
-Codec2Client::Component::Base* Codec2Client::Component::base() const {
- return static_cast<Base*>(mBase.get());
+// Codec2Client::Interface
+Codec2Client::Interface::Interface(const sp<Base>& base)
+ : Configurable{
+ [base]() -> sp<IConfigurable> {
+ Return<sp<IConfigurable>> transResult =
+ base->getConfigurable();
+ return transResult.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult) :
+ nullptr;
+ }()
+ },
+ mBase{base} {
}
-Codec2Client::Component::Component(const sp<Codec2Client::Component::Base>& base) :
- Codec2Client::Configurable(base),
- mBufferPoolSender(nullptr) {
+// Codec2Client::Component
+Codec2Client::Component::Component(const sp<Base>& base)
+ : Configurable{
+ [base]() -> sp<IConfigurable> {
+ Return<sp<IComponentInterface>> transResult1 =
+ base->getInterface();
+ if (!transResult1.isOk()) {
+ return nullptr;
+ }
+ Return<sp<IConfigurable>> transResult2 =
+ static_cast<sp<IComponentInterface>>(transResult1)->
+ getConfigurable();
+ return transResult2.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult2) :
+ nullptr;
+ }()
+ },
+ mBase{base},
+ mBufferPoolSender{nullptr} {
}
Codec2Client::Component::~Component() {
@@ -817,7 +884,7 @@
C2BlockPool::local_id_t* blockPoolId,
std::shared_ptr<Codec2Client::Configurable>* configurable) {
c2_status_t status;
- Return<void> transStatus = base()->createBlockPool(
+ Return<void> transStatus = mBase->createBlockPool(
static_cast<uint32_t>(id),
[&status, blockPoolId, configurable](
Status s,
@@ -826,15 +893,15 @@
status = static_cast<c2_status_t>(s);
configurable->reset();
if (status != C2_OK) {
- ALOGE("createBlockPool -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "createBlockPool -- call failed: "
+ << status << ".";
return;
}
*blockPoolId = static_cast<C2BlockPool::local_id_t>(pId);
- *configurable = std::make_shared<Codec2Client::Configurable>(c);
+ *configurable = std::make_shared<Configurable>(c);
});
if (!transStatus.isOk()) {
- ALOGE("createBlockPool -- transaction failed.");
+ LOG(ERROR) << "createBlockPool -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
return status;
@@ -842,10 +909,10 @@
c2_status_t Codec2Client::Component::destroyBlockPool(
C2BlockPool::local_id_t localId) {
- Return<Status> transResult = base()->destroyBlockPool(
+ Return<Status> transResult = mBase->destroyBlockPool(
static_cast<uint64_t>(localId));
if (!transResult.isOk()) {
- ALOGE("destroyBlockPool -- transaction failed.");
+ LOG(ERROR) << "destroyBlockPool -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
return static_cast<c2_status_t>(static_cast<Status>(transResult));
@@ -859,7 +926,8 @@
if (work) {
if (work->worklets.empty()
|| !work->worklets.back()
- || (work->worklets.back()->output.flags & C2FrameData::FLAG_INCOMPLETE) == 0) {
+ || (work->worklets.back()->output.flags &
+ C2FrameData::FLAG_INCOMPLETE) == 0) {
// input is complete
inputDone.emplace_back(work->input.ordinal.frameIndex.peeku());
}
@@ -872,13 +940,14 @@
for (uint64_t inputIndex : inputDone) {
auto it = mInputBuffers.find(inputIndex);
if (it == mInputBuffers.end()) {
- ALOGV("onWorkDone -- returned consumed/unknown "
- "input frame: index %llu",
- (long long)inputIndex);
+ LOG(VERBOSE) << "onWorkDone -- returned consumed/unknown "
+ "input frame: index = "
+ << inputIndex << ".";
} else {
- ALOGV("onWorkDone -- processed input frame: "
- "index %llu (containing %zu buffers)",
- (long long)inputIndex, it->second.size());
+ LOG(VERBOSE) << "onWorkDone -- processed input frame: "
+ << inputIndex
+ << " (containing " << it->second.size()
+ << " buffers).";
mInputBuffers.erase(it);
mInputBufferCount.erase(inputIndex);
++numDiscardedInputBuffers;
@@ -906,21 +975,21 @@
std::lock_guard<std::mutex> lock(mInputBuffersMutex);
auto it = mInputBuffers.find(frameIndex);
if (it == mInputBuffers.end()) {
- ALOGI("freeInputBuffer -- Unrecognized input frame index %llu.",
- static_cast<long long unsigned>(frameIndex));
+ LOG(INFO) << "freeInputBuffer -- Unrecognized input frame index "
+ << frameIndex << ".";
return nullptr;
}
if (bufferIndex >= it->second.size()) {
- ALOGI("freeInputBuffer -- Input buffer no. %zu is invalid in "
- "input frame index %llu.",
- bufferIndex, static_cast<long long unsigned>(frameIndex));
+ LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex
+ << " is not valid in input with frame index " << frameIndex
+ << ".";
return nullptr;
}
buffer = it->second[bufferIndex];
if (!buffer) {
- ALOGI("freeInputBuffer -- Input buffer no. %zu in "
- "input frame index %llu has already been freed.",
- bufferIndex, static_cast<long long unsigned>(frameIndex));
+ LOG(INFO) << "freeInputBuffer -- Input buffer number " << bufferIndex
+ << " in input with frame index " << frameIndex
+ << " has already been freed.";
return nullptr;
}
it->second[bufferIndex] = nullptr;
@@ -949,33 +1018,33 @@
if (!res.second) {
// TODO: append? - for now we are replacing
res.first->second = work->input.buffers;
- ALOGI("queue -- duplicate input frame: index %llu. "
- "Discarding the old input frame...",
- (long long)inputIndex);
+ LOG(INFO) << "queue -- duplicate input frame index: "
+ << inputIndex
+ << ". Discarding the old input frame...";
}
mInputBufferCount[inputIndex] = work->input.buffers.size();
- ALOGV("queue -- queueing input frame: "
- "index %llu (containing %zu buffers)",
- (long long)inputIndex, work->input.buffers.size());
+ LOG(VERBOSE) << "queue -- queuing input frame: "
+ << "index = " << inputIndex
+ << ", number of buffers = "
+ << work->input.buffers.size()
+ << ".";
}
}
WorkBundle workBundle;
- Status hidlStatus = objcpy(&workBundle, *items, &mBufferPoolSender);
- if (hidlStatus != Status::OK) {
- ALOGE("queue -- bad input.");
+ if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
+ LOG(ERROR) << "queue -- bad input.";
return C2_TRANSACTION_FAILED;
}
- Return<Status> transStatus = base()->queue(workBundle);
+ Return<Status> transStatus = mBase->queue(workBundle);
if (!transStatus.isOk()) {
- ALOGE("queue -- transaction failed.");
+ LOG(ERROR) << "queue -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("queue -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "queue -- call failed: " << status << ".";
}
return status;
}
@@ -985,19 +1054,22 @@
std::list<std::unique_ptr<C2Work>>* const flushedWork) {
(void)mode; // Flush mode isn't supported in HIDL yet.
c2_status_t status;
- Return<void> transStatus = base()->flush(
+ Return<void> transStatus = mBase->flush(
[&status, flushedWork](
Status s, const WorkBundle& wb) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
- ALOGE("flush -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "flush -- call failed: " << status << ".";
return;
}
- status = objcpy(flushedWork, wb);
+ if (!objcpy(flushedWork, wb)) {
+ status = C2_CORRUPTED;
+ } else {
+ status = C2_OK;
+ }
});
if (!transStatus.isOk()) {
- ALOGE("flush -- transaction failed.");
+ LOG(ERROR) << "flush -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
@@ -1021,13 +1093,14 @@
std::lock_guard<std::mutex> lock(mInputBuffersMutex);
auto it = mInputBuffers.find(flushedIndex);
if (it == mInputBuffers.end()) {
- ALOGV("flush -- returned consumed/unknown input frame: "
- "index %llu",
- (long long)flushedIndex);
+ LOG(VERBOSE) << "flush -- returned consumed/unknown input frame: "
+ "index = " << flushedIndex << ".";
} else {
- ALOGV("flush -- returned unprocessed input frame: "
- "index %llu (containing %zu buffers)",
- (long long)flushedIndex, mInputBufferCount[flushedIndex]);
+ LOG(VERBOSE) << "flush -- returned unprocessed input frame: "
+ "index = " << flushedIndex
+ << ", number of buffers = "
+ << mInputBufferCount[flushedIndex]
+ << ".";
mInputBuffers.erase(it);
mInputBufferCount.erase(flushedIndex);
}
@@ -1048,47 +1121,44 @@
}
c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
- Return<Status> transStatus = base()->drain(
+ Return<Status> transStatus = mBase->drain(
mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
if (!transStatus.isOk()) {
- ALOGE("drain -- transaction failed.");
+ LOG(ERROR) << "drain -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("drain -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "drain -- call failed: " << status << ".";
}
return status;
}
c2_status_t Codec2Client::Component::start() {
- Return<Status> transStatus = base()->start();
+ Return<Status> transStatus = mBase->start();
if (!transStatus.isOk()) {
- ALOGE("start -- transaction failed.");
+ LOG(ERROR) << "start -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("start -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "start -- call failed: " << status << ".";
}
return status;
}
c2_status_t Codec2Client::Component::stop() {
- Return<Status> transStatus = base()->stop();
+ Return<Status> transStatus = mBase->stop();
if (!transStatus.isOk()) {
- ALOGE("stop -- transaction failed.");
+ LOG(ERROR) << "stop -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("stop -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "stop -- call failed: " << status << ".";
}
mInputBuffersMutex.lock();
mInputBuffers.clear();
@@ -1098,16 +1168,15 @@
}
c2_status_t Codec2Client::Component::reset() {
- Return<Status> transStatus = base()->reset();
+ Return<Status> transStatus = mBase->reset();
if (!transStatus.isOk()) {
- ALOGE("reset -- transaction failed.");
+ LOG(ERROR) << "reset -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("reset -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "reset -- call failed: " << status << ".";
}
mInputBuffersMutex.lock();
mInputBuffers.clear();
@@ -1117,16 +1186,15 @@
}
c2_status_t Codec2Client::Component::release() {
- Return<Status> transStatus = base()->release();
+ Return<Status> transStatus = mBase->release();
if (!transStatus.isOk()) {
- ALOGE("release -- transaction failed.");
+ LOG(ERROR) << "release -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("release -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "release -- call failed: " << status << ".";
}
mInputBuffersMutex.lock();
mInputBuffers.clear();
@@ -1144,17 +1212,16 @@
igbp = new TWGraphicBufferProducer<HGraphicBufferProducer>(surface);
}
- Return<Status> transStatus = base()->setOutputSurface(
+ Return<Status> transStatus = mBase->setOutputSurface(
static_cast<uint64_t>(blockPoolId), igbp);
if (!transStatus.isOk()) {
- ALOGE("setOutputSurface -- transaction failed.");
+ LOG(ERROR) << "setOutputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("setOutputSurface -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
} else {
std::lock_guard<std::mutex> lock(mOutputBufferQueueMutex);
if (mOutputIgbp != surface) {
@@ -1162,7 +1229,8 @@
if (!surface) {
mOutputBqId = 0;
} else if (surface->getUniqueId(&mOutputBqId) != OK) {
- ALOGE("setOutputSurface -- cannot obtain bufferqueue id.");
+ LOG(ERROR) << "setOutputSurface -- "
+ "cannot obtain bufferqueue id.";
}
}
mOutputGeneration = generation;
@@ -1191,17 +1259,16 @@
outputGeneration,
&bqSlot);
if (status != OK) {
- ALOGW("queueToOutputSurface -- attaching failed.");
+ LOG(WARNING) << "queueToOutputSurface -- attaching failed.";
return INVALID_OPERATION;
}
status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
input, output);
if (status != OK) {
- ALOGE("queueToOutputSurface -- queueBuffer() failed "
- "on non-bufferqueue-based block. "
- "Error code = %d.",
- static_cast<int>(status));
+ LOG(ERROR) << "queueToOutputSurface -- queueBuffer() failed "
+ "on non-bufferqueue-based block. "
+ "Error = " << status << ".";
return status;
}
return OK;
@@ -1214,17 +1281,17 @@
mOutputBufferQueueMutex.unlock();
if (!outputIgbp) {
- ALOGV("queueToOutputSurface -- output surface is null.");
+ LOG(VERBOSE) << "queueToOutputSurface -- output surface is null.";
return NO_INIT;
}
if (bqId != outputBqId || generation != outputGeneration) {
if (!holdBufferQueueBlock(block, mOutputIgbp, mOutputBqId, mOutputGeneration)) {
- ALOGE("queueToOutputSurface -- migration fialed");
+ LOG(ERROR) << "queueToOutputSurface -- migration failed.";
return DEAD_OBJECT;
}
if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot)) {
- ALOGE("queueToOutputSurface -- corrupted bq assignment");
+ LOG(ERROR) << "queueToOutputSurface -- corrupted bufferqueue assignment.";
return UNKNOWN_ERROR;
}
}
@@ -1232,49 +1299,77 @@
status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
input, output);
if (status != OK) {
- ALOGD("queueToOutputSurface -- queueBuffer() failed "
- "on bufferqueue-based block. "
- "Error code = %d.",
- static_cast<int>(status));
+ LOG(DEBUG) << "queueToOutputSurface -- queueBuffer() failed "
+ "on bufferqueue-based block. "
+ "Error = " << status << ".";
return status;
}
if (!yieldBufferQueueBlock(block)) {
- ALOGD("queueToOutputSurface -- cannot yield bufferqueue-based block "
- "to the bufferqueue.");
+ LOG(DEBUG) << "queueToOutputSurface -- cannot yield "
+ "bufferqueue-based block to the bufferqueue.";
return UNKNOWN_ERROR;
}
return OK;
}
-c2_status_t Codec2Client::Component::connectToOmxInputSurface(
- const sp<HGraphicBufferProducer>& producer,
- const sp<HGraphicBufferSource>& source) {
- Return<Status> transStatus = base()->connectToOmxInputSurface(
- producer, source);
+c2_status_t Codec2Client::Component::connectToInputSurface(
+ const std::shared_ptr<InputSurface>& inputSurface,
+ std::shared_ptr<InputSurfaceConnection>* connection) {
+ c2_status_t status;
+ Return<void> transStatus = mBase->connectToInputSurface(
+ inputSurface->mBase,
+ [&status, connection](
+ Status s, const sp<IInputSurfaceConnection>& c) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "connectToInputSurface -- call failed: "
+ << status << ".";
+ return;
+ }
+ *connection = std::make_shared<InputSurfaceConnection>(c);
+ });
if (!transStatus.isOk()) {
- ALOGE("connectToOmxInputSurface -- transaction failed.");
+ LOG(ERROR) << "connectToInputSurface -- transaction failed";
return C2_TRANSACTION_FAILED;
}
- c2_status_t status =
- static_cast<c2_status_t>(static_cast<Status>(transStatus));
- if (status != C2_OK) {
- ALOGE("connectToOmxInputSurface -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ return status;
+}
+
+c2_status_t Codec2Client::Component::connectToOmxInputSurface(
+ const sp<HGraphicBufferProducer>& producer,
+ const sp<HGraphicBufferSource>& source,
+ std::shared_ptr<InputSurfaceConnection>* connection) {
+ c2_status_t status;
+ Return<void> transStatus = mBase->connectToOmxInputSurface(
+ producer, source,
+ [&status, connection](
+ Status s, const sp<IInputSurfaceConnection>& c) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
+ << status << ".";
+ return;
+ }
+ *connection = std::make_shared<InputSurfaceConnection>(c);
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
}
return status;
}
c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
- Return<Status> transStatus = base()->disconnectFromInputSurface();
+ Return<Status> transStatus = mBase->disconnectFromInputSurface();
if (!transStatus.isOk()) {
- ALOGE("disconnectToInputSurface -- transaction failed.");
+ LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
}
c2_status_t status =
static_cast<c2_status_t>(static_cast<Status>(transStatus));
if (status != C2_OK) {
- ALOGE("disconnectFromInputSurface -- call failed. "
- "Error code = %d", static_cast<int>(status));
+ LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
+ << status << ".";
}
return status;
}
@@ -1294,7 +1389,7 @@
if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
listener->onDeath(component);
} else {
- ALOGW("onDeath -- listener died.");
+ LOG(DEBUG) << "onDeath -- listener died.";
}
}
};
@@ -1304,93 +1399,68 @@
deathRecipient->component = component;
component->mDeathRecipient = deathRecipient;
- Return<bool> transResult = component->base()->linkToDeath(
+ Return<bool> transResult = component->mBase->linkToDeath(
component->mDeathRecipient, 0);
if (!transResult.isOk()) {
- ALOGE("setDeathListener -- failed transaction: linkToDeath.");
+ LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
return C2_TRANSACTION_FAILED;
}
if (!static_cast<bool>(transResult)) {
- ALOGE("setDeathListener -- linkToDeath call failed.");
+ LOG(DEBUG) << "setDeathListener -- linkToDeath() call failed.";
return C2_CORRUPTED;
}
return C2_OK;
}
// Codec2Client::InputSurface
-
-Codec2Client::InputSurface::Base* Codec2Client::InputSurface::base() const {
- return static_cast<Base*>(mBase.get());
-}
-
-Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base) :
- mBase(base),
- mGraphicBufferProducer(new
+Codec2Client::InputSurface::InputSurface(const sp<IInputSurface>& base)
+ : Configurable{
+ [base]() -> sp<IConfigurable> {
+ Return<sp<IConfigurable>> transResult =
+ base->getConfigurable();
+ return transResult.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult) :
+ nullptr;
+ }()
+ },
+ mBase{base},
+ mGraphicBufferProducer{new
::android::hardware::graphics::bufferqueue::V1_0::utils::
- H2BGraphicBufferProducer(base)) {
+ H2BGraphicBufferProducer([base]() -> sp<HGraphicBufferProducer> {
+ Return<sp<HGraphicBufferProducer>> transResult =
+ base->getGraphicBufferProducer();
+ return transResult.isOk() ?
+ static_cast<sp<HGraphicBufferProducer>>(transResult) :
+ nullptr;
+ }())} {
}
-c2_status_t Codec2Client::InputSurface::connectToComponent(
- const std::shared_ptr<Codec2Client::Component>& component,
- std::shared_ptr<Connection>* connection) {
- c2_status_t status;
- Return<void> transStatus = base()->connectToComponent(
- component->base(),
- [&status, connection](
- Status s,
- const sp<IInputSurfaceConnection>& c) {
- status = static_cast<c2_status_t>(s);
- if (status != C2_OK) {
- ALOGE("connectToComponent -- call failed. "
- "Error code = %d", static_cast<int>(status));
- return;
- }
- *connection = std::make_shared<Connection>(c);
- });
- if (!transStatus.isOk()) {
- ALOGE("connect -- transaction failed.");
- return C2_TRANSACTION_FAILED;
- }
- return status;
-}
-
-std::shared_ptr<Codec2Client::Configurable>
- Codec2Client::InputSurface::getConfigurable() const {
- Return<sp<IConfigurable>> transResult = base()->getConfigurable();
- if (!transResult.isOk()) {
- ALOGW("getConfigurable -- transaction failed.");
- return nullptr;
- }
- if (!static_cast<sp<IConfigurable>>(transResult)) {
- ALOGW("getConfigurable -- null pointer.");
- return nullptr;
- }
- return std::make_shared<Configurable>(transResult);
-}
-
-const sp<IGraphicBufferProducer>&
+sp<IGraphicBufferProducer>
Codec2Client::InputSurface::getGraphicBufferProducer() const {
return mGraphicBufferProducer;
}
-const sp<IInputSurface>& Codec2Client::InputSurface::getHalInterface() const {
+sp<IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
return mBase;
}
// Codec2Client::InputSurfaceConnection
-
-Codec2Client::InputSurfaceConnection::Base*
- Codec2Client::InputSurfaceConnection::base() const {
- return static_cast<Base*>(mBase.get());
-}
-
Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
- const sp<Codec2Client::InputSurfaceConnection::Base>& base) :
- mBase(base) {
+ const sp<IInputSurfaceConnection>& base)
+ : Configurable{
+ [base]() -> sp<IConfigurable> {
+ Return<sp<IConfigurable>> transResult =
+ base->getConfigurable();
+ return transResult.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult) :
+ nullptr;
+ }()
+ },
+ mBase{base} {
}
c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
- Return<Status> transResult = base()->disconnect();
+ Return<Status> transResult = mBase->disconnect();
return static_cast<c2_status_t>(static_cast<Status>(transResult));
}
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index c48bf0c..f320ef3 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_CLIENT_H_
-#define CODEC2_HIDL_CLIENT_H_
+#ifndef CODEC2_HIDL_CLIENT_H
+#define CODEC2_HIDL_CLIENT_H
#include <gui/IGraphicBufferProducer.h>
#include <codec2/hidl/1.0/types.h>
@@ -70,8 +70,8 @@
namespace c2 {
namespace V1_0 {
struct IConfigurable;
-struct IComponentInterface;
struct IComponent;
+struct IComponentInterface;
struct IComponentStore;
struct IInputSurface;
struct IInputSurfaceConnection;
@@ -146,10 +146,8 @@
Codec2ConfigurableClient(const sp<Base>& base);
protected:
- C2String mName;
sp<Base> mBase;
-
- Base* base() const;
+ C2String mName;
friend struct Codec2Client;
};
@@ -162,17 +160,17 @@
typedef Codec2ConfigurableClient Configurable;
- typedef Configurable Interface; // These two types may diverge in the future.
-
struct Component;
+ struct Interface;
+
struct InputSurface;
struct InputSurfaceConnection;
typedef Codec2Client Store;
- std::string getInstanceName() const { return mInstanceName; }
+ std::string getServiceName() const { return mServiceName; }
c2_status_t createComponent(
const C2String& name,
@@ -195,7 +193,7 @@
std::shared_ptr<C2ParamReflector> getParamReflector();
static std::shared_ptr<Codec2Client> CreateFromService(
- const char* instanceName,
+ const char* serviceName,
bool waitForService = true);
// Try to create a component with a given name from all known
@@ -218,10 +216,10 @@
static std::shared_ptr<InputSurface> CreateInputSurface();
// base cannot be null.
- Codec2Client(const sp<Base>& base, std::string instanceName);
+ Codec2Client(const sp<Base>& base, std::string serviceName);
protected:
- Base* base() const;
+ sp<Base> mBase;
// Finds the first store where the predicate returns OK, and returns the last
// predicate result. Uses key to remember the last store found, and if cached,
@@ -232,7 +230,7 @@
mutable std::mutex mMutex;
mutable bool mListed;
- std::string mInstanceName;
+ std::string mServiceName;
mutable std::vector<C2Component::Traits> mTraitsList;
mutable std::vector<std::unique_ptr<std::vector<std::string>>>
mAliasesBuffer;
@@ -241,6 +239,16 @@
mHostPoolManager;
};
+struct Codec2Client::Interface : public Codec2Client::Configurable {
+
+ typedef ::android::hardware::media::c2::V1_0::IComponentInterface Base;
+
+ Interface(const sp<Base>& base);
+
+protected:
+ sp<Base> mBase;
+};
+
struct Codec2Client::Listener {
// This is called when the component produces some output.
@@ -277,28 +285,12 @@
virtual void onInputBufferDone(
const std::shared_ptr<C2Buffer>& buffer) = 0;
- // This structure is used for transporting onFramesRendered() event to the
- // client in the case where the output buffers are obtained from a
- // bufferqueue.
- struct RenderedFrame {
- // The id of the bufferqueue.
- uint64_t bufferQueueId;
- // The slot of the buffer inside the bufferqueue.
- int32_t slotId;
- // The timestamp.
- int64_t timestampNs;
-
- RenderedFrame(uint64_t bufferQueueId, int32_t slotId,
- int64_t timestampNs)
- : bufferQueueId(bufferQueueId),
- slotId(slotId),
- timestampNs(timestampNs) {}
- RenderedFrame(const RenderedFrame&) = default;
- };
-
- // This is called when the component becomes aware of frames being rendered.
- virtual void onFramesRendered(
- const std::vector<RenderedFrame>& renderedFrames) = 0;
+ // This is called when the component becomes aware of a frame being
+ // rendered.
+ virtual void onFrameRendered(
+ uint64_t bufferQueueId,
+ int32_t slotId,
+ int64_t timestampNs) = 0;
virtual ~Listener();
@@ -373,9 +365,15 @@
const QueueBufferInput& input,
QueueBufferOutput* output);
+ // Connect to a given InputSurface.
+ c2_status_t connectToInputSurface(
+ const std::shared_ptr<InputSurface>& inputSurface,
+ std::shared_ptr<InputSurfaceConnection>* connection);
+
c2_status_t connectToOmxInputSurface(
const sp<HGraphicBufferProducer>& producer,
- const sp<HGraphicBufferSource>& source);
+ const sp<HGraphicBufferSource>& source,
+ std::shared_ptr<InputSurfaceConnection>* connection);
c2_status_t disconnectFromInputSurface();
@@ -385,7 +383,7 @@
~Component();
protected:
- Base* base() const;
+ sp<Base> mBase;
// Mutex for mInputBuffers and mInputBufferCount.
mutable std::mutex mInputBuffersMutex;
@@ -428,7 +426,7 @@
};
-struct Codec2Client::InputSurface {
+struct Codec2Client::InputSurface : public Codec2Client::Configurable {
public:
typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;
@@ -439,22 +437,15 @@
typedef ::android::IGraphicBufferProducer IGraphicBufferProducer;
- c2_status_t connectToComponent(
- const std::shared_ptr<Component>& component,
- std::shared_ptr<Connection>* connection);
-
- std::shared_ptr<Configurable> getConfigurable() const;
-
- const sp<IGraphicBufferProducer>& getGraphicBufferProducer() const;
+ sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
// Return the underlying IInputSurface.
- const sp<Base>& getHalInterface() const;
+ sp<Base> getHalInterface() const;
// base cannot be null.
InputSurface(const sp<Base>& base);
protected:
- Base* base() const;
sp<Base> mBase;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
@@ -463,7 +454,7 @@
friend struct Component;
};
-struct Codec2Client::InputSurfaceConnection {
+struct Codec2Client::InputSurfaceConnection : public Codec2Client::Configurable {
typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection Base;
@@ -473,7 +464,6 @@
InputSurfaceConnection(const sp<Base>& base);
protected:
- Base* base() const;
sp<Base> mBase;
friend struct Codec2Client::InputSurface;
@@ -481,5 +471,5 @@
} // namespace android
-#endif // CODEC2_HIDL_CLIENT_H_
+#endif // CODEC2_HIDL_CLIENT_H
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 852d6d6..2527b00 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -143,8 +143,7 @@
if (mConnection != nullptr) {
return ALREADY_EXISTS;
}
- return toStatusT(mSurface->connectToComponent(comp, &mConnection),
- C2_OPERATION_InputSurface_connectToComponent);
+ return toStatusT(comp->connectToInputSurface(mSurface, &mConnection));
}
void disconnect() override {
@@ -162,7 +161,7 @@
status_t signalEndOfInputStream() override {
C2InputSurfaceEosTuning eos(true);
std::vector<std::unique_ptr<C2SettingResult>> failures;
- c2_status_t err = mSurface->getConfigurable()->config({&eos}, C2_MAY_BLOCK, &failures);
+ c2_status_t err = mSurface->config({&eos}, C2_MAY_BLOCK, &failures);
if (err != C2_OK) {
return UNKNOWN_ERROR;
}
@@ -495,10 +494,13 @@
codec->mCallback->onError(DEAD_OBJECT, ACTION_CODE_FATAL);
}
- virtual void onFramesRendered(
- const std::vector<RenderedFrame>& renderedFrames) override {
- // TODO
- (void)renderedFrames;
+ virtual void onFrameRendered(uint64_t bufferQueueId,
+ int32_t slotId,
+ int64_t timestampNs) override {
+ // TODO: implement
+ (void)bufferQueueId;
+ (void)slotId;
+ (void)timestampNs;
}
virtual void onInputBufferDone(
@@ -599,7 +601,7 @@
// set up preferred component store to access vendor store parameters
client = Codec2Client::CreateFromService("default", false);
if (client) {
- ALOGI("setting up '%s' as default (vendor) store", client->getInstanceName().c_str());
+ ALOGI("setting up '%s' as default (vendor) store", client->getServiceName().c_str());
SetPreferredCodec2ComponentStore(
std::make_shared<Codec2ClientInterfaceWrapper>(client));
}
@@ -956,16 +958,18 @@
std::shared_ptr<PersistentSurface> persistentSurface(CreateInputSurface());
if (persistentSurface->getHidlTarget()) {
- sp<IInputSurface> inputSurface = IInputSurface::castFrom(
+ sp<IInputSurface> hidlInputSurface = IInputSurface::castFrom(
persistentSurface->getHidlTarget());
- if (!inputSurface) {
+ if (!hidlInputSurface) {
ALOGE("Corrupted input surface");
mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
return;
}
+ std::shared_ptr<Codec2Client::InputSurface> inputSurface =
+ std::make_shared<Codec2Client::InputSurface>(hidlInputSurface);
err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
- std::make_shared<Codec2Client::InputSurface>(inputSurface)));
- bufferProducer = new H2BGraphicBufferProducer(inputSurface);
+ inputSurface));
+ bufferProducer = inputSurface->getGraphicBufferProducer();
} else {
int32_t width = 0;
(void)outputFormat->findInt32("width", &width);
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index b529cbc..577aff3 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1645,6 +1645,7 @@
work->input.ordinal.customOrdinal = timeUs;
work->input.buffers.clear();
work->input.flags = C2FrameData::FLAG_END_OF_STREAM;
+ work->worklets.emplace_back(new C2Worklet);
items.clear();
items.push_back(std::move(work));