1180 lines
42 KiB
C++
Executable File
1180 lines
42 KiB
C++
Executable File
/*
|
|
* Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#define LOG_TAG "CameraBufferManager"
|
|
|
|
#include <utils/Log.h>
|
|
#if defined(ANDROID_VERSION_ABOVE_12_X)
|
|
#include <hardware/hardware_rockchip.h>
|
|
#endif
|
|
|
|
#include "common/camera_buffer_manager_gralloc4_impl.h"
|
|
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
#include <aidl/android/hardware/graphics/allocator/IAllocator.h>
|
|
#include <aidl/android/hardware/graphics/allocator/AllocationError.h>
|
|
#include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
|
|
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
|
|
#include <android/binder_manager.h>
|
|
#include <aidlcommonsupport/NativeHandle.h>
|
|
#endif
|
|
|
|
#include <hwbinder/IPCThreadState.h>
|
|
#include <sync/sync.h>
|
|
#include <drm_fourcc.h>
|
|
#include "LogHelper.h"
|
|
|
|
#include <linux/videodev2.h>
|
|
|
|
#include "arc/common.h"
|
|
|
|
using android::hardware::graphics::mapper::V4_0::Error;
|
|
using android::hardware::graphics::mapper::V4_0::IMapper;
|
|
using android::hardware::graphics::allocator::V4_0::IAllocator;
|
|
using android::hardware::graphics::common::V1_2::BufferUsage;
|
|
using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
|
|
using android::hardware::hidl_vec;
|
|
|
|
using android::gralloc4::MetadataType_PlaneLayouts;
|
|
using android::gralloc4::decodePlaneLayouts;
|
|
using android::gralloc4::MetadataType_Usage;
|
|
using android::gralloc4::decodeUsage;
|
|
using android::gralloc4::MetadataType_PlaneLayouts;
|
|
using android::gralloc4::decodePlaneLayouts;
|
|
using android::gralloc4::MetadataType_PixelFormatFourCC;
|
|
using android::gralloc4::decodePixelFormatFourCC;
|
|
using android::gralloc4::MetadataType_PixelFormatModifier;
|
|
using android::gralloc4::decodePixelFormatModifier;
|
|
using android::gralloc4::MetadataType_PixelFormatRequested;
|
|
using android::gralloc4::decodePixelFormatRequested;
|
|
using android::gralloc4::MetadataType_AllocationSize;
|
|
using android::gralloc4::decodeAllocationSize;
|
|
using android::gralloc4::MetadataType_LayerCount;
|
|
using android::gralloc4::decodeLayerCount;
|
|
using android::gralloc4::MetadataType_Dataspace;
|
|
using android::gralloc4::decodeDataspace;
|
|
using android::gralloc4::MetadataType_Crop;
|
|
using android::gralloc4::decodeCrop;
|
|
using android::gralloc4::MetadataType_Width;
|
|
using android::gralloc4::decodeWidth;
|
|
using android::gralloc4::MetadataType_Height;
|
|
using android::gralloc4::decodeHeight;
|
|
|
|
using aidl::android::hardware::graphics::common::Dataspace;
|
|
using aidl::android::hardware::graphics::common::PlaneLayout;
|
|
using aidl::android::hardware::graphics::common::ExtendableType;
|
|
using aidl::android::hardware::graphics::common::PlaneLayout;
|
|
using aidl::android::hardware::graphics::common::Rect;
|
|
using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
|
|
using android::hardware::graphics::common::V1_2::PixelFormat;
|
|
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
using aidl::android::hardware::graphics::allocator::AllocationError;
|
|
using aidl::android::hardware::graphics::allocator::AllocationResult;
|
|
using AidlIAllocator = ::aidl::android::hardware::graphics::allocator::IAllocator;
|
|
using AidlBufferUsage = ::aidl::android::hardware::graphics::common::BufferUsage;
|
|
#endif
|
|
|
|
#define IMPORTBUFFER_CB 1
|
|
|
|
|
|
namespace arc {
|
|
|
|
namespace {
|
|
|
|
static constexpr Error kTransactionError = Error::NO_RESOURCES;
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
static const auto kAidlAllocatorServiceName = AidlIAllocator::descriptor + std::string("/default");
|
|
#endif
|
|
#define GRALLOC_ARM_METADATA_TYPE_NAME "arm.graphics.ArmMetadataType"
|
|
const static IMapper::MetadataType ArmMetadataType_PLANE_FDS
|
|
{
|
|
GRALLOC_ARM_METADATA_TYPE_NAME,
|
|
// static_cast<int64_t>(aidl::arm::graphics::ArmMetadataType::PLANE_FDS)
|
|
1 // 就是上面的 'PLANE_FDS'
|
|
};
|
|
|
|
static IMapper &get_mapperservice()
|
|
{
|
|
static android::sp<IMapper> cached_service = IMapper::getService();
|
|
return *cached_service;
|
|
}
|
|
|
|
static IAllocator &get_allocservice()
|
|
{
|
|
static android::sp<IAllocator> cached_service = IAllocator::getService();
|
|
return *cached_service;
|
|
}
|
|
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
static bool hasIAllocatorAidl() {
|
|
static bool sHasIAllocatorAidl = []() -> bool {
|
|
if (__builtin_available(android 31, *)) {
|
|
return AServiceManager_isDeclared(kAidlAllocatorServiceName.c_str());
|
|
}
|
|
return false;
|
|
}();
|
|
return sHasIAllocatorAidl;
|
|
}
|
|
|
|
static AidlIAllocator &get_aidl_allocservice()
|
|
{
|
|
static std::shared_ptr<AidlIAllocator> cached_service = AidlIAllocator::fromBinder(ndk::SpAIBinder(
|
|
AServiceManager_waitForService(kAidlAllocatorServiceName.c_str())));
|
|
ALOGE_IF(!cached_service, "AIDL IAllocator declared but failed to get service");
|
|
return *cached_service;
|
|
}
|
|
#endif
|
|
|
|
static inline void sBufferDescriptorInfo(std::string name, uint32_t width, uint32_t height,
|
|
PixelFormat format, uint32_t layerCount, uint64_t usage,
|
|
IMapper::BufferDescriptorInfo* outDescriptorInfo) {
|
|
outDescriptorInfo->name = name;
|
|
outDescriptorInfo->width = width;
|
|
outDescriptorInfo->height = height;
|
|
outDescriptorInfo->layerCount = layerCount;
|
|
outDescriptorInfo->format = static_cast<android::hardware::graphics::common::V1_2::PixelFormat>(format);
|
|
#ifdef GRALLOC_USAGE_RGA_ACCESS
|
|
outDescriptorInfo->usage = RK_GRALLOC_USAGE_RGA_ACCESS|usage;
|
|
ALOGD("alloc RGA buf in 4G!\n");
|
|
#else
|
|
outDescriptorInfo->usage = usage;
|
|
#endif
|
|
|
|
outDescriptorInfo->reservedSize = 0;
|
|
}
|
|
|
|
uint64_t getValidUsageBits() {
|
|
static const uint64_t validUsageBits = []() -> uint64_t {
|
|
uint64_t bits = 0;
|
|
for (const auto bit :
|
|
android::hardware::hidl_enum_range<android::hardware::graphics::common::V1_2::BufferUsage>()) {
|
|
bits = bits | bit;
|
|
}
|
|
return bits;
|
|
}();
|
|
return validUsageBits;
|
|
}
|
|
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
uint64_t getValidUsageBits41() {
|
|
static const uint64_t validUsageBits = []() -> uint64_t {
|
|
uint64_t bits = 0;
|
|
for (const auto bit : ndk::enum_range<AidlBufferUsage>{}) {
|
|
bits |= static_cast<int64_t>(bit);
|
|
}
|
|
return bits;
|
|
}();
|
|
return validUsageBits;
|
|
}
|
|
#endif
|
|
|
|
template <typename T>
|
|
static int get_metadata(IMapper &mapper, buffer_handle_t handle, IMapper::MetadataType type,
|
|
android::status_t (*decode)(const hidl_vec<uint8_t> &, T *), T *value)
|
|
{
|
|
void *handle_arg = const_cast<native_handle_t *>(handle);
|
|
assert(handle_arg);
|
|
assert(value);
|
|
assert(decode);
|
|
|
|
int err = 0;
|
|
mapper.get(handle_arg, type, [&err, value, decode](Error error, const hidl_vec<uint8_t> &metadata)
|
|
{
|
|
if (error != Error::NONE)
|
|
{
|
|
err = android::BAD_VALUE;
|
|
return;
|
|
}
|
|
err = decode(metadata, value);
|
|
});
|
|
return err;
|
|
}
|
|
|
|
android::status_t static decodeArmPlaneFds(const hidl_vec<uint8_t>& input, std::vector<int64_t>* fds)
|
|
{
|
|
assert (fds != nullptr);
|
|
int64_t size = 0;
|
|
|
|
memcpy(&size, input.data(), sizeof(int64_t));
|
|
if (size < 0)
|
|
{
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
fds->resize(size);
|
|
|
|
const uint8_t *tmp = input.data() + sizeof(int64_t);
|
|
memcpy(fds->data(), tmp, sizeof(int64_t) * size);
|
|
|
|
return android::NO_ERROR;
|
|
}
|
|
|
|
}
|
|
// static
|
|
CameraBufferManager* CameraBufferManager::GetInstance() {
|
|
static CameraBufferManagerImpl instance;
|
|
return &instance;
|
|
}
|
|
|
|
//static
|
|
int CameraBufferManagerImpl::GetHalPixelFormat(buffer_handle_t buffer) {
|
|
LOGD("GetHalPixelFormat %p", buffer);
|
|
auto &mapper = get_mapperservice();
|
|
// android::PixelFormat format; // *format_requested
|
|
PixelFormat format; // *format_requested
|
|
|
|
int err = get_metadata(mapper, buffer, MetadataType_PixelFormatRequested, decodePixelFormatRequested, &format);
|
|
if (err != android::OK)
|
|
{
|
|
LOGF(ERROR) << "Failed to get pixel_format_requested. err :" << err;
|
|
return err;
|
|
}
|
|
|
|
LOGD("@%s: get buffer format(%d).", __FUNCTION__, format);
|
|
return (int)format;
|
|
}
|
|
|
|
// static
|
|
uint32_t CameraBufferManager::GetNumPlanes(buffer_handle_t buffer) {
|
|
LOGD("GetNumPlanes %p", buffer);
|
|
int hal_pixel_format = CameraBufferManagerImpl::GetHalPixelFormat(buffer);
|
|
/* only support one physical plane now */
|
|
switch (hal_pixel_format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
case HAL_PIXEL_FORMAT_RGB_888:
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
return 1;
|
|
case HAL_PIXEL_FORMAT_YCbCr_422_I:
|
|
case HAL_PIXEL_FORMAT_YCrCb_NV12:
|
|
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
|
|
case HAL_PIXEL_FORMAT_YCbCr_420_888:
|
|
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: //NV12
|
|
return 2;
|
|
default :
|
|
return 1;
|
|
}
|
|
|
|
LOGF(ERROR) << "Unknown format: " << hal_pixel_format << " - " << FormatToString(hal_pixel_format);
|
|
return 0;
|
|
}
|
|
|
|
// static
|
|
uint32_t CameraBufferManager::GetV4L2PixelFormat(buffer_handle_t buffer) {
|
|
LOGD("GetV4L2PixelFormat %p", buffer);
|
|
int hal_pixel_format = CameraBufferManagerImpl::GetHalPixelFormat(buffer);
|
|
|
|
switch (hal_pixel_format) {
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
return V4L2_PIX_FMT_ABGR32;
|
|
|
|
// There is no standard V4L2 pixel format corresponding to
|
|
// DRM_FORMAT_xBGR8888. We use our own V4L2 format extension
|
|
// V4L2_PIX_FMT_RGBX32 here.
|
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
return V4L2_PIX_FMT_RGBX32;
|
|
|
|
case HAL_PIXEL_FORMAT_BLOB:
|
|
return V4L2_PIX_FMT_JPEG;
|
|
// Semi-planar formats.
|
|
case HAL_PIXEL_FORMAT_YCrCb_NV12:
|
|
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
|
|
case HAL_PIXEL_FORMAT_YCbCr_420_888:
|
|
return V4L2_PIX_FMT_NV12;
|
|
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
|
return V4L2_PIX_FMT_NV21;
|
|
|
|
default:
|
|
return V4L2_PIX_FMT_NV12;
|
|
}
|
|
LOGF(ERROR) << "Could not convert format "
|
|
<< FormatToString(hal_pixel_format) << " to V4L2 pixel format";
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::get_width(buffer_handle_t handle, uint64_t* width)
|
|
{
|
|
auto &mapper = get_mapperservice();
|
|
|
|
int err = get_metadata(mapper, handle, MetadataType_Width, decodeWidth, width);
|
|
if (err != android::OK)
|
|
{
|
|
LOGF(ERROR) << "err :" << err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::get_height(buffer_handle_t handle, uint64_t* height)
|
|
{
|
|
auto &mapper = get_mapperservice();
|
|
|
|
int err = get_metadata(mapper, handle, MetadataType_Height, decodeHeight, height);
|
|
if (err != android::OK)
|
|
{
|
|
LOGF(ERROR) << "err :" << err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
// static
|
|
size_t CameraBufferManager::GetPlaneStride(buffer_handle_t buffer,
|
|
size_t plane) {
|
|
LOGD("GetPlaneStride %p plane:%d", buffer, plane);
|
|
if (plane >= GetNumPlanes(buffer)) {
|
|
LOGF(ERROR) << "Invalid plane: " << plane;
|
|
return 0;
|
|
}
|
|
|
|
auto &mapper = get_mapperservice();
|
|
std::vector<PlaneLayout> layouts;
|
|
int format_requested;
|
|
|
|
format_requested = CameraBufferManagerImpl::GetHalPixelFormat(buffer);
|
|
|
|
/* 若 'format_requested' "不是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */
|
|
if ( format_requested != HAL_PIXEL_FORMAT_YCrCb_NV12_10 )
|
|
{
|
|
int err = get_metadata(mapper, buffer, MetadataType_PlaneLayouts, decodePlaneLayouts, &layouts);
|
|
if (err != android::OK || layouts.size() < 1)
|
|
{
|
|
LOGF(ERROR) << "Failed to get plane layouts. err : " << err;
|
|
return err;
|
|
}
|
|
|
|
if ( layouts.size() < plane )
|
|
{
|
|
LOGF(ERROR) << "it's not reasonable to get global pixel_stride of buffer with planes less than " << plane;
|
|
}
|
|
|
|
LOGD(" w/h: %dx%d, stride:%d size:%d ", layouts[plane].widthInSamples, layouts[plane].heightInSamples,
|
|
layouts[plane].strideInBytes, layouts[plane].totalSizeInBytes);
|
|
|
|
return layouts[plane].strideInBytes;
|
|
}
|
|
/* 否则, 即 'format_requested' "是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */
|
|
else
|
|
{
|
|
uint64_t width;
|
|
int byte_stride;
|
|
|
|
int err = CameraBufferManagerImpl::get_width(buffer, &width);
|
|
if (err != android::OK )
|
|
{
|
|
ALOGE("err : %d", err);
|
|
return err;
|
|
}
|
|
|
|
// .trick : from CSY : 分配 rk_video_decoder 输出 buffers 时, 要求的 byte_stride of buffer in NV12_10, 已经通过 width 传入.
|
|
// 原理上, NV12_10 的 pixel_stride 和 byte_stride 是不同的, 但是这里保留 之前 rk_drm_gralloc 的赋值方式.
|
|
byte_stride = (int)width;
|
|
return byte_stride;
|
|
}
|
|
|
|
}
|
|
|
|
// static
|
|
size_t CameraBufferManager::GetPlaneSize(buffer_handle_t buffer, size_t plane) {
|
|
LOGD("GetPlaneSize %p plane:%d", buffer, plane);
|
|
if (plane >= GetNumPlanes(buffer)) {
|
|
LOGF(ERROR) << "Invalid plane: " << plane;
|
|
return 0;
|
|
}
|
|
|
|
auto &mapper = get_mapperservice();
|
|
std::vector<PlaneLayout> layouts;
|
|
int format_requested;
|
|
|
|
format_requested = CameraBufferManagerImpl::GetHalPixelFormat(buffer);
|
|
|
|
/* 若 'format_requested' "不是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */
|
|
if ( format_requested != HAL_PIXEL_FORMAT_YCrCb_NV12_10 )
|
|
{
|
|
int err = get_metadata(mapper, buffer, MetadataType_PlaneLayouts, decodePlaneLayouts, &layouts);
|
|
if (err != android::OK || layouts.size() < 1)
|
|
{
|
|
LOGF(ERROR) << "Failed to get plane layouts. err : " << err;
|
|
return err;
|
|
}
|
|
|
|
if ( layouts.size() < plane )
|
|
{
|
|
LOGF(ERROR) << "it's not reasonable to get global pixel_stride of buffer with planes less than " << plane;
|
|
}
|
|
|
|
LOGD(" w/h: %dx%d, stride:%d size:%d ", layouts[plane].widthInSamples, layouts[plane].heightInSamples,
|
|
layouts[plane].strideInBytes, layouts[plane].totalSizeInBytes);
|
|
|
|
if (format_requested == HAL_PIXEL_FORMAT_BLOB) {
|
|
LOGD("@%s: format is BLOB, return correct stride with layouts[plane].widthInSamples!", __FUNCTION__)
|
|
return layouts[plane].widthInSamples;
|
|
} else {
|
|
return layouts[plane].totalSizeInBytes;
|
|
}
|
|
}
|
|
/* 否则, 即 'format_requested' "是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */
|
|
else
|
|
{
|
|
uint64_t width;
|
|
int byte_stride;
|
|
|
|
int err = CameraBufferManagerImpl::get_width(buffer, &width);
|
|
if (err != android::OK )
|
|
{
|
|
ALOGE("err : %d", err);
|
|
return err;
|
|
}
|
|
|
|
// .trick : from CSY : 分配 rk_video_decoder 输出 buffers 时, 要求的 byte_stride of buffer in NV12_10, 已经通过 width 传入.
|
|
// 原理上, NV12_10 的 pixel_stride 和 byte_stride 是不同的, 但是这里保留 之前 rk_drm_gralloc 的赋值方式.
|
|
byte_stride = (int)width;
|
|
return byte_stride;
|
|
}
|
|
}
|
|
|
|
status_t CameraBufferManagerImpl::validateBufferDescriptorInfo(
|
|
IMapper::BufferDescriptorInfo* descriptorInfo) const {
|
|
uint64_t validUsageBits = getValidUsageBits();
|
|
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
if (hasIAllocatorAidl()) {
|
|
validUsageBits |= getValidUsageBits41();
|
|
}
|
|
#endif
|
|
if (descriptorInfo->usage & ~validUsageBits) {
|
|
ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
|
|
descriptorInfo->usage & ~validUsageBits);
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
// Combinations that are only allowed with gralloc 4.1.
|
|
// Previous grallocs must be protected from this.
|
|
if (!hasIAllocatorAidl() &&
|
|
descriptorInfo->format != android::hardware::graphics::common::V1_2::PixelFormat::BLOB &&
|
|
descriptorInfo->usage & BufferUsage::GPU_DATA_BUFFER) {
|
|
ALOGE("non-BLOB pixel format with GPU_DATA_BUFFER usage is not supported prior to gralloc 4.1");
|
|
return android::BAD_VALUE;
|
|
}
|
|
#endif
|
|
return android::NO_ERROR;
|
|
}
|
|
|
|
status_t CameraBufferManagerImpl::createDescriptor(void* bufferDescriptorInfo,
|
|
void* outBufferDescriptor) const {
|
|
IMapper::BufferDescriptorInfo* descriptorInfo =
|
|
static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
|
|
BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
|
|
|
|
status_t status = validateBufferDescriptorInfo(descriptorInfo);
|
|
if (status != android::NO_ERROR) {
|
|
return status;
|
|
}
|
|
|
|
Error error;
|
|
auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*outDescriptor = tmpDescriptor;
|
|
};
|
|
|
|
auto &mapper = get_mapperservice();
|
|
android::hardware::Return<void> ret = mapper.createDescriptor(*descriptorInfo, hidl_cb);
|
|
|
|
return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
|
|
}
|
|
|
|
|
|
status_t CameraBufferManagerImpl::importBuffer(buffer_handle_t rawHandle,
|
|
buffer_handle_t* outBufferHandle) const {
|
|
LOGD("import rawBuffer :%p", rawHandle);
|
|
Error error;
|
|
auto &mapper = get_mapperservice();
|
|
auto ret = mapper.importBuffer(android::hardware::hidl_handle(rawHandle), [&](const auto& tmpError, const auto& tmpBuffer) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
|
|
LOGD("import outBuffer :%p", outBufferHandle);
|
|
});
|
|
|
|
return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
|
|
}
|
|
|
|
status_t CameraBufferManagerImpl::freeBuffer(buffer_handle_t bufferHandle) const {
|
|
LOGD("freeBuffer %p", bufferHandle);
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
auto &mapper = get_mapperservice();
|
|
auto ret = mapper.freeBuffer(buffer);
|
|
|
|
auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
|
|
ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d", buffer, error);
|
|
return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
|
|
}
|
|
|
|
|
|
CameraBufferManagerImpl::CameraBufferManagerImpl() {
|
|
}
|
|
|
|
CameraBufferManagerImpl::~CameraBufferManagerImpl() {
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Allocate(size_t width,
|
|
size_t height,
|
|
uint32_t format,
|
|
uint32_t usage,
|
|
BufferType type,
|
|
buffer_handle_t* out_buffer,
|
|
uint32_t* out_stride) {
|
|
if (type == GRALLOC) {
|
|
return AllocateGrallocBuffer(width, height, format, usage, out_buffer,
|
|
out_stride);
|
|
} else {
|
|
NOTREACHED() << "Invalid buffer type: " << type;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Free(buffer_handle_t buffer) {
|
|
LOGD("Free %p", buffer);
|
|
base::AutoLock l(lock_);
|
|
|
|
auto context_it = buffer_context_.find(buffer);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
|
|
return -EINVAL;
|
|
}
|
|
|
|
auto buffer_context = context_it->second.get();
|
|
|
|
if (buffer_context->type == GRALLOC) {
|
|
#if IMPORTBUFFER_CB == 1
|
|
if (buffer) {
|
|
freeBuffer(buffer);
|
|
buffer = nullptr;
|
|
}
|
|
#else
|
|
if (buffer) {
|
|
auto abuffer = const_cast<native_handle_t*>(
|
|
buffer);
|
|
native_handle_close(abuffer);
|
|
native_handle_delete(abuffer);
|
|
buffer = nullptr;
|
|
}
|
|
#endif
|
|
return 0;
|
|
} else {
|
|
// TODO(jcliang): Implement deletion of SharedMemory.
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Register(buffer_handle_t buffer, buffer_handle_t* outbuffer) {
|
|
LOGD("Register buffer:%p", buffer);
|
|
base::AutoLock l(lock_);
|
|
auto context_it = buffer_context_.find(buffer);
|
|
if (context_it != buffer_context_.end()) {
|
|
context_it->second->usage++;
|
|
return 1;
|
|
}
|
|
|
|
std::unique_ptr<BufferContext> buffer_context(new struct BufferContext);
|
|
|
|
buffer_context->type = GRALLOC;
|
|
|
|
int ret = importBuffer(buffer, outbuffer);
|
|
|
|
LOGD("after register buffer:%p outbufferptr:%p outbuffer:%p", buffer, outbuffer, *outbuffer);
|
|
|
|
if (ret) {
|
|
LOGF(ERROR) << "Failed to register gralloc buffer";
|
|
return ret;
|
|
}
|
|
|
|
buffer_context->usage = 1;
|
|
buffer_context_[*outbuffer] = std::move(buffer_context);
|
|
LOGD("Register buffer ok");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Deregister(buffer_handle_t buffer) {
|
|
LOGD("Deregister %p", buffer);
|
|
base::AutoLock l(lock_);
|
|
|
|
auto context_it = buffer_context_.find(buffer);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
|
|
return -EINVAL;
|
|
}
|
|
auto buffer_context = context_it->second.get();
|
|
if (buffer_context->type == GRALLOC) {
|
|
if (!--buffer_context->usage) {
|
|
// Unmap all the existing mapping of bo.
|
|
buffer_context_.erase(context_it);
|
|
|
|
int ret = freeBuffer(buffer);
|
|
|
|
if (ret) {
|
|
LOGF(ERROR) << "Failed to unregister gralloc buffer";
|
|
return ret;
|
|
}
|
|
}
|
|
return 0;
|
|
} else {
|
|
NOTREACHED() << "Invalid buffer type: " << buffer_context->type;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Lockinternal(buffer_handle_t bufferHandle,
|
|
uint32_t flags,
|
|
uint32_t x,
|
|
uint32_t y,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
void** out_addr) {
|
|
LOGD("lock buffer:%p %d, %d, %d, %d, %d", bufferHandle, x, y,width, height, flags);
|
|
|
|
auto context_it = buffer_context_.find(bufferHandle);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << bufferHandle;
|
|
return -EINVAL;
|
|
}
|
|
auto buffer_context = context_it->second.get();
|
|
|
|
uint32_t num_planes = GetNumPlanes(bufferHandle);
|
|
if (!num_planes) {
|
|
return -EINVAL;
|
|
}
|
|
/*if (num_planes > 1) {
|
|
LOGF(ERROR) << "Lock called on multi-planar buffer 0x" << std::hex
|
|
<< bufferHandle;
|
|
return -EINVAL;
|
|
}*/
|
|
|
|
if (buffer_context->type == GRALLOC) {
|
|
auto &mapper = get_mapperservice();
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
LOGD("lock buffer:%p", &buffer);
|
|
|
|
IMapper::Rect accessRegion = {(int)x, (int)y, (int)width, (int)height};
|
|
|
|
android::hardware::hidl_handle acquireFenceHandle; // dummy
|
|
|
|
Error error;
|
|
auto ret = mapper.lock(buffer,
|
|
flags,
|
|
accessRegion,
|
|
acquireFenceHandle,
|
|
[&](const auto& tmpError, const auto& tmpData) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*out_addr = tmpData;
|
|
});
|
|
|
|
error = (ret.isOk()) ? error : kTransactionError;
|
|
|
|
ALOGE_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
|
|
|
|
return (int)error;
|
|
} else {
|
|
NOTREACHED() << "Invalid buffer type: " << buffer_context->type;
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Unlockinternal(buffer_handle_t bufferHandle) {
|
|
LOGD("Unlock buffer:%p", bufferHandle);
|
|
|
|
auto context_it = buffer_context_.find(bufferHandle);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << bufferHandle;
|
|
return -EINVAL;
|
|
}
|
|
auto buffer_context = context_it->second.get();
|
|
if (buffer_context->type == GRALLOC) {
|
|
auto &mapper = get_mapperservice();
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
LOGD("Unlock buffer:%p", buffer);
|
|
|
|
int releaseFence = -1;
|
|
Error error;
|
|
auto ret = mapper.unlock(buffer,
|
|
[&](const auto& tmpError, const auto& tmpReleaseFence)
|
|
{
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
|
|
auto fenceHandle = tmpReleaseFence.getNativeHandle(); // 预期 unlock() 不会返回有效的 release_fence.
|
|
if (fenceHandle && fenceHandle->numFds == 1)
|
|
{
|
|
ALOGE("got unexpected valid fd of release_fence : %d", fenceHandle->data[0]);
|
|
|
|
int fd = dup(fenceHandle->data[0]);
|
|
if (fd >= 0) {
|
|
releaseFence = fd;
|
|
} else {
|
|
ALOGE("failed to dup unlock release fence");
|
|
sync_wait(fenceHandle->data[0], -1);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("unlock(%p) failed with %d", bufferHandle, error);
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Lock(buffer_handle_t bufferHandle,
|
|
uint32_t flags,
|
|
uint32_t x,
|
|
uint32_t y,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
void** out_addr) {
|
|
LOGD("lock buffer:%p %d, %d, %d, %d, %d", bufferHandle, x, y,width, height, flags);
|
|
base::AutoLock l(lock_);
|
|
|
|
auto context_it = buffer_context_.find(bufferHandle);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << bufferHandle;
|
|
return -EINVAL;
|
|
}
|
|
auto buffer_context = context_it->second.get();
|
|
|
|
uint32_t num_planes = GetNumPlanes(bufferHandle);
|
|
if (!num_planes) {
|
|
return -EINVAL;
|
|
}
|
|
if (num_planes > 1) {
|
|
LOGF(ERROR) << "Lock called on multi-planar buffer 0x" << std::hex
|
|
<< bufferHandle;
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (buffer_context->type == GRALLOC) {
|
|
auto &mapper = get_mapperservice();
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
LOGD("lock buffer:%p", &buffer);
|
|
|
|
IMapper::Rect accessRegion = {(int)x, (int)y, (int)width, (int)height};
|
|
|
|
android::hardware::hidl_handle acquireFenceHandle; // dummy
|
|
|
|
Error error;
|
|
auto ret = mapper.lock(buffer,
|
|
flags,
|
|
accessRegion,
|
|
acquireFenceHandle,
|
|
[&](const auto& tmpError, const auto& tmpData) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*out_addr = tmpData;
|
|
});
|
|
|
|
error = (ret.isOk()) ? error : kTransactionError;
|
|
|
|
ALOGE_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
|
|
|
|
return (int)error;
|
|
} else {
|
|
NOTREACHED() << "Invalid buffer type: " << buffer_context->type;
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::LockYCbCr(buffer_handle_t buffer,
|
|
uint32_t flags,
|
|
uint32_t x,
|
|
uint32_t y,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
struct android_ycbcr* out_ycbcr) {
|
|
LOGD("LockYCbCr");
|
|
base::AutoLock l(lock_);
|
|
|
|
auto context_it = buffer_context_.find(buffer);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << buffer;
|
|
return -EINVAL;
|
|
}
|
|
auto buffer_context = context_it->second.get();
|
|
uint32_t num_planes = GetNumPlanes(buffer);
|
|
if (!num_planes) {
|
|
return -EINVAL;
|
|
}
|
|
if (num_planes < 2) {
|
|
LOGF(ERROR) << "LockYCbCr called on single-planar buffer 0x" << std::hex
|
|
<< buffer_context->buffer_id;
|
|
return -EINVAL;
|
|
}
|
|
|
|
DCHECK_LE(num_planes, 3u);
|
|
|
|
if (buffer_context->type == GRALLOC) {
|
|
auto &mapper = get_mapperservice();
|
|
std::vector<PlaneLayout> planeLayouts;
|
|
|
|
int error = get_metadata(mapper, buffer, MetadataType_PlaneLayouts, decodePlaneLayouts, &planeLayouts);
|
|
if (error != android::NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
void* data = nullptr;
|
|
error = Lockinternal(buffer, flags, x, y, width, height, &data);
|
|
if (error != android::NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
android_ycbcr ycbcr;
|
|
|
|
ycbcr.y = nullptr;
|
|
ycbcr.cb = nullptr;
|
|
ycbcr.cr = nullptr;
|
|
ycbcr.ystride = 0;
|
|
ycbcr.cstride = 0;
|
|
ycbcr.chroma_step = 0;
|
|
|
|
for (const auto& planeLayout : planeLayouts) {
|
|
for (const auto& planeLayoutComponent : planeLayout.components) {
|
|
if (!android::gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
|
|
continue;
|
|
}
|
|
if (0 != planeLayoutComponent.offsetInBits % 8) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
uint8_t* tmpData = static_cast<uint8_t*>(data) + planeLayout.offsetInBytes +
|
|
(planeLayoutComponent.offsetInBits / 8);
|
|
uint64_t sampleIncrementInBytes;
|
|
|
|
auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
|
|
switch (type) {
|
|
case PlaneLayoutComponentType::Y:
|
|
if ((ycbcr.y != nullptr) || (planeLayoutComponent.sizeInBits != 8) ||
|
|
(planeLayout.sampleIncrementInBits != 8)) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
ycbcr.y = tmpData;
|
|
ycbcr.ystride = planeLayout.strideInBytes;
|
|
break;
|
|
|
|
case PlaneLayoutComponentType::CB:
|
|
case PlaneLayoutComponentType::CR:
|
|
if (planeLayout.sampleIncrementInBits % 8 != 0) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
|
|
if ((sampleIncrementInBytes != 1) && (sampleIncrementInBytes != 2)) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
if (ycbcr.cstride == 0 && ycbcr.chroma_step == 0) {
|
|
ycbcr.cstride = planeLayout.strideInBytes;
|
|
ycbcr.chroma_step = sampleIncrementInBytes;
|
|
} else {
|
|
if ((static_cast<int64_t>(ycbcr.cstride) != planeLayout.strideInBytes) ||
|
|
(ycbcr.chroma_step != sampleIncrementInBytes)) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
}
|
|
|
|
if (type == PlaneLayoutComponentType::CB) {
|
|
if (ycbcr.cb != nullptr) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
ycbcr.cb = tmpData;
|
|
} else {
|
|
if (ycbcr.cr != nullptr) {
|
|
Unlockinternal(buffer);
|
|
return android::BAD_VALUE;
|
|
}
|
|
ycbcr.cr = tmpData;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
|
|
*out_ycbcr = ycbcr;
|
|
|
|
}
|
|
LOGD("lock ycbcr ok");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::Unlock(buffer_handle_t bufferHandle) {
|
|
LOGD("Unlock buffer:%p", bufferHandle);
|
|
base::AutoLock l(lock_);
|
|
|
|
auto context_it = buffer_context_.find(bufferHandle);
|
|
if (context_it == buffer_context_.end()) {
|
|
LOGF(ERROR) << "Unknown buffer 0x" << std::hex << bufferHandle;
|
|
return -EINVAL;
|
|
}
|
|
auto buffer_context = context_it->second.get();
|
|
if (buffer_context->type == GRALLOC) {
|
|
auto &mapper = get_mapperservice();
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
LOGD("Unlock buffer:%p", buffer);
|
|
|
|
int releaseFence = -1;
|
|
Error error;
|
|
auto ret = mapper.unlock(buffer,
|
|
[&](const auto& tmpError, const auto& tmpReleaseFence)
|
|
{
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
|
|
auto fenceHandle = tmpReleaseFence.getNativeHandle(); // 预期 unlock() 不会返回有效的 release_fence.
|
|
if (fenceHandle && fenceHandle->numFds == 1)
|
|
{
|
|
ALOGE("got unexpected valid fd of release_fence : %d", fenceHandle->data[0]);
|
|
|
|
int fd = dup(fenceHandle->data[0]);
|
|
if (fd >= 0) {
|
|
releaseFence = fd;
|
|
} else {
|
|
ALOGE("failed to dup unlock release fence");
|
|
sync_wait(fenceHandle->data[0], -1);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("unlock(%p) failed with %d", bufferHandle, error);
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int CameraBufferManagerImpl::FlushCache(buffer_handle_t buffer) {
|
|
int fd = -1;
|
|
|
|
auto &mapper = get_mapperservice();
|
|
std::vector<int64_t> fds;
|
|
|
|
int err = get_metadata(mapper, buffer, ArmMetadataType_PLANE_FDS, decodeArmPlaneFds, &fds);
|
|
if (err != android::OK)
|
|
{
|
|
ALOGE("Failed to get plane_fds. err : %d", err);
|
|
return err;
|
|
}
|
|
assert (fds.size() > 0);
|
|
|
|
fd = (int)(fds[0]);
|
|
if (fd == -1) {
|
|
LOGF(ERROR) << "get fd error for buffer 0x" << std::hex << buffer;
|
|
return -EINVAL;
|
|
}
|
|
|
|
/*struct dma_buf_sync sync_args;
|
|
sync_args.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
|
|
if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync_args))
|
|
return -EINVAL;*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::GetHandleFd(buffer_handle_t buffer) {
|
|
LOGD("GetHandleFd buffer:%p", buffer);
|
|
int fd = -1;
|
|
|
|
auto &mapper = get_mapperservice();
|
|
std::vector<int64_t> fds;
|
|
|
|
int err = get_metadata(mapper, buffer, ArmMetadataType_PLANE_FDS, decodeArmPlaneFds, &fds);
|
|
if (err != android::OK)
|
|
{
|
|
ALOGE("Failed to get plane_fds. err : %d", err);
|
|
return err;
|
|
}
|
|
assert (fds.size() > 0);
|
|
|
|
fd = (int)(fds[0]);
|
|
|
|
return fd;
|
|
}
|
|
|
|
int CameraBufferManagerImpl::AllocateGrallocBuffer(size_t width,
|
|
size_t height,
|
|
uint32_t format,
|
|
uint32_t usage,
|
|
buffer_handle_t* out_buffer,
|
|
uint32_t* out_stride) {
|
|
LOGD("AllocateGrallocBuffer %d, %d, %d, %d", width, height, format, usage);
|
|
base::AutoLock l(lock_);
|
|
|
|
IMapper::BufferDescriptorInfo descriptorInfo;
|
|
sBufferDescriptorInfo("allocateBuffer", width, height, (PixelFormat)format, 1/*layerCount*/, usage, &descriptorInfo);
|
|
|
|
BufferDescriptor descriptor;
|
|
status_t error = createDescriptor(static_cast<void*>(&descriptorInfo),
|
|
static_cast<void*>(&descriptor));
|
|
if (error != android::NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
std::unique_ptr<BufferContext> buffer_context(new struct BufferContext);
|
|
|
|
buffer_context->buffer_id = reinterpret_cast<uint64_t>(buffer_context.get());
|
|
buffer_context->type = GRALLOC;
|
|
|
|
int bufferCount = 1;
|
|
#if defined(ANDROID_VERSION_ABOVE_13_X)
|
|
if (hasIAllocatorAidl()) {
|
|
AllocationResult result;
|
|
auto &mAidlAllocator = get_aidl_allocservice();
|
|
auto status = mAidlAllocator.allocate(descriptor, bufferCount, &result);
|
|
if (!status.isOk()) {
|
|
error = status.getExceptionCode();
|
|
if (error == EX_SERVICE_SPECIFIC) {
|
|
error = status.getServiceSpecificError();
|
|
}
|
|
if (error == android::OK) {
|
|
error = android::UNKNOWN_ERROR;
|
|
}
|
|
} else {
|
|
#if IMPORTBUFFER_CB == 1
|
|
for (uint32_t i = 0; i < bufferCount; i++) {
|
|
auto handle = android::makeFromAidl(result.buffers[i]);
|
|
error = importBuffer(handle, out_buffer);
|
|
native_handle_delete(handle);
|
|
if (error != android::NO_ERROR) {
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
freeBuffer(*out_buffer);
|
|
*out_buffer = nullptr;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
for (uint32_t i = 0; i < bufferCount; i++) {
|
|
*out_buffer = dupFromAidl(result.buffers[i]);
|
|
if (!out_buffer) {
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
// auto buffer = const_cast<native_handle_t*>(outBufferHandles[j]);
|
|
native_handle_close(out_buffer);
|
|
native_handle_delete(out_buffer);
|
|
*out_buffer = nullptr;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
*out_stride = result.stride;
|
|
}
|
|
// Release all the resources held by AllocationResult (specifically any remaining FDs)
|
|
LOGD("AllocateGrallocBuffer with aidl %p", *out_buffer);
|
|
buffer_context->usage = 1;
|
|
buffer_context_[*out_buffer] = std::move(buffer_context);
|
|
|
|
result = {};
|
|
// make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
|
|
android::hardware::IPCThreadState::self()->flushCommands();
|
|
return error;
|
|
}
|
|
LOGD("Get back to gralloc 4 hidl.");
|
|
#endif
|
|
auto &allocator = get_allocservice();
|
|
auto ret = allocator.allocate(descriptor, bufferCount,
|
|
[&](const auto& tmpError, const auto& tmpStride,
|
|
const auto& tmpBuffers) {
|
|
error = static_cast<status_t>(tmpError);
|
|
if (tmpError != Error::NONE) {
|
|
return;
|
|
}
|
|
|
|
#if IMPORTBUFFER_CB == 1
|
|
for (uint32_t i = 0; i < bufferCount; i++) {
|
|
error = importBuffer(tmpBuffers[i],
|
|
out_buffer);
|
|
if (error != android::NO_ERROR) {
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
freeBuffer(*out_buffer);
|
|
*out_buffer = nullptr;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
#else
|
|
for (uint32_t i = 0; i < bufferCount; i++) {
|
|
*out_buffer = native_handle_clone(
|
|
tmpBuffers[i].getNativeHandle());
|
|
if (!out_buffer) {
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
//auto buffer = const_cast<native_handle_t*>(
|
|
// out_buffer);
|
|
native_handle_close(out_buffer);
|
|
native_handle_delete(out_buffer);
|
|
*out_buffer = nullptr;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
*out_stride = tmpStride;
|
|
});
|
|
|
|
if (!ret.isOk())
|
|
return -EINVAL;
|
|
|
|
LOGD("AllocateGrallocBuffer %p", *out_buffer);
|
|
buffer_context->usage = 1;
|
|
buffer_context_[*out_buffer] = std::move(buffer_context);
|
|
|
|
// make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
|
|
android::hardware::IPCThreadState::self()->flushCommands();
|
|
|
|
return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
|
|
}
|
|
|
|
} // namespace arc
|