You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
9.3 KiB
282 lines
9.3 KiB
/* |
|
* Copyright (C) 2012 Intel Corporation. All rights reserved. |
|
* |
|
* 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. |
|
* |
|
*/ |
|
|
|
#include <inttypes.h> |
|
|
|
#include <media/hardware/HardwareAPI.h> |
|
#include <system/graphics.h> |
|
#include <nativebase/nativebase.h> |
|
|
|
#include "isv_bufmanager.h" |
|
#ifndef TARGET_VPP_USE_GEN |
|
#include "hal_public.h" |
|
#include <sync/sync.h> |
|
#endif |
|
|
|
//#define LOG_NDEBUG 0 |
|
#undef LOG_TAG |
|
#define LOG_TAG "isv-omxil" |
|
|
|
using namespace android; |
|
|
|
#define GRALLOC_SUB_BUFFER_MAX 3 |
|
#define RANDOM_BUFFER_SIZE 200 |
|
static char random_buf[RANDOM_BUFFER_SIZE]; |
|
|
|
ISVBuffer::~ISVBuffer() { |
|
if (mWorker != NULL) { |
|
ALOGV("%s: mSurface %d", __func__, mSurface); |
|
mWorker->freeSurface(&mSurface); |
|
} |
|
} |
|
|
|
status_t ISVBuffer::initBufferInfo(uint32_t hackFormat) |
|
{ |
|
if (mType == ISV_BUFFER_METADATA) { |
|
VideoDecoderOutputMetaData *metaData = |
|
reinterpret_cast<VideoDecoderOutputMetaData*>(mBuffer); |
|
|
|
if (metaData->eType != kMetadataBufferTypeGrallocSource) { |
|
ALOGE("%s: unsupported meta data format eType = %d", __func__, metaData->eType); |
|
return UNKNOWN_ERROR; |
|
} |
|
|
|
if (mGrallocHandle != 0) { |
|
if ((unsigned long)metaData->pHandle != mGrallocHandle) { |
|
if (STATUS_OK != mWorker->freeSurface(&mSurface)) { |
|
ALOGE("%s: free surface %d failed.", __func__, mSurface); |
|
return UNKNOWN_ERROR; |
|
} |
|
} else |
|
return OK; |
|
} |
|
mGrallocHandle = (unsigned long)metaData->pHandle; |
|
} else { |
|
if (mSurface != -1) |
|
return OK; |
|
mGrallocHandle = mBuffer; |
|
} |
|
|
|
int32_t err = 0; |
|
#ifdef TARGET_VPP_USE_GEN |
|
if (!mpGralloc) { |
|
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const**)&mpGralloc); |
|
if (0 != err) |
|
return UNKNOWN_ERROR; |
|
} |
|
ufo_buffer_details_t info; |
|
|
|
memset(&info, 0, sizeof(ufo_buffer_details_t)); |
|
err = mpGralloc->perform(mpGralloc, INTEL_UFO_GRALLOC_MODULE_PERFORM_GET_BO_INFO, mGrallocHandle, &info); |
|
|
|
if (0 != err) { |
|
ALOGE("%s: can't get graphic buffer info", __func__); |
|
} |
|
mWidth = info.width; |
|
mHeight = info.height; |
|
mStride = info.pitch; |
|
mColorFormat = info.format; |
|
#else |
|
if (!mpGralloc) { |
|
err = gralloc_open_img(&mpGralloc); |
|
if (0 != err) |
|
return UNKNOWN_ERROR; |
|
} |
|
IMG_native_handle_t* grallocHandle = (IMG_native_handle_t*)mGrallocHandle; |
|
mStride = grallocHandle->aiStride[0]; |
|
mSurfaceHeight = grallocHandle->iHeight; |
|
mColorFormat = (hackFormat != 0) ? hackFormat : grallocHandle->iFormat; |
|
#endif |
|
if (mWorker == NULL) { |
|
ALOGE("%s: mWorker == NULL!!", __func__); |
|
return UNKNOWN_ERROR; |
|
} |
|
|
|
if (STATUS_OK != mWorker->allocSurface(&mWidth, &mHeight, mStride, mColorFormat, mGrallocHandle, &mSurface)) { |
|
ALOGE("%s: alloc surface failed, mGrallocHandle %lu", __func__, mGrallocHandle); |
|
return UNKNOWN_ERROR; |
|
} |
|
|
|
ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, |
|
"%s: mWidth %d, mHeight %d, mStride %d, mColorFormat %d, " |
|
"mGrallocHandle %p, mSurface %d", |
|
__func__, mWidth, mHeight, mStride, mColorFormat, |
|
reinterpret_cast<void*>(mGrallocHandle), mSurface); |
|
return OK; |
|
} |
|
|
|
status_t ISVBuffer::clearIfNeed() |
|
{ |
|
#ifndef TARGET_VPP_USE_GEN |
|
static bool bRandomBufferInit = false; |
|
if (!bRandomBufferInit) { |
|
time_t my_time; |
|
srand((unsigned)time(&my_time)); |
|
for (int32_t i = 0; i < RANDOM_BUFFER_SIZE; i++) |
|
random_buf[i] = (char)(((double)rand()/(double)RAND_MAX) * 255.0); |
|
bRandomBufferInit = true; |
|
} |
|
|
|
if ((mFlags & ISV_BUFFER_NEED_CLEAR) && mpGralloc) { |
|
int32_t usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; |
|
void *vaddr[GRALLOC_SUB_BUFFER_MAX]; |
|
const gralloc1_rect_t r = { |
|
.width = (int32_t)mStride, |
|
.height = (int32_t)mSurfaceHeight |
|
}; |
|
int err, releaseFence = -1; |
|
|
|
err = gralloc_lock_async_img(mpGralloc, (buffer_handle_t)mGrallocHandle, usage, &r, &vaddr[0], -1); |
|
if (0 != err) { |
|
ALOGE("%s: get graphic buffer ptr failed", __func__); |
|
return UNKNOWN_ERROR; |
|
} |
|
|
|
int32_t buffer_size = mStride * mSurfaceHeight * 3 / 2; |
|
char* ptr = (char*)vaddr[0]; |
|
for (int32_t i = 0; i < buffer_size/RANDOM_BUFFER_SIZE; i++) { |
|
memcpy(ptr, random_buf, sizeof(random_buf)); |
|
ptr += sizeof(random_buf); |
|
} |
|
gralloc_unlock_async_img(mpGralloc, (buffer_handle_t)mGrallocHandle, &releaseFence); |
|
if (releaseFence >= 0) { |
|
sync_wait(releaseFence, -1); |
|
close(releaseFence); |
|
} |
|
ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: clear isv buffer %p finished, buffer size %d", __func__, this, buffer_size); |
|
mFlags &= ~ISV_BUFFER_NEED_CLEAR; |
|
} |
|
#endif |
|
return OK; |
|
} |
|
|
|
status_t ISVBufferManager::setBufferCount(int32_t size) |
|
{ |
|
Mutex::Autolock autoLock(mBufferLock); |
|
#if 0 |
|
if (!mBuffers.isEmpty()) { |
|
ALOGE("%s: the buffer queue should be empty before we set its size", __func__); |
|
return STATUS_ERROR; |
|
} |
|
#endif |
|
mBuffers.setCapacity(size); |
|
|
|
return OK; |
|
} |
|
|
|
status_t ISVBufferManager::freeBuffer(unsigned long handle) |
|
{ |
|
Mutex::Autolock autoLock(mBufferLock); |
|
for (uint32_t i = 0; i < mBuffers.size(); i++) { |
|
ISVBuffer* isvBuffer = mBuffers.itemAt(i); |
|
if (isvBuffer->getHandle() == handle) { |
|
delete isvBuffer; |
|
mBuffers.removeAt(i); |
|
ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, "%s: remove handle 0x%08lx, and then mBuffers.size() %d", __func__, |
|
handle, mBuffers.size()); |
|
return OK; |
|
} |
|
} |
|
|
|
ALOGW("%s: can't find buffer %lu", __func__, handle); |
|
return UNKNOWN_ERROR; |
|
} |
|
|
|
status_t ISVBufferManager::useBuffer(unsigned long handle) |
|
{ |
|
Mutex::Autolock autoLock(mBufferLock); |
|
if (handle == 0 || mBuffers.size() >= mBuffers.capacity()) |
|
return BAD_VALUE; |
|
|
|
for (uint32_t i = 0; i < mBuffers.size(); i++) { |
|
ISVBuffer* isvBuffer = mBuffers.itemAt(i); |
|
if (isvBuffer->getHandle() == handle) { |
|
ALOGE("%s: this buffer 0x%08lx has already been registered", __func__, handle); |
|
return UNKNOWN_ERROR; |
|
} |
|
} |
|
|
|
ISVBuffer* isvBuffer = new ISVBuffer(mWorker, handle, |
|
mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC, |
|
mNeedClearBuffers ? ISVBuffer::ISV_BUFFER_NEED_CLEAR : 0); |
|
|
|
ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, |
|
"%s: add handle 0x%08lx, and then mBuffers.size() %d", __func__, |
|
handle, mBuffers.size()); |
|
mBuffers.push_back(isvBuffer); |
|
return OK; |
|
|
|
} |
|
|
|
status_t ISVBufferManager::useBuffer(const sp<ANativeWindowBuffer> nativeBuffer) |
|
{ |
|
Mutex::Autolock autoLock(mBufferLock); |
|
if (nativeBuffer == NULL || mBuffers.size() >= mBuffers.capacity()) |
|
return BAD_VALUE; |
|
|
|
for (uint32_t i = 0; i < mBuffers.size(); i++) { |
|
ISVBuffer* isvBuffer = mBuffers.itemAt(i); |
|
if (isvBuffer->getHandle() == (unsigned long)nativeBuffer->handle) { |
|
ALOGE( |
|
"%s: this buffer 0x%08" PRIxPTR " has already been registered", |
|
__func__, reinterpret_cast<uintptr_t>(nativeBuffer->handle)); |
|
return UNKNOWN_ERROR; |
|
} |
|
} |
|
|
|
ISVBuffer* isvBuffer = new ISVBuffer(mWorker, |
|
(unsigned long)nativeBuffer->handle, (unsigned long)nativeBuffer->handle, |
|
nativeBuffer->width, nativeBuffer->height, |
|
nativeBuffer->stride, nativeBuffer->format, |
|
mMetaDataMode ? ISVBuffer::ISV_BUFFER_METADATA : ISVBuffer::ISV_BUFFER_GRALLOC, |
|
mNeedClearBuffers ? ISVBuffer::ISV_BUFFER_NEED_CLEAR : 0); |
|
|
|
ALOGD_IF(ISV_BUFFER_MANAGER_DEBUG, |
|
"%s: add handle 0x%08" PRIxPTR ", and then mBuffers.size() %d", |
|
__func__, reinterpret_cast<uintptr_t>(nativeBuffer->handle), |
|
mBuffers.size()); |
|
mBuffers.push_back(isvBuffer); |
|
return OK; |
|
} |
|
|
|
ISVBuffer* ISVBufferManager::mapBuffer(unsigned long handle) |
|
{ |
|
Mutex::Autolock autoLock(mBufferLock); |
|
for (uint32_t i = 0; i < mBuffers.size(); i++) { |
|
ISVBuffer* isvBuffer = mBuffers.itemAt(i); |
|
if (isvBuffer->getHandle() == handle) |
|
return isvBuffer; |
|
} |
|
return NULL; |
|
} |
|
|
|
status_t ISVBufferManager::setBuffersFlag(uint32_t flag) |
|
{ |
|
Mutex::Autolock autoLock(mBufferLock); |
|
|
|
if (flag & ISVBuffer::ISV_BUFFER_NEED_CLEAR) { |
|
if (mBuffers.size() == 0) |
|
mNeedClearBuffers = true; |
|
else { |
|
for (uint32_t i = 0; i < mBuffers.size(); i++) { |
|
ISVBuffer* isvBuffer = mBuffers.itemAt(i); |
|
isvBuffer->setFlag(ISVBuffer::ISV_BUFFER_NEED_CLEAR); |
|
} |
|
} |
|
} |
|
return OK; |
|
}
|
|
|