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