C++程序  |  668行  |  21.7 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 <math.h>
#include <utils/Errors.h>
#include "isv_processor.h"
#include "isv_profile.h"
#include "isv_omxcomponent.h"

//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "isv-omxil"

using namespace android;

#define MAX_RETRY_NUM   10

ISVProcessor::ISVProcessor(bool canCallJava,
        sp<ISVBufferManager> bufferManager,
        sp<ISVProcessorObserver> owner,
        uint32_t width, uint32_t height)
    :Thread(canCallJava),
    mpOwner(owner),
    mThreadId(NULL),
    mThreadRunning(false),
    mISVWorker(NULL),
    mBufferManager(bufferManager),
    mOutputProcIdx(0),
    mInputProcIdx(0),
    mNumTaskInProcesing(0),
    mNumRetry(0),
    mError(false),
    mbFlush(false),
    mbBypass(false),
    mFlagEnd(false),
    mFilters(0)
{
    //FIXME: for 1920 x 1088, we also consider it as 1080p
    mISVProfile = new ISVProfile(width, (height == 1088) ? 1080 : height);

    // get platform ISV cap first
    mFilters = mISVProfile->getFilterStatus();

    // turn off filters if dynamic vpp/frc setting is off
    if (!ISVProfile::isVPPOn())
        mFilters &= FilterFrameRateConversion;

    if (!ISVProfile::isFRCOn())
        mFilters &= ~FilterFrameRateConversion;

    //FIXME: move this into profile.
    if (width > 2048)
        mFilters &= ~FilterSharpening;

    memset(&mFilterParam, 0, sizeof(mFilterParam));
    //FIXME: we don't support scaling yet, so set src region equal to dst region
    mFilterParam.srcWidth = mFilterParam.dstWidth = width;
    mFilterParam.srcHeight = mFilterParam.dstHeight = height;
    mOutputBuffers.clear();
    mInputBuffers.clear();
    mTimeWindow.clear();
}

ISVProcessor::~ISVProcessor() {
    ALOGV("ISVProcessor is deleted");
    flush();
    mOutputBuffers.clear();
    mInputBuffers.clear();

    mISVProfile = NULL;
    mFilters = 0;
    memset(&mFilterParam, 0, sizeof(mFilterParam));
}

status_t ISVProcessor::readyToRun()
{
    mThreadId = androidGetThreadId();
    //do init ops here
    return Thread::readyToRun();
}

void ISVProcessor::start()
{
    ALOGD_IF(ISV_THREAD_DEBUG, "ISVProcessor::start");

    if (mISVWorker == NULL) {
        mISVWorker = new ISVWorker();
        if (STATUS_OK != mISVWorker->init(mFilterParam.srcWidth, mFilterParam.srcHeight))
            ALOGE("%s: mISVWorker init failed", __func__);
    }

    mBufferManager->setWorker(mISVWorker);

    this->run("ISVProcessor", ANDROID_PRIORITY_NORMAL);
    mThreadRunning = true;
    return;
}

void ISVProcessor::stop()
{
    ALOGD_IF(ISV_THREAD_DEBUG, "ISVProcessor::stop");

    if(mThreadRunning) {
        this->requestExit();
        {
            Mutex::Autolock autoLock(mLock);
            mRunCond.signal();
        }
        this->requestExitAndWait();
        mThreadRunning = false;
    }

    if (STATUS_OK != mISVWorker->deinit())
        ALOGE("%s: mISVWorker deinit failed", __func__);

    mISVWorker = NULL;
    return;
}

bool ISVProcessor::getBufForFirmwareOutput(Vector<ISVBuffer*> *fillBufList,uint32_t *fillBufNum){
    uint32_t i = 0;
    // output buffer number for filling
    *fillBufNum = 0;
    uint32_t needFillNum = 0;
    OMX_BUFFERHEADERTYPE *outputBuffer;

    //output data available
    needFillNum = mISVWorker->getFillBufCount();
    if (mOutputProcIdx < needFillNum ||
            mInputProcIdx < 1) {
        ALOGE("%s: no enough input or output buffer which need to be sync", __func__);
        return false;
    }

    if ((needFillNum == 0) || (needFillNum > 4))
       return false;

    Mutex::Autolock autoLock(mOutputLock);
    for (i = 0; i < needFillNum; i++) {
        //fetch the render buffer from the top of output buffer queue
        outputBuffer = mOutputBuffers.itemAt(i);
        if (!outputBuffer) {
            ALOGE("%s: failed to fetch output buffer for sync.", __func__);
            return false;
        }
        unsigned long fillHandle = reinterpret_cast<unsigned long>(outputBuffer->pBuffer);
        ISVBuffer* fillBuf = mBufferManager->mapBuffer(fillHandle);
        fillBufList->push_back(fillBuf);
    }

    *fillBufNum  = i;
    return true;
}


status_t ISVProcessor::updateFirmwareOutputBufStatus(uint32_t fillBufNum) {
    int64_t timeUs;
    OMX_BUFFERHEADERTYPE *outputBuffer;
    OMX_BUFFERHEADERTYPE *inputBuffer;
    OMX_ERRORTYPE err;
    bool cropChanged = false;

    if (mInputBuffers.empty()) {
        ALOGE("%s: input buffer queue is empty. no buffer need to be sync", __func__);
        return UNKNOWN_ERROR;
    }

    if (mOutputBuffers.size() < fillBufNum) {
        ALOGE("%s: no enough output buffer which need to be sync", __func__);
        return UNKNOWN_ERROR;
    }
    // remove one buffer from intput buffer queue
    {
        Mutex::Autolock autoLock(mInputLock);
        inputBuffer = mInputBuffers.itemAt(0);
        unsigned long inputHandle = reinterpret_cast<unsigned long>(inputBuffer->pBuffer);
        ISVBuffer* inputBuf = mBufferManager->mapBuffer(inputHandle);
        uint32_t flags = inputBuf->getFlags();

        if (flags & ISVBuffer::ISV_BUFFER_CROP_CHANGED) {
            err = mpOwner->reportOutputCrop();
            if (err != OMX_ErrorNone) {
                ALOGE("%s: failed to reportOutputCrop", __func__);
                return UNKNOWN_ERROR;
            }
            cropChanged = true;
            inputBuf->unsetFlag(ISVBuffer::ISV_BUFFER_CROP_CHANGED);
        }

        err = mpOwner->releaseBuffer(kPortIndexInput, inputBuffer, false);
        if (err != OMX_ErrorNone) {
            ALOGE("%s: failed to fillInputBuffer", __func__);
            return UNKNOWN_ERROR;
        }

        mInputBuffers.removeAt(0);
        ALOGD_IF(
            ISV_THREAD_DEBUG,
            "%s: fetch buffer %" PRIuPTR " from input buffer queue for fill to "
            "decoder, and then queue size is %d", __func__,
            reinterpret_cast<uintptr_t>(inputBuffer), mInputBuffers.size());
        mInputProcIdx--;
    }

    //set the time stamp for interpreted frames
    {
        Mutex::Autolock autoLock(mOutputLock);
        timeUs = mOutputBuffers[0]->nTimeStamp;

        for(uint32_t i = 0; i < fillBufNum; i++) {
            outputBuffer = mOutputBuffers.itemAt(i);
            if (fillBufNum > 1) {
                if (mFilterParam.frameRate == 24) {
                    if (fillBufNum == 2) {
                        outputBuffer->nTimeStamp = timeUs + 1000000ll * (i + 1) / 60 - 1000000ll * 1 / 24;
                    } else if (fillBufNum == 3) {
                        outputBuffer->nTimeStamp = timeUs + 1000000ll * (i + 3) / 60 - 1000000ll * 2 / 24;
                    }
                }
                else
                    outputBuffer->nTimeStamp = timeUs - 1000000ll * (fillBufNum - i - 1) / (mFilterParam.frameRate * 2);
            }

            //return filled buffers for rendering
            //skip rendering for crop change
            err = mpOwner->releaseBuffer(kPortIndexOutput, outputBuffer, cropChanged);

            if (err != OMX_ErrorNone) {
                ALOGE("%s: failed to releaseOutputBuffer", __func__);
                return UNKNOWN_ERROR;
            }

            ALOGD_IF(
                ISV_THREAD_DEBUG,
                "%s: fetch buffer %" PRIuPTR "(timestamp %.2f ms) from output "
                "buffer queue for render, and then queue size is %d", __func__,
                reinterpret_cast<uintptr_t>(outputBuffer),
                outputBuffer->nTimeStamp/1E3, mOutputBuffers.size());
        }
        // remove filled buffers from output buffer queue
        mOutputBuffers.removeItemsAt(0, fillBufNum);
        mOutputProcIdx -= fillBufNum;
    }
    return OK;
}


bool ISVProcessor::getBufForFirmwareInput(Vector<ISVBuffer*> *procBufList,
                                   ISVBuffer **inputBuf,
                                   uint32_t *procBufNum)
{
    OMX_BUFFERHEADERTYPE *outputBuffer;
    OMX_BUFFERHEADERTYPE *inputBuffer;

    if (mbFlush) {
        *inputBuf = NULL;
        *procBufNum = 0;
        return true;
    }

    int32_t procBufCount = mISVWorker->getProcBufCount();
    if ((procBufCount == 0) || (procBufCount > 4)) {
       return false;
    }

    //fetch a input buffer for processing
    {
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mInputLock", __func__);
        Mutex::Autolock autoLock(mInputLock);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mInputLock", __func__);
        inputBuffer = mInputBuffers.itemAt(mInputProcIdx);
        if (!inputBuffer) {
            ALOGE("%s: failed to get input buffer for processing.", __func__);
            return false;
        }
        unsigned long inputHandle = reinterpret_cast<unsigned long>(inputBuffer->pBuffer);
        *inputBuf = mBufferManager->mapBuffer(inputHandle);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mInputLock", __func__);
    }

    //fetch output buffers for processing
    {
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mOutputLock", __func__);
        Mutex::Autolock autoLock(mOutputLock);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mOutputLock", __func__);
        for (int32_t i = 0; i < procBufCount; i++) {
            outputBuffer = mOutputBuffers.itemAt(mOutputProcIdx + i);
            if (!outputBuffer) {
                ALOGE("%s: failed to get output buffer for processing.", __func__);
                return false;
            }
            unsigned long outputHandle = reinterpret_cast<unsigned long>(outputBuffer->pBuffer);
            procBufList->push_back(mBufferManager->mapBuffer(outputHandle));
        }
        *procBufNum = procBufCount;
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mOutputLock", __func__);
    }

    return true;
}


status_t ISVProcessor::updateFirmwareInputBufStatus(uint32_t procBufNum)
{
    OMX_BUFFERHEADERTYPE *outputBuffer;
    OMX_BUFFERHEADERTYPE *inputBuffer;

    inputBuffer = mInputBuffers.itemAt(mInputProcIdx);
    mInputProcIdx++;

    Mutex::Autolock autoLock(mOutputLock);
    for(uint32_t i = 0; i < procBufNum; i++) {
        outputBuffer = mOutputBuffers.editItemAt(mOutputProcIdx + i);
        // set output buffer timestamp as the same as input
        outputBuffer->nTimeStamp = inputBuffer->nTimeStamp;
        outputBuffer->nFilledLen = inputBuffer->nFilledLen;
        outputBuffer->nOffset = inputBuffer->nOffset;
        outputBuffer->nFlags = inputBuffer->nFlags;
        //outputBuffer->nTickCount = inputBuffer->nTickCount;
        //outputBuffer->pMarkData = intputBuffer->pMarkData;
    }
    mOutputProcIdx += procBufNum;
    return OK;
}


bool ISVProcessor::isReadytoRun()
{
    ALOGD_IF(ISV_THREAD_DEBUG, "%s: mISVWorker->getProcBufCount() return %d", __func__,
            mISVWorker->getProcBufCount());
    if (mInputProcIdx < mInputBuffers.size() 
            && (mOutputBuffers.size() - mOutputProcIdx) >= mISVWorker->getProcBufCount())
       return true;
    else
       return false;
}


bool ISVProcessor::threadLoop() {
    uint32_t procBufNum = 0, fillBufNum = 0;
    ISVBuffer* inputBuf;
    Vector<ISVBuffer*> procBufList;
    Vector<ISVBuffer*> fillBufList;
    uint32_t flags = 0;
    bool bGetBufSuccess = true;

    Mutex::Autolock autoLock(mLock);

    if (!isReadytoRun() && !mbFlush) {
        mRunCond.wait(mLock);
    }

    if (isReadytoRun() || mbFlush) {
        procBufList.clear();
        bool bGetInBuf = getBufForFirmwareInput(&procBufList, &inputBuf, &procBufNum);
        if (bGetInBuf) {
            if (!mbFlush)
                flags = mInputBuffers[mInputProcIdx]->nFlags;
            status_t ret = mISVWorker->process(inputBuf, procBufList, procBufNum, mbFlush, flags);
            if (ret == STATUS_OK) {
                // for seek and EOS
                if (mbFlush) {
                    mISVWorker->reset();
                    flush();

                    mNumTaskInProcesing = 0;
                    mInputProcIdx = 0;
                    mOutputProcIdx = 0;

                    mbFlush = false;

                    Mutex::Autolock endLock(mEndLock);
                    mEndCond.signal();
                    return true;
                }
                mNumTaskInProcesing++;
                updateFirmwareInputBufStatus(procBufNum);
            } else {
                mbBypass = true;
                flush();
                ALOGE("VSP process error %d .... ISV changes to bypass mode", __LINE__);
            }
        }
    }

    ALOGV("mNumTaskInProcesing %d", mNumTaskInProcesing);
    while ((mNumTaskInProcesing > 0) && mNumTaskInProcesing >= mISVWorker->mNumForwardReferences && bGetBufSuccess ) {
        fillBufList.clear();
        bGetBufSuccess = getBufForFirmwareOutput(&fillBufList, &fillBufNum);
        ALOGD_IF(ISV_THREAD_DEBUG, "%s: bGetOutput %d, buf num %d", __func__,
                bGetBufSuccess, fillBufNum);
        if (bGetBufSuccess) {
            status_t ret = mISVWorker->fill(fillBufList, fillBufNum);
            if (ret == STATUS_OK) {
                mNumTaskInProcesing--;
                ALOGV("mNumTaskInProcesing: %d ...", mNumTaskInProcesing);
                updateFirmwareOutputBufStatus(fillBufNum);
            } else {
                mError = true;
                ALOGE("ISV read firmware data error! Thread EXIT...");
                return false;
            }
        }
    }

    return true;
}

bool ISVProcessor::isCurrentThread() const {
    return mThreadId == androidGetThreadId();
}

inline bool ISVProcessor::isFrameRateValid(uint32_t fps)
{
    return (fps == 15 || fps == 24 || fps == 25 || fps == 30 || fps == 50 || fps == 60) ? true : false;
}

status_t ISVProcessor::configFRC(uint32_t fps)
{
    if (isFrameRateValid(fps)) {
        if (fps == 50 || fps == 60) {
            ALOGD_IF(ISV_THREAD_DEBUG, "%s: %d fps don't need do FRC, so disable FRC", __func__, fps);
            mFilters &= ~FilterFrameRateConversion;
            mFilterParam.frcRate = FRC_RATE_1X;
        } else {
            mFilterParam.frameRate = fps;
            mFilterParam.frcRate = mISVProfile->getFRCRate(mFilterParam.frameRate);
            ALOGD_IF(ISV_THREAD_DEBUG, "%s: fps is set to %d, frc rate is %d", __func__,
                    mFilterParam.frameRate, mFilterParam.frcRate);
        }
        return OK;
    }

    return UNKNOWN_ERROR;
}

status_t ISVProcessor::calculateFps(int64_t timeStamp, uint32_t* fps)
{
    int32_t i = 0;
    *fps = 0;

    mTimeWindow.push_back(timeStamp);
    if (mTimeWindow.size() > WINDOW_SIZE) {
        mTimeWindow.removeAt(0);
    }
    else if (mTimeWindow.size() < WINDOW_SIZE)
        return NOT_ENOUGH_DATA;

    int64_t delta = mTimeWindow[WINDOW_SIZE-1] - mTimeWindow[0];
    if (delta == 0)
        return NOT_ENOUGH_DATA;

    *fps = ceil(1.0 / delta * 1E6 * (WINDOW_SIZE-1));
    return OK;
}

status_t ISVProcessor::configFilters(OMX_BUFFERHEADERTYPE* buffer)
{
    if ((mFilters & FilterFrameRateConversion) != 0) {
        if (!isFrameRateValid(mFilterParam.frameRate)) {
            if (mNumRetry++ < MAX_RETRY_NUM) {
                uint32_t fps = 0;
                if (OK != calculateFps(buffer->nTimeStamp, &fps))
                    return NOT_ENOUGH_DATA;

                if (OK != configFRC(fps))
                    return NOT_ENOUGH_DATA;
            } else {
                ALOGD_IF(ISV_THREAD_DEBUG, "%s: exceed max retry to get a valid frame rate(%d), disable FRC", __func__,
                        mFilterParam.frameRate);
                mFilters &= ~FilterFrameRateConversion;
                mFilterParam.frcRate = FRC_RATE_1X;
            }
        }
    }

    if ((buffer->nFlags & OMX_BUFFERFLAG_TFF) != 0 ||
            (buffer->nFlags & OMX_BUFFERFLAG_BFF) != 0)
        mFilters |= FilterDeinterlacing;
    else
        mFilters &= ~FilterDeinterlacing;

    if (mFilters == 0) {
        ALOGI("%s: no filter need to be config, bypass ISV", __func__);
        return UNKNOWN_ERROR;
    }

    //config filters to mISVWorker
    return (mISVWorker->configFilters(mFilters, &mFilterParam) == STATUS_OK) ? OK : UNKNOWN_ERROR;
}

void ISVProcessor::addInput(OMX_BUFFERHEADERTYPE* input)
{
    if (mbFlush) {
        mpOwner->releaseBuffer(kPortIndexInput, input, true);
        return;
    }

    if (mbBypass) {
        // return this buffer to framework
        mpOwner->releaseBuffer(kPortIndexOutput, input, false);
        return;
    }

    if (input->nFlags & OMX_BUFFERFLAG_EOS) {
        //the last buffer is the last to release
        notifyFlush();
        mpOwner->releaseBuffer(kPortIndexInput, input, true);
        return;
    }

    status_t ret = configFilters(input);
    if (ret == NOT_ENOUGH_DATA) {
        // release this buffer if frc is not ready.
        // send the buffer to framework
        mpOwner->releaseBuffer(kPortIndexOutput, input, false);
        ALOGD_IF(ISV_THREAD_DEBUG,
                 "%s: frc rate is not ready, release this buffer %" PRIuPTR
                 ", fps %d", __func__, reinterpret_cast<uintptr_t>(input),
                 mFilterParam.frameRate);
        return;
    } else if (ret == UNKNOWN_ERROR) {
        ALOGD_IF(ISV_THREAD_DEBUG, "%s: configFilters failed, bypass ISV", __func__);
        mbBypass = true;
        mpOwner->releaseBuffer(kPortIndexOutput, input, false);
        return;
    }

    {
        //put the decoded buffer into fill buffer queue
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mInputLock", __func__);
        Mutex::Autolock autoLock(mInputLock);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mInputLock", __func__);

        mInputBuffers.push_back(input);
        ALOGD_IF(ISV_THREAD_DEBUG,
                 "%s: hold pBuffer %" PRIuPTR " in input buffer queue. Input "
                 "queue size is %d, mInputProIdx %d. Output queue size is %d, "
                 "mOutputProcIdx %d", __func__,
                 reinterpret_cast<uintptr_t>(input), mInputBuffers.size(),
                 mInputProcIdx, mOutputBuffers.size(), mOutputProcIdx);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mInputLock", __func__);
    }

    {
        Mutex::Autolock autoLock(mLock);
        mRunCond.signal();
    }
    return;
}

void ISVProcessor::addOutput(OMX_BUFFERHEADERTYPE* output)
{
    if (mbFlush) {
        mpOwner->releaseBuffer(kPortIndexOutput, output, true);
        return;
    }

    if (mbBypass || mOutputBuffers.size() >= MIN_OUTPUT_NUM) {
        // return this buffer to decoder
        mpOwner->releaseBuffer(kPortIndexInput, output, false);
        return;
    }

    {
        //push the buffer into the output queue if it is not full
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mOutputLock", __func__);
        Mutex::Autolock autoLock(mOutputLock);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mOutputLock", __func__);

        mOutputBuffers.push_back(output);
        ALOGD_IF(ISV_THREAD_DEBUG,
                 "%s: hold pBuffer %" PRIuPTR " in output buffer queue. Input "
                 "queue size is %d, mInputProIdx %d. Output queue size is %d, "
                 "mOutputProcIdx %d", __func__,
                 reinterpret_cast<uintptr_t>(output), mInputBuffers.size(),
                 mInputProcIdx, mOutputBuffers.size(), mOutputProcIdx);
        ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mOutputLock", __func__);
    }

    {
        Mutex::Autolock autoLock(mLock);
        mRunCond.signal();
    }
    return;
}

void ISVProcessor::notifyFlush()
{
    if (mInputBuffers.empty() && mOutputBuffers.empty()) {
        ALOGD_IF(ISV_THREAD_DEBUG, "%s: input and ouput buffer queue is empty, nothing need to do", __func__);
        return;
    }

    Mutex::Autolock autoLock(mLock);
    //make sure the useful buffer will be sended to framework first
    OMX_BUFFERHEADERTYPE* pBuffer = NULL;
    {
        Mutex::Autolock autoLock(mInputLock);
        while (!mInputBuffers.empty()) {
            pBuffer = mInputBuffers.itemAt(0);
            mpOwner->releaseBuffer(kPortIndexInput, pBuffer, true);
            ALOGD_IF(ISV_THREAD_DEBUG,"%s: Flush the pBuffer %" PRIuPTR " in input buffer queue.",__func__, reinterpret_cast<uintptr_t>(pBuffer));
            mInputBuffers.removeAt(0);
        }
    }
    mbFlush = true;
    mRunCond.signal();
    ALOGD_IF(ISV_THREAD_DEBUG, "wake up proc thread");
    return;
}

void ISVProcessor::waitFlushFinished()
{
    Mutex::Autolock endLock(mEndLock);
    ALOGD_IF(ISV_THREAD_DEBUG, "waiting mEnd lock(seek finish) ");
    while(mbFlush) {
        mEndCond.wait(mEndLock);
    }
    return;
}

void ISVProcessor::flush()
{
    OMX_BUFFERHEADERTYPE* pBuffer = NULL;
    {
        Mutex::Autolock autoLock(mInputLock);
        while (!mInputBuffers.empty()) {
            pBuffer = mInputBuffers.itemAt(0);
            mpOwner->releaseBuffer(kPortIndexInput, pBuffer, true);
            ALOGD_IF(
                ISV_THREAD_DEBUG,
                "%s: Flush the pBuffer %" PRIuPTR " in input buffer queue.",
                __func__, reinterpret_cast<uintptr_t>(pBuffer));
            mInputBuffers.removeAt(0);
        }
    }
    {
        Mutex::Autolock autoLock(mOutputLock);
        while (!mOutputBuffers.empty()) {
            pBuffer = mOutputBuffers.itemAt(0);
            mpOwner->releaseBuffer(kPortIndexOutput, pBuffer, true);
            ALOGD_IF(
                ISV_THREAD_DEBUG,
                "%s: Flush the pBuffer %" PRIuPTR " in output buffer queue.",
                __func__, reinterpret_cast<uintptr_t>(pBuffer));
            mOutputBuffers.removeAt(0);
        }
    }
    //flush finished.
    return;
}