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
29using namespace android;
30
31#define MAX_RETRY_NUM   10
32
33ISVProcessor::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
79ISVProcessor::~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
90status_t ISVProcessor::readyToRun()
91{
92    mThreadId = androidGetThreadId();
93    //do init ops here
94    return Thread::readyToRun();
95}
96
97void 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
114void 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
135bool 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
171status_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
263bool 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
318status_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
342bool 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
354bool 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
424bool ISVProcessor::isCurrentThread() const {
425    return mThreadId == androidGetThreadId();
426}
427
428inline 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
433status_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
452status_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
472status_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
507void 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
567void 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
603void 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
628void 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
638void 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