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