Merge "Add support for MPEG editlist gapless info"
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index 5f21da9..7d40379 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -146,9 +146,13 @@
// this consumer
sp<BufferQueue> mBufferQueue;
- // mBufferSlot caches GraphicBuffers from the buffer queue
- sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
+ struct SlotData {
+ sp<GraphicBuffer> mGraphicBuffer;
+ uint64_t mFrameNumber;
+ };
+ // mSlots caches GraphicBuffers and frameNumbers from the buffer queue
+ SlotData mSlots[BufferQueue::NUM_BUFFER_SLOTS];
// The permenent width and height of SMS buffers
int mWidth;
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 409038a..71b6569 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -305,8 +305,9 @@
// First time seeing the buffer? Added it to the SMS slot
if (item.mGraphicBuffer != NULL) {
- mBufferSlot[item.mBuf] = item.mGraphicBuffer;
+ mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
}
+ mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;
// check for the timing of this buffer
if (mNumFramesReceived == 0 && !mUseAbsoluteTimestamps) {
@@ -315,7 +316,8 @@
if (mStartTimeNs > 0) {
if (item.mTimestamp < mStartTimeNs) {
// This frame predates start of record, discard
- mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY,
+ mBufferQueue->releaseBuffer(
+ item.mBuf, item.mFrameNumber, EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR, Fence::NO_FENCE);
continue;
}
@@ -345,17 +347,18 @@
// First time seeing the buffer? Added it to the SMS slot
if (item.mGraphicBuffer != NULL) {
- mBufferSlot[mCurrentSlot] = item.mGraphicBuffer;
+ mSlots[item.mBuf].mGraphicBuffer = item.mGraphicBuffer;
}
+ mSlots[item.mBuf].mFrameNumber = item.mFrameNumber;
- mCurrentBuffers.push_back(mBufferSlot[mCurrentSlot]);
+ mCurrentBuffers.push_back(mSlots[mCurrentSlot].mGraphicBuffer);
int64_t prevTimeStamp = mCurrentTimestamp;
mCurrentTimestamp = item.mTimestamp;
mNumFramesEncoded++;
// Pass the data to the MediaBuffer. Pass in only the metadata
- passMetadataBuffer(buffer, mBufferSlot[mCurrentSlot]->handle);
+ passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle);
(*buffer)->setObserver(this);
(*buffer)->add_ref();
@@ -405,15 +408,16 @@
}
for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
- if (mBufferSlot[id] == NULL) {
+ if (mSlots[id].mGraphicBuffer == NULL) {
continue;
}
- if (bufferHandle == mBufferSlot[id]->handle) {
+ if (bufferHandle == mSlots[id].mGraphicBuffer->handle) {
ALOGV("Slot %d returned, matches handle = %p", id,
- mBufferSlot[id]->handle);
+ mSlots[id].mGraphicBuffer->handle);
- mBufferQueue->releaseBuffer(id, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
+ mBufferQueue->releaseBuffer(id, mSlots[id].mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
Fence::NO_FENCE);
buffer->setObserver(0);
@@ -469,7 +473,7 @@
mFrameAvailableCondition.signal();
for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- mBufferSlot[i] = 0;
+ mSlots[i].mGraphicBuffer = 0;
}
}
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index ef27879..b3a8463 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -206,24 +206,15 @@
// Find matching entry in our cached copy of the BufferQueue slots.
// If we find a match, release that slot. If we don't, the BufferQueue
// has dropped that GraphicBuffer, and there's nothing for us to release.
- //
- // (We could store "id" in CodecBuffer and avoid the slot search.)
- int id;
- for (id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
- if (mBufferSlot[id] == NULL) {
- continue;
- }
+ int id = codecBuffer.mBuf;
+ if (mBufferSlot[id] != NULL &&
+ mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
+ ALOGV("cbi %d matches bq slot %d, handle=%p",
+ cbi, id, mBufferSlot[id]->handle);
- if (mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
- ALOGV("cbi %d matches bq slot %d, handle=%p",
- cbi, id, mBufferSlot[id]->handle);
-
- mBufferQueue->releaseBuffer(id, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
- Fence::NO_FENCE);
- break;
- }
- }
- if (id == BufferQueue::NUM_BUFFER_SLOTS) {
+ mBufferQueue->releaseBuffer(id, codecBuffer.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
+ } else {
ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
cbi);
}
@@ -287,11 +278,11 @@
mBufferSlot[item.mBuf] = item.mGraphicBuffer;
}
- err = submitBuffer_l(mBufferSlot[item.mBuf], item.mTimestamp / 1000, cbi);
+ err = submitBuffer_l(item, 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);
+ mBufferQueue->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);
}
@@ -326,11 +317,13 @@
return OK;
}
-status_t GraphicBufferSource::submitBuffer_l(sp<GraphicBuffer>& graphicBuffer,
- int64_t timestampUsec, int cbi) {
+status_t GraphicBufferSource::submitBuffer_l(
+ const BufferQueue::BufferItem &item, int cbi) {
ALOGV("submitBuffer_l cbi=%d", cbi);
CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
- codecBuffer.mGraphicBuffer = graphicBuffer;
+ codecBuffer.mGraphicBuffer = mBufferSlot[item.mBuf];
+ codecBuffer.mBuf = item.mBuf;
+ codecBuffer.mFrameNumber = item.mFrameNumber;
OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
@@ -342,7 +335,7 @@
status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
- timestampUsec);
+ item.mTimestamp / 1000);
if (err != OK) {
ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
codecBuffer.mGraphicBuffer = NULL;
@@ -431,8 +424,8 @@
BufferQueue::BufferItem item;
status_t err = mBufferQueue->acquireBuffer(&item);
if (err == OK) {
- mBufferQueue->releaseBuffer(item.mBuf, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR, item.mFence);
+ mBufferQueue->releaseBuffer(item.mBuf, item.mFrameNumber,
+ EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, item.mFence);
}
return;
}
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 562d342..8c6b470 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -104,6 +104,13 @@
// (mGraphicBuffer == NULL) or in use by the codec.
struct CodecBuffer {
OMX_BUFFERHEADERTYPE* mHeader;
+
+ // buffer producer's frame-number for buffer
+ uint64_t mFrameNumber;
+
+ // buffer producer's buffer slot for buffer
+ int mBuf;
+
sp<GraphicBuffer> mGraphicBuffer;
};
@@ -130,8 +137,7 @@
// Marks the mCodecBuffers entry as in-use, copies the GraphicBuffer
// reference into the codec buffer, and submits the data to the codec.
- status_t submitBuffer_l(sp<GraphicBuffer>& graphicBuffer,
- int64_t timestampUsec, int cbi);
+ status_t submitBuffer_l(const BufferQueue::BufferItem &item, int cbi);
// Submits an empty buffer, with the EOS flag set. Returns without
// doing anything if we don't have a codec buffer available.
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index 6f4f4c8..1d38993 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -1329,6 +1329,10 @@
// Finally, dispatch any 3A change events to listeners if we got metadata
+ if (result->result != NULL) {
+ mResultSignal.signal();
+ }
+
if (result->result != NULL && listener != NULL) {
if (new3aState.aeState != cur3aState.aeState) {
ALOGVV("%s: AE state changed from 0x%x to 0x%x",
diff --git a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
index 257a45f..4012fc5 100644
--- a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp
@@ -93,6 +93,9 @@
status_t res;
ATRACE_CALL();
CameraMetadata frame;
+
+ ALOGV("%s: Camera %d: Process new frames", __FUNCTION__, device->getId());
+
while ( (res = device->getNextFrame(&frame)) == OK) {
camera_metadata_entry_t entry;
@@ -124,6 +127,8 @@
bool ProFrameProcessor::processSingleFrame(CameraMetadata &frame,
const sp<CameraDeviceBase> &device) {
+ ALOGV("%s: Camera %d: Process single frame (is empty? %d)",
+ __FUNCTION__, device->getId(), frame.isEmpty());
return processListeners(frame, device) == OK;
}
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
index e2c120c..2e06691 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
@@ -373,9 +373,15 @@
size_t idx = 0;
nsecs_t minTimestamp = -1;
+
+ size_t emptyCount = mFrameList.size();
+
for (size_t j = 0; j < mFrameList.size(); j++) {
const CameraMetadata &frame = mFrameList[j];
if (!frame.isEmpty()) {
+
+ emptyCount--;
+
camera_metadata_ro_entry_t entry;
entry = frame.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
@@ -387,7 +393,12 @@
if (minTimestamp > frameTimestamp || minTimestamp == -1) {
entry = frame.find(ANDROID_CONTROL_AE_STATE);
+
if (entry.count == 0) {
+ /**
+ * This is most likely a HAL bug. The aeState field is
+ * mandatory, so it should always be in a metadata packet.
+ */
ALOGW("%s: ZSL queue frame has no AE state field!",
__FUNCTION__);
continue;
@@ -402,9 +413,30 @@
minTimestamp = frameTimestamp;
idx = j;
}
+
+ ALOGVV("%s: Saw timestamp %lld", __FUNCTION__, frameTimestamp);
}
}
+ if (emptyCount == mFrameList.size()) {
+ /**
+ * This could be mildly bad and means our ZSL was triggered before
+ * there were any frames yet received by the camera framework.
+ *
+ * This is a fairly corner case which can happen under:
+ * + a user presses the shutter button real fast when the camera starts
+ * (startPreview followed immediately by takePicture).
+ * + burst capture case (hitting shutter button as fast possible)
+ *
+ * If this happens in steady case (preview running for a while, call
+ * a single takePicture) then this might be a fwk bug.
+ */
+ ALOGW("%s: ZSL queue has no metadata frames", __FUNCTION__);
+ }
+
+ ALOGV("%s: Candidate timestamp %lld (idx %d), empty frames: %d",
+ __FUNCTION__, minTimestamp, idx, emptyCount);
+
if (metadataIdx) {
*metadataIdx = idx;
}
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index 2fa78a4..dfa1066 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -101,12 +101,6 @@
} // end scope of mMutex autolock
- if (pinnedBuffer != 0) {
- BI_LOGV("Pinned buffer frame %lld, timestamp %lld",
- pinnedBuffer->getBufferItem().mFrameNumber,
- pinnedBuffer->getBufferItem().mTimestamp);
- }
-
if (waitForFence) {
status_t err = pinnedBuffer->getBufferItem().mFence->waitForever(
"RingBufferConsumer::pinSelectedBuffer");
@@ -172,6 +166,9 @@
if (it == end) {
BI_LOGE("Failed to pin buffer (timestamp %lld, framenumber %lld)",
item.mTimestamp, item.mFrameNumber);
+ } else {
+ BI_LOGV("Pinned buffer (frame %lld, timestamp %lld)",
+ item.mFrameNumber, item.mTimestamp);
}
}
@@ -182,7 +179,7 @@
it = mBufferItemList.begin();
end = mBufferItemList.end();
- accIt = it;
+ accIt = end;
if (it == end) {
/**
@@ -197,12 +194,17 @@
for (; it != end; ++it) {
RingBufferItem& find = *it;
- if (find.mTimestamp < accIt->mTimestamp && find.mPinCount <= 0) {
- accIt = it;
+
+ if (find.mPinCount > 0) {
+ if (pinnedFrames != NULL) {
+ ++(*pinnedFrames);
+ }
+ // Filter out pinned frame when searching for buffer to release
+ continue;
}
- if (find.mPinCount > 0 && pinnedFrames != NULL) {
- ++(*pinnedFrames);
+ if (find.mTimestamp < accIt->mTimestamp || accIt == end) {
+ accIt = it;
}
}
@@ -212,7 +214,11 @@
// In case the object was never pinned, pass the acquire fence
// back to the release fence. If the fence was already waited on,
// it'll just be a no-op to wait on it again.
- err = addReleaseFenceLocked(item.mBuf, item.mFence);
+
+ // item.mGraphicBuffer was populated with the proper graphic-buffer
+ // at acquire even if it was previously acquired
+ err = addReleaseFenceLocked(item.mBuf,
+ item.mGraphicBuffer, item.mFence);
if (err != OK) {
BI_LOGE("Failed to add release fence to buffer "
@@ -224,7 +230,9 @@
BI_LOGV("Attempting to release buffer timestamp %lld, frame %lld",
item.mTimestamp, item.mFrameNumber);
- err = releaseBufferLocked(item.mBuf,
+ // item.mGraphicBuffer was populated with the proper graphic-buffer
+ // at acquire even if it was previously acquired
+ err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer,
EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR);
if (err != OK) {
@@ -308,7 +316,8 @@
RingBufferItem& find = *it;
if (item.mGraphicBuffer == find.mGraphicBuffer) {
- status_t res = addReleaseFenceLocked(item.mBuf, item.mFence);
+ status_t res = addReleaseFenceLocked(item.mBuf,
+ item.mGraphicBuffer, item.mFence);
if (res != OK) {
BI_LOGE("Failed to add release fence to buffer "
@@ -323,7 +332,11 @@
}
if (it == end) {
- BI_LOGE("Failed to unpin buffer (timestamp %lld, framenumber %lld",
+ // This should never happen. If it happens, we have a bug.
+ BI_LOGE("Failed to unpin buffer (timestamp %lld, framenumber %lld)",
+ item.mTimestamp, item.mFrameNumber);
+ } else {
+ BI_LOGV("Unpinned buffer (timestamp %lld, framenumber %lld)",
item.mTimestamp, item.mFrameNumber);
}
}