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