codec2: implement C2InfoBuffer
Bug: 161914501
Change-Id: I22ddb752ee3b9f661c1c70d2d0bbe0321886f930
diff --git a/media/codec2/core/include/C2Buffer.h b/media/codec2/core/include/C2Buffer.h
index 3d3587c..c4683c0 100644
--- a/media/codec2/core/include/C2Buffer.h
+++ b/media/codec2/core/include/C2Buffer.h
@@ -2156,9 +2156,12 @@
};
/**
- * An extension of C2Info objects that can contain arbitrary buffer data.
+ * A const metadata object that can contain arbitrary buffer data.
*
- * \note This object is not describable and contains opaque data.
+ * This object is not an actual C2Info and is not attached to buffers (C2Buffer), but rather to
+ * frames (C2FrameData). It is not describable via C2ParamDescriptor.
+ *
+ * C2InfoBuffer is a const object that can be allocated on stack and is copiable.
*/
class C2InfoBuffer {
public:
@@ -2167,14 +2170,65 @@
*
* \return the parameter index.
*/
- const C2Param::Index index() const;
+ const C2Param::Index index() const { return mIndex; }
/**
* Gets the buffer's data.
*
* \return the buffer's data.
*/
- const C2BufferData data() const;
+ const C2BufferData data() const { return mData; }
+
+ /// Returns a clone of this as a global info buffer.
+ C2InfoBuffer asGlobal() const {
+ C2Param::Index index = mIndex;
+ index.convertToGlobal();
+ return C2InfoBuffer(index, mData);
+ }
+
+ /// Returns a clone of this as a port info buffer.
+ C2InfoBuffer asPort(bool output) const {
+ C2Param::Index index = mIndex;
+ index.convertToPort(output);
+ return C2InfoBuffer(index, mData);
+ }
+
+ /// Returns a clone of this as a stream info buffer.
+ C2InfoBuffer asStream(bool output, unsigned stream) const {
+ C2Param::Index index = mIndex;
+ index.convertToStream(output, stream);
+ return C2InfoBuffer(index, mData);
+ }
+
+ /**
+ * Creates a global info buffer containing a single linear block.
+ *
+ * \param index the core parameter index of this info buffer.
+ * \param block the content of the info buffer.
+ *
+ * \return shared pointer to the created info buffer.
+ */
+ static C2InfoBuffer CreateLinearBuffer(C2Param::CoreIndex index, const C2ConstLinearBlock &block);
+
+ /**
+ * Creates a global info buffer containing a single graphic block.
+ *
+ * \param index the core parameter index of this info buffer.
+ * \param block the content of the info buffer.
+ *
+ * \return shared pointer to the created info buffer.
+ */
+ static C2InfoBuffer CreateGraphicBuffer(C2Param::CoreIndex index, const C2ConstGraphicBlock &block);
+
+protected:
+ // no public constructor
+ explicit C2InfoBuffer(C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks);
+ explicit C2InfoBuffer(C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks);
+
+private:
+ C2Param::Index mIndex;
+ C2BufferData mData;
+ explicit C2InfoBuffer(C2Param::Index index, const C2BufferData &data);
};
/// @}
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index 436269a..e938f96 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -317,7 +317,8 @@
DEFINE_FIELD_BASED_COMPARISON_OPERATORS(Index, mIndex)
private:
- friend struct C2Param; // for setStream, MakeStreamId, isValid
+ friend class C2InfoBuffer; // for convertTo*
+ friend struct C2Param; // for setStream, MakeStreamId, isValid, convertTo*
friend struct _C2ParamInspector; // for testing
/**
diff --git a/media/codec2/tests/vndk/C2BufferTest.cpp b/media/codec2/tests/vndk/C2BufferTest.cpp
index 780994a..a9f8e17 100644
--- a/media/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/codec2/tests/vndk/C2BufferTest.cpp
@@ -765,4 +765,54 @@
}
}
+TEST_F(C2BufferTest, InfoBufferTest) {
+ constexpr size_t kCapacity = 524288u;
+
+ // allocate a linear block
+ std::shared_ptr<C2BlockPool> linearPool(makeLinearBlockPool());
+ std::shared_ptr<C2LinearBlock> linearBlock;
+ ASSERT_EQ(C2_OK, linearPool->fetchLinearBlock(
+ kCapacity,
+ { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
+ &linearBlock));
+
+ C2InfoBuffer info = C2InfoBuffer::CreateLinearBuffer(
+ kParamIndexNumber1, linearBlock->share(1024, kCapacity / 2, C2Fence()));
+ std::shared_ptr<C2InfoBuffer> spInfo(new C2InfoBuffer(info));
+ ASSERT_EQ(kParamIndexNumber1, spInfo->index().coreIndex());
+ ASSERT_TRUE(spInfo->index().isGlobal());
+ ASSERT_EQ(C2Param::INFO, spInfo->index().kind());
+ ASSERT_EQ(C2BufferData::LINEAR, spInfo->data().type());
+ ASSERT_EQ(1024, spInfo->data().linearBlocks()[0].offset());
+ ASSERT_EQ(kCapacity / 2, spInfo->data().linearBlocks()[0].size());
+ // handles must actually be identical after sharing into an info buffer
+ ASSERT_EQ(linearBlock->handle(), spInfo->data().linearBlocks()[0].handle());
+ ASSERT_EQ(linearPool->getAllocatorId(), spInfo->data().linearBlocks()[0].getAllocatorId());
+
+ C2InfoBuffer streamInfo = info.asStream(false /* output */, 1u);
+ ASSERT_EQ(kParamIndexNumber1, streamInfo.index().coreIndex());
+ ASSERT_TRUE(streamInfo.index().forStream());
+ ASSERT_TRUE(streamInfo.index().forInput());
+ ASSERT_EQ(1u, streamInfo.index().stream());
+ ASSERT_EQ(C2Param::INFO, streamInfo.index().kind());
+ ASSERT_EQ(C2BufferData::LINEAR, streamInfo.data().type());
+ ASSERT_EQ(1024, streamInfo.data().linearBlocks()[0].offset());
+ ASSERT_EQ(kCapacity / 2, streamInfo.data().linearBlocks()[0].size());
+ // handles must actually be identical after sharing into an info buffer
+ ASSERT_EQ(linearBlock->handle(), streamInfo.data().linearBlocks()[0].handle());
+ ASSERT_EQ(linearPool->getAllocatorId(), streamInfo.data().linearBlocks()[0].getAllocatorId());
+
+ C2InfoBuffer portInfo = streamInfo.asPort(true /* output */);
+ ASSERT_EQ(kParamIndexNumber1, portInfo.index().coreIndex());
+ ASSERT_TRUE(portInfo.index().forPort());
+ ASSERT_TRUE(portInfo.index().forOutput());
+ ASSERT_EQ(C2Param::INFO, portInfo.index().kind());
+ ASSERT_EQ(C2BufferData::LINEAR, portInfo.data().type());
+ ASSERT_EQ(1024, portInfo.data().linearBlocks()[0].offset());
+ ASSERT_EQ(kCapacity / 2, portInfo.data().linearBlocks()[0].size());
+ // handles must actually be identical after sharing into an info buffer
+ ASSERT_EQ(linearBlock->handle(), portInfo.data().linearBlocks()[0].handle());
+ ASSERT_EQ(linearPool->getAllocatorId(), portInfo.data().linearBlocks()[0].getAllocatorId());
+}
+
} // namespace android
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 0b08f31..2294fa8 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -106,6 +106,7 @@
class BufferDataBuddy : public C2BufferData {
using C2BufferData::C2BufferData;
friend class ::C2Buffer;
+ friend class ::C2InfoBuffer;
};
} // namespace
@@ -1185,6 +1186,7 @@
type_t mType;
std::vector<C2ConstLinearBlock> mLinearBlocks;
std::vector<C2ConstGraphicBlock> mGraphicBlocks;
+ friend class C2InfoBuffer;
};
C2BufferData::C2BufferData(const std::vector<C2ConstLinearBlock> &blocks) : mImpl(new Impl(blocks)) {}
@@ -1200,6 +1202,35 @@
return mImpl->graphicBlocks();
}
+C2InfoBuffer::C2InfoBuffer(
+ C2Param::Index index, const std::vector<C2ConstLinearBlock> &blocks)
+ : mIndex(index), mData(BufferDataBuddy(blocks)) {
+}
+
+C2InfoBuffer::C2InfoBuffer(
+ C2Param::Index index, const std::vector<C2ConstGraphicBlock> &blocks)
+ : mIndex(index), mData(BufferDataBuddy(blocks)) {
+}
+
+C2InfoBuffer::C2InfoBuffer(
+ C2Param::Index index, const C2BufferData &data)
+ : mIndex(index), mData(data) {
+}
+
+// static
+C2InfoBuffer C2InfoBuffer::CreateLinearBuffer(
+ C2Param::CoreIndex index, const C2ConstLinearBlock &block) {
+ return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
+ { block });
+}
+
+// static
+C2InfoBuffer C2InfoBuffer::CreateGraphicBuffer(
+ C2Param::CoreIndex index, const C2ConstGraphicBlock &block) {
+ return C2InfoBuffer(index.coreIndex() | C2Param::Index::KIND_INFO | C2Param::Index::DIR_GLOBAL,
+ { block });
+}
+
class C2Buffer::Impl {
public:
Impl(C2Buffer *thiz, const std::vector<C2ConstLinearBlock> &blocks)