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