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
ISVProcessor(bool canCallJava,sp<ISVBufferManager> bufferManager,sp<ISVProcessorObserver> owner,uint32_t width,uint32_t height)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
~ISVProcessor()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
readyToRun()90 status_t ISVProcessor::readyToRun()
91 {
92 mThreadId = androidGetThreadId();
93 //do init ops here
94 return Thread::readyToRun();
95 }
96
start()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
stop()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
getBufForFirmwareOutput(Vector<ISVBuffer * > * fillBufList,uint32_t * fillBufNum)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
updateFirmwareOutputBufStatus(uint32_t fillBufNum)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
getBufForFirmwareInput(Vector<ISVBuffer * > * procBufList,ISVBuffer ** inputBuf,uint32_t * procBufNum)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
updateFirmwareInputBufStatus(uint32_t procBufNum)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
isReadytoRun()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
threadLoop()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
isCurrentThread() const424 bool ISVProcessor::isCurrentThread() const {
425 return mThreadId == androidGetThreadId();
426 }
427
isFrameRateValid(uint32_t fps)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
configFRC(uint32_t fps)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
calculateFps(int64_t timeStamp,uint32_t * fps)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
configFilters(OMX_BUFFERHEADERTYPE * buffer)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
addInput(OMX_BUFFERHEADERTYPE * input)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
addOutput(OMX_BUFFERHEADERTYPE * output)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
notifyFlush()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
waitFlushFinished()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
flush()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