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

Commit d0ef20e9 authored by Chien-Yu Chen's avatar Chien-Yu Chen Committed by Android (Google) Code Review
Browse files

Merge "Camera: Support BufferQueue between Camera and StageFright"

parents 6152b8ce 8cca0750
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -136,6 +136,15 @@ status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProduc
    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
status_t Camera::startPreview()
{
@@ -145,13 +154,12 @@ status_t Camera::startPreview()
    return c->startPreview();
}

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

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

class BpCamera: public BpInterface<ICamera>
@@ -151,13 +152,13 @@ public:
        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;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        data.writeInt32(enabled);
        remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
        data.writeInt32(videoBufferMode);
        remote()->transact(SET_VIDEO_BUFFER_MODE, data, &reply);
        return reply.readInt32();
    }

@@ -268,6 +269,17 @@ public:
        remote()->transact(UNLOCK, data, &reply);
        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");
@@ -339,11 +351,11 @@ status_t BnCamera::onTransact(
            releaseRecordingFrame(mem);
            return NO_ERROR;
        } break;
        case STORE_META_DATA_IN_BUFFERS: {
            ALOGV("STORE_META_DATA_IN_BUFFERS");
        case SET_VIDEO_BUFFER_MODE: {
            ALOGV("SET_VIDEO_BUFFER_MODE");
            CHECK_INTERFACE(ICamera, data, reply);
            bool enabled = data.readInt32();
            reply->writeInt32(storeMetaDataInBuffers(enabled));
            int32_t mode = data.readInt32();
            reply->writeInt32(setVideoBufferMode(mode));
            return NO_ERROR;
        } break;
        case PREVIEW_ENABLED: {
@@ -415,6 +427,14 @@ status_t BnCamera::onTransact(
            reply->writeInt32(unlock());
            return NO_ERROR;
        } 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:
            return BBinder::onTransact(code, data, reply, flags);
    }
+9 −2
Original line number Diff line number Diff line
@@ -126,8 +126,15 @@ public:
            // 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);
+19 −2
Original line number Diff line number Diff line
@@ -36,6 +36,15 @@ class ICamera: public IInterface
     * 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 @@ public:
    // 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;
};

// ----------------------------------------------------------------------------
+57 −2
Original line number Diff line number Diff line
@@ -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 @@ public:
    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 @@ protected:
        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 @@ private:
    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 @@ private:
                  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 @@ private:
    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();

Loading