bool GraphicBufferSource::repeatLatestSubmittedBuffer_l() { CHECK(mExecuting && mNumFramesAvailable == 0); if (mLatestSubmittedBufferId < 0 || mSuspended) { return false; } if (mBufferSlot[mLatestSubmittedBufferId] == NULL) { // This can happen if the remote side disconnects, causing // onBuffersReleased() to NULL out our copy of the slots. The // buffer is gone, so we have nothing to show. // To be on the safe side we try to release the buffer. mBufferQueue->releaseBuffer( mLatestSubmittedBufferId, mLatestSubmittedBufferFrameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); mLatestSubmittedBufferId = -1; mLatestSubmittedBufferFrameNum = 0; return false; } int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { // No buffers available, bail. return false; } BufferQueue::BufferItem item; item.mBuf = mLatestSubmittedBufferId; item.mFrameNumber = mLatestSubmittedBufferFrameNum; item.mTimestamp = mRepeatLastFrameTimestamp; status_t err = submitBuffer_l(item, cbi); if (err != OK) { return false; } ++mLatestSubmittedBufferUseCount; /* repeat last frame up to kRepeatLastFrameCount times. * in case of static scene, a single repeat might not get rid of encoder * ghosting completely, refresh a couple more times to get better quality */ if (--mRepeatLastFrameCount > 0) { mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000; if (mReflector != NULL) { sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector->id()); msg->setInt32("generation", ++mRepeatLastFrameGeneration); msg->post(mRepeatAfterUs); } } return true; }
bool GraphicBufferSource::fillCodecBuffer_l() { CHECK(mExecuting && mNumFramesAvailable > 0); int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { // No buffers available, bail. ALOGV("fillCodecBuffer_l: no codec buffers, avail now %d", mNumFramesAvailable); return false; } ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%d", mNumFramesAvailable); BufferQueue::BufferItem item; status_t err = mBufferQueue->acquireBuffer(&item); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // shouldn't happen ALOGW("fillCodecBuffer_l: frame was not available"); return false; } else if (err != OK) { // now what? fake end-of-stream? ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err); return false; } mNumFramesAvailable--; // Wait for it to become available. err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l"); if (err != OK) { ALOGW("failed to wait for buffer fence: %d", err); // keep going } // If this is the first time we're seeing this buffer, add it to our // slot table. if (item.mGraphicBuffer != NULL) { ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); mBufferSlot[item.mBuf] = item.mGraphicBuffer; } err = submitBuffer_l(mBufferSlot[item.mBuf], item.mTimestamp / 1000, cbi); if (err != OK) { ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf); mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); } else { ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); } return true; }
bool GraphicBufferSource::fillCodecBuffer_l() { CHECK(mExecuting && mNumFramesAvailable > 0); if (mSuspended) { return false; } int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { // No buffers available, bail. return false; } BufferQueue::BufferItem item; status_t err = mBufferQueue->acquireBuffer(&item, 0); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // shouldn't happen ALOGW("fillCodecBuffer_l: frame was not available"); return false; } else if (err != OK) { // now what? fake end-of-stream? ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err); return false; } mNumFramesAvailable--; // Wait for it to become available. err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l"); if (err != OK) { ALOGW("failed to wait for buffer fence: %d", err); // keep going } // If this is the first time we're seeing this buffer, add it to our // slot table. if (item.mGraphicBuffer != NULL) { mBufferSlot[item.mBuf] = item.mGraphicBuffer; } err = submitBuffer_l(item, cbi); if (err != OK) { mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); } else { setLatestSubmittedBuffer_l(item); } return true; }
void GraphicBufferSource::submitEndOfInputStream_l() { CHECK(mEndOfStream); if (mEndOfStreamSent) { ALOGV("EOS already sent"); return; } int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { ALOGV("submitEndOfInputStream_l: no codec buffers available"); return; } // We reject any additional incoming graphic buffers, so there's no need // to stick a placeholder into codecBuffer.mGraphicBuffer to mark it as // in-use. CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi)); OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader; if (EXTRA_CHECK) { // Guard against implementations that don't check nFilledLen. size_t fillLen = 4 + sizeof(buffer_handle_t); CHECK(header->nAllocLen >= fillLen); OMX_U8* data = header->pBuffer; memset(data, 0xcd, fillLen); } uint64_t timestamp = 0; // does this matter? status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0, /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS, timestamp); if (err != OK) { ALOGW("emptyDirectBuffer EOS failed: 0x%x", err); } else { ALOGV("submitEndOfInputStream_l: buffer submitted, header=%p cbi=%d", header, cbi); mEndOfStreamSent = true; } }
bool GraphicBufferSource::fillCodecBuffer_l() { CHECK(mExecuting && mNumFramesAvailable > 0); if (mSuspended) { return false; } int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { // No buffers available, bail. ALOGV("fillCodecBuffer_l: no codec buffers, avail now %zu", mNumFramesAvailable); return false; } ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu", mNumFramesAvailable); BufferItem item; status_t err = mConsumer->acquireBuffer(&item, 0); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // shouldn't happen ALOGW("fillCodecBuffer_l: frame was not available"); return false; } else if (err != OK) { // now what? fake end-of-stream? ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err); return false; } mNumBufferAcquired++; mNumFramesAvailable--; // If this is the first time we're seeing this buffer, add it to our // slot table. if (item.mGraphicBuffer != NULL) { ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); mBufferSlot[item.mBuf] = item.mGraphicBuffer; } err = UNKNOWN_ERROR; // only submit sample if start time is unspecified, or sample // is queued after the specified start time bool dropped = false; if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) { // if start time is set, offset time stamp by start time if (mSkipFramesBeforeNs > 0) { item.mTimestamp -= mSkipFramesBeforeNs; } int64_t timeUs = item.mTimestamp / 1000; if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) { ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs)); // set err to OK so that the skipped frame can still be saved as the lastest frame err = OK; dropped = true; } else { err = submitBuffer_l(item, cbi); } } if (err != OK) { ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf); releaseBuffer(item.mBuf, item.mFrameNumber, item.mGraphicBuffer, item.mFence); } else { ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); setLatestBuffer_l(item, dropped); } return true; }
bool GraphicBufferSource::fillCodecBuffer_l() { CHECK(mExecuting && mNumFramesAvailable > 0); if (mSuspended) { return false; } int cbi = findAvailableCodecBuffer_l(); if (cbi < 0) { // No buffers available, bail. ALOGV("fillCodecBuffer_l: no codec buffers, avail now %zu", mNumFramesAvailable); return false; } ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu", mNumFramesAvailable); BufferQueue::BufferItem item; status_t err = mConsumer->acquireBuffer(&item, 0); if (err == BufferQueue::NO_BUFFER_AVAILABLE) { // shouldn't happen ALOGW("fillCodecBuffer_l: frame was not available"); return false; } else if (err != OK) { // now what? fake end-of-stream? ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err); return false; } mNumFramesAvailable--; // Wait for it to become available. err = item.mFence->waitForever("GraphicBufferSource::fillCodecBuffer_l"); if (err != OK) { ALOGW("failed to wait for buffer fence: %d", err); // keep going } // If this is the first time we're seeing this buffer, add it to our // slot table. if (item.mGraphicBuffer != NULL) { ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mBuf); mBufferSlot[item.mBuf] = item.mGraphicBuffer; } err = UNKNOWN_ERROR; // only submit sample if start time is unspecified, or sample // is queued after the specified start time if (mSkipFramesBeforeNs < 0ll || item.mTimestamp >= mSkipFramesBeforeNs) { // if start time is set, offset time stamp by start time if (mSkipFramesBeforeNs > 0) { item.mTimestamp -= mSkipFramesBeforeNs; } err = submitBuffer_l(item, cbi); } if (err != OK) { ALOGV("submitBuffer_l failed, releasing bq buf %d", item.mBuf); mConsumer->releaseBuffer(item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE); } else { ALOGV("buffer submitted (bq %d, cbi %d)", item.mBuf, cbi); setLatestSubmittedBuffer_l(item); } return true; }