stagefright: MediaCodec buffer API revision
Bug: 136283874
Test: atest CtsMediaTestCases:MediaCodecBlockModelTest
Test: atest CtsMediaTestCases -- --module-arg CtsMediaTestCases:size:small
Change-Id: Idc02c7758da8b266099a4134b438e4478c38f912
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 5c572e1..39263f9 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -48,6 +48,7 @@
#include "C2OMXNode.h"
#include "CCodecBufferChannel.h"
#include "CCodecConfig.h"
+#include "Codec2Mapper.h"
#include "InputSurfaceWrapper.h"
extern "C" android::PersistentSurface *CreateInputSurface();
@@ -717,6 +718,11 @@
encoder = false;
}
+ int32_t flags;
+ if (!msg->findInt32("flags", &flags)) {
+ return BAD_VALUE;
+ }
+
// TODO: read from intf()
if ((!encoder) != (comp->getName().find("encoder") == std::string::npos)) {
return UNKNOWN_ERROR;
@@ -743,6 +749,9 @@
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
config->mUsingSurface = surface != nullptr;
+ config->mBuffersBoundToCodec = ((flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) == 0);
+ ALOGD("[%s] buffers are %sbound to CCodec for this session",
+ comp->getName().c_str(), config->mBuffersBoundToCodec ? "" : "not ");
// Enforce required parameters
int32_t i32;
@@ -1299,6 +1308,7 @@
sp<AMessage> inputFormat;
sp<AMessage> outputFormat;
status_t err2 = OK;
+ bool buffersBoundToCodec = false;
{
Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
const std::unique_ptr<Config> &config = *configLocked;
@@ -1307,12 +1317,13 @@
if (config->mInputSurface) {
err2 = config->mInputSurface->start();
}
+ buffersBoundToCodec = config->mBuffersBoundToCodec;
}
if (err2 != OK) {
mCallback->onError(err2, ACTION_CODE_FATAL);
return;
}
- err2 = mChannel->start(inputFormat, outputFormat);
+ err2 = mChannel->start(inputFormat, outputFormat, buffersBoundToCodec);
if (err2 != OK) {
mCallback->onError(err2, ACTION_CODE_FATAL);
return;
@@ -1556,7 +1567,11 @@
return;
}
- (void)mChannel->start(nullptr, nullptr);
+ (void)mChannel->start(nullptr, nullptr, [&]{
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ return config->mBuffersBoundToCodec;
+ }());
{
Mutexed<State>::Locked state(mState);
@@ -1911,5 +1926,243 @@
inputSurface->getHalInterface()));
}
+static status_t GetCommonAllocatorIds(
+ const std::vector<std::string> &names,
+ C2Allocator::type_t type,
+ std::set<C2Allocator::id_t> *ids) {
+ int poolMask = GetCodec2PoolMask();
+ C2PlatformAllocatorStore::id_t preferredLinearId = GetPreferredLinearAllocatorId(poolMask);
+ C2Allocator::id_t defaultAllocatorId =
+ (type == C2Allocator::LINEAR) ? preferredLinearId : C2PlatformAllocatorStore::GRALLOC;
+
+ ids->clear();
+ if (names.empty()) {
+ return OK;
+ }
+ std::shared_ptr<Codec2Client::Interface> intf{
+ Codec2Client::CreateInterfaceByName(names[0].c_str())};
+ std::vector<std::unique_ptr<C2Param>> params;
+ c2_status_t err = intf->query(
+ {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, ¶ms);
+ if (err == C2_OK && params.size() == 1u) {
+ C2PortAllocatorsTuning::input *allocators =
+ C2PortAllocatorsTuning::input::From(params[0].get());
+ if (allocators && allocators->flexCount() > 0) {
+ ids->insert(allocators->m.values, allocators->m.values + allocators->flexCount());
+ }
+ }
+ if (ids->empty()) {
+ // The component does not advertise allocators. Use default.
+ ids->insert(defaultAllocatorId);
+ }
+ for (size_t i = 1; i < names.size(); ++i) {
+ intf = Codec2Client::CreateInterfaceByName(names[i].c_str());
+ err = intf->query(
+ {}, {C2PortAllocatorsTuning::input::PARAM_TYPE}, C2_MAY_BLOCK, ¶ms);
+ bool filtered = false;
+ if (err == C2_OK && params.size() == 1u) {
+ C2PortAllocatorsTuning::input *allocators =
+ C2PortAllocatorsTuning::input::From(params[0].get());
+ if (allocators && allocators->flexCount() > 0) {
+ filtered = true;
+ for (auto it = ids->begin(); it != ids->end(); ) {
+ bool found = false;
+ for (size_t j = 0; j < allocators->flexCount(); ++j) {
+ if (allocators->m.values[j] == *it) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ ++it;
+ } else {
+ it = ids->erase(it);
+ }
+ }
+ }
+ }
+ if (!filtered) {
+ // The component does not advertise supported allocators. Use default.
+ bool containsDefault = (ids->count(defaultAllocatorId) > 0u);
+ if (ids->size() != (containsDefault ? 1 : 0)) {
+ ids->clear();
+ if (containsDefault) {
+ ids->insert(defaultAllocatorId);
+ }
+ }
+ }
+ }
+ // Finally, filter with pool masks
+ for (auto it = ids->begin(); it != ids->end(); ) {
+ if ((poolMask >> *it) & 1) {
+ ++it;
+ } else {
+ it = ids->erase(it);
+ }
+ }
+ return OK;
+}
+
+static status_t CalculateMinMaxUsage(
+ const std::vector<std::string> &names, uint64_t *minUsage, uint64_t *maxUsage) {
+ static C2StreamUsageTuning::input sUsage{0u /* stream id */};
+ *minUsage = 0;
+ *maxUsage = ~0ull;
+ for (const std::string &name : names) {
+ std::shared_ptr<Codec2Client::Interface> intf{
+ Codec2Client::CreateInterfaceByName(name.c_str())};
+ std::vector<C2FieldSupportedValuesQuery> fields;
+ fields.push_back(C2FieldSupportedValuesQuery::Possible(
+ C2ParamField{&sUsage, &sUsage.value}));
+ c2_status_t err = intf->querySupportedValues(fields, C2_MAY_BLOCK);
+ if (err != C2_OK) {
+ continue;
+ }
+ if (fields[0].status != C2_OK) {
+ continue;
+ }
+ const C2FieldSupportedValues &supported = fields[0].values;
+ if (supported.type != C2FieldSupportedValues::FLAGS) {
+ continue;
+ }
+ if (supported.values.empty()) {
+ *maxUsage = 0;
+ continue;
+ }
+ *minUsage |= supported.values[0].u64;
+ int64_t currentMaxUsage = 0;
+ for (const C2Value::Primitive &flags : supported.values) {
+ currentMaxUsage |= flags.u64;
+ }
+ *maxUsage &= currentMaxUsage;
+ }
+ return OK;
+}
+
+// static
+status_t CCodec::CanFetchLinearBlock(
+ const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible) {
+ uint64_t minUsage = usage.expected;
+ uint64_t maxUsage = ~0ull;
+ std::set<C2Allocator::id_t> allocators;
+ GetCommonAllocatorIds(names, C2Allocator::LINEAR, &allocators);
+ if (allocators.empty()) {
+ *isCompatible = false;
+ return OK;
+ }
+ CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+ *isCompatible = ((maxUsage & minUsage) == minUsage);
+ return OK;
+}
+
+static std::shared_ptr<C2BlockPool> GetPool(C2Allocator::id_t allocId) {
+ static std::mutex sMutex{};
+ static std::map<C2Allocator::id_t, std::shared_ptr<C2BlockPool>> sPools;
+ std::unique_lock<std::mutex> lock{sMutex};
+ std::shared_ptr<C2BlockPool> pool;
+ auto it = sPools.find(allocId);
+ if (it == sPools.end()) {
+ c2_status_t err = CreateCodec2BlockPool(allocId, nullptr, &pool);
+ if (err == OK) {
+ sPools.emplace(allocId, pool);
+ } else {
+ pool.reset();
+ }
+ } else {
+ pool = it->second;
+ }
+ return pool;
+}
+
+// static
+std::shared_ptr<C2LinearBlock> CCodec::FetchLinearBlock(
+ size_t capacity, const C2MemoryUsage &usage, const std::vector<std::string> &names) {
+ uint64_t minUsage = usage.expected;
+ uint64_t maxUsage = ~0ull;
+ std::set<C2Allocator::id_t> allocators;
+ GetCommonAllocatorIds(names, C2Allocator::LINEAR, &allocators);
+ if (allocators.empty()) {
+ allocators.insert(C2PlatformAllocatorStore::DEFAULT_LINEAR);
+ }
+ CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+ if ((maxUsage & minUsage) != minUsage) {
+ allocators.clear();
+ allocators.insert(C2PlatformAllocatorStore::DEFAULT_LINEAR);
+ }
+ std::shared_ptr<C2LinearBlock> block;
+ for (C2Allocator::id_t allocId : allocators) {
+ std::shared_ptr<C2BlockPool> pool = GetPool(allocId);
+ if (!pool) {
+ continue;
+ }
+ c2_status_t err = pool->fetchLinearBlock(capacity, C2MemoryUsage{minUsage}, &block);
+ if (err != C2_OK || !block) {
+ block.reset();
+ continue;
+ }
+ break;
+ }
+ return block;
+}
+
+// static
+status_t CCodec::CanFetchGraphicBlock(
+ const std::vector<std::string> &names, bool *isCompatible) {
+ uint64_t minUsage = 0;
+ uint64_t maxUsage = ~0ull;
+ std::set<C2Allocator::id_t> allocators;
+ GetCommonAllocatorIds(names, C2Allocator::GRAPHIC, &allocators);
+ if (allocators.empty()) {
+ *isCompatible = false;
+ return OK;
+ }
+ CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+ *isCompatible = ((maxUsage & minUsage) == minUsage);
+ return OK;
+}
+
+// static
+std::shared_ptr<C2GraphicBlock> CCodec::FetchGraphicBlock(
+ int32_t width,
+ int32_t height,
+ int32_t format,
+ uint64_t usage,
+ const std::vector<std::string> &names) {
+ uint32_t halPixelFormat = HAL_PIXEL_FORMAT_YCBCR_420_888;
+ if (!C2Mapper::mapPixelFormatFrameworkToCodec(format, &halPixelFormat)) {
+ ALOGD("Unrecognized pixel format: %d", format);
+ return nullptr;
+ }
+ uint64_t minUsage = 0;
+ uint64_t maxUsage = ~0ull;
+ std::set<C2Allocator::id_t> allocators;
+ GetCommonAllocatorIds(names, C2Allocator::GRAPHIC, &allocators);
+ if (allocators.empty()) {
+ allocators.insert(C2PlatformAllocatorStore::DEFAULT_GRAPHIC);
+ }
+ CalculateMinMaxUsage(names, &minUsage, &maxUsage);
+ minUsage |= usage;
+ if ((maxUsage & minUsage) != minUsage) {
+ allocators.clear();
+ allocators.insert(C2PlatformAllocatorStore::DEFAULT_GRAPHIC);
+ }
+ std::shared_ptr<C2GraphicBlock> block;
+ for (C2Allocator::id_t allocId : allocators) {
+ std::shared_ptr<C2BlockPool> pool;
+ c2_status_t err = CreateCodec2BlockPool(allocId, nullptr, &pool);
+ if (err != C2_OK || !pool) {
+ continue;
+ }
+ err = pool->fetchGraphicBlock(
+ width, height, halPixelFormat, C2MemoryUsage{minUsage}, &block);
+ if (err != C2_OK || !block) {
+ block.reset();
+ continue;
+ }
+ break;
+ }
+ return block;
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3218491..ae95336 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -29,6 +29,7 @@
#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <android/hardware/drm/1.0/types.h>
#include <android-base/stringprintf.h>
+#include <binder/MemoryBase.h>
#include <binder/MemoryDealer.h>
#include <cutils/properties.h>
#include <gui/Surface.h>
@@ -249,7 +250,7 @@
}
CCodecBufferChannel::~CCodecBufferChannel() {
- if (mCrypto != nullptr && mDealer != nullptr && mHeapSeqNum >= 0) {
+ if (mCrypto != nullptr && mHeapSeqNum >= 0) {
mCrypto->unsetHeap(mHeapSeqNum);
}
}
@@ -409,6 +410,173 @@
return OK;
}
+status_t CCodecBufferChannel::attachBuffer(
+ const std::shared_ptr<C2Buffer> &c2Buffer,
+ const sp<MediaCodecBuffer> &buffer) {
+ if (!buffer->copy(c2Buffer)) {
+ return -ENOSYS;
+ }
+ return OK;
+}
+
+void CCodecBufferChannel::ensureDecryptDestination(size_t size) {
+ if (!mDecryptDestination || mDecryptDestination->size() < size) {
+ sp<IMemoryHeap> heap{new MemoryHeapBase(size * 2)};
+ if (mDecryptDestination && mCrypto && mHeapSeqNum >= 0) {
+ mCrypto->unsetHeap(mHeapSeqNum);
+ }
+ mDecryptDestination = new MemoryBase(heap, 0, size * 2);
+ if (mCrypto) {
+ mHeapSeqNum = mCrypto->setHeap(hardware::fromHeap(heap));
+ }
+ }
+}
+
+int32_t CCodecBufferChannel::getHeapSeqNum(const sp<HidlMemory> &memory) {
+ CHECK(mCrypto);
+ auto it = mHeapSeqNumMap.find(memory);
+ int32_t heapSeqNum = -1;
+ if (it == mHeapSeqNumMap.end()) {
+ heapSeqNum = mCrypto->setHeap(memory);
+ mHeapSeqNumMap.emplace(memory, heapSeqNum);
+ } else {
+ heapSeqNum = it->second;
+ }
+ return heapSeqNum;
+}
+
+status_t CCodecBufferChannel::attachEncryptedBuffer(
+ const sp<hardware::HidlMemory> &memory,
+ bool secure,
+ const uint8_t *key,
+ const uint8_t *iv,
+ CryptoPlugin::Mode mode,
+ CryptoPlugin::Pattern pattern,
+ size_t offset,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ const sp<MediaCodecBuffer> &buffer) {
+ static const C2MemoryUsage kSecureUsage{C2MemoryUsage::READ_PROTECTED, 0};
+ static const C2MemoryUsage kDefaultReadWriteUsage{
+ C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+ size_t size = 0;
+ for (size_t i = 0; i < numSubSamples; ++i) {
+ size += subSamples[i].mNumBytesOfClearData + subSamples[i].mNumBytesOfEncryptedData;
+ }
+ std::shared_ptr<C2BlockPool> pool = mBlockPools.lock()->inputPool;
+ std::shared_ptr<C2LinearBlock> block;
+ c2_status_t err = pool->fetchLinearBlock(
+ size,
+ secure ? kSecureUsage : kDefaultReadWriteUsage,
+ &block);
+ if (err != C2_OK) {
+ return NO_MEMORY;
+ }
+ if (!secure) {
+ ensureDecryptDestination(size);
+ }
+ ssize_t result = -1;
+ ssize_t codecDataOffset = 0;
+ if (mCrypto) {
+ AString errorDetailMsg;
+ int32_t heapSeqNum = getHeapSeqNum(memory);
+ hardware::drm::V1_0::SharedBuffer src{(uint32_t)heapSeqNum, offset, size};
+ hardware::drm::V1_0::DestinationBuffer dst;
+ if (secure) {
+ dst.type = DrmBufferType::NATIVE_HANDLE;
+ dst.secureMemory = hardware::hidl_handle(block->handle());
+ } else {
+ dst.type = DrmBufferType::SHARED_MEMORY;
+ IMemoryToSharedBuffer(
+ mDecryptDestination, mHeapSeqNum, &dst.nonsecureMemory);
+ }
+ result = mCrypto->decrypt(
+ key, iv, mode, pattern, src, 0, subSamples, numSubSamples,
+ dst, &errorDetailMsg);
+ if (result < 0) {
+ return result;
+ }
+ if (dst.type == DrmBufferType::SHARED_MEMORY) {
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ return false;
+ }
+ if (view.size() < result) {
+ return false;
+ }
+ memcpy(view.data(), mDecryptDestination->unsecurePointer(), result);
+ }
+ } else {
+ // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
+ // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
+ hidl_vec<SubSample> hidlSubSamples;
+ hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
+
+ hardware::cas::native::V1_0::SharedBuffer src{*memory, offset, size};
+ hardware::cas::native::V1_0::DestinationBuffer dst;
+ if (secure) {
+ dst.type = BufferType::NATIVE_HANDLE;
+ dst.secureMemory = hardware::hidl_handle(block->handle());
+ } else {
+ dst.type = BufferType::SHARED_MEMORY;
+ dst.nonsecureMemory = src;
+ }
+
+ CasStatus status = CasStatus::OK;
+ hidl_string detailedError;
+ ScramblingControl sctrl = ScramblingControl::UNSCRAMBLED;
+
+ if (key != nullptr) {
+ sctrl = (ScramblingControl)key[0];
+ // Adjust for the PES offset
+ codecDataOffset = key[2] | (key[3] << 8);
+ }
+
+ auto returnVoid = mDescrambler->descramble(
+ sctrl,
+ hidlSubSamples,
+ src,
+ 0,
+ dst,
+ 0,
+ [&status, &result, &detailedError] (
+ CasStatus _status, uint32_t _bytesWritten,
+ const hidl_string& _detailedError) {
+ status = _status;
+ result = (ssize_t)_bytesWritten;
+ detailedError = _detailedError;
+ });
+
+ if (!returnVoid.isOk() || status != CasStatus::OK || result < 0) {
+ ALOGI("[%s] descramble failed, trans=%s, status=%d, result=%zd",
+ mName, returnVoid.description().c_str(), status, result);
+ return UNKNOWN_ERROR;
+ }
+
+ if (result < codecDataOffset) {
+ ALOGD("invalid codec data offset: %zd, result %zd", codecDataOffset, result);
+ return BAD_VALUE;
+ }
+ }
+ if (!secure) {
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ return UNKNOWN_ERROR;
+ }
+ if (view.size() < result) {
+ return UNKNOWN_ERROR;
+ }
+ memcpy(view.data(), mDecryptDestination->unsecurePointer(), result);
+ }
+ std::shared_ptr<C2Buffer> c2Buffer{C2Buffer::CreateLinearBuffer(
+ block->share(codecDataOffset, result - codecDataOffset, C2Fence{}))};
+ if (!buffer->copy(c2Buffer)) {
+ return -ENOSYS;
+ }
+ return OK;
+}
+
status_t CCodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffer) {
QueueGuard guard(mSync);
if (!guard.isRunning()) {
@@ -774,7 +942,9 @@
}
status_t CCodecBufferChannel::start(
- const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat) {
+ const sp<AMessage> &inputFormat,
+ const sp<AMessage> &outputFormat,
+ bool buffersBoundToCodec) {
C2StreamBufferTypeSetting::input iStreamFormat(0u);
C2StreamBufferTypeSetting::output oStreamFormat(0u);
C2PortReorderBufferDepthTuning::output reorderDepth;
@@ -897,7 +1067,9 @@
input->numSlots = numInputSlots;
input->extraBuffers.flush();
input->numExtraSlots = 0u;
- if (graphic) {
+ if (!buffersBoundToCodec) {
+ input->buffers.reset(new SlotInputBuffers(mName));
+ } else if (graphic) {
if (mInputSurface) {
input->buffers.reset(new DummyInputBuffers(mName));
} else if (mMetaMode == MODE_ANW) {
@@ -1071,7 +1243,7 @@
output->outputDelay = outputDelayValue;
output->numSlots = numOutputSlots;
if (graphic) {
- if (outputSurface) {
+ if (outputSurface || !buffersBoundToCodec) {
output->buffers.reset(new GraphicOutputBuffers(mName));
} else {
output->buffers.reset(new RawGraphicOutputBuffers(numOutputSlots, mName));
@@ -1669,6 +1841,16 @@
}
void CCodecBufferChannel::setCrypto(const sp<ICrypto> &crypto) {
+ if (mCrypto != nullptr) {
+ for (std::pair<wp<HidlMemory>, int32_t> entry : mHeapSeqNumMap) {
+ mCrypto->unsetHeap(entry.second);
+ }
+ mHeapSeqNumMap.clear();
+ if (mHeapSeqNum >= 0) {
+ mCrypto->unsetHeap(mHeapSeqNum);
+ mHeapSeqNum = -1;
+ }
+ }
mCrypto = crypto;
}
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 82fec18..0263211 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -70,6 +70,20 @@
const CryptoPlugin::SubSample *subSamples,
size_t numSubSamples,
AString *errorDetailMsg) override;
+ virtual status_t attachBuffer(
+ const std::shared_ptr<C2Buffer> &c2Buffer,
+ const sp<MediaCodecBuffer> &buffer) override;
+ virtual status_t attachEncryptedBuffer(
+ const sp<hardware::HidlMemory> &memory,
+ bool secure,
+ const uint8_t *key,
+ const uint8_t *iv,
+ CryptoPlugin::Mode mode,
+ CryptoPlugin::Pattern pattern,
+ size_t offset,
+ const CryptoPlugin::SubSample *subSamples,
+ size_t numSubSamples,
+ const sp<MediaCodecBuffer> &buffer) override;
virtual status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
@@ -108,7 +122,10 @@
* Start queueing buffers to the component. This object should never queue
* buffers before this call has completed.
*/
- status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat);
+ status_t start(
+ const sp<AMessage> &inputFormat,
+ const sp<AMessage> &outputFormat,
+ bool buffersBoundToCodec);
/**
* Request initial input buffers to be filled by client.
@@ -216,11 +233,14 @@
std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
const C2StreamInitDataInfo::output *initData);
void sendOutputBuffers();
+ void ensureDecryptDestination(size_t size);
+ int32_t getHeapSeqNum(const sp<hardware::HidlMemory> &memory);
QueueSync mSync;
sp<MemoryDealer> mDealer;
sp<IMemory> mDecryptDestination;
int32_t mHeapSeqNum;
+ std::map<wp<hardware::HidlMemory>, int32_t> mHeapSeqNumMap;
std::shared_ptr<Codec2Client::Component> mComponent;
std::string mComponentName; ///< component name for debugging
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index 2a04810..265eeb7 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -494,6 +494,44 @@
return mAllocate();
}
+// SlotInputBuffers
+
+bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
+ sp<Codec2Buffer> newBuffer = createNewBuffer();
+ *index = mImpl.assignSlot(newBuffer);
+ *buffer = newBuffer;
+ return true;
+}
+
+bool SlotInputBuffers::releaseBuffer(
+ const sp<MediaCodecBuffer> &buffer,
+ std::shared_ptr<C2Buffer> *c2buffer,
+ bool release) {
+ return mImpl.releaseSlot(buffer, c2buffer, release);
+}
+
+bool SlotInputBuffers::expireComponentBuffer(
+ const std::shared_ptr<C2Buffer> &c2buffer) {
+ return mImpl.expireComponentBuffer(c2buffer);
+}
+
+void SlotInputBuffers::flush() {
+ mImpl.flush();
+}
+
+std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
+ TRESPASS("Array mode should not be called at non-legacy mode");
+ return nullptr;
+}
+
+size_t SlotInputBuffers::numClientBuffers() const {
+ return mImpl.numClientBuffers();
+}
+
+sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
+ return new DummyContainerBuffer{mFormat, nullptr};
+}
+
// LinearInputBuffers
bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index ad972ce..bae08e0 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -547,6 +547,36 @@
std::function<sp<Codec2Buffer>()> mAllocate;
};
+class SlotInputBuffers : public InputBuffers {
+public:
+ SlotInputBuffers(const char *componentName, const char *name = "Slot-Input")
+ : InputBuffers(componentName, name),
+ mImpl(mName) { }
+ ~SlotInputBuffers() override = default;
+
+ bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) final;
+
+ bool releaseBuffer(
+ const sp<MediaCodecBuffer> &buffer,
+ std::shared_ptr<C2Buffer> *c2buffer,
+ bool release) final;
+
+ bool expireComponentBuffer(
+ const std::shared_ptr<C2Buffer> &c2buffer) final;
+
+ void flush() final;
+
+ std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
+
+ size_t numClientBuffers() const final;
+
+protected:
+ sp<Codec2Buffer> createNewBuffer() final;
+
+private:
+ FlexBuffersImpl mImpl;
+};
+
class LinearInputBuffers : public InputBuffers {
public:
LinearInputBuffers(const char *componentName, const char *name = "1D-Input")
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index ee3cdf6..d2f5ea7 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -595,34 +595,18 @@
.withMappers([](C2Value v) -> C2Value {
int32_t value;
if (v.get(&value)) {
- switch (value) {
- case COLOR_FormatSurface:
- return (uint32_t)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- case COLOR_FormatYUV420Flexible:
- return (uint32_t)HAL_PIXEL_FORMAT_YCBCR_420_888;
- case COLOR_FormatYUV420Planar:
- case COLOR_FormatYUV420SemiPlanar:
- case COLOR_FormatYUV420PackedPlanar:
- case COLOR_FormatYUV420PackedSemiPlanar:
- return (uint32_t)HAL_PIXEL_FORMAT_YV12;
- default:
- // TODO: support some sort of passthrough
- break;
+ uint32_t result;
+ if (C2Mapper::mapPixelFormatFrameworkToCodec(value, &result)) {
+ return result;
}
}
return C2Value();
}, [](C2Value v) -> C2Value {
uint32_t value;
if (v.get(&value)) {
- switch (value) {
- case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
- return COLOR_FormatSurface;
- case HAL_PIXEL_FORMAT_YV12:
- case HAL_PIXEL_FORMAT_YCBCR_420_888:
- return COLOR_FormatYUV420Flexible;
- default:
- // TODO: support some sort of passthrough
- break;
+ int32_t result;
+ if (C2Mapper::mapPixelFormatCodecToFramework(value, &result)) {
+ return result;
}
}
return C2Value();
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index a61c8b7..093bfdd 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -118,6 +118,7 @@
sp<AMessage> mOutputFormat;
bool mUsingSurface; ///< using input or output surface
+ bool mBuffersBoundToCodec; ///< whether buffers are bound to codecs or not.
std::shared_ptr<InputSurfaceWrapper> mInputSurface;
std::unique_ptr<InputSurfaceWrapper::Config> mISConfig;
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 9291c52..09475ef 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -57,36 +57,6 @@
using MediaCodecBuffer::MediaCodecBuffer;
~Codec2Buffer() override = default;
- /**
- * \return C2Buffer object represents this buffer.
- */
- virtual std::shared_ptr<C2Buffer> asC2Buffer() = 0;
-
- /**
- * Test if we can copy the content of |buffer| into this object.
- *
- * \param buffer C2Buffer object to copy.
- * \return true if the content of buffer can be copied over to this buffer
- * false otherwise.
- */
- virtual bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
- (void)buffer;
- return false;
- }
-
- /**
- * Copy the content of |buffer| into this object. This method assumes that
- * canCopy() check already passed.
- *
- * \param buffer C2Buffer object to copy.
- * \return true if successful
- * false otherwise.
- */
- virtual bool copy(const std::shared_ptr<C2Buffer> &buffer) {
- (void)buffer;
- return false;
- }
-
sp<ABuffer> getImageData() const { return mImageData; }
protected:
diff --git a/media/codec2/sfplugin/include/media/stagefright/CCodec.h b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
index 30dc945..6ff2c4a 100644
--- a/media/codec2/sfplugin/include/media/stagefright/CCodec.h
+++ b/media/codec2/sfplugin/include/media/stagefright/CCodec.h
@@ -70,6 +70,22 @@
static PersistentSurface *CreateInputSurface();
+ static status_t CanFetchLinearBlock(
+ const std::vector<std::string> &names, const C2MemoryUsage &usage, bool *isCompatible);
+
+ static std::shared_ptr<C2LinearBlock> FetchLinearBlock(
+ size_t capacity, const C2MemoryUsage &usage, const std::vector<std::string> &names);
+
+ static status_t CanFetchGraphicBlock(
+ const std::vector<std::string> &names, bool *isCompatible);
+
+ static std::shared_ptr<C2GraphicBlock> FetchGraphicBlock(
+ int32_t width,
+ int32_t height,
+ int32_t format,
+ uint64_t usage,
+ const std::vector<std::string> &names);
+
protected:
virtual ~CCodec();
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 2f3d688..903db6c 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -949,3 +949,41 @@
bool C2Mapper::map(ColorAspects::Transfer from, C2Color::transfer_t *to) {
return sColorTransfersSf.map(from, to);
}
+
+// static
+bool C2Mapper::mapPixelFormatFrameworkToCodec(
+ int32_t frameworkValue, uint32_t *c2Value) {
+ switch (frameworkValue) {
+ case COLOR_FormatSurface:
+ *c2Value = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ return true;
+ case COLOR_FormatYUV420Flexible:
+ *c2Value = HAL_PIXEL_FORMAT_YCBCR_420_888;
+ return true;
+ case COLOR_FormatYUV420Planar:
+ case COLOR_FormatYUV420SemiPlanar:
+ case COLOR_FormatYUV420PackedPlanar:
+ case COLOR_FormatYUV420PackedSemiPlanar:
+ *c2Value = HAL_PIXEL_FORMAT_YV12;
+ return true;
+ default:
+ // TODO: support some sort of passthrough
+ return false;
+ }
+}
+
+// static
+bool C2Mapper::mapPixelFormatCodecToFramework(
+ uint32_t c2Value, int32_t *frameworkValue) {
+ switch (c2Value) {
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ *frameworkValue = COLOR_FormatSurface;
+ return true;
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCBCR_420_888:
+ *frameworkValue = COLOR_FormatYUV420Flexible;
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.h b/media/codec2/sfplugin/utils/Codec2Mapper.h
index cec6f07..797c8a8 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.h
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.h
@@ -75,6 +75,11 @@
static bool map(ColorAspects::MatrixCoeffs, C2Color::matrix_t*);
static bool map(C2Color::transfer_t, ColorAspects::Transfer*);
static bool map(ColorAspects::Transfer, C2Color::transfer_t*);
+
+ static bool mapPixelFormatFrameworkToCodec(
+ int32_t frameworkValue, uint32_t *c2Value);
+ static bool mapPixelFormatCodecToFramework(
+ uint32_t c2Value, int32_t *frameworkValue);
};
}