GraphicBufferSource.cpp revision cf49a51ff59c3cd228d178d23252ac0d39d5a893
1/* 2 * Copyright (C) 2013 The Android Open Source Project 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#define LOG_TAG "GraphicBufferSource" 18//#define LOG_NDEBUG 0 19#include <utils/Log.h> 20 21#include "GraphicBufferSource.h" 22 23#include <OMX_Core.h> 24#include <media/stagefright/foundation/ADebug.h> 25#include <media/stagefright/foundation/AMessage.h> 26 27#include <media/hardware/MetadataBufferType.h> 28#include <ui/GraphicBuffer.h> 29 30namespace android { 31 32static const bool EXTRA_CHECK = true; 33 34 35GraphicBufferSource::GraphicBufferSource(OMXNodeInstance* nodeInstance, 36 uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bufferCount) : 37 mInitCheck(UNKNOWN_ERROR), 38 mNodeInstance(nodeInstance), 39 mExecuting(false), 40 mSuspended(false), 41 mNumFramesAvailable(0), 42 mEndOfStream(false), 43 mEndOfStreamSent(false), 44 mRepeatAfterUs(-1ll), 45 mMaxTimestampGapUs(-1ll), 46 mPrevOriginalTimeUs(-1ll), 47 mPrevModifiedTimeUs(-1ll), 48 mRepeatLastFrameGeneration(0), 49 mRepeatLastFrameTimestamp(-1ll), 50 mLatestSubmittedBufferId(-1), 51 mLatestSubmittedBufferFrameNum(0), 52 mLatestSubmittedBufferUseCount(0), 53 mRepeatBufferDeferred(false) { 54 55 ALOGV("GraphicBufferSource w=%u h=%u c=%u", 56 bufferWidth, bufferHeight, bufferCount); 57 58 if (bufferWidth == 0 || bufferHeight == 0) { 59 ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight); 60 mInitCheck = BAD_VALUE; 61 return; 62 } 63 64 String8 name("GraphicBufferSource"); 65 66 mBufferQueue = new BufferQueue(); 67 mBufferQueue->setConsumerName(name); 68 mBufferQueue->setDefaultBufferSize(bufferWidth, bufferHeight); 69 mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER | 70 GRALLOC_USAGE_HW_TEXTURE); 71 72 mInitCheck = mBufferQueue->setMaxAcquiredBufferCount(bufferCount); 73 if (mInitCheck != NO_ERROR) { 74 ALOGE("Unable to set BQ max acquired buffer count to %u: %d", 75 bufferCount, mInitCheck); 76 return; 77 } 78 79 // Note that we can't create an sp<...>(this) in a ctor that will not keep a 80 // reference once the ctor ends, as that would cause the refcount of 'this' 81 // dropping to 0 at the end of the ctor. Since all we need is a wp<...> 82 // that's what we create. 83 wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this); 84 sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(listener); 85 86 mInitCheck = mBufferQueue->consumerConnect(proxy, false); 87 if (mInitCheck != NO_ERROR) { 88 ALOGE("Error connecting to BufferQueue: %s (%d)", 89 strerror(-mInitCheck), mInitCheck); 90 return; 91 } 92 93 CHECK(mInitCheck == NO_ERROR); 94} 95 96GraphicBufferSource::~GraphicBufferSource() { 97 ALOGV("~GraphicBufferSource"); 98 if (mBufferQueue != NULL) { 99 status_t err = mBufferQueue->consumerDisconnect(); 100 if (err != NO_ERROR) { 101 ALOGW("consumerDisconnect failed: %d", err); 102 } 103 } 104} 105 106void GraphicBufferSource::omxExecuting() { 107 Mutex::Autolock autoLock(mMutex); 108 ALOGV("--> executing; avail=%d, codec vec size=%zd", 109 mNumFramesAvailable, mCodecBuffers.size()); 110 CHECK(!mExecuting); 111 mExecuting = true; 112 113 // Start by loading up as many buffers as possible. We want to do this, 114 // rather than just submit the first buffer, to avoid a degenerate case: 115 // if all BQ buffers arrive before we start executing, and we only submit 116 // one here, the other BQ buffers will just sit until we get notified 117 // that the codec buffer has been released. We'd then acquire and 118 // submit a single additional buffer, repeatedly, never using more than 119 // one codec buffer simultaneously. (We could instead try to submit 120 // all BQ buffers whenever any codec buffer is freed, but if we get the 121 // initial conditions right that will never be useful.) 122 while (mNumFramesAvailable) { 123 if (!fillCodecBuffer_l()) { 124 ALOGV("stop load with frames available (codecAvail=%d)", 125 isCodecBufferAvailable_l()); 126 break; 127 } 128 } 129 130 ALOGV("done loading initial frames, avail=%d", mNumFramesAvailable); 131 132 // If EOS has already been signaled, and there are no more frames to 133 // submit, try to send EOS now as well. 134 if (mEndOfStream && mNumFramesAvailable == 0) { 135 submitEndOfInputStream_l(); 136 } 137 138 if (mRepeatAfterUs > 0ll && mLooper == NULL) { 139 mReflector = new AHandlerReflector<GraphicBufferSource>(this); 140 141 mLooper = new ALooper; 142 mLooper->registerHandler(mReflector); 143 mLooper->start(); 144 145 if (mLatestSubmittedBufferId >= 0) { 146 sp<AMessage> msg = 147 new AMessage(kWhatRepeatLastFrame, mReflector->id()); 148 149 msg->setInt32("generation", ++mRepeatLastFrameGeneration); 150 msg->post(mRepeatAfterUs); 151 } 152 } 153} 154 155void GraphicBufferSource::omxIdle() { 156 ALOGV("omxIdle"); 157 158 Mutex::Autolock autoLock(mMutex); 159 160 if (mExecuting) { 161 // We are only interested in the transition from executing->idle, 162 // not loaded->idle. 163 mExecuting = false; 164 } 165} 166 167void GraphicBufferSource::omxLoaded(){ 168 Mutex::Autolock autoLock(mMutex); 169 if (!mExecuting) { 170 // This can happen if something failed very early. 171 ALOGW("Dropped back down to Loaded without Executing"); 172 } 173 174 if (mLooper != NULL) { 175 mLooper->unregisterHandler(mReflector->id()); 176 mReflector.clear(); 177 178 mLooper->stop(); 179 mLooper.clear(); 180 } 181 182 ALOGV("--> loaded; avail=%d eos=%d eosSent=%d", 183 mNumFramesAvailable, mEndOfStream, mEndOfStreamSent); 184 185 // Codec is no longer executing. Discard all codec-related state. 186 mCodecBuffers.clear(); 187 // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries 188 // are null; complain if not 189 190 mExecuting = false; 191} 192 193void GraphicBufferSource::addCodecBuffer(OMX_BUFFERHEADERTYPE* header) { 194 Mutex::Autolock autoLock(mMutex); 195 196 if (mExecuting) { 197 // This should never happen -- buffers can only be allocated when 198 // transitioning from "loaded" to "idle". 199 ALOGE("addCodecBuffer: buffer added while executing"); 200 return; 201 } 202 203 ALOGV("addCodecBuffer h=%p size=%lu p=%p", 204 header, header->nAllocLen, header->pBuffer); 205 CodecBuffer codecBuffer; 206 codecBuffer.mHeader = header; 207 mCodecBuffers.add(codecBuffer); 208} 209 210void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) { 211 Mutex::Autolock autoLock(mMutex); 212 213 if (!mExecuting) { 214 return; 215 } 216 217 int cbi = findMatchingCodecBuffer_l(header); 218 if (cbi < 0) { 219 // This should never happen. 220 ALOGE("codecBufferEmptied: buffer not recognized (h=%p)", header); 221 return; 222 } 223 224 ALOGV("codecBufferEmptied h=%p size=%lu filled=%lu p=%p", 225 header, header->nAllocLen, header->nFilledLen, 226 header->pBuffer); 227 CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi)); 228 229 // header->nFilledLen may not be the original value, so we can't compare 230 // that to zero to see of this was the EOS buffer. Instead we just 231 // see if the GraphicBuffer reference was null, which should only ever 232 // happen for EOS. 233 if (codecBuffer.mGraphicBuffer == NULL) { 234 if (!(mEndOfStream && mEndOfStreamSent)) { 235 // This can happen when broken code sends us the same buffer 236 // twice in a row. 237 ALOGE("ERROR: codecBufferEmptied on non-EOS null buffer " 238 "(buffer emptied twice?)"); 239 } 240 // No GraphicBuffer to deal with, no additional input or output is 241 // expected, so just return. 242 return; 243 } 244 245 if (EXTRA_CHECK) { 246 // Pull the graphic buffer handle back out of the buffer, and confirm 247 // that it matches expectations. 248 OMX_U8* data = header->pBuffer; 249 buffer_handle_t bufferHandle; 250 memcpy(&bufferHandle, data + 4, sizeof(buffer_handle_t)); 251 if (bufferHandle != codecBuffer.mGraphicBuffer->handle) { 252 // should never happen 253 ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p", 254 bufferHandle, codecBuffer.mGraphicBuffer->handle); 255 CHECK(!"codecBufferEmptied: mismatched buffer"); 256 } 257 } 258 259 // Find matching entry in our cached copy of the BufferQueue slots. 260 // If we find a match, release that slot. If we don't, the BufferQueue 261 // has dropped that GraphicBuffer, and there's nothing for us to release. 262 int id = codecBuffer.mBuf; 263 if (mBufferSlot[id] != NULL && 264 mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) { 265 ALOGV("cbi %d matches bq slot %d, handle=%p", 266 cbi, id, mBufferSlot[id]->handle); 267 268 if (id == mLatestSubmittedBufferId) { 269 CHECK_GT(mLatestSubmittedBufferUseCount--, 0); 270 } else { 271 mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber, 272 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); 273 } 274 } else { 275 ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d", 276 cbi); 277 } 278 279 // Mark the codec buffer as available by clearing the GraphicBuffer ref. 280 codecBuffer.mGraphicBuffer = NULL; 281 282 if (mNumFramesAvailable) { 283 // Fill this codec buffer. 284 CHECK(!mEndOfStreamSent); 285 ALOGV("buffer freed, %d frames avail (eos=%d)", 286 mNumFramesAvailable, mEndOfStream); 287 fillCodecBuffer_l(); 288 } else if (mEndOfStream) { 289 // No frames available, but EOS is pending, so use this buffer to 290 // send that. 291 ALOGV("buffer freed, EOS pending"); 292 submitEndOfInputStream_l(); 293 } else if (mRepeatBufferDeferred) { 294 bool success = repeatLatestSubmittedBuffer_l(); 295 if (success) { 296 ALOGV("deferred repeatLatestSubmittedBuffer_l SUCCESS"); 297 } else { 298 ALOGV("deferred repeatLatestSubmittedBuffer_l FAILURE"); 299 } 300 mRepeatBufferDeferred = false; 301 } 302 303 return; 304} 305 306void GraphicBufferSource::codecBufferFilled(OMX_BUFFERHEADERTYPE* header) { 307 Mutex::Autolock autoLock(mMutex); 308 309 if (mMaxTimestampGapUs > 0ll 310 && !(header->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 311 ssize_t index = mOriginalTimeUs.indexOfKey(header->nTimeStamp); 312 if (index >= 0) { 313 ALOGV("OUT timestamp: %lld -> %lld", 314 header->nTimeStamp, mOriginalTimeUs[index]); 315 header->nTimeStamp = mOriginalTimeUs[index]; 316 mOriginalTimeUs.removeItemsAt(index); 317 } else { 318 // giving up the effort as encoder doesn't appear to preserve pts 319 ALOGW("giving up limiting timestamp gap (pts = %lld)", 320 header->nTimeStamp); 321 mMaxTimestampGapUs = -1ll; 322 } 323 if (mOriginalTimeUs.size() > BufferQueue::NUM_BUFFER_SLOTS) { 324 // something terribly wrong must have happened, giving up... 325 ALOGE("mOriginalTimeUs has too many entries (%d)", 326 mOriginalTimeUs.size()); 327 mMaxTimestampGapUs = -1ll; 328 } 329 } 330} 331 332void GraphicBufferSource::suspend(bool suspend) { 333 Mutex::Autolock autoLock(mMutex); 334 335 if (suspend) { 336 mSuspended = true; 337 338 while (mNumFramesAvailable > 0) { 339 BufferQueue::BufferItem item; 340 status_t err = mBufferQueue->acquireBuffer(&item, 0); 341 342 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 343 // shouldn't happen. 344 ALOGW("suspend: frame was not available"); 345 break; 346 } else if (err != OK) { 347 ALOGW("suspend: acquireBuffer returned err=%d", err); 348 break; 349 } 350 351 --mNumFramesAvailable; 352 353 mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, 354 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); 355 } 356 return; 357 } 358 359 mSuspended = false; 360 361 if (mExecuting && mNumFramesAvailable == 0 && mRepeatBufferDeferred) { 362 if (repeatLatestSubmittedBuffer_l()) { 363 ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l SUCCESS"); 364 365 mRepeatBufferDeferred = false; 366 } else { 367 ALOGV("suspend/deferred repeatLatestSubmittedBuffer_l FAILURE"); 368 } 369 } 370} 371 372bool GraphicBufferSource::fillCodecBuffer_l() { 373 CHECK(mExecuting && mNumFramesAvailable > 0); 374 375 if (mSuspended) { 376 return false; 377 } 378 379 int cbi = findAvailableCodecBuffer_l(); 380 if (cbi < 0) { 381 // No buffers available, bail. 382 ALOGV("fillCodecBuffer_l: no codec buffers, avail now %d", 383 mNumFramesAvailable); 384 return false; 385 } 386 387 ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%d", 388 mNumFramesAvailable); 389 BufferQueue::BufferItem item; 390 status_t err = mBufferQueue->acquireBuffer(&item, 0); 391 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 392 // shouldn't happen 393 ALOGW("fillCodecBuffer_l: frame was not available"); 394 return false; 395 } else if (err != OK) { 396 // now what? fake end-of-stream? 397 ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err); 398 return false; 399 } 400 401 mNumFramesAvailable--; 402 403 // Wait for it to become available. 404 err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l"); 405 if (err != OK) { 406 ALOGW("failed to wait for buffer fence: %d", err); 407 // keep going 408 } 409 410 // If this is the first time we're seeing this buffer, add it to our 411 // slot table. 412 if (item.mGraphicBuffer != NULL) { 413 ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); 414 mBufferSlot[item.mBuf] = item.mGraphicBuffer; 415 } 416 417 err = submitBuffer_l(item, cbi); 418 if (err != OK) { 419 ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf); 420 mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, 421 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); 422 } else { 423 ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); 424 setLatestSubmittedBuffer_l(item); 425 } 426 427 return true; 428} 429 430bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { 431 CHECK(mExecuting && mNumFramesAvailable == 0); 432 433 if (mLatestSubmittedBufferId < 0 || mSuspended) { 434 return false; 435 } 436 if (mBufferSlot[mLatestSubmittedBufferId] == NULL) { 437 // This can happen if the remote side disconnects, causing 438 // onBuffersReleased() to NULL out our copy of the slots. The 439 // buffer is gone, so we have nothing to show. 440 // 441 // To be on the safe side we try to release the buffer. 442 ALOGD("repeatLatestSubmittedBuffer_l: slot was NULL"); 443 mBufferQueue->releaseBuffer( 444 mLatestSubmittedBufferId, 445 mLatestSubmittedBufferFrameNum, 446 EGL_NO_DISPLAY, 447 EGL_NO_SYNC_KHR, 448 Fence::NO_FENCE); 449 mLatestSubmittedBufferId = -1; 450 mLatestSubmittedBufferFrameNum = 0; 451 return false; 452 } 453 454 int cbi = findAvailableCodecBuffer_l(); 455 if (cbi < 0) { 456 // No buffers available, bail. 457 ALOGV("repeatLatestSubmittedBuffer_l: no codec buffers."); 458 return false; 459 } 460 461 BufferQueue::BufferItem item; 462 item.mBuf = mLatestSubmittedBufferId; 463 item.mFrameNumber = mLatestSubmittedBufferFrameNum; 464 item.mTimestamp = mRepeatLastFrameTimestamp; 465 466 status_t err = submitBuffer_l(item, cbi); 467 468 if (err != OK) { 469 return false; 470 } 471 472 ++mLatestSubmittedBufferUseCount; 473 474 /* repeat last frame up to kRepeatLastFrameCount times. 475 * in case of static scene, a single repeat might not get rid of encoder 476 * ghosting completely, refresh a couple more times to get better quality 477 */ 478 if (--mRepeatLastFrameCount > 0) { 479 mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000; 480 481 if (mReflector != NULL) { 482 sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id()); 483 msg->setInt32("generation", ++mRepeatLastFrameGeneration); 484 msg->post(mRepeatAfterUs); 485 } 486 } 487 488 return true; 489} 490 491void GraphicBufferSource::setLatestSubmittedBuffer_l( 492 const BufferQueue::BufferItem &item) { 493 ALOGV("setLatestSubmittedBuffer_l"); 494 495 if (mLatestSubmittedBufferId >= 0) { 496 if (mLatestSubmittedBufferUseCount == 0) { 497 mBufferQueue->releaseBuffer( 498 mLatestSubmittedBufferId, 499 mLatestSubmittedBufferFrameNum, 500 EGL_NO_DISPLAY, 501 EGL_NO_SYNC_KHR, 502 Fence::NO_FENCE); 503 } 504 } 505 506 mLatestSubmittedBufferId = item.mBuf; 507 mLatestSubmittedBufferFrameNum = item.mFrameNumber; 508 mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000; 509 510 mLatestSubmittedBufferUseCount = 1; 511 mRepeatBufferDeferred = false; 512 mRepeatLastFrameCount = kRepeatLastFrameCount; 513 514 if (mReflector != NULL) { 515 sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id()); 516 msg->setInt32("generation", ++mRepeatLastFrameGeneration); 517 msg->post(mRepeatAfterUs); 518 } 519} 520 521status_t GraphicBufferSource::signalEndOfInputStream() { 522 Mutex::Autolock autoLock(mMutex); 523 ALOGV("signalEndOfInputStream: exec=%d avail=%d eos=%d", 524 mExecuting, mNumFramesAvailable, mEndOfStream); 525 526 if (mEndOfStream) { 527 ALOGE("EOS was already signaled"); 528 return INVALID_OPERATION; 529 } 530 531 // Set the end-of-stream flag. If no frames are pending from the 532 // BufferQueue, and a codec buffer is available, and we're executing, 533 // we initiate the EOS from here. Otherwise, we'll let 534 // codecBufferEmptied() (or omxExecuting) do it. 535 // 536 // Note: if there are no pending frames and all codec buffers are 537 // available, we *must* submit the EOS from here or we'll just 538 // stall since no future events are expected. 539 mEndOfStream = true; 540 541 if (mExecuting && mNumFramesAvailable == 0) { 542 submitEndOfInputStream_l(); 543 } 544 545 return OK; 546} 547 548int64_t GraphicBufferSource::getTimestamp(const BufferQueue::BufferItem &item) { 549 int64_t timeUs = item.mTimestamp / 1000; 550 551 if (mMaxTimestampGapUs > 0ll) { 552 /* Cap timestamp gap between adjacent frames to specified max 553 * 554 * In the scenario of cast mirroring, encoding could be suspended for 555 * prolonged periods. Limiting the pts gap to workaround the problem 556 * where encoder's rate control logic produces huge frames after a 557 * long period of suspension. 558 */ 559 560 int64_t originalTimeUs = timeUs; 561 if (mPrevOriginalTimeUs >= 0ll) { 562 if (originalTimeUs < mPrevOriginalTimeUs) { 563 // Drop the frame if it's going backward in time. Bad timestamp 564 // could disrupt encoder's rate control completely. 565 ALOGW("Dropping frame that's going backward in time"); 566 return -1; 567 } 568 int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs; 569 timeUs = (timestampGapUs < mMaxTimestampGapUs ? 570 timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs; 571 } 572 mPrevOriginalTimeUs = originalTimeUs; 573 mPrevModifiedTimeUs = timeUs; 574 mOriginalTimeUs.add(timeUs, originalTimeUs); 575 ALOGV("IN timestamp: %lld -> %lld", originalTimeUs, timeUs); 576 } 577 578 return timeUs; 579} 580 581status_t GraphicBufferSource::submitBuffer_l( 582 const BufferQueue::BufferItem &item, int cbi) { 583 ALOGV("submitBuffer_l cbi=%d", cbi); 584 585 int64_t timeUs = getTimestamp(item); 586 if (timeUs < 0ll) { 587 return UNKNOWN_ERROR; 588 } 589 590 CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi)); 591 codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf]; 592 codecBuffer.mBuf = item.mBuf; 593 codecBuffer.mFrameNumber = item.mFrameNumber; 594 595 OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader; 596 CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t)); 597 OMX_U8* data = header->pBuffer; 598 const OMX_U32 type = kMetadataBufferTypeGrallocSource; 599 buffer_handle_t handle = codecBuffer.mGraphicBuffer->handle; 600 memcpy(data, &type, 4); 601 memcpy(data + 4, &handle, sizeof(buffer_handle_t)); 602 603 status_t err = mNodeInstance->emptyDirectBuffer(header, 0, 604 4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME, 605 timeUs); 606 if (err != OK) { 607 ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err); 608 codecBuffer.mGraphicBuffer = NULL; 609 return err; 610 } 611 612 ALOGV("emptyDirectBuffer succeeded, h=%p p=%p bufhandle=%p", 613 header, header->pBuffer, handle); 614 return OK; 615} 616 617void GraphicBufferSource::submitEndOfInputStream_l() { 618 CHECK(mEndOfStream); 619 if (mEndOfStreamSent) { 620 ALOGV("EOS already sent"); 621 return; 622 } 623 624 int cbi = findAvailableCodecBuffer_l(); 625 if (cbi < 0) { 626 ALOGV("submitEndOfInputStream_l: no codec buffers available"); 627 return; 628 } 629 630 // We reject any additional incoming graphic buffers, so there's no need 631 // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as 632 // in-use. 633 CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi)); 634 635 OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader; 636 if (EXTRA_CHECK) { 637 // Guard against implementations that don't check nFilledLen. 638 size_t fillLen = 4 + sizeof(buffer_handle_t); 639 CHECK(header->nAllocLen >= fillLen); 640 OMX_U8* data = header->pBuffer; 641 memset(data, 0xcd, fillLen); 642 } 643 644 uint64_t timestamp = 0; // does this matter? 645 646 status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0, 647 /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS, 648 timestamp); 649 if (err != OK) { 650 ALOGW("emptyDirectBuffer EOS failed: 0x%x", err); 651 } else { 652 ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d", 653 header, cbi); 654 mEndOfStreamSent = true; 655 } 656} 657 658int GraphicBufferSource::findAvailableCodecBuffer_l() { 659 CHECK(mCodecBuffers.size() > 0); 660 661 for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) { 662 if (mCodecBuffers[i].mGraphicBuffer == NULL) { 663 return i; 664 } 665 } 666 return -1; 667} 668 669int GraphicBufferSource::findMatchingCodecBuffer_l( 670 const OMX_BUFFERHEADERTYPE* header) { 671 for (int i = (int)mCodecBuffers.size() - 1; i>= 0; --i) { 672 if (mCodecBuffers[i].mHeader == header) { 673 return i; 674 } 675 } 676 return -1; 677} 678 679// BufferQueue::ConsumerListener callback 680void GraphicBufferSource::onFrameAvailable() { 681 Mutex::Autolock autoLock(mMutex); 682 683 ALOGV("onFrameAvailable exec=%d avail=%d", 684 mExecuting, mNumFramesAvailable); 685 686 if (mEndOfStream || mSuspended) { 687 if (mEndOfStream) { 688 // This should only be possible if a new buffer was queued after 689 // EOS was signaled, i.e. the app is misbehaving. 690 691 ALOGW("onFrameAvailable: EOS is set, ignoring frame"); 692 } else { 693 ALOGV("onFrameAvailable: suspended, ignoring frame"); 694 } 695 696 BufferQueue::BufferItem item; 697 status_t err = mBufferQueue->acquireBuffer(&item, 0); 698 if (err == OK) { 699 // If this is the first time we're seeing this buffer, add it to our 700 // slot table. 701 if (item.mGraphicBuffer != NULL) { 702 ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); 703 mBufferSlot[item.mBuf] = item.mGraphicBuffer; 704 } 705 mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, 706 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence); 707 } 708 return; 709 } 710 711 mNumFramesAvailable++; 712 713 mRepeatBufferDeferred = false; 714 ++mRepeatLastFrameGeneration; 715 716 if (mExecuting) { 717 fillCodecBuffer_l(); 718 } 719} 720 721// BufferQueue::ConsumerListener callback 722void GraphicBufferSource::onBuffersReleased() { 723 Mutex::Autolock lock(mMutex); 724 725 uint32_t slotMask; 726 if (mBufferQueue->getReleasedBuffers(&slotMask) != NO_ERROR) { 727 ALOGW("onBuffersReleased: unable to get released buffer set"); 728 slotMask = 0xffffffff; 729 } 730 731 ALOGV("onBuffersReleased: 0x%08x", slotMask); 732 733 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { 734 if ((slotMask & 0x01) != 0) { 735 mBufferSlot[i] = NULL; 736 } 737 slotMask >>= 1; 738 } 739} 740 741status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs( 742 int64_t repeatAfterUs) { 743 Mutex::Autolock autoLock(mMutex); 744 745 if (mExecuting || repeatAfterUs <= 0ll) { 746 return INVALID_OPERATION; 747 } 748 749 mRepeatAfterUs = repeatAfterUs; 750 751 return OK; 752} 753 754status_t GraphicBufferSource::setMaxTimestampGapUs(int64_t maxGapUs) { 755 Mutex::Autolock autoLock(mMutex); 756 757 if (mExecuting || maxGapUs <= 0ll) { 758 return INVALID_OPERATION; 759 } 760 761 mMaxTimestampGapUs = maxGapUs; 762 763 return OK; 764} 765void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) { 766 switch (msg->what()) { 767 case kWhatRepeatLastFrame: 768 { 769 Mutex::Autolock autoLock(mMutex); 770 771 int32_t generation; 772 CHECK(msg->findInt32("generation", &generation)); 773 774 if (generation != mRepeatLastFrameGeneration) { 775 // stale 776 break; 777 } 778 779 if (!mExecuting || mNumFramesAvailable > 0) { 780 break; 781 } 782 783 bool success = repeatLatestSubmittedBuffer_l(); 784 785 if (success) { 786 ALOGV("repeatLatestSubmittedBuffer_l SUCCESS"); 787 } else { 788 ALOGV("repeatLatestSubmittedBuffer_l FAILURE"); 789 mRepeatBufferDeferred = true; 790 } 791 break; 792 } 793 794 default: 795 TRESPASS(); 796 } 797} 798 799} // namespace android 800