C++程序  |  283行  |  9.31 KB

/*
 * 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;
}