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