Camera: Support BufferQueue between Camera and StageFright
Use a BufferQueue between Camera and StageFright to pass video
buffers for Camera HALv3 devices.
CameraSource in StageFright will try to use "buffer queue" mode
if it is supported by the camera device. In "buffer queue" mode,
CameraSource creates a buffer queue and a listener thread to recieve
video buffers from camera device. CameraSource then wraps the
ANWBuffer in MediaBuffer. If the camera device doesn't support
"buffer queue" mode, it falls back to "metadata in video buffer"
mode or "real YUV data" mode.
"Metadata in video buffer" mode is removed from Camera2Client and
only "buffer queue" mode is supported.
Bug: 24511454
Change-Id: Ice833b57bcd8d91852d6415402013f56f3e3970a
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 2b60842..f7bf29c 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -126,8 +126,15 @@
// send command to camera driver
status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
- // tell camera hal to store meta data or real YUV in video buffers.
- status_t storeMetaDataInBuffers(bool enabled);
+ // Tell camera how to pass video buffers. videoBufferMode is one of VIDEO_BUFFER_MODE_*.
+ // Returns OK if the specified video buffer mode is supported. If videoBufferMode is
+ // VIDEO_BUFFER_MODE_BUFFER_QUEUE, setVideoTarget() must be called before starting
+ // video recording.
+ status_t setVideoBufferMode(int32_t videoBufferMode);
+
+ // Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE
+ // mode.
+ status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
void setListener(const sp<CameraListener>& listener);
void setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index b025735..e35c3a4 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -36,6 +36,15 @@
* Keep up-to-date with ICamera.aidl in frameworks/base
*/
public:
+ enum {
+ // Pass real YUV data in video buffers through ICameraClient.dataCallbackTimestamp().
+ VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV = 0,
+ // Pass metadata in video buffers through ICameraClient.dataCallbackTimestamp().
+ VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA = 1,
+ // Pass video buffers through IGraphicBufferProducer set with setVideoTarget().
+ VIDEO_BUFFER_MODE_BUFFER_QUEUE = 2,
+ };
+
DECLARE_META_INTERFACE(Camera);
virtual void disconnect() = 0;
@@ -109,8 +118,16 @@
// send command to camera driver
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
- // tell the camera hal to store meta data or real YUV data in video buffers.
- virtual status_t storeMetaDataInBuffers(bool enabled) = 0;
+
+ // Tell camera how to pass video buffers. videoBufferMode is one of VIDEO_BUFFER_MODE_*.
+ // Returns OK if the specified video buffer mode is supported. If videoBufferMode is
+ // VIDEO_BUFFER_MODE_BUFFER_QUEUE, setVideoTarget() must be called before starting video
+ // recording.
+ virtual status_t setVideoBufferMode(int32_t videoBufferMode) = 0;
+
+ // Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
+ virtual status_t setVideoTarget(
+ const sp<IGraphicBufferProducer>& bufferProducer) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 069e897..769adf8 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -23,6 +23,7 @@
#include <camera/ICamera.h>
#include <camera/ICameraRecordingProxyListener.h>
#include <camera/CameraParameters.h>
+#include <gui/BufferItemConsumer.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
@@ -122,6 +123,12 @@
virtual void signalBufferReturned(MediaBuffer* buffer);
protected:
+
+ /**
+ * The class for listening to BnCameraRecordingProxyListener. This is used to receive video
+ * buffers in VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV and VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA
+ * mode. When a frame is available, CameraSource::dataCallbackTimestamp() will be called.
+ */
class ProxyListener: public BnCameraRecordingProxyListener {
public:
ProxyListener(const sp<CameraSource>& source);
@@ -132,6 +139,28 @@
sp<CameraSource> mSource;
};
+ /**
+ * The class for listening to BufferQueue's onFrameAvailable. This is used to receive video
+ * buffers in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode. When a frame is available,
+ * CameraSource::processBufferQueueFrame() will be called.
+ */
+ class BufferQueueListener : public Thread, public BufferItemConsumer::FrameAvailableListener {
+ public:
+ BufferQueueListener(const sp<BufferItemConsumer> &consumer,
+ const sp<CameraSource> &cameraSource);
+ virtual void onFrameAvailable(const BufferItem& item);
+ virtual bool threadLoop();
+ private:
+ static const nsecs_t kFrameAvailableTimeout = 50000000; // 50ms
+
+ sp<BufferItemConsumer> mConsumer;
+ sp<CameraSource> mCameraSource;
+
+ Mutex mLock;
+ Condition mFrameAvailableSignal;
+ bool mFrameAvailable;
+ };
+
// isBinderAlive needs linkToDeath to work.
class DeathNotifier: public IBinder::DeathRecipient {
public:
@@ -204,11 +233,29 @@
int32_t mNumGlitches;
int64_t mGlitchDurationThresholdUs;
bool mCollectStats;
- bool mIsMetaDataStoredInVideoBuffers;
+
+ // The mode video buffers are received from camera. One of VIDEO_BUFFER_MODE_*.
+ int32_t mVideoBufferMode;
+
+ /**
+ * The following variables are used in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
+ */
+ static const size_t kConsumerBufferCount = 8;
+ // Consumer and producer of the buffer queue between this class and camera.
+ sp<BufferItemConsumer> mVideoBufferConsumer;
+ sp<IGraphicBufferProducer> mVideoBufferProducer;
+ // Memory used to send the buffers to encoder, where sp<IMemory> stores VideoNativeMetadata.
+ sp<IMemoryHeap> mMemoryHeapBase;
+ List<sp<IMemory>> mMemoryBases;
+ // A mapping from ANativeWindowBuffer sent to encoder to BufferItem received from camera.
+ // This is protected by mLock.
+ KeyedVector<ANativeWindowBuffer*, BufferItem> mReceivedBufferItemMap;
+ sp<BufferQueueListener> mBufferQueueListener;
void releaseQueuedFrames();
void releaseOneRecordingFrame(const sp<IMemory>& frame);
-
+ // Process a buffer item received in BufferQueueListener.
+ void processBufferQueueFrame(const BufferItem& buffer);
status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId, const String16& clientName, uid_t clientUid,
@@ -219,6 +266,10 @@
int32_t cameraId, const String16& clientName, uid_t clientUid,
Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
+ // Initialize the buffer queue used in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
+ status_t initBufferQueue(uint32_t width, uint32_t height, uint32_t format,
+ android_dataspace dataSpace, uint32_t bufferCount);
+
status_t isCameraAvailable(const sp<ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy,
int32_t cameraId,
@@ -236,6 +287,10 @@
status_t checkFrameRate(const CameraParameters& params,
int32_t frameRate);
+ // Check if this frame should be skipped based on the frame's timestamp in microsecond.
+ // mLock must be locked before calling this function.
+ bool shouldSkipFrameLocked(int64_t timestampUs);
+
void stopCameraRecording();
status_t reset();