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