Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8cca0750 authored by Chien-Yu Chen's avatar Chien-Yu Chen
Browse files

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
parent cf52591e
Loading
Loading
Loading
Loading
+12 −4
Original line number Original line Diff line number Diff line
@@ -136,6 +136,15 @@ status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProduc
    return c->setPreviewTarget(bufferProducer);
    return c->setPreviewTarget(bufferProducer);
}
}


status_t Camera::setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer)
{
    ALOGV("setVideoTarget(%p)", bufferProducer.get());
    sp <ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    ALOGD_IF(bufferProducer == 0, "app passed NULL video surface");
    return c->setVideoTarget(bufferProducer);
}

// start preview mode
// start preview mode
status_t Camera::startPreview()
status_t Camera::startPreview()
{
{
@@ -145,13 +154,12 @@ status_t Camera::startPreview()
    return c->startPreview();
    return c->startPreview();
}
}


status_t Camera::storeMetaDataInBuffers(bool enabled)
status_t Camera::setVideoBufferMode(int32_t videoBufferMode)
{
{
    ALOGV("storeMetaDataInBuffers: %s",
    ALOGV("setVideoBufferMode: %d", videoBufferMode);
            enabled? "true": "false");
    sp <ICamera> c = mCamera;
    sp <ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    if (c == 0) return NO_INIT;
    return c->storeMetaDataInBuffers(enabled);
    return c->setVideoBufferMode(videoBufferMode);
}
}


// start recording mode, must call setPreviewTarget first
// start recording mode, must call setPreviewTarget first
+29 −9
Original line number Original line Diff line number Diff line
@@ -48,7 +48,8 @@ enum {
    STOP_RECORDING,
    STOP_RECORDING,
    RECORDING_ENABLED,
    RECORDING_ENABLED,
    RELEASE_RECORDING_FRAME,
    RELEASE_RECORDING_FRAME,
    STORE_META_DATA_IN_BUFFERS,
    SET_VIDEO_BUFFER_MODE,
    SET_VIDEO_BUFFER_TARGET,
};
};


class BpCamera: public BpInterface<ICamera>
class BpCamera: public BpInterface<ICamera>
@@ -151,13 +152,13 @@ public:
        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
    }
    }


    status_t storeMetaDataInBuffers(bool enabled)
    status_t setVideoBufferMode(int32_t videoBufferMode)
    {
    {
        ALOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
        ALOGV("setVideoBufferMode: %d", videoBufferMode);
        Parcel data, reply;
        Parcel data, reply;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        data.writeInt32(enabled);
        data.writeInt32(videoBufferMode);
        remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
        remote()->transact(SET_VIDEO_BUFFER_MODE, data, &reply);
        return reply.readInt32();
        return reply.readInt32();
    }
    }


@@ -268,6 +269,17 @@ public:
        remote()->transact(UNLOCK, data, &reply);
        remote()->transact(UNLOCK, data, &reply);
        return reply.readInt32();
        return reply.readInt32();
    }
    }

    status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer)
    {
        ALOGV("setVideoTarget");
        Parcel data, reply;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        sp<IBinder> b(IInterface::asBinder(bufferProducer));
        data.writeStrongBinder(b);
        remote()->transact(SET_VIDEO_BUFFER_TARGET, data, &reply);
        return reply.readInt32();
    }
};
};


IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera");
IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera");
@@ -339,11 +351,11 @@ status_t BnCamera::onTransact(
            releaseRecordingFrame(mem);
            releaseRecordingFrame(mem);
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case STORE_META_DATA_IN_BUFFERS: {
        case SET_VIDEO_BUFFER_MODE: {
            ALOGV("STORE_META_DATA_IN_BUFFERS");
            ALOGV("SET_VIDEO_BUFFER_MODE");
            CHECK_INTERFACE(ICamera, data, reply);
            CHECK_INTERFACE(ICamera, data, reply);
            bool enabled = data.readInt32();
            int32_t mode = data.readInt32();
            reply->writeInt32(storeMetaDataInBuffers(enabled));
            reply->writeInt32(setVideoBufferMode(mode));
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case PREVIEW_ENABLED: {
        case PREVIEW_ENABLED: {
@@ -415,6 +427,14 @@ status_t BnCamera::onTransact(
            reply->writeInt32(unlock());
            reply->writeInt32(unlock());
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case SET_VIDEO_BUFFER_TARGET: {
            ALOGV("SET_VIDEO_BUFFER_TARGET");
            CHECK_INTERFACE(ICamera, data, reply);
            sp<IGraphicBufferProducer> st =
                interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
            reply->writeInt32(setVideoTarget(st));
            return NO_ERROR;
        } break;
        default:
        default:
            return BBinder::onTransact(code, data, reply, flags);
            return BBinder::onTransact(code, data, reply, flags);
    }
    }
+9 −2
Original line number Original line Diff line number Diff line
@@ -126,8 +126,15 @@ public:
            // send command to camera driver
            // send command to camera driver
            status_t    sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
            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.
            // Tell camera how to pass video buffers. videoBufferMode is one of VIDEO_BUFFER_MODE_*.
            status_t    storeMetaDataInBuffers(bool enabled);
            // 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        setListener(const sp<CameraListener>& listener);
            void        setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
            void        setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
+19 −2
Original line number Original line Diff line number Diff line
@@ -36,6 +36,15 @@ class ICamera: public IInterface
     * Keep up-to-date with ICamera.aidl in frameworks/base
     * Keep up-to-date with ICamera.aidl in frameworks/base
     */
     */
public:
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);
    DECLARE_META_INTERFACE(Camera);


    virtual void            disconnect() = 0;
    virtual void            disconnect() = 0;
@@ -109,8 +118,16 @@ public:
    // send command to camera driver
    // send command to camera driver
    virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
    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;
};
};


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
+57 −2
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include <camera/ICamera.h>
#include <camera/ICamera.h>
#include <camera/ICameraRecordingProxyListener.h>
#include <camera/ICameraRecordingProxyListener.h>
#include <camera/CameraParameters.h>
#include <camera/CameraParameters.h>
#include <gui/BufferItemConsumer.h>
#include <utils/List.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <utils/String16.h>
@@ -122,6 +123,12 @@ public:
    virtual void signalBufferReturned(MediaBuffer* buffer);
    virtual void signalBufferReturned(MediaBuffer* buffer);


protected:
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 {
    class ProxyListener: public BnCameraRecordingProxyListener {
    public:
    public:
        ProxyListener(const sp<CameraSource>& source);
        ProxyListener(const sp<CameraSource>& source);
@@ -132,6 +139,28 @@ protected:
        sp<CameraSource> mSource;
        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.
    // isBinderAlive needs linkToDeath to work.
    class DeathNotifier: public IBinder::DeathRecipient {
    class DeathNotifier: public IBinder::DeathRecipient {
    public:
    public:
@@ -204,11 +233,29 @@ private:
    int32_t mNumGlitches;
    int32_t mNumGlitches;
    int64_t mGlitchDurationThresholdUs;
    int64_t mGlitchDurationThresholdUs;
    bool mCollectStats;
    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 releaseQueuedFrames();
    void releaseOneRecordingFrame(const sp<IMemory>& frame);
    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,
    status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
                  int32_t cameraId, const String16& clientName, uid_t clientUid,
                  int32_t cameraId, const String16& clientName, uid_t clientUid,
@@ -219,6 +266,10 @@ private:
                  int32_t cameraId, const String16& clientName, uid_t clientUid,
                  int32_t cameraId, const String16& clientName, uid_t clientUid,
                  Size videoSize, int32_t frameRate, bool storeMetaDataInVideoBuffers);
                  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,
    status_t isCameraAvailable(const sp<ICamera>& camera,
                               const sp<ICameraRecordingProxy>& proxy,
                               const sp<ICameraRecordingProxy>& proxy,
                               int32_t cameraId,
                               int32_t cameraId,
@@ -236,6 +287,10 @@ private:
    status_t checkFrameRate(const CameraParameters& params,
    status_t checkFrameRate(const CameraParameters& params,
                    int32_t frameRate);
                    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();
    void stopCameraRecording();
    status_t reset();
    status_t reset();


Loading