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