Home | History | Annotate | Download | only in base
      1 /*
      2  * Copyright (C) 2012 Intel Corporation.  All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  */
     17 
     18 #include <inttypes.h>
     19 #include <math.h>
     20 #include <utils/Errors.h>
     21 #include "isv_processor.h"
     22 #include "isv_profile.h"
     23 #include "isv_omxcomponent.h"
     24 
     25 //#define LOG_NDEBUG 0
     26 #undef LOG_TAG
     27 #define LOG_TAG "isv-omxil"
     28 
     29 using namespace android;
     30 
     31 #define MAX_RETRY_NUM   10
     32 
     33 ISVProcessor::ISVProcessor(bool canCallJava,
     34         sp<ISVBufferManager> bufferManager,
     35         sp<ISVProcessorObserver> owner,
     36         uint32_t width, uint32_t height)
     37     :Thread(canCallJava),
     38     mpOwner(owner),
     39     mThreadId(NULL),
     40     mThreadRunning(false),
     41     mISVWorker(NULL),
     42     mBufferManager(bufferManager),
     43     mOutputProcIdx(0),
     44     mInputProcIdx(0),
     45     mNumTaskInProcesing(0),
     46     mNumRetry(0),
     47     mError(false),
     48     mbFlush(false),
     49     mbBypass(false),
     50     mFlagEnd(false),
     51     mFilters(0)
     52 {
     53     //FIXME: for 1920 x 1088, we also consider it as 1080p
     54     mISVProfile = new ISVProfile(width, (height == 1088) ? 1080 : height);
     55 
     56     // get platform ISV cap first
     57     mFilters = mISVProfile->getFilterStatus();
     58 
     59     // turn off filters if dynamic vpp/frc setting is off
     60     if (!ISVProfile::isVPPOn())
     61         mFilters &= FilterFrameRateConversion;
     62 
     63     if (!ISVProfile::isFRCOn())
     64         mFilters &= ~FilterFrameRateConversion;
     65 
     66     //FIXME: move this into profile.
     67     if (width > 2048)
     68         mFilters &= ~FilterSharpening;
     69 
     70     memset(&mFilterParam, 0, sizeof(mFilterParam));
     71     //FIXME: we don't support scaling yet, so set src region equal to dst region
     72     mFilterParam.srcWidth = mFilterParam.dstWidth = width;
     73     mFilterParam.srcHeight = mFilterParam.dstHeight = height;
     74     mOutputBuffers.clear();
     75     mInputBuffers.clear();
     76     mTimeWindow.clear();
     77 }
     78 
     79 ISVProcessor::~ISVProcessor() {
     80     ALOGV("ISVProcessor is deleted");
     81     flush();
     82     mOutputBuffers.clear();
     83     mInputBuffers.clear();
     84 
     85     mISVProfile = NULL;
     86     mFilters = 0;
     87     memset(&mFilterParam, 0, sizeof(mFilterParam));
     88 }
     89 
     90 status_t ISVProcessor::readyToRun()
     91 {
     92     mThreadId = androidGetThreadId();
     93     //do init ops here
     94     return Thread::readyToRun();
     95 }
     96 
     97 void ISVProcessor::start()
     98 {
     99     ALOGD_IF(ISV_THREAD_DEBUG, "ISVProcessor::start");
    100 
    101     if (mISVWorker == NULL) {
    102         mISVWorker = new ISVWorker();
    103         if (STATUS_OK != mISVWorker->init(mFilterParam.srcWidth, mFilterParam.srcHeight))
    104             ALOGE("%s: mISVWorker init failed", __func__);
    105     }
    106 
    107     mBufferManager->setWorker(mISVWorker);
    108 
    109     this->run("ISVProcessor", ANDROID_PRIORITY_NORMAL);
    110     mThreadRunning = true;
    111     return;
    112 }
    113 
    114 void ISVProcessor::stop()
    115 {
    116     ALOGD_IF(ISV_THREAD_DEBUG, "ISVProcessor::stop");
    117 
    118     if(mThreadRunning) {
    119         this->requestExit();
    120         {
    121             Mutex::Autolock autoLock(mLock);
    122             mRunCond.signal();
    123         }
    124         this->requestExitAndWait();
    125         mThreadRunning = false;
    126     }
    127 
    128     if (STATUS_OK != mISVWorker->deinit())
    129         ALOGE("%s: mISVWorker deinit failed", __func__);
    130 
    131     mISVWorker = NULL;
    132     return;
    133 }
    134 
    135 bool ISVProcessor::getBufForFirmwareOutput(Vector<ISVBuffer*> *fillBufList,uint32_t *fillBufNum){
    136     uint32_t i = 0;
    137     // output buffer number for filling
    138     *fillBufNum = 0;
    139     uint32_t needFillNum = 0;
    140     OMX_BUFFERHEADERTYPE *outputBuffer;
    141 
    142     //output data available
    143     needFillNum = mISVWorker->getFillBufCount();
    144     if (mOutputProcIdx < needFillNum ||
    145             mInputProcIdx < 1) {
    146         ALOGE("%s: no enough input or output buffer which need to be sync", __func__);
    147         return false;
    148     }
    149 
    150     if ((needFillNum == 0) || (needFillNum > 4))
    151        return false;
    152 
    153     Mutex::Autolock autoLock(mOutputLock);
    154     for (i = 0; i < needFillNum; i++) {
    155         //fetch the render buffer from the top of output buffer queue
    156         outputBuffer = mOutputBuffers.itemAt(i);
    157         if (!outputBuffer) {
    158             ALOGE("%s: failed to fetch output buffer for sync.", __func__);
    159             return false;
    160         }
    161         unsigned long fillHandle = reinterpret_cast<unsigned long>(outputBuffer->pBuffer);
    162         ISVBuffer* fillBuf = mBufferManager->mapBuffer(fillHandle);
    163         fillBufList->push_back(fillBuf);
    164     }
    165 
    166     *fillBufNum  = i;
    167     return true;
    168 }
    169 
    170 
    171 status_t ISVProcessor::updateFirmwareOutputBufStatus(uint32_t fillBufNum) {
    172     int64_t timeUs;
    173     OMX_BUFFERHEADERTYPE *outputBuffer;
    174     OMX_BUFFERHEADERTYPE *inputBuffer;
    175     OMX_ERRORTYPE err;
    176     bool cropChanged = false;
    177 
    178     if (mInputBuffers.empty()) {
    179         ALOGE("%s: input buffer queue is empty. no buffer need to be sync", __func__);
    180         return UNKNOWN_ERROR;
    181     }
    182 
    183     if (mOutputBuffers.size() < fillBufNum) {
    184         ALOGE("%s: no enough output buffer which need to be sync", __func__);
    185         return UNKNOWN_ERROR;
    186     }
    187     // remove one buffer from intput buffer queue
    188     {
    189         Mutex::Autolock autoLock(mInputLock);
    190         inputBuffer = mInputBuffers.itemAt(0);
    191         unsigned long inputHandle = reinterpret_cast<unsigned long>(inputBuffer->pBuffer);
    192         ISVBuffer* inputBuf = mBufferManager->mapBuffer(inputHandle);
    193         uint32_t flags = inputBuf->getFlags();
    194 
    195         if (flags & ISVBuffer::ISV_BUFFER_CROP_CHANGED) {
    196             err = mpOwner->reportOutputCrop();
    197             if (err != OMX_ErrorNone) {
    198                 ALOGE("%s: failed to reportOutputCrop", __func__);
    199                 return UNKNOWN_ERROR;
    200             }
    201             cropChanged = true;
    202             inputBuf->unsetFlag(ISVBuffer::ISV_BUFFER_CROP_CHANGED);
    203         }
    204 
    205         err = mpOwner->releaseBuffer(kPortIndexInput, inputBuffer, false);
    206         if (err != OMX_ErrorNone) {
    207             ALOGE("%s: failed to fillInputBuffer", __func__);
    208             return UNKNOWN_ERROR;
    209         }
    210 
    211         mInputBuffers.removeAt(0);
    212         ALOGD_IF(
    213             ISV_THREAD_DEBUG,
    214             "%s: fetch buffer %" PRIuPTR " from input buffer queue for fill to "
    215             "decoder, and then queue size is %d", __func__,
    216             reinterpret_cast<uintptr_t>(inputBuffer), mInputBuffers.size());
    217         mInputProcIdx--;
    218     }
    219 
    220     //set the time stamp for interpreted frames
    221     {
    222         Mutex::Autolock autoLock(mOutputLock);
    223         timeUs = mOutputBuffers[0]->nTimeStamp;
    224 
    225         for(uint32_t i = 0; i < fillBufNum; i++) {
    226             outputBuffer = mOutputBuffers.itemAt(i);
    227             if (fillBufNum > 1) {
    228                 if (mFilterParam.frameRate == 24) {
    229                     if (fillBufNum == 2) {
    230                         outputBuffer->nTimeStamp = timeUs + 1000000ll * (i + 1) / 60 - 1000000ll * 1 / 24;
    231                     } else if (fillBufNum == 3) {
    232                         outputBuffer->nTimeStamp = timeUs + 1000000ll * (i + 3) / 60 - 1000000ll * 2 / 24;
    233                     }
    234                 }
    235                 else
    236                     outputBuffer->nTimeStamp = timeUs - 1000000ll * (fillBufNum - i - 1) / (mFilterParam.frameRate * 2);
    237             }
    238 
    239             //return filled buffers for rendering
    240             //skip rendering for crop change
    241             err = mpOwner->releaseBuffer(kPortIndexOutput, outputBuffer, cropChanged);
    242 
    243             if (err != OMX_ErrorNone) {
    244                 ALOGE("%s: failed to releaseOutputBuffer", __func__);
    245                 return UNKNOWN_ERROR;
    246             }
    247 
    248             ALOGD_IF(
    249                 ISV_THREAD_DEBUG,
    250                 "%s: fetch buffer %" PRIuPTR "(timestamp %.2f ms) from output "
    251                 "buffer queue for render, and then queue size is %d", __func__,
    252                 reinterpret_cast<uintptr_t>(outputBuffer),
    253                 outputBuffer->nTimeStamp/1E3, mOutputBuffers.size());
    254         }
    255         // remove filled buffers from output buffer queue
    256         mOutputBuffers.removeItemsAt(0, fillBufNum);
    257         mOutputProcIdx -= fillBufNum;
    258     }
    259     return OK;
    260 }
    261 
    262 
    263 bool ISVProcessor::getBufForFirmwareInput(Vector<ISVBuffer*> *procBufList,
    264                                    ISVBuffer **inputBuf,
    265                                    uint32_t *procBufNum)
    266 {
    267     OMX_BUFFERHEADERTYPE *outputBuffer;
    268     OMX_BUFFERHEADERTYPE *inputBuffer;
    269 
    270     if (mbFlush) {
    271         *inputBuf = NULL;
    272         *procBufNum = 0;
    273         return true;
    274     }
    275 
    276     int32_t procBufCount = mISVWorker->getProcBufCount();
    277     if ((procBufCount == 0) || (procBufCount > 4)) {
    278        return false;
    279     }
    280 
    281     //fetch a input buffer for processing
    282     {
    283         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mInputLock", __func__);
    284         Mutex::Autolock autoLock(mInputLock);
    285         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mInputLock", __func__);
    286         inputBuffer = mInputBuffers.itemAt(mInputProcIdx);
    287         if (!inputBuffer) {
    288             ALOGE("%s: failed to get input buffer for processing.", __func__);
    289             return false;
    290         }
    291         unsigned long inputHandle = reinterpret_cast<unsigned long>(inputBuffer->pBuffer);
    292         *inputBuf = mBufferManager->mapBuffer(inputHandle);
    293         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mInputLock", __func__);
    294     }
    295 
    296     //fetch output buffers for processing
    297     {
    298         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mOutputLock", __func__);
    299         Mutex::Autolock autoLock(mOutputLock);
    300         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mOutputLock", __func__);
    301         for (int32_t i = 0; i < procBufCount; i++) {
    302             outputBuffer = mOutputBuffers.itemAt(mOutputProcIdx + i);
    303             if (!outputBuffer) {
    304                 ALOGE("%s: failed to get output buffer for processing.", __func__);
    305                 return false;
    306             }
    307             unsigned long outputHandle = reinterpret_cast<unsigned long>(outputBuffer->pBuffer);
    308             procBufList->push_back(mBufferManager->mapBuffer(outputHandle));
    309         }
    310         *procBufNum = procBufCount;
    311         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mOutputLock", __func__);
    312     }
    313 
    314     return true;
    315 }
    316 
    317 
    318 status_t ISVProcessor::updateFirmwareInputBufStatus(uint32_t procBufNum)
    319 {
    320     OMX_BUFFERHEADERTYPE *outputBuffer;
    321     OMX_BUFFERHEADERTYPE *inputBuffer;
    322 
    323     inputBuffer = mInputBuffers.itemAt(mInputProcIdx);
    324     mInputProcIdx++;
    325 
    326     Mutex::Autolock autoLock(mOutputLock);
    327     for(uint32_t i = 0; i < procBufNum; i++) {
    328         outputBuffer = mOutputBuffers.editItemAt(mOutputProcIdx + i);
    329         // set output buffer timestamp as the same as input
    330         outputBuffer->nTimeStamp = inputBuffer->nTimeStamp;
    331         outputBuffer->nFilledLen = inputBuffer->nFilledLen;
    332         outputBuffer->nOffset = inputBuffer->nOffset;
    333         outputBuffer->nFlags = inputBuffer->nFlags;
    334         //outputBuffer->nTickCount = inputBuffer->nTickCount;
    335         //outputBuffer->pMarkData = intputBuffer->pMarkData;
    336     }
    337     mOutputProcIdx += procBufNum;
    338     return OK;
    339 }
    340 
    341 
    342 bool ISVProcessor::isReadytoRun()
    343 {
    344     ALOGD_IF(ISV_THREAD_DEBUG, "%s: mISVWorker->getProcBufCount() return %d", __func__,
    345             mISVWorker->getProcBufCount());
    346     if (mInputProcIdx < mInputBuffers.size()
    347             && (mOutputBuffers.size() - mOutputProcIdx) >= mISVWorker->getProcBufCount())
    348        return true;
    349     else
    350        return false;
    351 }
    352 
    353 
    354 bool ISVProcessor::threadLoop() {
    355     uint32_t procBufNum = 0, fillBufNum = 0;
    356     ISVBuffer* inputBuf;
    357     Vector<ISVBuffer*> procBufList;
    358     Vector<ISVBuffer*> fillBufList;
    359     uint32_t flags = 0;
    360     bool bGetBufSuccess = true;
    361 
    362     Mutex::Autolock autoLock(mLock);
    363 
    364     if (!isReadytoRun() && !mbFlush) {
    365         mRunCond.wait(mLock);
    366     }
    367 
    368     if (isReadytoRun() || mbFlush) {
    369         procBufList.clear();
    370         bool bGetInBuf = getBufForFirmwareInput(&procBufList, &inputBuf, &procBufNum);
    371         if (bGetInBuf) {
    372             if (!mbFlush)
    373                 flags = mInputBuffers[mInputProcIdx]->nFlags;
    374             status_t ret = mISVWorker->process(inputBuf, procBufList, procBufNum, mbFlush, flags);
    375             if (ret == STATUS_OK) {
    376                 // for seek and EOS
    377                 if (mbFlush) {
    378                     mISVWorker->reset();
    379                     flush();
    380 
    381                     mNumTaskInProcesing = 0;
    382                     mInputProcIdx = 0;
    383                     mOutputProcIdx = 0;
    384 
    385                     mbFlush = false;
    386 
    387                     Mutex::Autolock endLock(mEndLock);
    388                     mEndCond.signal();
    389                     return true;
    390                 }
    391                 mNumTaskInProcesing++;
    392                 updateFirmwareInputBufStatus(procBufNum);
    393             } else {
    394                 mbBypass = true;
    395                 flush();
    396                 ALOGE("VSP process error %d .... ISV changes to bypass mode", __LINE__);
    397             }
    398         }
    399     }
    400 
    401     ALOGV("mNumTaskInProcesing %d", mNumTaskInProcesing);
    402     while ((mNumTaskInProcesing > 0) && mNumTaskInProcesing >= mISVWorker->mNumForwardReferences && bGetBufSuccess ) {
    403         fillBufList.clear();
    404         bGetBufSuccess = getBufForFirmwareOutput(&fillBufList, &fillBufNum);
    405         ALOGD_IF(ISV_THREAD_DEBUG, "%s: bGetOutput %d, buf num %d", __func__,
    406                 bGetBufSuccess, fillBufNum);
    407         if (bGetBufSuccess) {
    408             status_t ret = mISVWorker->fill(fillBufList, fillBufNum);
    409             if (ret == STATUS_OK) {
    410                 mNumTaskInProcesing--;
    411                 ALOGV("mNumTaskInProcesing: %d ...", mNumTaskInProcesing);
    412                 updateFirmwareOutputBufStatus(fillBufNum);
    413             } else {
    414                 mError = true;
    415                 ALOGE("ISV read firmware data error! Thread EXIT...");
    416                 return false;
    417             }
    418         }
    419     }
    420 
    421     return true;
    422 }
    423 
    424 bool ISVProcessor::isCurrentThread() const {
    425     return mThreadId == androidGetThreadId();
    426 }
    427 
    428 inline bool ISVProcessor::isFrameRateValid(uint32_t fps)
    429 {
    430     return (fps == 15 || fps == 24 || fps == 25 || fps == 30 || fps == 50 || fps == 60) ? true : false;
    431 }
    432 
    433 status_t ISVProcessor::configFRC(uint32_t fps)
    434 {
    435     if (isFrameRateValid(fps)) {
    436         if (fps == 50 || fps == 60) {
    437             ALOGD_IF(ISV_THREAD_DEBUG, "%s: %d fps don't need do FRC, so disable FRC", __func__, fps);
    438             mFilters &= ~FilterFrameRateConversion;
    439             mFilterParam.frcRate = FRC_RATE_1X;
    440         } else {
    441             mFilterParam.frameRate = fps;
    442             mFilterParam.frcRate = mISVProfile->getFRCRate(mFilterParam.frameRate);
    443             ALOGD_IF(ISV_THREAD_DEBUG, "%s: fps is set to %d, frc rate is %d", __func__,
    444                     mFilterParam.frameRate, mFilterParam.frcRate);
    445         }
    446         return OK;
    447     }
    448 
    449     return UNKNOWN_ERROR;
    450 }
    451 
    452 status_t ISVProcessor::calculateFps(int64_t timeStamp, uint32_t* fps)
    453 {
    454     int32_t i = 0;
    455     *fps = 0;
    456 
    457     mTimeWindow.push_back(timeStamp);
    458     if (mTimeWindow.size() > WINDOW_SIZE) {
    459         mTimeWindow.removeAt(0);
    460     }
    461     else if (mTimeWindow.size() < WINDOW_SIZE)
    462         return NOT_ENOUGH_DATA;
    463 
    464     int64_t delta = mTimeWindow[WINDOW_SIZE-1] - mTimeWindow[0];
    465     if (delta == 0)
    466         return NOT_ENOUGH_DATA;
    467 
    468     *fps = ceil(1.0 / delta * 1E6 * (WINDOW_SIZE-1));
    469     return OK;
    470 }
    471 
    472 status_t ISVProcessor::configFilters(OMX_BUFFERHEADERTYPE* buffer)
    473 {
    474     if ((mFilters & FilterFrameRateConversion) != 0) {
    475         if (!isFrameRateValid(mFilterParam.frameRate)) {
    476             if (mNumRetry++ < MAX_RETRY_NUM) {
    477                 uint32_t fps = 0;
    478                 if (OK != calculateFps(buffer->nTimeStamp, &fps))
    479                     return NOT_ENOUGH_DATA;
    480 
    481                 if (OK != configFRC(fps))
    482                     return NOT_ENOUGH_DATA;
    483             } else {
    484                 ALOGD_IF(ISV_THREAD_DEBUG, "%s: exceed max retry to get a valid frame rate(%d), disable FRC", __func__,
    485                         mFilterParam.frameRate);
    486                 mFilters &= ~FilterFrameRateConversion;
    487                 mFilterParam.frcRate = FRC_RATE_1X;
    488             }
    489         }
    490     }
    491 
    492     if ((buffer->nFlags & OMX_BUFFERFLAG_TFF) != 0 ||
    493             (buffer->nFlags & OMX_BUFFERFLAG_BFF) != 0)
    494         mFilters |= FilterDeinterlacing;
    495     else
    496         mFilters &= ~FilterDeinterlacing;
    497 
    498     if (mFilters == 0) {
    499         ALOGI("%s: no filter need to be config, bypass ISV", __func__);
    500         return UNKNOWN_ERROR;
    501     }
    502 
    503     //config filters to mISVWorker
    504     return (mISVWorker->configFilters(mFilters, &mFilterParam) == STATUS_OK) ? OK : UNKNOWN_ERROR;
    505 }
    506 
    507 void ISVProcessor::addInput(OMX_BUFFERHEADERTYPE* input)
    508 {
    509     if (mbFlush) {
    510         mpOwner->releaseBuffer(kPortIndexInput, input, true);
    511         return;
    512     }
    513 
    514     if (mbBypass) {
    515         // return this buffer to framework
    516         mpOwner->releaseBuffer(kPortIndexOutput, input, false);
    517         return;
    518     }
    519 
    520     if (input->nFlags & OMX_BUFFERFLAG_EOS) {
    521         //the last buffer is the last to release
    522         notifyFlush();
    523         mpOwner->releaseBuffer(kPortIndexInput, input, true);
    524         return;
    525     }
    526 
    527     status_t ret = configFilters(input);
    528     if (ret == NOT_ENOUGH_DATA) {
    529         // release this buffer if frc is not ready.
    530         // send the buffer to framework
    531         mpOwner->releaseBuffer(kPortIndexOutput, input, false);
    532         ALOGD_IF(ISV_THREAD_DEBUG,
    533                  "%s: frc rate is not ready, release this buffer %" PRIuPTR
    534                  ", fps %d", __func__, reinterpret_cast<uintptr_t>(input),
    535                  mFilterParam.frameRate);
    536         return;
    537     } else if (ret == UNKNOWN_ERROR) {
    538         ALOGD_IF(ISV_THREAD_DEBUG, "%s: configFilters failed, bypass ISV", __func__);
    539         mbBypass = true;
    540         mpOwner->releaseBuffer(kPortIndexOutput, input, false);
    541         return;
    542     }
    543 
    544     {
    545         //put the decoded buffer into fill buffer queue
    546         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mInputLock", __func__);
    547         Mutex::Autolock autoLock(mInputLock);
    548         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mInputLock", __func__);
    549 
    550         mInputBuffers.push_back(input);
    551         ALOGD_IF(ISV_THREAD_DEBUG,
    552                  "%s: hold pBuffer %" PRIuPTR " in input buffer queue. Input "
    553                  "queue size is %d, mInputProIdx %d. Output queue size is %d, "
    554                  "mOutputProcIdx %d", __func__,
    555                  reinterpret_cast<uintptr_t>(input), mInputBuffers.size(),
    556                  mInputProcIdx, mOutputBuffers.size(), mOutputProcIdx);
    557         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mInputLock", __func__);
    558     }
    559 
    560     {
    561         Mutex::Autolock autoLock(mLock);
    562         mRunCond.signal();
    563     }
    564     return;
    565 }
    566 
    567 void ISVProcessor::addOutput(OMX_BUFFERHEADERTYPE* output)
    568 {
    569     if (mbFlush) {
    570         mpOwner->releaseBuffer(kPortIndexOutput, output, true);
    571         return;
    572     }
    573 
    574     if (mbBypass || mOutputBuffers.size() >= MIN_OUTPUT_NUM) {
    575         // return this buffer to decoder
    576         mpOwner->releaseBuffer(kPortIndexInput, output, false);
    577         return;
    578     }
    579 
    580     {
    581         //push the buffer into the output queue if it is not full
    582         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqiring mOutputLock", __func__);
    583         Mutex::Autolock autoLock(mOutputLock);
    584         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: acqired mOutputLock", __func__);
    585 
    586         mOutputBuffers.push_back(output);
    587         ALOGD_IF(ISV_THREAD_DEBUG,
    588                  "%s: hold pBuffer %" PRIuPTR " in output buffer queue. Input "
    589                  "queue size is %d, mInputProIdx %d. Output queue size is %d, "
    590                  "mOutputProcIdx %d", __func__,
    591                  reinterpret_cast<uintptr_t>(output), mInputBuffers.size(),
    592                  mInputProcIdx, mOutputBuffers.size(), mOutputProcIdx);
    593         ALOGD_IF(ISV_COMPONENT_LOCK_DEBUG, "%s: releasing mOutputLock", __func__);
    594     }
    595 
    596     {
    597         Mutex::Autolock autoLock(mLock);
    598         mRunCond.signal();
    599     }
    600     return;
    601 }
    602 
    603 void ISVProcessor::notifyFlush()
    604 {
    605     if (mInputBuffers.empty() && mOutputBuffers.empty()) {
    606         ALOGD_IF(ISV_THREAD_DEBUG, "%s: input and ouput buffer queue is empty, nothing need to do", __func__);
    607         return;
    608     }
    609 
    610     Mutex::Autolock autoLock(mLock);
    611     //make sure the useful buffer will be sended to framework first
    612     OMX_BUFFERHEADERTYPE* pBuffer = NULL;
    613     {
    614         Mutex::Autolock autoLock(mInputLock);
    615         while (!mInputBuffers.empty()) {
    616             pBuffer = mInputBuffers.itemAt(0);
    617             mpOwner->releaseBuffer(kPortIndexInput, pBuffer, true);
    618             ALOGD_IF(ISV_THREAD_DEBUG,"%s: Flush the pBuffer %" PRIuPTR " in input buffer queue.",__func__, reinterpret_cast<uintptr_t>(pBuffer));
    619             mInputBuffers.removeAt(0);
    620         }
    621     }
    622     mbFlush = true;
    623     mRunCond.signal();
    624     ALOGD_IF(ISV_THREAD_DEBUG, "wake up proc thread");
    625     return;
    626 }
    627 
    628 void ISVProcessor::waitFlushFinished()
    629 {
    630     Mutex::Autolock endLock(mEndLock);
    631     ALOGD_IF(ISV_THREAD_DEBUG, "waiting mEnd lock(seek finish) ");
    632     while(mbFlush) {
    633         mEndCond.wait(mEndLock);
    634     }
    635     return;
    636 }
    637 
    638 void ISVProcessor::flush()
    639 {
    640     OMX_BUFFERHEADERTYPE* pBuffer = NULL;
    641     {
    642         Mutex::Autolock autoLock(mInputLock);
    643         while (!mInputBuffers.empty()) {
    644             pBuffer = mInputBuffers.itemAt(0);
    645             mpOwner->releaseBuffer(kPortIndexInput, pBuffer, true);
    646             ALOGD_IF(
    647                 ISV_THREAD_DEBUG,
    648                 "%s: Flush the pBuffer %" PRIuPTR " in input buffer queue.",
    649                 __func__, reinterpret_cast<uintptr_t>(pBuffer));
    650             mInputBuffers.removeAt(0);
    651         }
    652     }
    653     {
    654         Mutex::Autolock autoLock(mOutputLock);
    655         while (!mOutputBuffers.empty()) {
    656             pBuffer = mOutputBuffers.itemAt(0);
    657             mpOwner->releaseBuffer(kPortIndexOutput, pBuffer, true);
    658             ALOGD_IF(
    659                 ISV_THREAD_DEBUG,
    660                 "%s: Flush the pBuffer %" PRIuPTR " in output buffer queue.",
    661                 __func__, reinterpret_cast<uintptr_t>(pBuffer));
    662             mOutputBuffers.removeAt(0);
    663         }
    664     }
    665     //flush finished.
    666     return;
    667 }
    668