C++程序  |  160行  |  4.86 KB

/*
 * Copyright (C) 2012 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 "CpuConsumer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Log.h>

#include <gui/CpuConsumer.h>

#define CC_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
#define CC_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
#define CC_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
#define CC_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
#define CC_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)

namespace android {

CpuConsumer::CpuConsumer(uint32_t maxLockedBuffers) :
    ConsumerBase(new BufferQueue(true) ),
    mMaxLockedBuffers(maxLockedBuffers),
    mCurrentLockedBuffers(0)
{

    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        mBufferPointers[i] = NULL;
    }

    mBufferQueue->setSynchronousMode(true);
    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
    mBufferQueue->setMaxAcquiredBufferCount(maxLockedBuffers);
}

CpuConsumer::~CpuConsumer() {
}

void CpuConsumer::setName(const String8& name) {
    Mutex::Autolock _l(mMutex);
    mName = name;
    mBufferQueue->setConsumerName(name);
}

status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
    status_t err;

    if (!nativeBuffer) return BAD_VALUE;
    if (mCurrentLockedBuffers == mMaxLockedBuffers) {
        return INVALID_OPERATION;
    }

    BufferQueue::BufferItem b;

    Mutex::Autolock _l(mMutex);

    err = acquireBufferLocked(&b);
    if (err != OK) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            return BAD_VALUE;
        } else {
            CC_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
            return err;
        }
    }

    int buf = b.mBuf;

    if (b.mFence.get()) {
        err = b.mFence->waitForever(1000, "CpuConsumer::lockNextBuffer");
        if (err != OK) {
            CC_LOGE("Failed to wait for fence of acquired buffer: %s (%d)",
                    strerror(-err), err);
            return err;
        }
    }

    err = mSlots[buf].mGraphicBuffer->lock(
        GraphicBuffer::USAGE_SW_READ_OFTEN,
        b.mCrop,
        &mBufferPointers[buf]);

    if (mBufferPointers[buf] != NULL && err != OK) {
        CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err),
                err);
        return err;
    }

    nativeBuffer->data   = reinterpret_cast<uint8_t*>(mBufferPointers[buf]);
    nativeBuffer->width  = mSlots[buf].mGraphicBuffer->getWidth();
    nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
    nativeBuffer->format = mSlots[buf].mGraphicBuffer->getPixelFormat();
    nativeBuffer->stride = mSlots[buf].mGraphicBuffer->getStride();

    nativeBuffer->crop        = b.mCrop;
    nativeBuffer->transform   = b.mTransform;
    nativeBuffer->scalingMode = b.mScalingMode;
    nativeBuffer->timestamp   = b.mTimestamp;
    nativeBuffer->frameNumber = b.mFrameNumber;

    mCurrentLockedBuffers++;

    return OK;
}

status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
    Mutex::Autolock _l(mMutex);
    int slotIndex = 0;
    status_t err;

    void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
    for (; slotIndex < BufferQueue::NUM_BUFFER_SLOTS; slotIndex++) {
        if (bufPtr == mBufferPointers[slotIndex]) break;
    }
    if (slotIndex == BufferQueue::NUM_BUFFER_SLOTS) {
        CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
        return BAD_VALUE;
    }

    mBufferPointers[slotIndex] = NULL;
    err = mSlots[slotIndex].mGraphicBuffer->unlock();
    if (err != OK) {
        CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__, slotIndex);
        return err;
    }
    releaseBufferLocked(slotIndex, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);

    mCurrentLockedBuffers--;

    return OK;
}

void CpuConsumer::freeBufferLocked(int slotIndex) {
    if (mBufferPointers[slotIndex] != NULL) {
        status_t err;
        CC_LOGW("Buffer %d freed while locked by consumer", slotIndex);
        mBufferPointers[slotIndex] = NULL;
        err = mSlots[slotIndex].mGraphicBuffer->unlock();
        if (err != OK) {
            CC_LOGE("%s: Unable to unlock graphic buffer %d", __FUNCTION__,
                    slotIndex);
        }
        mCurrentLockedBuffers--;
    }
    ConsumerBase::freeBufferLocked(slotIndex);
}

} // namespace android