Codec2: move allocators into their own files
Bug: 64121714
Test: unittest
Change-Id: Ic7fd9f1f186e2ad9130935060bd560b861e3271b
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index 18d0841..a185880 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -16,6 +16,8 @@
#include <gtest/gtest.h>
+#include <C2AllocatorIon.h>
+#include <C2AllocatorGralloc.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2ParamDef.h>
diff --git a/media/libstagefright/codec2/vndk/Android.bp b/media/libstagefright/codec2/vndk/Android.bp
index 66f31cb..93bcb3a 100644
--- a/media/libstagefright/codec2/vndk/Android.bp
+++ b/media/libstagefright/codec2/vndk/Android.bp
@@ -2,6 +2,8 @@
name: "libstagefright_codec2_vndk",
srcs: [
+ "C2AllocatorIon.cpp",
+ "C2AllocatorGralloc.cpp",
"C2Buffer.cpp",
"C2Config.cpp",
],
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
new file mode 100644
index 0000000..16b818b
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/C2AllocatorGralloc.cpp
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2016 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 "C2AllocatorIon"
+#include <utils/Log.h>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <hardware/gralloc.h>
+
+#include <C2AllocatorGralloc.h>
+#include <C2Buffer.h>
+
+namespace android {
+
+using ::android::hardware::graphics::allocator::V2_0::IAllocator;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using ::android::hardware::graphics::mapper::V2_0::Error;
+using ::android::hardware::graphics::mapper::V2_0::IMapper;
+using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_vec;
+
+/* ===================================== GRALLOC ALLOCATION ==================================== */
+static C2Error maperr2error(Error maperr) {
+ switch (maperr) {
+ case Error::NONE: return C2_OK;
+ case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
+ case Error::BAD_BUFFER: return C2_BAD_VALUE;
+ case Error::BAD_VALUE: return C2_BAD_VALUE;
+ case Error::NO_RESOURCES: return C2_NO_MEMORY;
+ case Error::UNSUPPORTED: return C2_UNSUPPORTED;
+ }
+ return C2_CORRUPTED;
+}
+
+class C2AllocationGralloc : public C2GraphicAllocation {
+public:
+ virtual ~C2AllocationGralloc();
+
+ virtual C2Error map(
+ C2Rect rect, C2MemoryUsage usage, int *fenceFd,
+ C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
+ virtual C2Error unmap(C2Fence *fenceFd /* nullable */) override;
+ virtual bool isValid() const override { return true; }
+ virtual const C2Handle *handle() const override { return mHandle; }
+ virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
+
+ // internal methods
+ // |handle| will be moved.
+ C2AllocationGralloc(
+ const IMapper::BufferDescriptorInfo &info,
+ const sp<IMapper> &mapper,
+ hidl_handle &handle);
+ int dup() const;
+ C2Error status() const;
+
+private:
+ const IMapper::BufferDescriptorInfo mInfo;
+ const sp<IMapper> mMapper;
+ const hidl_handle mHandle;
+ buffer_handle_t mBuffer;
+ bool mLocked;
+};
+
+C2AllocationGralloc::C2AllocationGralloc(
+ const IMapper::BufferDescriptorInfo &info,
+ const sp<IMapper> &mapper,
+ hidl_handle &handle)
+ : C2GraphicAllocation(info.width, info.height),
+ mInfo(info),
+ mMapper(mapper),
+ mHandle(std::move(handle)),
+ mBuffer(nullptr),
+ mLocked(false) {}
+
+C2AllocationGralloc::~C2AllocationGralloc() {
+ if (!mBuffer) {
+ return;
+ }
+ if (mLocked) {
+ unmap(nullptr);
+ }
+ mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
+}
+
+C2Error C2AllocationGralloc::map(
+ C2Rect rect, C2MemoryUsage usage, int *fenceFd,
+ C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
+ // TODO
+ (void) fenceFd;
+ (void) usage;
+
+ if (mBuffer && mLocked) {
+ return C2_DUPLICATE;
+ }
+ if (!layout || !addr) {
+ return C2_BAD_VALUE;
+ }
+
+ C2Error err = C2_OK;
+ if (!mBuffer) {
+ mMapper->importBuffer(
+ mHandle, [&err, this](const auto &maperr, const auto &buffer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ mBuffer = static_cast<buffer_handle_t>(buffer);
+ }
+ });
+ if (err != C2_OK) {
+ return err;
+ }
+ }
+
+ if (mInfo.format == PixelFormat::YCBCR_420_888 || mInfo.format == PixelFormat::YV12) {
+ YCbCrLayout ycbcrLayout;
+ mMapper->lockYCbCr(
+ const_cast<native_handle_t *>(mBuffer),
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
+ { (int32_t)rect.mLeft, (int32_t)rect.mTop, (int32_t)rect.mWidth, (int32_t)rect.mHeight },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ ycbcrLayout = mapLayout;
+ }
+ });
+ if (err != C2_OK) {
+ return err;
+ }
+ addr[C2PlaneLayout::Y] = (uint8_t *)ycbcrLayout.y;
+ addr[C2PlaneLayout::U] = (uint8_t *)ycbcrLayout.cb;
+ addr[C2PlaneLayout::V] = (uint8_t *)ycbcrLayout.cr;
+ layout->mType = C2PlaneLayout::MEDIA_IMAGE_TYPE_YUV;
+ layout->mNumPlanes = 3;
+ layout->mPlanes[C2PlaneLayout::Y] = {
+ C2PlaneInfo::Y, // mChannel
+ 1, // mColInc
+ (int32_t)ycbcrLayout.yStride, // mRowInc
+ 1, // mHorizSubsampling
+ 1, // mVertSubsampling
+ 8, // mBitDepth
+ 8, // mAllocatedDepth
+ };
+ layout->mPlanes[C2PlaneLayout::U] = {
+ C2PlaneInfo::Cb, // mChannel
+ (int32_t)ycbcrLayout.chromaStep, // mColInc
+ (int32_t)ycbcrLayout.cStride, // mRowInc
+ 2, // mHorizSubsampling
+ 2, // mVertSubsampling
+ 8, // mBitDepth
+ 8, // mAllocatedDepth
+ };
+ layout->mPlanes[C2PlaneLayout::V] = {
+ C2PlaneInfo::Cr, // mChannel
+ (int32_t)ycbcrLayout.chromaStep, // mColInc
+ (int32_t)ycbcrLayout.cStride, // mRowInc
+ 2, // mHorizSubsampling
+ 2, // mVertSubsampling
+ 8, // mBitDepth
+ 8, // mAllocatedDepth
+ };
+ } else {
+ void *pointer = nullptr;
+ mMapper->lock(
+ const_cast<native_handle_t *>(mBuffer),
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
+ { (int32_t)rect.mLeft, (int32_t)rect.mTop, (int32_t)rect.mWidth, (int32_t)rect.mHeight },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ });
+ if (err != C2_OK) {
+ return err;
+ }
+ // TODO
+ return C2_UNSUPPORTED;
+ }
+ mLocked = true;
+
+ return C2_OK;
+}
+
+C2Error C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
+ // TODO: fence
+ C2Error err = C2_OK;
+ mMapper->unlock(
+ const_cast<native_handle_t *>(mBuffer),
+ [&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
+ // TODO
+ (void) fenceFd;
+ (void) releaseFence;
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ // TODO: fence
+ }
+ });
+ if (err == C2_OK) {
+ mLocked = false;
+ }
+ return err;
+}
+
+bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
+ return other && other->handle() == handle();
+}
+
+/* ===================================== GRALLOC ALLOCATOR ==================================== */
+class C2AllocatorGralloc::Impl {
+public:
+ Impl();
+
+ C2Error allocateGraphicBuffer(
+ uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
+ std::shared_ptr<C2GraphicAllocation> *allocation);
+
+ C2Error recreateGraphicBuffer(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *allocation);
+
+ C2Error status() const { return mInit; }
+
+private:
+ C2Error mInit;
+ sp<IAllocator> mAllocator;
+ sp<IMapper> mMapper;
+};
+
+C2AllocatorGralloc::Impl::Impl() : mInit(C2_OK) {
+ // TODO: share a global service
+ mAllocator = IAllocator::getService();
+ mMapper = IMapper::getService();
+ if (mAllocator == nullptr || mMapper == nullptr) {
+ mInit = C2_CORRUPTED;
+ }
+}
+
+C2Error C2AllocatorGralloc::Impl::allocateGraphicBuffer(
+ uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
+ std::shared_ptr<C2GraphicAllocation> *allocation) {
+ // TODO: buffer usage should be determined according to |usage|
+ (void) usage;
+
+ IMapper::BufferDescriptorInfo info = {
+ width,
+ height,
+ 1u, // layerCount
+ (PixelFormat)format,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
+ };
+ C2Error err = C2_OK;
+ BufferDescriptor desc;
+ mMapper->createDescriptor(
+ info, [&err, &desc](const auto &maperr, const auto &descriptor) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ desc = descriptor;
+ }
+ });
+ if (err != C2_OK) {
+ return err;
+ }
+
+ // IAllocator shares IMapper error codes.
+ hidl_handle buffer;
+ mAllocator->allocate(
+ desc,
+ 1u,
+ [&err, &buffer](const auto &maperr, const auto &stride, auto &buffers) {
+ (void) stride;
+ err = maperr2error(maperr);
+ if (err != C2_OK) {
+ return;
+ }
+ if (buffers.size() != 1u) {
+ err = C2_CORRUPTED;
+ return;
+ }
+ buffer = std::move(buffers[0]);
+ });
+ if (err != C2_OK) {
+ return err;
+ }
+
+ allocation->reset(new C2AllocationGralloc(info, mMapper, buffer));
+ return C2_OK;
+}
+
+C2Error C2AllocatorGralloc::Impl::recreateGraphicBuffer(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *allocation) {
+ (void) handle;
+
+ // TODO: need to figure out BufferDescriptorInfo from the handle.
+ allocation->reset();
+ return C2_UNSUPPORTED;
+}
+
+C2AllocatorGralloc::C2AllocatorGralloc() : mImpl(new Impl) {}
+
+C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
+
+C2Error C2AllocatorGralloc::allocateGraphicBuffer(
+ uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicAllocation> *allocation) {
+ return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
+}
+
+C2Error C2AllocatorGralloc::recreateGraphicBuffer(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *allocation) {
+ return mImpl->recreateGraphicBuffer(handle, allocation);
+}
+
+C2Error C2AllocatorGralloc::status() const {
+ return mImpl->status();
+}
+
+} // namespace android
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
new file mode 100644
index 0000000..7aa7769
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016 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 "C2AllocatorIon"
+#include <utils/Log.h>
+
+#include <ion/ion.h>
+#include <sys/mman.h>
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2ErrnoUtils.h>
+
+namespace android {
+
+/* ========================================= ION HANDLE ======================================== */
+struct C2HandleIon : public C2Handle {
+ C2HandleIon(int ionFd, ion_user_handle_t buffer) : C2Handle(cHeader),
+ mFds{ ionFd, buffer },
+ mInts{ kMagic } { }
+
+ static bool isValid(const C2Handle * const o);
+
+ int ionFd() const { return mFds.mIon; }
+ ion_user_handle_t buffer() const { return mFds.mBuffer; }
+
+ void setBuffer(ion_user_handle_t bufferFd) { mFds.mBuffer = bufferFd; }
+
+protected:
+ struct {
+ int mIon;
+ int mBuffer; // ion_user_handle_t
+ } mFds;
+ struct {
+ int mMagic;
+ } mInts;
+
+private:
+ typedef C2HandleIon _type;
+ enum {
+ kMagic = 'ion1',
+ numFds = sizeof(mFds) / sizeof(int),
+ numInts = sizeof(mInts) / sizeof(int),
+ version = sizeof(C2Handle) + sizeof(mFds) + sizeof(mInts)
+ };
+ //constexpr static C2Handle cHeader = { version, numFds, numInts, {} };
+ const static C2Handle cHeader;
+};
+
+const C2Handle C2HandleIon::cHeader = {
+ C2HandleIon::version,
+ C2HandleIon::numFds,
+ C2HandleIon::numInts,
+ {}
+};
+
+// static
+bool C2HandleIon::isValid(const C2Handle * const o) {
+ if (!o || memcmp(o, &cHeader, sizeof(cHeader))) {
+ return false;
+ }
+ const C2HandleIon *other = static_cast<const C2HandleIon*>(o);
+ return other->mInts.mMagic == kMagic;
+}
+
+// TODO: is the dup of an ion fd identical to ion_share?
+
+/* ======================================= ION ALLOCATION ====================================== */
+class C2AllocationIon : public C2LinearAllocation {
+public:
+ virtual C2Error map(
+ size_t offset, size_t size, C2MemoryUsage usage, int *fence,
+ void **addr /* nonnull */);
+ virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
+ virtual bool isValid() const;
+ virtual ~C2AllocationIon();
+ virtual const C2Handle *handle() const;
+ virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const;
+
+ // internal methods
+ C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
+ C2AllocationIon(int ionFd, size_t size, int shareFd);
+ int dup() const;
+ C2Error status() const;
+
+protected:
+ class Impl;
+ Impl *mImpl;
+};
+
+class C2AllocationIon::Impl {
+public:
+ // NOTE: using constructor here instead of a factory method as we will need the
+ // error value and this simplifies the error handling by the wrapper.
+ Impl(int ionFd, size_t capacity, size_t align, unsigned heapMask, unsigned flags)
+ : mInit(C2_OK),
+ mHandle(ionFd, -1),
+ mMapFd(-1),
+ mCapacity(capacity) {
+ ion_user_handle_t buffer = -1;
+ int ret = ion_alloc(mHandle.ionFd(), mCapacity, align, heapMask, flags, &buffer);
+ if (ret == 0) {
+ mHandle.setBuffer(buffer);
+ } else {
+ mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
+ }
+ }
+
+ Impl(int ionFd, size_t capacity, int shareFd)
+ : mHandle(ionFd, -1),
+ mMapFd(-1),
+ mCapacity(capacity) {
+ ion_user_handle_t buffer;
+ mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
+ if (mInit == 0) {
+ mHandle.setBuffer(buffer);
+ }
+ (void)mCapacity; // TODO
+ }
+
+ C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ (void)fenceFd; // TODO: wait for fence
+ *addr = nullptr;
+ int prot = PROT_NONE;
+ int flags = MAP_PRIVATE;
+ if (usage.mConsumer & GRALLOC_USAGE_SW_READ_MASK) {
+ prot |= PROT_READ;
+ }
+ if (usage.mProducer & GRALLOC_USAGE_SW_WRITE_MASK) {
+ prot |= PROT_WRITE;
+ flags = MAP_SHARED;
+ }
+
+ size_t alignmentBytes = offset % PAGE_SIZE;
+ size_t mapOffset = offset - alignmentBytes;
+ size_t mapSize = size + alignmentBytes;
+
+ C2Error err = C2_OK;
+ if (mMapFd == -1) {
+ int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
+ flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
+ if (ret) {
+ mMapFd = -1;
+ *addr = nullptr;
+ err = c2_map_errno<EINVAL>(-ret);
+ } else {
+ *addr = (uint8_t *)mMapAddr + alignmentBytes;
+ mMapAlignmentBytes = alignmentBytes;
+ mMapSize = mapSize;
+ }
+ } else {
+ mMapAddr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
+ if (mMapAddr == MAP_FAILED) {
+ mMapAddr = *addr = nullptr;
+ err = c2_map_errno<EINVAL>(errno);
+ } else {
+ *addr = (uint8_t *)mMapAddr + alignmentBytes;
+ mMapAlignmentBytes = alignmentBytes;
+ mMapSize = mapSize;
+ }
+ }
+ return err;
+ }
+
+ C2Error unmap(void *addr, size_t size, int *fenceFd) {
+ if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
+ size + mMapAlignmentBytes != mMapSize) {
+ return C2_BAD_VALUE;
+ }
+ int err = munmap(mMapAddr, mMapSize);
+ if (err != 0) {
+ return c2_map_errno<EINVAL>(errno);
+ }
+ if (fenceFd) {
+ *fenceFd = -1;
+ }
+ return C2_OK;
+ }
+
+ ~Impl() {
+ if (mMapFd != -1) {
+ close(mMapFd);
+ mMapFd = -1;
+ }
+
+ (void)ion_free(mHandle.ionFd(), mHandle.buffer());
+ }
+
+ C2Error status() const {
+ return mInit;
+ }
+
+ const C2Handle * handle() const {
+ return &mHandle;
+ }
+
+ int dup() const {
+ int fd = -1;
+ if (mInit != 0 || ion_share(mHandle.ionFd(), mHandle.buffer(), &fd) != 0) {
+ fd = -1;
+ }
+ return fd;
+ }
+
+private:
+ C2Error mInit;
+ C2HandleIon mHandle;
+ int mMapFd; // only one for now
+ void *mMapAddr;
+ size_t mMapAlignmentBytes;
+ size_t mMapSize;
+ size_t mCapacity;
+};
+
+C2Error C2AllocationIon::map(
+ size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
+ return mImpl->map(offset, size, usage, fenceFd, addr);
+}
+
+C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
+ return mImpl->unmap(addr, size, fenceFd);
+}
+
+bool C2AllocationIon::isValid() const {
+ return mImpl->status() == C2_OK;
+}
+
+C2Error C2AllocationIon::status() const {
+ return mImpl->status();
+}
+
+bool C2AllocationIon::equals(const std::shared_ptr<C2LinearAllocation> &other) const {
+ return other != nullptr &&
+ other->handle(); // TODO
+}
+
+const C2Handle *C2AllocationIon::handle() const {
+ return mImpl->handle();
+}
+
+C2AllocationIon::~C2AllocationIon() {
+ delete mImpl;
+}
+
+C2AllocationIon::C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags)
+ : C2LinearAllocation(size),
+ mImpl(new Impl(ionFd, size, align, heapMask, flags)) { }
+
+C2AllocationIon::C2AllocationIon(int ionFd, size_t size, int shareFd)
+ : C2LinearAllocation(size),
+ mImpl(new Impl(ionFd, size, shareFd)) { }
+
+int C2AllocationIon::dup() const {
+ return mImpl->dup();
+}
+
+/* ======================================= ION ALLOCATOR ====================================== */
+C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
+ if (mIonFd < 0) {
+ switch (errno) {
+ case ENOENT: mInit = C2_UNSUPPORTED; break;
+ default: mInit = c2_map_errno<EACCES>(errno); break;
+ }
+ }
+}
+
+C2AllocatorIon::~C2AllocatorIon() {
+ if (mInit == C2_OK) {
+ ion_close(mIonFd);
+ }
+}
+
+C2Error C2AllocatorIon::allocateLinearBuffer(
+ uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
+ if (allocation == nullptr) {
+ return C2_BAD_VALUE;
+ }
+
+ allocation->reset();
+ if (mInit != C2_OK) {
+ return C2_UNSUPPORTED;
+ }
+
+ // get align, heapMask and flags
+ //size_t align = 1;
+ size_t align = 0;
+ unsigned heapMask = ~0;
+ unsigned flags = 0;
+ //TODO
+ (void) usage;
+#if 0
+ int err = mUsageMapper(usage, capacity, &align, &heapMask, &flags);
+ if (err < 0) {
+ return c2_map_errno<EINVAL, ENOMEM, EACCES>(-err);
+ }
+#endif
+
+ std::shared_ptr<C2AllocationIon> alloc
+ = std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
+ C2Error ret = alloc->status();
+ if (ret == C2_OK) {
+ *allocation = alloc;
+ }
+ return ret;
+}
+
+C2Error C2AllocatorIon::recreateLinearBuffer(
+ const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
+ *allocation = nullptr;
+ if (mInit != C2_OK) {
+ return C2_UNSUPPORTED;
+ }
+
+ if (!C2HandleIon::isValid(handle)) {
+ return C2_BAD_VALUE;
+ }
+
+ // TODO: get capacity and validate it
+ const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
+ std::shared_ptr<C2AllocationIon> alloc
+ = std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
+ C2Error ret = alloc->status();
+ if (ret == C2_OK) {
+ *allocation = alloc;
+ }
+ return ret;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 92ccfd1..1ffbf49 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -18,57 +18,12 @@
#define LOG_TAG "C2Buffer"
#include <utils/Log.h>
+#include <map>
+
#include <C2BufferPriv.h>
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-
-#include <ion/ion.h>
-#include <hardware/gralloc.h>
-#include <sys/mman.h>
-
namespace android {
-using ::android::hardware::graphics::allocator::V2_0::IAllocator;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using ::android::hardware::graphics::mapper::V2_0::Error;
-using ::android::hardware::graphics::mapper::V2_0::IMapper;
-using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_vec;
-
-// standard ERRNO mappings
-template<int N> constexpr C2Error _c2_errno2error_impl();
-template<> constexpr C2Error _c2_errno2error_impl<0>() { return C2_OK; }
-template<> constexpr C2Error _c2_errno2error_impl<EINVAL>() { return C2_BAD_VALUE; }
-template<> constexpr C2Error _c2_errno2error_impl<EACCES>() { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<EPERM>() { return C2_NO_PERMISSION; }
-template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>() { return C2_NO_MEMORY; }
-
-// map standard errno-s to the equivalent C2Error
-template<int... N> struct _c2_map_errno_impl;
-template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
- static C2Error map(int result) {
- if (result == E) {
- return _c2_errno2error_impl<E>();
- } else {
- return _c2_map_errno_impl<N...>::map(result);
- }
- }
-};
-template<> struct _c2_map_errno_impl<> {
- static C2Error map(int result) {
- return result == 0 ? C2_OK : C2_CORRUPTED;
- }
-};
-
-template<int... N>
-C2Error c2_map_errno(int result) {
- return _c2_map_errno_impl<N...>::map(result);
-}
-
namespace {
// Inherit from the parent, share with the friend.
@@ -142,357 +97,6 @@
} // namespace
-/* ======================================= ION ALLOCATION ====================================== */
-
-/**
- * ION handle
- */
-struct C2HandleIon : public C2Handle {
- C2HandleIon(int ionFd, ion_user_handle_t buffer) : C2Handle(cHeader),
- mFds{ ionFd, buffer },
- mInts{ kMagic } { }
-
- static bool isValid(const C2Handle * const o);
-
- int ionFd() const { return mFds.mIon; }
- ion_user_handle_t buffer() const { return mFds.mBuffer; }
-
- void setBuffer(ion_user_handle_t bufferFd) { mFds.mBuffer = bufferFd; }
-
-protected:
- struct {
- int mIon;
- int mBuffer; // ion_user_handle_t
- } mFds;
- struct {
- int mMagic;
- } mInts;
-
-private:
- typedef C2HandleIon _type;
- enum {
- kMagic = 'ion1',
- numFds = sizeof(mFds) / sizeof(int),
- numInts = sizeof(mInts) / sizeof(int),
- version = sizeof(C2Handle) + sizeof(mFds) + sizeof(mInts)
- };
- //constexpr static C2Handle cHeader = { version, numFds, numInts, {} };
- const static C2Handle cHeader;
-};
-
-const C2Handle C2HandleIon::cHeader = {
- C2HandleIon::version,
- C2HandleIon::numFds,
- C2HandleIon::numInts,
- {}
-};
-
-// static
-bool C2HandleIon::isValid(const C2Handle * const o) {
- if (!o || memcmp(o, &cHeader, sizeof(cHeader))) {
- return false;
- }
- const C2HandleIon *other = static_cast<const C2HandleIon*>(o);
- return other->mInts.mMagic == kMagic;
-}
-
-// TODO: is the dup of an ion fd identical to ion_share?
-
-class C2AllocationIon : public C2LinearAllocation {
-public:
- virtual C2Error map(
- size_t offset, size_t size, C2MemoryUsage usage, int *fence,
- void **addr /* nonnull */);
- virtual C2Error unmap(void *addr, size_t size, int *fenceFd);
- virtual bool isValid() const;
- virtual ~C2AllocationIon();
- virtual const C2Handle *handle() const;
- virtual bool equals(const std::shared_ptr<C2LinearAllocation> &other) const;
-
- // internal methods
- C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags);
- C2AllocationIon(int ionFd, size_t size, int shareFd);
- int dup() const;
- C2Error status() const;
-
-protected:
- class Impl;
- Impl *mImpl;
-};
-
-class C2AllocationIon::Impl {
-public:
- // NOTE: using constructor here instead of a factory method as we will need the
- // error value and this simplifies the error handling by the wrapper.
- Impl(int ionFd, size_t capacity, size_t align, unsigned heapMask, unsigned flags)
- : mInit(C2_OK),
- mHandle(ionFd, -1),
- mMapFd(-1),
- mCapacity(capacity) {
- ion_user_handle_t buffer = -1;
- int ret = ion_alloc(mHandle.ionFd(), mCapacity, align, heapMask, flags, &buffer);
- if (ret == 0) {
- mHandle.setBuffer(buffer);
- } else {
- mInit = c2_map_errno<ENOMEM, EACCES, EINVAL>(-ret);
- }
- }
-
- Impl(int ionFd, size_t capacity, int shareFd)
- : mHandle(ionFd, -1),
- mMapFd(-1),
- mCapacity(capacity) {
- ion_user_handle_t buffer;
- mInit = ion_import(mHandle.ionFd(), shareFd, &buffer);
- if (mInit == 0) {
- mHandle.setBuffer(buffer);
- }
- (void)mCapacity; // TODO
- }
-
- C2Error map(size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
- (void)fenceFd; // TODO: wait for fence
- *addr = nullptr;
- int prot = PROT_NONE;
- int flags = MAP_PRIVATE;
- if (usage.mConsumer & GRALLOC_USAGE_SW_READ_MASK) {
- prot |= PROT_READ;
- }
- if (usage.mProducer & GRALLOC_USAGE_SW_WRITE_MASK) {
- prot |= PROT_WRITE;
- flags = MAP_SHARED;
- }
-
- size_t alignmentBytes = offset % PAGE_SIZE;
- size_t mapOffset = offset - alignmentBytes;
- size_t mapSize = size + alignmentBytes;
-
- C2Error err = C2_OK;
- if (mMapFd == -1) {
- int ret = ion_map(mHandle.ionFd(), mHandle.buffer(), mapSize, prot,
- flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
- if (ret) {
- mMapFd = -1;
- *addr = nullptr;
- err = c2_map_errno<EINVAL>(-ret);
- } else {
- *addr = (uint8_t *)mMapAddr + alignmentBytes;
- mMapAlignmentBytes = alignmentBytes;
- mMapSize = mapSize;
- }
- } else {
- mMapAddr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
- if (mMapAddr == MAP_FAILED) {
- mMapAddr = *addr = nullptr;
- err = c2_map_errno<EINVAL>(errno);
- } else {
- *addr = (uint8_t *)mMapAddr + alignmentBytes;
- mMapAlignmentBytes = alignmentBytes;
- mMapSize = mapSize;
- }
- }
- return err;
- }
-
- C2Error unmap(void *addr, size_t size, int *fenceFd) {
- if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
- size + mMapAlignmentBytes != mMapSize) {
- return C2_BAD_VALUE;
- }
- int err = munmap(mMapAddr, mMapSize);
- if (err != 0) {
- return c2_map_errno<EINVAL>(errno);
- }
- if (fenceFd) {
- *fenceFd = -1;
- }
- return C2_OK;
- }
-
- ~Impl() {
- if (mMapFd != -1) {
- close(mMapFd);
- mMapFd = -1;
- }
-
- (void)ion_free(mHandle.ionFd(), mHandle.buffer());
- }
-
- C2Error status() const {
- return mInit;
- }
-
- const C2Handle * handle() const {
- return &mHandle;
- }
-
- int dup() const {
- int fd = -1;
- if (mInit != 0 || ion_share(mHandle.ionFd(), mHandle.buffer(), &fd) != 0) {
- fd = -1;
- }
- return fd;
- }
-
-private:
- C2Error mInit;
- C2HandleIon mHandle;
- int mMapFd; // only one for now
- void *mMapAddr;
- size_t mMapAlignmentBytes;
- size_t mMapSize;
- size_t mCapacity;
-};
-
-C2Error C2AllocationIon::map(
- size_t offset, size_t size, C2MemoryUsage usage, int *fenceFd, void **addr) {
- return mImpl->map(offset, size, usage, fenceFd, addr);
-}
-
-C2Error C2AllocationIon::unmap(void *addr, size_t size, int *fenceFd) {
- return mImpl->unmap(addr, size, fenceFd);
-}
-
-bool C2AllocationIon::isValid() const {
- return mImpl->status() == C2_OK;
-}
-
-C2Error C2AllocationIon::status() const {
- return mImpl->status();
-}
-
-bool C2AllocationIon::equals(const std::shared_ptr<C2LinearAllocation> &other) const {
- return other != nullptr &&
- other->handle(); // TODO
-}
-
-const C2Handle *C2AllocationIon::handle() const {
- return mImpl->handle();
-}
-
-C2AllocationIon::~C2AllocationIon() {
- delete mImpl;
-}
-
-C2AllocationIon::C2AllocationIon(int ionFd, size_t size, size_t align, unsigned heapMask, unsigned flags)
- : C2LinearAllocation(size),
- mImpl(new Impl(ionFd, size, align, heapMask, flags)) { }
-
-C2AllocationIon::C2AllocationIon(int ionFd, size_t size, int shareFd)
- : C2LinearAllocation(size),
- mImpl(new Impl(ionFd, size, shareFd)) { }
-
-int C2AllocationIon::dup() const {
- return mImpl->dup();
-}
-
-/* ======================================= ION ALLOCATOR ====================================== */
-
-C2AllocatorIon::C2AllocatorIon() : mInit(C2_OK), mIonFd(ion_open()) {
- if (mIonFd < 0) {
- switch (errno) {
- case ENOENT: mInit = C2_UNSUPPORTED; break;
- default: mInit = c2_map_errno<EACCES>(errno); break;
- }
- }
-}
-
-C2AllocatorIon::~C2AllocatorIon() {
- if (mInit == C2_OK) {
- ion_close(mIonFd);
- }
-}
-
-/**
- * Allocates a 1D allocation of given |capacity| and |usage|. If successful, the allocation is
- * stored in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
- *
- * \param capacity the size of requested allocation (the allocation could be slightly
- * larger, e.g. to account for any system-required alignment)
- * \param usage the memory usage info for the requested allocation. \note that the
- * returned allocation may be later used/mapped with different usage.
- * The allocator should layout the buffer to be optimized for this usage,
- * but must support any usage. One exception: protected buffers can
- * only be used in a protected scenario.
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the allocation was successful
- * \retval C2_NO_MEMORY not enough memory to complete the allocation
- * \retval C2_TIMED_OUT the allocation timed out
- * \retval C2_NO_PERMISSION no permission to complete the allocation
- * \retval C2_BAD_VALUE capacity or usage are not supported (invalid) (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
- */
-C2Error C2AllocatorIon::allocateLinearBuffer(
- uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation> *allocation) {
- *allocation = nullptr;
- if (mInit != C2_OK) {
- return C2_UNSUPPORTED;
- }
-
- // get align, heapMask and flags
- //size_t align = 1;
- size_t align = 0;
- unsigned heapMask = ~0;
- unsigned flags = 0;
- //TODO
- (void) usage;
-#if 0
- int err = mUsageMapper(usage, capacity, &align, &heapMask, &flags);
- if (err < 0) {
- return c2_map_errno<EINVAL, ENOMEM, EACCES>(-err);
- }
-#endif
-
- std::shared_ptr<C2AllocationIon> alloc
- = std::make_shared<C2AllocationIon>(mIonFd, capacity, align, heapMask, flags);
- C2Error ret = alloc->status();
- if (ret == C2_OK) {
- *allocation = alloc;
- }
- return ret;
-}
-
-/**
- * (Re)creates a 1D allocation from a native |handle|. If successful, the allocation is stored
- * in |allocation|. Otherwise, |allocation| is set to 'nullptr'.
- *
- * \param handle the handle for the existing allocation
- * \param allocation pointer to where the allocation shall be stored on success. nullptr
- * will be stored here on failure
- *
- * \retval C2_OK the allocation was recreated successfully
- * \retval C2_NO_MEMORY not enough memory to recreate the allocation
- * \retval C2_TIMED_OUT the recreation timed out (unexpected)
- * \retval C2_NO_PERMISSION no permission to recreate the allocation
- * \retval C2_BAD_VALUE invalid handle (caller error)
- * \retval C2_UNSUPPORTED this allocator does not support 1D allocations
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during allocation (unexpected)
- */
-C2Error C2AllocatorIon::recreateLinearBuffer(
- const C2Handle *handle, std::shared_ptr<C2LinearAllocation> *allocation) {
- *allocation = nullptr;
- if (mInit != C2_OK) {
- return C2_UNSUPPORTED;
- }
-
- if (!C2HandleIon::isValid(handle)) {
- return C2_BAD_VALUE;
- }
-
- // TODO: get capacity and validate it
- const C2HandleIon *h = static_cast<const C2HandleIon*>(handle);
- std::shared_ptr<C2AllocationIon> alloc
- = std::make_shared<C2AllocationIon>(mIonFd, 0 /* capacity */, h->buffer());
- C2Error ret = alloc->status();
- if (ret == C2_OK) {
- *allocation = alloc;
- }
- return ret;
-}
-
/* ========================================== 1D BLOCK ========================================= */
class C2Block1D::Impl {
@@ -762,304 +366,6 @@
return C2_OK;
}
-/* ===================================== GRALLOC ALLOCATION ==================================== */
-
-static C2Error maperr2error(Error maperr) {
- switch (maperr) {
- case Error::NONE: return C2_OK;
- case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
- case Error::BAD_BUFFER: return C2_BAD_VALUE;
- case Error::BAD_VALUE: return C2_BAD_VALUE;
- case Error::NO_RESOURCES: return C2_NO_MEMORY;
- case Error::UNSUPPORTED: return C2_UNSUPPORTED;
- }
- return C2_CORRUPTED;
-}
-
-class C2AllocationGralloc : public C2GraphicAllocation {
-public:
- virtual ~C2AllocationGralloc();
-
- virtual C2Error map(
- C2Rect rect, C2MemoryUsage usage, int *fenceFd,
- C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
- virtual C2Error unmap(C2Fence *fenceFd /* nullable */) override;
- virtual bool isValid() const override { return true; }
- virtual const C2Handle *handle() const override { return mHandle; }
- virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
-
- // internal methods
- // |handle| will be moved.
- C2AllocationGralloc(
- const IMapper::BufferDescriptorInfo &info,
- const sp<IMapper> &mapper,
- hidl_handle &handle);
- int dup() const;
- C2Error status() const;
-
-private:
- const IMapper::BufferDescriptorInfo mInfo;
- const sp<IMapper> mMapper;
- const hidl_handle mHandle;
- buffer_handle_t mBuffer;
- bool mLocked;
-};
-
-C2AllocationGralloc::C2AllocationGralloc(
- const IMapper::BufferDescriptorInfo &info,
- const sp<IMapper> &mapper,
- hidl_handle &handle)
- : C2GraphicAllocation(info.width, info.height),
- mInfo(info),
- mMapper(mapper),
- mHandle(std::move(handle)),
- mBuffer(nullptr),
- mLocked(false) {}
-
-C2AllocationGralloc::~C2AllocationGralloc() {
- if (!mBuffer) {
- return;
- }
- if (mLocked) {
- unmap(nullptr);
- }
- mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
-}
-
-C2Error C2AllocationGralloc::map(
- C2Rect rect, C2MemoryUsage usage, int *fenceFd,
- C2PlaneLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
- // TODO
- (void) fenceFd;
- (void) usage;
-
- if (mBuffer && mLocked) {
- return C2_DUPLICATE;
- }
- if (!layout || !addr) {
- return C2_BAD_VALUE;
- }
-
- C2Error err = C2_OK;
- if (!mBuffer) {
- mMapper->importBuffer(
- mHandle, [&err, this](const auto &maperr, const auto &buffer) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- mBuffer = static_cast<buffer_handle_t>(buffer);
- }
- });
- if (err != C2_OK) {
- return err;
- }
- }
-
- if (mInfo.format == PixelFormat::YCBCR_420_888 || mInfo.format == PixelFormat::YV12) {
- YCbCrLayout ycbcrLayout;
- mMapper->lockYCbCr(
- const_cast<native_handle_t *>(mBuffer),
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
- { (int32_t)rect.mLeft, (int32_t)rect.mTop, (int32_t)rect.mWidth, (int32_t)rect.mHeight },
- // TODO: fence
- hidl_handle(),
- [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- ycbcrLayout = mapLayout;
- }
- });
- if (err != C2_OK) {
- return err;
- }
- addr[C2PlaneLayout::Y] = (uint8_t *)ycbcrLayout.y;
- addr[C2PlaneLayout::U] = (uint8_t *)ycbcrLayout.cb;
- addr[C2PlaneLayout::V] = (uint8_t *)ycbcrLayout.cr;
- layout->mType = C2PlaneLayout::MEDIA_IMAGE_TYPE_YUV;
- layout->mNumPlanes = 3;
- layout->mPlanes[C2PlaneLayout::Y] = {
- C2PlaneInfo::Y, // mChannel
- 1, // mColInc
- (int32_t)ycbcrLayout.yStride, // mRowInc
- 1, // mHorizSubsampling
- 1, // mVertSubsampling
- 8, // mBitDepth
- 8, // mAllocatedDepth
- };
- layout->mPlanes[C2PlaneLayout::U] = {
- C2PlaneInfo::Cb, // mChannel
- (int32_t)ycbcrLayout.chromaStep, // mColInc
- (int32_t)ycbcrLayout.cStride, // mRowInc
- 2, // mHorizSubsampling
- 2, // mVertSubsampling
- 8, // mBitDepth
- 8, // mAllocatedDepth
- };
- layout->mPlanes[C2PlaneLayout::V] = {
- C2PlaneInfo::Cr, // mChannel
- (int32_t)ycbcrLayout.chromaStep, // mColInc
- (int32_t)ycbcrLayout.cStride, // mRowInc
- 2, // mHorizSubsampling
- 2, // mVertSubsampling
- 8, // mBitDepth
- 8, // mAllocatedDepth
- };
- } else {
- void *pointer = nullptr;
- mMapper->lock(
- const_cast<native_handle_t *>(mBuffer),
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
- { (int32_t)rect.mLeft, (int32_t)rect.mTop, (int32_t)rect.mWidth, (int32_t)rect.mHeight },
- // TODO: fence
- hidl_handle(),
- [&err, &pointer](const auto &maperr, const auto &mapPointer) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- pointer = mapPointer;
- }
- });
- if (err != C2_OK) {
- return err;
- }
- // TODO
- return C2_UNSUPPORTED;
- }
- mLocked = true;
-
- return C2_OK;
-}
-
-C2Error C2AllocationGralloc::unmap(C2Fence *fenceFd /* nullable */) {
- // TODO: fence
- C2Error err = C2_OK;
- mMapper->unlock(
- const_cast<native_handle_t *>(mBuffer),
- [&err, &fenceFd](const auto &maperr, const auto &releaseFence) {
- // TODO
- (void) fenceFd;
- (void) releaseFence;
- err = maperr2error(maperr);
- if (err == C2_OK) {
- // TODO: fence
- }
- });
- if (err == C2_OK) {
- mLocked = false;
- }
- return err;
-}
-
-bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
- return other && other->handle() == handle();
-}
-
-/* ===================================== GRALLOC ALLOCATOR ==================================== */
-
-class C2AllocatorGralloc::Impl {
-public:
- Impl();
-
- C2Error allocateGraphicBuffer(
- uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
- std::shared_ptr<C2GraphicAllocation> *allocation);
-
- C2Error recreateGraphicBuffer(
- const C2Handle *handle,
- std::shared_ptr<C2GraphicAllocation> *allocation);
-
- C2Error status() const { return mInit; }
-
-private:
- C2Error mInit;
- sp<IAllocator> mAllocator;
- sp<IMapper> mMapper;
-};
-
-C2AllocatorGralloc::Impl::Impl() : mInit(C2_OK) {
- mAllocator = IAllocator::getService();
- mMapper = IMapper::getService();
- if (mAllocator == nullptr || mMapper == nullptr) {
- mInit = C2_CORRUPTED;
- }
-}
-
-C2Error C2AllocatorGralloc::Impl::allocateGraphicBuffer(
- uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
- std::shared_ptr<C2GraphicAllocation> *allocation) {
- // TODO: buffer usage should be determined according to |usage|
- (void) usage;
-
- IMapper::BufferDescriptorInfo info = {
- width,
- height,
- 1u, // layerCount
- (PixelFormat)format,
- BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
- };
- C2Error err = C2_OK;
- BufferDescriptor desc;
- mMapper->createDescriptor(
- info, [&err, &desc](const auto &maperr, const auto &descriptor) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- desc = descriptor;
- }
- });
- if (err != C2_OK) {
- return err;
- }
-
- // IAllocator shares IMapper error codes.
- hidl_handle buffer;
- mAllocator->allocate(
- desc,
- 1u,
- [&err, &buffer](const auto &maperr, const auto &stride, auto &buffers) {
- (void) stride;
- err = maperr2error(maperr);
- if (err != C2_OK) {
- return;
- }
- if (buffers.size() != 1u) {
- err = C2_CORRUPTED;
- return;
- }
- buffer = std::move(buffers[0]);
- });
- if (err != C2_OK) {
- return err;
- }
-
- allocation->reset(new C2AllocationGralloc(info, mMapper, buffer));
- return C2_OK;
-}
-
-C2Error C2AllocatorGralloc::Impl::recreateGraphicBuffer(
- const C2Handle *handle,
- std::shared_ptr<C2GraphicAllocation> *allocation) {
- (void) handle;
-
- // TODO: need to figure out BufferDescriptorInfo from the handle.
- allocation->reset();
- return C2_UNSUPPORTED;
-}
-
-C2AllocatorGralloc::C2AllocatorGralloc() : mImpl(new Impl) {}
-C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
-
-C2Error C2AllocatorGralloc::allocateGraphicBuffer(
- uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
- std::shared_ptr<C2GraphicAllocation> *allocation) {
- return mImpl->allocateGraphicBuffer(width, height, format, usage, allocation);
-}
-
-C2Error C2AllocatorGralloc::recreateGraphicBuffer(
- const C2Handle *handle,
- std::shared_ptr<C2GraphicAllocation> *allocation) {
- return mImpl->recreateGraphicBuffer(handle, allocation);
-}
-
-C2Error C2AllocatorGralloc::status() const { return mImpl->status(); }
-
/* ========================================== 2D BLOCK ========================================= */
class C2Block2D::Impl {
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
new file mode 100644
index 0000000..94f74c8
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorGralloc.h
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright (C) 2016 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 STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
+
+#include <functional>
+
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorGralloc : public C2Allocator {
+public:
+ // (usage, capacity) => (align, heapMask, flags)
+ typedef std::function<int (C2MemoryUsage, size_t,
+ /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
+
+ virtual C2Error allocateGraphicBuffer(
+ uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicAllocation> *allocation) override;
+
+ virtual C2Error recreateGraphicBuffer(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *allocation) override;
+
+ C2AllocatorGralloc();
+
+ C2Error status() const;
+
+ virtual ~C2AllocatorGralloc();
+
+private:
+ class Impl;
+ Impl *mImpl;
+};
+
+#if 0
+class C2Allocation::Impl {
+public:
+ Impl() : mMapped(false), mBase(nullptr) { }
+ uint8_t* base() { return mMapped ? mBase : nullptr; }
+
+ // TODO: call map...
+
+private:
+ bool mMapped;
+ uint8_t *mBase;
+};
+#endif
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_GRALLOC_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
new file mode 100644
index 0000000..a453a7d
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/include/C2AllocatorIon.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 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 STAGEFRIGHT_CODEC2_ALLOCATOR_ION_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_ION_H_
+
+#include <functional>
+
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorIon : public C2Allocator {
+public:
+ // (usage, capacity) => (align, heapMask, flags)
+ typedef std::function<int (C2MemoryUsage, size_t,
+ /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
+
+ virtual C2Error allocateLinearBuffer(
+ uint32_t capacity, C2MemoryUsage usage,
+ std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+ virtual C2Error recreateLinearBuffer(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+ C2AllocatorIon();
+
+ C2Error status() const { return mInit; }
+
+ virtual ~C2AllocatorIon();
+
+private:
+ C2Error mInit;
+ int mIonFd;
+ usage_mapper_fn mUsageMapper;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_ION_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index b7c752f..6a8f94e 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -23,32 +23,6 @@
namespace android {
-class C2AllocatorIon : public C2Allocator {
-public:
- // (usage, capacity) => (align, heapMask, flags)
- typedef std::function<int (C2MemoryUsage, size_t,
- /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
-
- virtual C2Error allocateLinearBuffer(
- uint32_t capacity, C2MemoryUsage usage,
- std::shared_ptr<C2LinearAllocation> *allocation) override;
-
- virtual C2Error recreateLinearBuffer(
- const C2Handle *handle,
- std::shared_ptr<C2LinearAllocation> *allocation) override;
-
- C2AllocatorIon();
-
- C2Error status() const { return mInit; }
-
- virtual ~C2AllocatorIon();
-
-private:
- C2Error mInit;
- int mIonFd;
- usage_mapper_fn mUsageMapper;
-};
-
class C2DefaultBlockAllocator : public C2BlockAllocator {
public:
explicit C2DefaultBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
@@ -65,31 +39,6 @@
const std::shared_ptr<C2Allocator> mAllocator;
};
-class C2AllocatorGralloc : public C2Allocator {
-public:
- // (usage, capacity) => (align, heapMask, flags)
- typedef std::function<int (C2MemoryUsage, size_t,
- /* => */ size_t*, unsigned*, unsigned*)> usage_mapper_fn;
-
- virtual C2Error allocateGraphicBuffer(
- uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
- std::shared_ptr<C2GraphicAllocation> *allocation) override;
-
- virtual C2Error recreateGraphicBuffer(
- const C2Handle *handle,
- std::shared_ptr<C2GraphicAllocation> *allocation) override;
-
- C2AllocatorGralloc();
-
- C2Error status() const;
-
- virtual ~C2AllocatorGralloc();
-
-private:
- class Impl;
- Impl *mImpl;
-};
-
class C2DefaultGraphicBlockAllocator : public C2BlockAllocator {
public:
explicit C2DefaultGraphicBlockAllocator(const std::shared_ptr<C2Allocator> &allocator);
diff --git a/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
new file mode 100644
index 0000000..f834cdb
--- /dev/null
+++ b/media/libstagefright/codec2/vndk/include/C2ErrnoUtils.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 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 STAGEFRIGHT_CODEC2_ERRNO_UTILS_H_
+#define STAGEFRIGHT_CODEC2_ERRNO_UTILS_H_
+
+#include <errno.h>
+#include <C2.h>
+
+namespace android {
+
+// standard ERRNO mappings
+template<int N> constexpr C2Error _c2_errno2error_impl();
+template<> constexpr C2Error _c2_errno2error_impl<0>() { return C2_OK; }
+template<> constexpr C2Error _c2_errno2error_impl<EINVAL>() { return C2_BAD_VALUE; }
+template<> constexpr C2Error _c2_errno2error_impl<EACCES>() { return C2_NO_PERMISSION; }
+template<> constexpr C2Error _c2_errno2error_impl<EPERM>() { return C2_NO_PERMISSION; }
+template<> constexpr C2Error _c2_errno2error_impl<ENOMEM>() { return C2_NO_MEMORY; }
+
+// map standard errno-s to the equivalent C2Error
+template<int... N> struct _c2_map_errno_impl;
+template<int E, int ... N> struct _c2_map_errno_impl<E, N...> {
+ static C2Error map(int result) {
+ if (result == E) {
+ return _c2_errno2error_impl<E>();
+ } else {
+ return _c2_map_errno_impl<N...>::map(result);
+ }
+ }
+};
+template<> struct _c2_map_errno_impl<> {
+ static C2Error map(int result) {
+ return result == 0 ? C2_OK : C2_CORRUPTED;
+ }
+};
+
+template<int... N>
+C2Error c2_map_errno(int result) {
+ return _c2_map_errno_impl<N...>::map(result);
+}
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ERRNO_UTILS_H_
+
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index 4de14d2..c4cc6a6 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -52,6 +52,8 @@
#include <gui/SurfaceComposerClient.h>
#include <util/C2ParamUtils.h>
+#include <C2AllocatorGralloc.h>
+#include <C2AllocatorIon.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
#include <C2Component.h>