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