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 <media/stagefright/foundation/ADebug.h> 27 #include <media/stagefright/foundation/AMessage.h> 28 #include <media/stagefright/foundation/ColorUtils.h> 29 #include <media/stagefright/foundation/FileDescriptor.h> 30 31 #include <media/hardware/MetadataBufferType.h> 32 #include <ui/GraphicBuffer.h> 33 #include <gui/BufferItem.h> 34 #include <HardwareAPI.h> 35 #include "omx/OMXUtils.h" 36 #include <OMX_Component.h> 37 #include <OMX_IndexExt.h> 38 #include "OMXBuffer.h" 39 40 #include <inttypes.h> 41 #include "FrameDropper.h" 42 43 #include <functional> 44 #include <memory> 45 #include <cmath> 46 47 namespace android { 48 49 /** 50 * A copiable object managing a buffer in the buffer cache managed by the producer. This object 51 * holds a reference to the buffer, and maintains which buffer slot it belongs to (if any), and 52 * whether it is still in a buffer slot. It also maintains whether there are any outstanging acquire 53 * references to it (by buffers acquired from the slot) mainly so that we can keep a debug 54 * count of how many buffers we need to still release back to the producer. 55 */ 56 struct GraphicBufferSource::CachedBuffer { 57 /** 58 * Token that is used to track acquire counts (as opposed to all references to this object). 59 */ 60 struct Acquirable { }; 61 62 /** 63 * Create using a buffer cached in a slot. 64 */ 65 CachedBuffer(slot_id slot, const sp<GraphicBuffer> &graphicBuffer) 66 : mIsCached(true), 67 mSlot(slot), 68 mGraphicBuffer(graphicBuffer), 69 mAcquirable(std::make_shared<Acquirable>()) { 70 } 71 72 /** 73 * Returns the cache slot that this buffer is cached in, or -1 if it is no longer cached. 74 * 75 * This assumes that -1 slot id is invalid; though, it is just a benign collision used for 76 * debugging. This object explicitly manages whether it is still cached. 77 */ 78 slot_id getSlot() const { 79 return mIsCached ? mSlot : -1; 80 } 81 82 /** 83 * Returns the cached buffer. 84 */ 85 sp<GraphicBuffer> getGraphicBuffer() const { 86 return mGraphicBuffer; 87 } 88 89 /** 90 * Checks whether this buffer is still in the buffer cache. 91 */ 92 bool isCached() const { 93 return mIsCached; 94 } 95 96 /** 97 * Checks whether this buffer has an acquired reference. 98 */ 99 bool isAcquired() const { 100 return mAcquirable.use_count() > 1; 101 } 102 103 /** 104 * Gets and returns a shared acquired reference. 105 */ 106 std::shared_ptr<Acquirable> getAcquirable() { 107 return mAcquirable; 108 } 109 110 private: 111 friend void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t); 112 113 /** 114 * This method to be called when the buffer is no longer in the buffer cache. 115 * Called from discardBufferAtSlotIndex_l. 116 */ 117 void onDroppedFromCache() { 118 CHECK_DBG(mIsCached); 119 mIsCached = false; 120 } 121 122 bool mIsCached; 123 slot_id mSlot; 124 sp<GraphicBuffer> mGraphicBuffer; 125 std::shared_ptr<Acquirable> mAcquirable; 126 }; 127 128 /** 129 * A copiable object managing a buffer acquired from the producer. This must always be a cached 130 * buffer. This objects also manages its acquire fence and any release fences that may be returned 131 * by the encoder for this buffer (this buffer may be queued to the encoder multiple times). 132 * If no release fences are added by the encoder, the acquire fence is returned as the release 133 * fence for this - as it is assumed that noone waited for the acquire fence. Otherwise, it is 134 * assumed that the encoder has waited for the acquire fence (or returned it as the release 135 * fence). 136 */ 137 struct GraphicBufferSource::AcquiredBuffer { 138 AcquiredBuffer( 139 const std::shared_ptr<CachedBuffer> &buffer, 140 std::function<void(AcquiredBuffer *)> onReleased, 141 const sp<Fence> &acquireFence) 142 : mBuffer(buffer), 143 mAcquirable(buffer->getAcquirable()), 144 mAcquireFence(acquireFence), 145 mGotReleaseFences(false), 146 mOnReleased(onReleased) { 147 } 148 149 /** 150 * Adds a release fence returned by the encoder to this object. If this is called with an 151 * valid file descriptor, it is added to the list of release fences. These are returned to the 152 * producer on release() as a merged fence. Regardless of the validity of the file descriptor, 153 * we take note that a release fence was attempted to be added and the acquire fence can now be 154 * assumed as acquired. 155 */ 156 void addReleaseFenceFd(int fenceFd) { 157 // save all release fences - these will be propagated to the producer if this buffer is 158 // ever released to it 159 if (fenceFd >= 0) { 160 mReleaseFenceFds.push_back(fenceFd); 161 } 162 mGotReleaseFences = true; 163 } 164 165 /** 166 * Returns the acquire fence file descriptor associated with this object. 167 */ 168 int getAcquireFenceFd() { 169 if (mAcquireFence == nullptr || !mAcquireFence->isValid()) { 170 return -1; 171 } 172 return mAcquireFence->dup(); 173 } 174 175 /** 176 * Returns whether the buffer is still in the buffer cache. 177 */ 178 bool isCached() const { 179 return mBuffer->isCached(); 180 } 181 182 /** 183 * Returns the acquired buffer. 184 */ 185 sp<GraphicBuffer> getGraphicBuffer() const { 186 return mBuffer->getGraphicBuffer(); 187 } 188 189 /** 190 * Returns the slot that this buffer is cached at, or -1 otherwise. 191 * 192 * This assumes that -1 slot id is invalid; though, it is just a benign collision used for 193 * debugging. This object explicitly manages whether it is still cached. 194 */ 195 slot_id getSlot() const { 196 return mBuffer->getSlot(); 197 } 198 199 /** 200 * Creates and returns a release fence object from the acquire fence and/or any release fences 201 * added. If no release fences were added (even if invalid), returns the acquire fence. 202 * Otherwise, it returns a merged fence from all the valid release fences added. 203 */ 204 sp<Fence> getReleaseFence() { 205 // If did not receive release fences, we assume this buffer was not consumed (it was 206 // discarded or dropped). In this case release the acquire fence as the release fence. 207 // We do this here to avoid a dup, close and recreation of the Fence object. 208 if (!mGotReleaseFences) { 209 return mAcquireFence; 210 } 211 sp<Fence> ret = getReleaseFence(0, mReleaseFenceFds.size()); 212 // clear fds as fence took ownership of them 213 mReleaseFenceFds.clear(); 214 return ret; 215 } 216 217 // this video buffer is no longer referenced by the codec (or kept for later encoding) 218 // it is now safe to release to the producer 219 ~AcquiredBuffer() { 220 //mAcquirable.clear(); 221 mOnReleased(this); 222 // mOnRelease method should call getReleaseFence() that releases all fds but just in case 223 ALOGW_IF(!mReleaseFenceFds.empty(), "release fences were not obtained, closing fds"); 224 for (int fildes : mReleaseFenceFds) { 225 ::close(fildes); 226 TRESPASS_DBG(); 227 } 228 } 229 230 private: 231 std::shared_ptr<GraphicBufferSource::CachedBuffer> mBuffer; 232 std::shared_ptr<GraphicBufferSource::CachedBuffer::Acquirable> mAcquirable; 233 sp<Fence> mAcquireFence; 234 Vector<int> mReleaseFenceFds; 235 bool mGotReleaseFences; 236 std::function<void(AcquiredBuffer *)> mOnReleased; 237 238 /** 239 * Creates and returns a release fence from 0 or more release fence file descriptors in from 240 * the specified range in the array. 241 * 242 * @param start start index 243 * @param num number of release fds to merge 244 */ 245 sp<Fence> getReleaseFence(size_t start, size_t num) const { 246 if (num == 0) { 247 return Fence::NO_FENCE; 248 } else if (num == 1) { 249 return new Fence(mReleaseFenceFds[start]); 250 } else { 251 return Fence::merge("GBS::AB", 252 getReleaseFence(start, num >> 1), 253 getReleaseFence(start + (num >> 1), num - (num >> 1))); 254 } 255 } 256 }; 257 258 GraphicBufferSource::GraphicBufferSource() : 259 mInitCheck(UNKNOWN_ERROR), 260 mNumAvailableUnacquiredBuffers(0), 261 mNumOutstandingAcquires(0), 262 mEndOfStream(false), 263 mEndOfStreamSent(false), 264 mLastDataspace(HAL_DATASPACE_UNKNOWN), 265 mExecuting(false), 266 mSuspended(false), 267 mStopTimeUs(-1), 268 mLastActionTimeUs(-1ll), 269 mSkipFramesBeforeNs(-1ll), 270 mFrameRepeatIntervalUs(-1ll), 271 mRepeatLastFrameGeneration(0), 272 mOutstandingFrameRepeatCount(0), 273 mFrameRepeatBlockedOnCodecBuffer(false), 274 mFps(-1.0), 275 mCaptureFps(-1.0), 276 mBaseCaptureUs(-1ll), 277 mBaseFrameUs(-1ll), 278 mFrameCount(0), 279 mPrevCaptureUs(-1ll), 280 mPrevFrameUs(-1ll), 281 mInputBufferTimeOffsetUs(0ll) { 282 ALOGV("GraphicBufferSource"); 283 284 String8 name("GraphicBufferSource"); 285 286 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 287 mConsumer->setConsumerName(name); 288 289 // Note that we can't create an sp<...>(this) in a ctor that will not keep a 290 // reference once the ctor ends, as that would cause the refcount of 'this' 291 // dropping to 0 at the end of the ctor. Since all we need is a wp<...> 292 // that's what we create. 293 wp<BufferQueue::ConsumerListener> listener = 294 static_cast<BufferQueue::ConsumerListener*>(this); 295 sp<IConsumerListener> proxy = 296 new BufferQueue::ProxyConsumerListener(listener); 297 298 mInitCheck = mConsumer->consumerConnect(proxy, false); 299 if (mInitCheck != NO_ERROR) { 300 ALOGE("Error connecting to BufferQueue: %s (%d)", 301 strerror(-mInitCheck), mInitCheck); 302 return; 303 } 304 305 memset(&mDefaultColorAspectsPacked, 0, sizeof(mDefaultColorAspectsPacked)); 306 307 CHECK(mInitCheck == NO_ERROR); 308 } 309 310 GraphicBufferSource::~GraphicBufferSource() { 311 ALOGV("~GraphicBufferSource"); 312 { 313 // all acquired buffers must be freed with the mutex locked otherwise our debug assertion 314 // may trigger 315 Mutex::Autolock autoLock(mMutex); 316 mAvailableBuffers.clear(); 317 mSubmittedCodecBuffers.clear(); 318 mLatestBuffer.mBuffer.reset(); 319 } 320 321 if (mNumOutstandingAcquires != 0) { 322 ALOGW("potential buffer leak: acquired=%d", mNumOutstandingAcquires); 323 TRESPASS_DBG(); 324 } 325 if (mConsumer != NULL) { 326 status_t err = mConsumer->consumerDisconnect(); 327 if (err != NO_ERROR) { 328 ALOGW("consumerDisconnect failed: %d", err); 329 } 330 } 331 } 332 333 Status GraphicBufferSource::onOmxExecuting() { 334 Mutex::Autolock autoLock(mMutex); 335 ALOGV("--> executing; available=%zu, submittable=%zd", 336 mAvailableBuffers.size(), mFreeCodecBuffers.size()); 337 CHECK(!mExecuting); 338 mExecuting = true; 339 mLastDataspace = HAL_DATASPACE_UNKNOWN; 340 ALOGV("clearing last dataSpace"); 341 342 // Start by loading up as many buffers as possible. We want to do this, 343 // rather than just submit the first buffer, to avoid a degenerate case: 344 // if all BQ buffers arrive before we start executing, and we only submit 345 // one here, the other BQ buffers will just sit until we get notified 346 // that the codec buffer has been released. We'd then acquire and 347 // submit a single additional buffer, repeatedly, never using more than 348 // one codec buffer simultaneously. (We could instead try to submit 349 // all BQ buffers whenever any codec buffer is freed, but if we get the 350 // initial conditions right that will never be useful.) 351 while (haveAvailableBuffers_l()) { 352 if (!fillCodecBuffer_l()) { 353 ALOGV("stop load with available=%zu+%d", 354 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); 355 break; 356 } 357 } 358 359 ALOGV("done loading initial frames, available=%zu+%d", 360 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); 361 362 // If EOS has already been signaled, and there are no more frames to 363 // submit, try to send EOS now as well. 364 if (mStopTimeUs == -1 && mEndOfStream && !haveAvailableBuffers_l()) { 365 submitEndOfInputStream_l(); 366 } 367 368 if (mFrameRepeatIntervalUs > 0ll && mLooper == NULL) { 369 mReflector = new AHandlerReflector<GraphicBufferSource>(this); 370 371 mLooper = new ALooper; 372 mLooper->registerHandler(mReflector); 373 mLooper->start(); 374 375 if (mLatestBuffer.mBuffer != nullptr) { 376 queueFrameRepeat_l(); 377 } 378 } 379 380 return Status::ok(); 381 } 382 383 Status GraphicBufferSource::onOmxIdle() { 384 ALOGV("omxIdle"); 385 386 Mutex::Autolock autoLock(mMutex); 387 388 if (mExecuting) { 389 // We are only interested in the transition from executing->idle, 390 // not loaded->idle. 391 mExecuting = false; 392 } 393 return Status::ok(); 394 } 395 396 Status GraphicBufferSource::onOmxLoaded(){ 397 Mutex::Autolock autoLock(mMutex); 398 if (mLooper != NULL) { 399 mLooper->unregisterHandler(mReflector->id()); 400 mReflector.clear(); 401 402 mLooper->stop(); 403 mLooper.clear(); 404 } 405 406 ALOGV("--> loaded; available=%zu+%d eos=%d eosSent=%d acquired=%d", 407 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, 408 mEndOfStream, mEndOfStreamSent, mNumOutstandingAcquires); 409 410 // Codec is no longer executing. Releasing all buffers to bq. 411 mFreeCodecBuffers.clear(); 412 mSubmittedCodecBuffers.clear(); 413 mLatestBuffer.mBuffer.reset(); 414 mOMXNode.clear(); 415 mExecuting = false; 416 417 return Status::ok(); 418 } 419 420 Status GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) { 421 Mutex::Autolock autoLock(mMutex); 422 423 if (mExecuting) { 424 // This should never happen -- buffers can only be allocated when 425 // transitioning from "loaded" to "idle". 426 ALOGE("addCodecBuffer: buffer added while executing"); 427 return Status::fromServiceSpecificError(INVALID_OPERATION); 428 } 429 430 ALOGV("addCodecBuffer: bufferId=%u", bufferId); 431 432 mFreeCodecBuffers.push_back(bufferId); 433 return Status::ok(); 434 } 435 436 Status GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) { 437 Mutex::Autolock autoLock(mMutex); 438 FileDescriptor::Autoclose fence(fenceFd); 439 440 ssize_t cbi = mSubmittedCodecBuffers.indexOfKey(bufferId); 441 if (cbi < 0) { 442 // This should never happen. 443 ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId); 444 return Status::fromServiceSpecificError(BAD_VALUE); 445 } 446 447 std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi); 448 449 // Move buffer to available buffers 450 mSubmittedCodecBuffers.removeItemsAt(cbi); 451 mFreeCodecBuffers.push_back(bufferId); 452 453 // header->nFilledLen may not be the original value, so we can't compare 454 // that to zero to see of this was the EOS buffer. Instead we just 455 // see if there is a null AcquiredBuffer, which should only ever happen for EOS. 456 if (buffer == nullptr) { 457 if (!(mEndOfStream && mEndOfStreamSent)) { 458 // This can happen when broken code sends us the same buffer twice in a row. 459 ALOGE("onInputBufferEmptied: non-EOS null buffer (bufferId=%u)", bufferId); 460 } else { 461 ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi); 462 } 463 // No GraphicBuffer to deal with, no additional input or output is expected, so just return. 464 return Status::fromServiceSpecificError(BAD_VALUE); 465 } 466 467 if (!mExecuting) { 468 // this is fine since this could happen when going from Idle to Loaded 469 ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi); 470 return Status::fromServiceSpecificError(OK); 471 } 472 473 ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d", 474 bufferId, cbi, buffer->getSlot(), buffer.use_count(), buffer->getGraphicBuffer()->handle, 475 mNumOutstandingAcquires); 476 477 buffer->addReleaseFenceFd(fence.release()); 478 // release codec reference for video buffer just in case remove does not it 479 buffer.reset(); 480 481 if (haveAvailableBuffers_l()) { 482 // Fill this codec buffer. 483 CHECK(!mEndOfStreamSent); 484 ALOGV("onInputBufferEmptied: buffer freed, feeding codec (available=%zu+%d, eos=%d)", 485 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream); 486 fillCodecBuffer_l(); 487 } else if (mEndOfStream && mStopTimeUs == -1) { 488 // No frames available, but EOS is pending and no stop time, so use this buffer to 489 // send that. 490 ALOGV("onInputBufferEmptied: buffer freed, submitting EOS"); 491 submitEndOfInputStream_l(); 492 } else if (mFrameRepeatBlockedOnCodecBuffer) { 493 bool success = repeatLatestBuffer_l(); 494 ALOGV("onInputBufferEmptied: completing deferred repeatLatestBuffer_l %s", 495 success ? "SUCCESS" : "FAILURE"); 496 mFrameRepeatBlockedOnCodecBuffer = false; 497 } 498 499 // releaseReleasableBuffers_l(); 500 return Status::ok(); 501 } 502 503 void GraphicBufferSource::onDataspaceChanged_l( 504 android_dataspace dataspace, android_pixel_format pixelFormat) { 505 ALOGD("got buffer with new dataSpace #%x", dataspace); 506 mLastDataspace = dataspace; 507 508 if (ColorUtils::convertDataSpaceToV0(dataspace)) { 509 mOMXNode->dispatchDataSpaceChanged(mLastDataspace, mDefaultColorAspectsPacked, pixelFormat); 510 } 511 } 512 513 bool GraphicBufferSource::fillCodecBuffer_l() { 514 CHECK(mExecuting && haveAvailableBuffers_l()); 515 516 if (mFreeCodecBuffers.empty()) { 517 // No buffers available, bail. 518 ALOGV("fillCodecBuffer_l: no codec buffers, available=%zu+%d", 519 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); 520 return false; 521 } 522 523 VideoBuffer item; 524 if (mAvailableBuffers.empty()) { 525 ALOGV("fillCodecBuffer_l: acquiring available buffer, available=%zu+%d", 526 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); 527 if (acquireBuffer_l(&item) != OK) { 528 ALOGE("fillCodecBuffer_l: failed to acquire available buffer"); 529 return false; 530 } 531 } else { 532 ALOGV("fillCodecBuffer_l: getting available buffer, available=%zu+%d", 533 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); 534 item = *mAvailableBuffers.begin(); 535 mAvailableBuffers.erase(mAvailableBuffers.begin()); 536 } 537 538 int64_t itemTimeUs = item.mTimestampNs / 1000; 539 540 // Process ActionItem in the Queue if there is any. If a buffer's timestamp 541 // is smaller than the first action's timestamp, no action need to be performed. 542 // If buffer's timestamp is larger or equal than the last action's timestamp, 543 // only the last action needs to be performed as all the acitions before the 544 // the action are overridden by the last action. For the other cases, traverse 545 // the Queue to find the newest action that with timestamp smaller or equal to 546 // the buffer's timestamp. For example, an action queue like 547 // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon 548 // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs 549 // to be handled and [pause, 1us], [resume 2us] will be discarded. 550 bool done = false; 551 bool seeStopAction = false; 552 if (!mActionQueue.empty()) { 553 // First scan to check if bufferTimestamp is smaller than first action's timestamp. 554 ActionItem nextAction = *(mActionQueue.begin()); 555 if (itemTimeUs < nextAction.mActionTimeUs) { 556 ALOGV("No action. buffer timestamp %lld us < action timestamp: %lld us", 557 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs); 558 // All the actions are ahead. No action need to perform now. 559 // Release the buffer if is in suspended state, or process the buffer 560 // if not in suspended state. 561 done = true; 562 } 563 564 if (!done) { 565 // Find the newest action that with timestamp smaller than itemTimeUs. Then 566 // remove all the actions before and include the newest action. 567 List<ActionItem>::iterator it = mActionQueue.begin(); 568 while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs 569 && nextAction.mAction != ActionItem::STOP) { 570 nextAction = *it; 571 ++it; 572 } 573 mActionQueue.erase(mActionQueue.begin(), it); 574 575 CHECK(itemTimeUs >= nextAction.mActionTimeUs); 576 switch (nextAction.mAction) { 577 case ActionItem::PAUSE: 578 { 579 mSuspended = true; 580 ALOGV("RUNNING/PAUSE -> PAUSE at buffer %lld us PAUSE Time: %lld us", 581 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs); 582 break; 583 } 584 case ActionItem::RESUME: 585 { 586 mSuspended = false; 587 ALOGV("PAUSE/RUNNING -> RUNNING at buffer %lld us RESUME Time: %lld us", 588 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs); 589 break; 590 } 591 case ActionItem::STOP: 592 { 593 ALOGV("RUNNING/PAUSE -> STOP at buffer %lld us STOP Time: %lld us", 594 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs); 595 // Clear the whole ActionQueue as recording is done 596 mActionQueue.clear(); 597 seeStopAction = true; 598 break; 599 } 600 default: 601 TRESPASS_DBG("Unknown action type"); 602 // return true here because we did consume an available buffer, so the 603 // loop in onOmxExecuting will eventually terminate even if we hit this. 604 return false; 605 } 606 } 607 } 608 609 if (seeStopAction) { 610 // Clear all the buffers before setting mEndOfStream and signal EndOfInputStream. 611 releaseAllAvailableBuffers_l(); 612 mEndOfStream = true; 613 submitEndOfInputStream_l(); 614 return true; 615 } 616 617 if (mSuspended) { 618 return true; 619 } 620 621 int err = UNKNOWN_ERROR; 622 623 // only submit sample if start time is unspecified, or sample 624 // is queued after the specified start time 625 if (mSkipFramesBeforeNs < 0ll || item.mTimestampNs >= mSkipFramesBeforeNs) { 626 // if start time is set, offset time stamp by start time 627 if (mSkipFramesBeforeNs > 0) { 628 item.mTimestampNs -= mSkipFramesBeforeNs; 629 } 630 631 int64_t timeUs = item.mTimestampNs / 1000; 632 if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) { 633 ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs)); 634 // set err to OK so that the skipped frame can still be saved as the lastest frame 635 err = OK; 636 } else { 637 err = submitBuffer_l(item); // this takes shared ownership of the acquired buffer on succeess 638 } 639 } 640 641 if (err != OK) { 642 ALOGV("submitBuffer_l failed, will release bq slot %d", item.mBuffer->getSlot()); 643 return true; 644 } else { 645 // Don't set the last buffer id if we're not repeating, 646 // we'll be holding on to the last buffer for nothing. 647 if (mFrameRepeatIntervalUs > 0ll) { 648 setLatestBuffer_l(item); 649 } 650 ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d", 651 item.mBuffer->getSlot(), item.mBuffer.use_count(), mNumOutstandingAcquires); 652 } 653 654 return true; 655 } 656 657 bool GraphicBufferSource::repeatLatestBuffer_l() { 658 CHECK(mExecuting && !haveAvailableBuffers_l()); 659 660 if (mLatestBuffer.mBuffer == nullptr || mSuspended) { 661 return false; 662 } 663 664 if (mFreeCodecBuffers.empty()) { 665 // No buffers available, bail. 666 ALOGV("repeatLatestBuffer_l: no codec buffers."); 667 return false; 668 } 669 670 if (!mLatestBuffer.mBuffer->isCached()) { 671 ALOGV("repeatLatestBuffer_l: slot was discarded, but repeating our own reference"); 672 } 673 674 // it is ok to update the timestamp of latest buffer as it is only used for submission 675 status_t err = submitBuffer_l(mLatestBuffer); 676 if (err != OK) { 677 return false; 678 } 679 680 /* repeat last frame up to kRepeatLastFrameCount times. 681 * in case of static scene, a single repeat might not get rid of encoder 682 * ghosting completely, refresh a couple more times to get better quality 683 */ 684 if (--mOutstandingFrameRepeatCount > 0) { 685 // set up timestamp for repeat frame 686 mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000; 687 queueFrameRepeat_l(); 688 } 689 690 return true; 691 } 692 693 void GraphicBufferSource::setLatestBuffer_l(const VideoBuffer &item) { 694 mLatestBuffer = item; 695 696 ALOGV("setLatestBuffer_l: [slot=%d, useCount=%ld]", 697 mLatestBuffer.mBuffer->getSlot(), mLatestBuffer.mBuffer.use_count()); 698 699 mOutstandingFrameRepeatCount = kRepeatLastFrameCount; 700 // set up timestamp for repeat frame 701 mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000; 702 queueFrameRepeat_l(); 703 } 704 705 void GraphicBufferSource::queueFrameRepeat_l() { 706 mFrameRepeatBlockedOnCodecBuffer = false; 707 708 if (mReflector != NULL) { 709 sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector); 710 msg->setInt32("generation", ++mRepeatLastFrameGeneration); 711 msg->post(mFrameRepeatIntervalUs); 712 } 713 } 714 715 bool GraphicBufferSource::calculateCodecTimestamp_l( 716 nsecs_t bufferTimeNs, int64_t *codecTimeUs) { 717 int64_t timeUs = bufferTimeNs / 1000; 718 timeUs += mInputBufferTimeOffsetUs; 719 720 if (mCaptureFps > 0. 721 && (mFps > 2 * mCaptureFps 722 || mCaptureFps > 2 * mFps)) { 723 // Time lapse or slow motion mode 724 if (mPrevCaptureUs < 0ll) { 725 // first capture 726 mPrevCaptureUs = mBaseCaptureUs = timeUs; 727 // adjust the first sample timestamp. 728 mPrevFrameUs = mBaseFrameUs = 729 std::llround((timeUs * mCaptureFps) / mFps); 730 mFrameCount = 0; 731 } else { 732 // snap to nearest capture point 733 int64_t nFrames = std::llround( 734 (timeUs - mPrevCaptureUs) * mCaptureFps); 735 if (nFrames <= 0) { 736 // skip this frame as it's too close to previous capture 737 ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs)); 738 return false; 739 } 740 mFrameCount += nFrames; 741 mPrevCaptureUs = mBaseCaptureUs + std::llround( 742 mFrameCount / mCaptureFps); 743 mPrevFrameUs = mBaseFrameUs + std::llround( 744 mFrameCount / mFps); 745 } 746 747 ALOGV("timeUs %lld, captureUs %lld, frameUs %lld", 748 static_cast<long long>(timeUs), 749 static_cast<long long>(mPrevCaptureUs), 750 static_cast<long long>(mPrevFrameUs)); 751 } else { 752 if (timeUs <= mPrevFrameUs) { 753 // Drop the frame if it's going backward in time. Bad timestamp 754 // could disrupt encoder's rate control completely. 755 ALOGW("Dropping frame that's going backward in time"); 756 return false; 757 } 758 759 mPrevFrameUs = timeUs; 760 } 761 762 *codecTimeUs = mPrevFrameUs; 763 return true; 764 } 765 766 status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) { 767 CHECK(!mFreeCodecBuffers.empty()); 768 IOMX::buffer_id codecBufferId = *mFreeCodecBuffers.begin(); 769 770 ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId); 771 772 int64_t codecTimeUs; 773 if (!calculateCodecTimestamp_l(item.mTimestampNs, &codecTimeUs)) { 774 return UNKNOWN_ERROR; 775 } 776 777 if ((android_dataspace)item.mDataspace != mLastDataspace) { 778 onDataspaceChanged_l( 779 item.mDataspace, 780 (android_pixel_format)item.mBuffer->getGraphicBuffer()->format); 781 } 782 783 std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer; 784 // use a GraphicBuffer for now as OMXNodeInstance is using GraphicBuffers to hold references 785 // and it requires this graphic buffer to be able to hold its reference 786 // and thus we would need to create a new GraphicBuffer from an ANWBuffer separate from the 787 // acquired GraphicBuffer. 788 // TODO: this can be reworked globally to use ANWBuffer references 789 sp<GraphicBuffer> graphicBuffer = buffer->getGraphicBuffer(); 790 status_t err = mOMXNode->emptyBuffer( 791 codecBufferId, OMX_BUFFERFLAG_ENDOFFRAME, graphicBuffer, codecTimeUs, 792 buffer->getAcquireFenceFd()); 793 794 if (err != OK) { 795 ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err); 796 return err; 797 } 798 799 mFreeCodecBuffers.erase(mFreeCodecBuffers.begin()); 800 801 ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer); 802 ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p", 803 codecBufferId, cbix, graphicBuffer->handle); 804 return OK; 805 } 806 807 void GraphicBufferSource::submitEndOfInputStream_l() { 808 CHECK(mEndOfStream); 809 if (mEndOfStreamSent) { 810 ALOGV("EOS already sent"); 811 return; 812 } 813 814 if (mFreeCodecBuffers.empty()) { 815 ALOGV("submitEndOfInputStream_l: no codec buffers available"); 816 return; 817 } 818 IOMX::buffer_id codecBufferId = *mFreeCodecBuffers.begin(); 819 820 // We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS 821 status_t err = mOMXNode->emptyBuffer( 822 codecBufferId, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS); 823 if (err != OK) { 824 ALOGW("emptyDirectBuffer EOS failed: 0x%x", err); 825 } else { 826 mFreeCodecBuffers.erase(mFreeCodecBuffers.begin()); 827 ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr); 828 ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix); 829 mEndOfStreamSent = true; 830 831 // no need to hold onto any buffers for frame repeating 832 ++mRepeatLastFrameGeneration; 833 mLatestBuffer.mBuffer.reset(); 834 } 835 } 836 837 status_t GraphicBufferSource::acquireBuffer_l(VideoBuffer *ab) { 838 BufferItem bi; 839 status_t err = mConsumer->acquireBuffer(&bi, 0); 840 if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 841 // shouldn't happen 842 ALOGW("acquireBuffer_l: frame was not available"); 843 return err; 844 } else if (err != OK) { 845 ALOGW("acquireBuffer_l: failed with err=%d", err); 846 return err; 847 } 848 --mNumAvailableUnacquiredBuffers; 849 850 // Manage our buffer cache. 851 std::shared_ptr<CachedBuffer> buffer; 852 ssize_t bsi = mBufferSlots.indexOfKey(bi.mSlot); 853 if (bi.mGraphicBuffer != NULL) { 854 // replace/initialize slot with new buffer 855 ALOGV("acquireBuffer_l: %s buffer slot %d", bsi < 0 ? "setting" : "UPDATING", bi.mSlot); 856 if (bsi >= 0) { 857 discardBufferAtSlotIndex_l(bsi); 858 } else { 859 bsi = mBufferSlots.add(bi.mSlot, nullptr); 860 } 861 buffer = std::make_shared<CachedBuffer>(bi.mSlot, bi.mGraphicBuffer); 862 mBufferSlots.replaceValueAt(bsi, buffer); 863 } else { 864 buffer = mBufferSlots.valueAt(bsi); 865 } 866 int64_t frameNum = bi.mFrameNumber; 867 868 std::shared_ptr<AcquiredBuffer> acquiredBuffer = 869 std::make_shared<AcquiredBuffer>( 870 buffer, 871 [frameNum, this](AcquiredBuffer *buffer){ 872 // AcquiredBuffer's destructor should always be called when mMutex is locked. 873 // If we had a reentrant mutex, we could just lock it again to ensure this. 874 if (mMutex.tryLock() == 0) { 875 TRESPASS_DBG(); 876 mMutex.unlock(); 877 } 878 879 // we can release buffers immediately if not using adapters 880 // alternately, we could add them to mSlotsToRelease, but we would 881 // somehow need to propagate frame number to that queue 882 if (buffer->isCached()) { 883 --mNumOutstandingAcquires; 884 mConsumer->releaseBuffer( 885 buffer->getSlot(), frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, 886 buffer->getReleaseFence()); 887 } 888 }, 889 bi.mFence); 890 VideoBuffer videoBuffer{acquiredBuffer, bi.mTimestamp, bi.mDataSpace}; 891 *ab = videoBuffer; 892 ++mNumOutstandingAcquires; 893 return OK; 894 } 895 896 // BufferQueue::ConsumerListener callback 897 void GraphicBufferSource::onFrameAvailable(const BufferItem& item __unused) { 898 Mutex::Autolock autoLock(mMutex); 899 900 ALOGV("onFrameAvailable: executing=%d available=%zu+%d", 901 mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers); 902 ++mNumAvailableUnacquiredBuffers; 903 904 // For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec 905 // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes 906 // this an ugly logic. 907 // NOTE: We could also rely on our debug counter but that is meant only as a debug counter. 908 if (!areWeDiscardingAvailableBuffers_l() && mFreeCodecBuffers.empty()) { 909 // we may not be allowed to acquire a possibly encodable buffer, so just note that 910 // it is available 911 ALOGV("onFrameAvailable: cannot acquire buffer right now, do it later"); 912 913 ++mRepeatLastFrameGeneration; // cancel any pending frame repeat 914 return; 915 } 916 917 VideoBuffer buffer; 918 status_t err = acquireBuffer_l(&buffer); 919 if (err != OK) { 920 ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err); 921 } else { 922 onBufferAcquired_l(buffer); 923 } 924 } 925 926 bool GraphicBufferSource::areWeDiscardingAvailableBuffers_l() { 927 return mEndOfStreamSent // already sent EOS to codec 928 || mOMXNode == nullptr // there is no codec connected 929 || (mSuspended && mActionQueue.empty()) // we are suspended and not waiting for 930 // any further action 931 || !mExecuting; 932 } 933 934 void GraphicBufferSource::onBufferAcquired_l(const VideoBuffer &buffer) { 935 if (mEndOfStreamSent) { 936 // This should only be possible if a new buffer was queued after 937 // EOS was signaled, i.e. the app is misbehaving. 938 ALOGW("onFrameAvailable: EOS is sent, ignoring frame"); 939 } else if (mOMXNode == NULL || (mSuspended && mActionQueue.empty())) { 940 // FIXME: if we are suspended but have a resume queued we will stop repeating the last 941 // frame. Is that the desired behavior? 942 ALOGV("onFrameAvailable: suspended, ignoring frame"); 943 } else { 944 ++mRepeatLastFrameGeneration; // cancel any pending frame repeat 945 mAvailableBuffers.push_back(buffer); 946 if (mExecuting) { 947 fillCodecBuffer_l(); 948 } 949 } 950 } 951 952 // BufferQueue::ConsumerListener callback 953 void GraphicBufferSource::onBuffersReleased() { 954 Mutex::Autolock lock(mMutex); 955 956 uint64_t slotMask; 957 if (mConsumer->getReleasedBuffers(&slotMask) != NO_ERROR) { 958 ALOGW("onBuffersReleased: unable to get released buffer set"); 959 slotMask = 0xffffffffffffffffULL; 960 } 961 962 ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask); 963 964 for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { 965 if ((slotMask & 0x01) != 0) { 966 discardBufferInSlot_l(i); 967 } 968 slotMask >>= 1; 969 } 970 } 971 972 void GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) { 973 ssize_t bsi = mBufferSlots.indexOfKey(i); 974 if (bsi < 0) { 975 ALOGW("releasing an unpopulated slot: %d", i); 976 } else { 977 discardBufferAtSlotIndex_l(bsi); 978 mBufferSlots.removeItemsAt(bsi); 979 } 980 } 981 982 void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t bsi) { 983 const std::shared_ptr<CachedBuffer>& buffer = mBufferSlots.valueAt(bsi); 984 // use -2 if there is no latest buffer, and -1 if it is no longer cached 985 slot_id latestBufferSlot = 986 mLatestBuffer.mBuffer == nullptr ? -2 : mLatestBuffer.mBuffer->getSlot(); 987 ALOGV("releasing acquired buffer: [slot=%d, useCount=%ld], latest: [slot=%d]", 988 mBufferSlots.keyAt(bsi), buffer.use_count(), latestBufferSlot); 989 mBufferSlots.valueAt(bsi)->onDroppedFromCache(); 990 991 // If the slot of an acquired buffer is discarded, that buffer will not have to be 992 // released to the producer, so account it here. However, it is possible that the 993 // acquired buffer has already been discarded so check if it still is. 994 if (buffer->isAcquired()) { 995 --mNumOutstandingAcquires; 996 } 997 998 // clear the buffer reference (not technically needed as caller either replaces or deletes 999 // it; done here for safety). 1000 mBufferSlots.editValueAt(bsi).reset(); 1001 CHECK_DBG(buffer == nullptr); 1002 } 1003 1004 void GraphicBufferSource::releaseAllAvailableBuffers_l() { 1005 mAvailableBuffers.clear(); 1006 while (mNumAvailableUnacquiredBuffers > 0) { 1007 VideoBuffer item; 1008 if (acquireBuffer_l(&item) != OK) { 1009 ALOGW("releaseAllAvailableBuffers: failed to acquire available unacquired buffer"); 1010 break; 1011 } 1012 } 1013 } 1014 1015 // BufferQueue::ConsumerListener callback 1016 void GraphicBufferSource::onSidebandStreamChanged() { 1017 ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams"); 1018 } 1019 1020 status_t GraphicBufferSource::configure( 1021 const sp<IOmxNodeWrapper>& omxNode, 1022 int32_t dataSpace, 1023 int32_t bufferCount, 1024 uint32_t frameWidth, 1025 uint32_t frameHeight, 1026 uint32_t consumerUsage) { 1027 if (omxNode == NULL) { 1028 return BAD_VALUE; 1029 } 1030 1031 1032 // Call setMaxAcquiredBufferCount without lock. 1033 // setMaxAcquiredBufferCount could call back to onBuffersReleased 1034 // if the buffer count change results in releasing of existing buffers, 1035 // which would lead to deadlock. 1036 status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount); 1037 if (err != NO_ERROR) { 1038 ALOGE("Unable to set BQ max acquired buffer count to %u: %d", 1039 bufferCount, err); 1040 return err; 1041 } 1042 1043 { 1044 Mutex::Autolock autoLock(mMutex); 1045 mOMXNode = omxNode; 1046 1047 err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight); 1048 if (err != NO_ERROR) { 1049 ALOGE("Unable to set BQ default buffer size to %ux%u: %d", 1050 frameWidth, frameHeight, err); 1051 return err; 1052 } 1053 1054 consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER; 1055 mConsumer->setConsumerUsageBits(consumerUsage); 1056 1057 // Sets the default buffer data space 1058 ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires); 1059 mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace); 1060 mLastDataspace = (android_dataspace)dataSpace; 1061 1062 mExecuting = false; 1063 mSuspended = false; 1064 mEndOfStream = false; 1065 mEndOfStreamSent = false; 1066 mSkipFramesBeforeNs = -1ll; 1067 mFrameRepeatIntervalUs = -1ll; 1068 mRepeatLastFrameGeneration = 0; 1069 mOutstandingFrameRepeatCount = 0; 1070 mLatestBuffer.mBuffer.reset(); 1071 mFrameRepeatBlockedOnCodecBuffer = false; 1072 mFps = -1.0; 1073 mCaptureFps = -1.0; 1074 mBaseCaptureUs = -1ll; 1075 mBaseFrameUs = -1ll; 1076 mPrevCaptureUs = -1ll; 1077 mPrevFrameUs = -1ll; 1078 mFrameCount = 0; 1079 mInputBufferTimeOffsetUs = 0; 1080 mStopTimeUs = -1; 1081 mActionQueue.clear(); 1082 } 1083 1084 return OK; 1085 } 1086 1087 status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) { 1088 ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs); 1089 1090 Mutex::Autolock autoLock(mMutex); 1091 1092 if (mStopTimeUs != -1) { 1093 ALOGE("setSuspend failed as STOP action is pending"); 1094 return INVALID_OPERATION; 1095 } 1096 1097 // Push the action to the queue. 1098 if (suspendStartTimeUs != -1) { 1099 // suspendStartTimeUs must be smaller or equal to current systemTime. 1100 int64_t currentSystemTimeUs = systemTime() / 1000; 1101 if (suspendStartTimeUs > currentSystemTimeUs) { 1102 ALOGE("setSuspend failed. %lld is larger than current system time %lld us", 1103 (long long)suspendStartTimeUs, (long long)currentSystemTimeUs); 1104 return INVALID_OPERATION; 1105 } 1106 if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) { 1107 ALOGE("setSuspend failed. %lld is smaller than last action time %lld us", 1108 (long long)suspendStartTimeUs, (long long)mLastActionTimeUs); 1109 return INVALID_OPERATION; 1110 } 1111 mLastActionTimeUs = suspendStartTimeUs; 1112 ActionItem action; 1113 action.mAction = suspend ? ActionItem::PAUSE : ActionItem::RESUME; 1114 action.mActionTimeUs = suspendStartTimeUs; 1115 ALOGV("Push %s action into actionQueue", suspend ? "PAUSE" : "RESUME"); 1116 mActionQueue.push_back(action); 1117 } else { 1118 if (suspend) { 1119 mSuspended = true; 1120 releaseAllAvailableBuffers_l(); 1121 return OK; 1122 } else { 1123 mSuspended = false; 1124 if (mExecuting && !haveAvailableBuffers_l() 1125 && mFrameRepeatBlockedOnCodecBuffer) { 1126 if (repeatLatestBuffer_l()) { 1127 ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS"); 1128 mFrameRepeatBlockedOnCodecBuffer = false; 1129 } else { 1130 ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE"); 1131 } 1132 } 1133 } 1134 } 1135 return OK; 1136 } 1137 1138 status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) { 1139 ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs); 1140 1141 Mutex::Autolock autoLock(mMutex); 1142 1143 if (mExecuting || repeatAfterUs <= 0ll) { 1144 return INVALID_OPERATION; 1145 } 1146 1147 mFrameRepeatIntervalUs = repeatAfterUs; 1148 return OK; 1149 } 1150 1151 status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) { 1152 Mutex::Autolock autoLock(mMutex); 1153 1154 // timeOffsetUs must be negative for adjustment. 1155 if (timeOffsetUs >= 0ll) { 1156 return INVALID_OPERATION; 1157 } 1158 1159 mInputBufferTimeOffsetUs = timeOffsetUs; 1160 return OK; 1161 } 1162 1163 status_t GraphicBufferSource::setMaxFps(float maxFps) { 1164 ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps); 1165 1166 Mutex::Autolock autoLock(mMutex); 1167 1168 if (mExecuting) { 1169 return INVALID_OPERATION; 1170 } 1171 1172 mFrameDropper = new FrameDropper(); 1173 status_t err = mFrameDropper->setMaxFrameRate(maxFps); 1174 if (err != OK) { 1175 mFrameDropper.clear(); 1176 return err; 1177 } 1178 1179 return OK; 1180 } 1181 1182 status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) { 1183 ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs); 1184 1185 Mutex::Autolock autoLock(mMutex); 1186 1187 mSkipFramesBeforeNs = 1188 (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll; 1189 1190 return OK; 1191 } 1192 1193 status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) { 1194 ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs); 1195 Mutex::Autolock autoLock(mMutex); 1196 1197 if (mStopTimeUs != -1) { 1198 // Ignore if stop time has already been set 1199 return OK; 1200 } 1201 1202 // stopTimeUs must be smaller or equal to current systemTime. 1203 int64_t currentSystemTimeUs = systemTime() / 1000; 1204 if (stopTimeUs > currentSystemTimeUs) { 1205 ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us", 1206 (long long)stopTimeUs, (long long)currentSystemTimeUs); 1207 return INVALID_OPERATION; 1208 } 1209 if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) { 1210 ALOGE("setSuspend failed. %lld is smaller than last action time %lld us", 1211 (long long)stopTimeUs, (long long)mLastActionTimeUs); 1212 return INVALID_OPERATION; 1213 } 1214 mLastActionTimeUs = stopTimeUs; 1215 ActionItem action; 1216 action.mAction = ActionItem::STOP; 1217 action.mActionTimeUs = stopTimeUs; 1218 mActionQueue.push_back(action); 1219 mStopTimeUs = stopTimeUs; 1220 return OK; 1221 } 1222 1223 status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps) { 1224 ALOGV("setTimeLapseConfig: fps=%lg, captureFps=%lg", 1225 fps, captureFps); 1226 1227 Mutex::Autolock autoLock(mMutex); 1228 1229 if (mExecuting || !(fps > 0) || !(captureFps > 0)) { 1230 return INVALID_OPERATION; 1231 } 1232 1233 mFps = fps; 1234 mCaptureFps = captureFps; 1235 1236 return OK; 1237 } 1238 1239 status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) { 1240 Mutex::Autolock autoLock(mMutex); 1241 mDefaultColorAspectsPacked = aspectsPacked; 1242 ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked); 1243 ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))", 1244 colorAspects.mRange, asString(colorAspects.mRange), 1245 colorAspects.mPrimaries, asString(colorAspects.mPrimaries), 1246 colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs), 1247 colorAspects.mTransfer, asString(colorAspects.mTransfer)); 1248 1249 return OK; 1250 } 1251 1252 status_t GraphicBufferSource::signalEndOfInputStream() { 1253 Mutex::Autolock autoLock(mMutex); 1254 ALOGV("signalEndOfInputStream: executing=%d available=%zu+%d eos=%d", 1255 mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream); 1256 1257 if (mEndOfStream) { 1258 ALOGE("EOS was already signaled"); 1259 return INVALID_OPERATION; 1260 } 1261 1262 // Set the end-of-stream flag. If no frames are pending from the 1263 // BufferQueue, and a codec buffer is available, and we're executing, 1264 // and there is no stop timestamp, we initiate the EOS from here. 1265 // Otherwise, we'll let codecBufferEmptied() (or omxExecuting) do it. 1266 // 1267 // Note: if there are no pending frames and all codec buffers are 1268 // available, we *must* submit the EOS from here or we'll just 1269 // stall since no future events are expected. 1270 mEndOfStream = true; 1271 1272 if (mStopTimeUs == -1 && mExecuting && !haveAvailableBuffers_l()) { 1273 submitEndOfInputStream_l(); 1274 } 1275 1276 return OK; 1277 } 1278 1279 void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) { 1280 switch (msg->what()) { 1281 case kWhatRepeatLastFrame: 1282 { 1283 Mutex::Autolock autoLock(mMutex); 1284 1285 int32_t generation; 1286 CHECK(msg->findInt32("generation", &generation)); 1287 1288 if (generation != mRepeatLastFrameGeneration) { 1289 // stale 1290 break; 1291 } 1292 1293 if (!mExecuting || haveAvailableBuffers_l()) { 1294 break; 1295 } 1296 1297 bool success = repeatLatestBuffer_l(); 1298 if (success) { 1299 ALOGV("repeatLatestBuffer_l SUCCESS"); 1300 } else { 1301 ALOGV("repeatLatestBuffer_l FAILURE"); 1302 mFrameRepeatBlockedOnCodecBuffer = true; 1303 } 1304 break; 1305 } 1306 1307 default: 1308 TRESPASS(); 1309 } 1310 } 1311 1312 } // namespace android 1313