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