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

Commit 025e2744 authored by Chih-Chung Chang's avatar Chih-Chung Chang Committed by Android Git Automerger
Browse files

am e25cc656: Support multiple cameras in framework.

parents 18f4b744 5997faf9
Loading
Loading
Loading
Loading
+22 −13
Original line number Diff line number Diff line
LOCAL_PATH:= $(call my-dir)

#
# Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want
# the camera service to use the fake camera.  For emulator or simulator builds,
# we always use the fake camera.
# Set USE_CAMERA_STUB if you want to use the fake camera.
# Set USE_CAMERA_HARDWARE if you want to use the hardware camera.
# For emulator or simulator builds, we use the fake camera only by default.

ifeq ($(USE_CAMERA_STUB),)
USE_CAMERA_STUB:=false
ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
    ifeq ($(USE_CAMERA_STUB),)
        USE_CAMERA_STUB:=true
    endif
    ifeq ($(USE_CAMERA_HARDWARE),)
        USE_CAMERA_HARDWARE:=false
    endif
else
# force USE_CAMERA_STUB for testing temporarily
#    ifeq ($(USE_CAMERA_STUB),)
        USE_CAMERA_STUB:=true
endif #libcamerastub
#    endif
    ifeq ($(USE_CAMERA_HARDWARE),)
        USE_CAMERA_HARDWARE:=true
    endif
endif

ifeq ($(USE_CAMERA_STUB),true)
@@ -54,18 +63,18 @@ LOCAL_SHARED_LIBRARIES:= \

LOCAL_MODULE:= libcameraservice

LOCAL_CFLAGS += -DLOG_TAG=\"CameraService\"

ifeq ($(TARGET_SIMULATOR),true)
LOCAL_CFLAGS += -DSINGLE_PROCESS
endif

ifeq ($(USE_CAMERA_STUB), true)
LOCAL_STATIC_LIBRARIES += libcamerastub
LOCAL_CFLAGS += -include CameraHardwareStub.h
else
LOCAL_CFLAGS += -DUSE_CAMERA_STUB
endif

ifeq ($(USE_CAMERA_HARDWARE),true)
LOCAL_CFLAGS += -DUSE_CAMERA_HARDWARE
LOCAL_SHARED_LIBRARIES += libcamera 
endif

include $(BUILD_SHARED_LIBRARY)
+18 −27
Original line number Diff line number Diff line
@@ -47,14 +47,14 @@ void CameraHardwareStub::initDefaultParameters()
{
    CameraParameters p;

    p.set("preview-size-values","320x240");
    p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
    p.setPreviewSize(320, 240);
    p.setPreviewFrameRate(15);
    p.setPreviewFormat("yuv422sp");
    p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);

    p.set("picture-size-values", "320x240");
    p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
    p.setPictureSize(320, 240);
    p.setPictureFormat("jpeg");
    p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);

    if (setParameters(p) != NO_ERROR) {
        LOGE("Failed to set default parameters?!");
@@ -66,14 +66,14 @@ void CameraHardwareStub::initHeapLocked()
    // Create raw heap.
    int picture_width, picture_height;
    mParameters.getPictureSize(&picture_width, &picture_height);
    mRawHeap = new MemoryHeapBase(picture_width * 2 * picture_height);
    mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);

    int preview_width, preview_height;
    mParameters.getPreviewSize(&preview_width, &preview_height);
    LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);

    // Note that we enforce yuv422 in setParameters().
    int how_big = preview_width * preview_height * 2;
    // Note that we enforce yuv420sp in setParameters().
    int how_big = preview_width * preview_height * 3 / 2;

    // If we are being reinitialized to the same size as before, no
    // work needs to be done.
@@ -99,7 +99,6 @@ CameraHardwareStub::~CameraHardwareStub()
{
    delete mFakeCamera;
    mFakeCamera = 0; // paranoia
    singleton.clear();
}

sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
@@ -175,7 +174,7 @@ int CameraHardwareStub::previewThread()

        // Fill the current frame with the fake camera.
        uint8_t *frame = ((uint8_t *)base) + offset;
        fakeCamera->getNextFrameAsYuv422(frame);
        fakeCamera->getNextFrameAsYuv420(frame);

        //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);

@@ -288,9 +287,9 @@ int CameraHardwareStub::pictureThread()
        // In the meantime just make another fake camera picture.
        int w, h;
        mParameters.getPictureSize(&w, &h);
        sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
        sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
        FakeCamera cam(w, h);
        cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
        cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
        mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
    }

@@ -307,7 +306,7 @@ status_t CameraHardwareStub::takePicture()
{
    stopPreview();
    if (createThread(beginPictureThread, this) == false)
        return -1;
        return UNKNOWN_ERROR;
    return NO_ERROR;
}

@@ -339,12 +338,14 @@ status_t CameraHardwareStub::setParameters(const CameraParameters& params)
    Mutex::Autolock lock(mLock);
    // XXX verify params

    if (strcmp(params.getPreviewFormat(), "yuv422sp") != 0) {
        LOGE("Only yuv422sp preview is supported");
    if (strcmp(params.getPreviewFormat(),
        CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
        LOGE("Only yuv420sp preview is supported");
        return -1;
    }

    if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
    if (strcmp(params.getPictureFormat(),
        CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
        LOGE("Only jpeg still pictures are supported");
        return -1;
    }
@@ -379,22 +380,12 @@ void CameraHardwareStub::release()
{
}

wp<CameraHardwareInterface> CameraHardwareStub::singleton;

sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
{
    if (singleton != 0) {
        sp<CameraHardwareInterface> hardware = singleton.promote();
        if (hardware != 0) {
            return hardware;
        }
    }
    sp<CameraHardwareInterface> hardware(new CameraHardwareStub());
    singleton = hardware;
    return hardware;
    return new CameraHardwareStub();
}

extern "C" sp<CameraHardwareInterface> openCameraHardware()
extern "C" sp<CameraHardwareInterface> openCameraHardwareStub()
{
    return CameraHardwareStub::createInstance();
}
+2 −2
Original line number Diff line number Diff line
@@ -67,8 +67,6 @@ private:
                        CameraHardwareStub();
    virtual             ~CameraHardwareStub();

    static wp<CameraHardwareInterface> singleton;

    static const int kBufferCount = 4;

    class PreviewThread : public Thread {
@@ -130,6 +128,8 @@ private:
    int                 mCurrentPreviewFrame;
};

extern "C" sp<CameraHardwareInterface> openCameraHardwareStub();

}; // namespace android

#endif
+824 −956

File changed.

Preview size limit exceeded, changes collapsed.

+109 −145
Original line number Diff line number Diff line
@@ -21,207 +21,171 @@

#include <camera/ICameraService.h>
#include <camera/CameraHardwareInterface.h>
#include <camera/Camera.h>

/* This needs to be increased if we can have more cameras */
#define MAX_CAMERAS 2

namespace android {

class MemoryHeapBase;
class MediaPlayer;

// ----------------------------------------------------------------------------

#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))

// When enabled, this feature allows you to send an event to the CameraService
// so that you can cause all references to the heap object gWeakHeap, defined
// below, to be printed. You will also need to set DEBUG_REFS=1 and
// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to
// set gWeakHeap to the appropriate heap you want to track.

#define DEBUG_HEAP_LEAKS 0

// ----------------------------------------------------------------------------

class CameraService: public BnCameraService
{
    class Client;

public:
    static void         instantiate();

    // ICameraService interface
    virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient);
                        CameraService();
    virtual             ~CameraService();

    virtual int32_t     getNumberOfCameras();
    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
    virtual void        removeClient(const sp<ICameraClient>& cameraClient);
    virtual sp<Client>  getClientById(int cameraId);

    virtual status_t    dump(int fd, const Vector<String16>& args);
    virtual status_t    onTransact(uint32_t code, const Parcel& data,
                                   Parcel* reply, uint32_t flags);

            void            removeClient(const sp<ICameraClient>& cameraClient);
    enum sound_kind {
        SOUND_SHUTTER = 0,
        SOUND_RECORDING = 1,
        NUM_SOUNDS
    };

    virtual status_t onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
    void                loadSound();
    void                playSound(sound_kind kind);
    void                releaseSound();

private:
    Mutex               mServiceLock;
    wp<Client>          mClient[MAX_CAMERAS];  // protected by mServiceLock

// ----------------------------------------------------------------------------
    // atomics to record whether the hardware is allocated to some client.
    volatile int32_t    mBusy[MAX_CAMERAS];
    void                setCameraBusy(int cameraId);
    void                setCameraFree(int cameraId);

    class Client : public BnCamera {
    // sounds
    Mutex               mSoundLock;
    sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
    int                 mSoundRef;  // reference count (release all MediaPlayer when 0)

    class Client : public BnCamera
    {
    public:
        // ICamera interface (see ICamera for details)
        virtual void            disconnect();

        // connect new client with existing camera remote
        virtual status_t        connect(const sp<ICameraClient>& client);

        // prevent other processes from using this ICamera interface
        virtual status_t        lock();

        // allow other processes to use this ICamera interface
        virtual status_t        unlock();

        // pass the buffered ISurface to the camera service
        virtual status_t        setPreviewDisplay(const sp<ISurface>& surface);

        // set the preview callback flag to affect how the received frames from
        // preview are handled.
        virtual void            setPreviewCallbackFlag(int callback_flag);

        // start preview mode, must call setPreviewDisplay first
        virtual void            setPreviewCallbackFlag(int flag);
        virtual status_t        startPreview();

        // stop preview mode
        virtual void            stopPreview();

        // get preview state
        virtual bool            previewEnabled();

        // start recording mode
        virtual status_t        startRecording();

        // stop recording mode
        virtual void            stopRecording();

        // get recording state
        virtual bool            recordingEnabled();

        // release a recording frame
        virtual void            releaseRecordingFrame(const sp<IMemory>& mem);

        // auto focus
        virtual status_t        autoFocus();

        // cancel auto focus
        virtual status_t        cancelAutoFocus();

        // take a picture - returns an IMemory (ref-counted mmap)
        virtual status_t        takePicture();

        // set preview/capture parameters - key/value pairs
        virtual status_t        setParameters(const String8& params);

        // get preview/capture parameters - key/value pairs
        virtual String8         getParameters() const;

        // send command to camera driver
        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);

        // our client...
        const sp<ICameraClient>&    getCameraClient() const { return mCameraClient; }

    private:
        friend class CameraService;
                                Client(const sp<CameraService>& cameraService,
                                       const sp<ICameraClient>& cameraClient,
                                        pid_t clientPid);
                                Client();
        virtual                 ~Client();
                                       int cameraId,
                                       int clientPid);
                                ~Client();

                    status_t    checkPid();
        // return our camera client
        const sp<ICameraClient>&    getCameraClient() { return mCameraClient; }

        static      void        notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
        static      void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
        static      void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
                                                      const sp<IMemory>& dataPtr, void* user);
        // check whether the calling process matches mClientPid.
        status_t                checkPid() const;
        status_t                checkPidAndHardware() const;  // also check mHardware != 0

        static      sp<Client>  getClientFromCookie(void* user);

                    void        handlePreviewData(const sp<IMemory>&);
                    void        handleShutter(image_rect_type *image);
                    void        handlePostview(const sp<IMemory>&);
                    void        handleRawPicture(const sp<IMemory>&);
                    void        handleCompressedPicture(const sp<IMemory>&);

                    void        copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
                                    const sp<IMemoryHeap>& heap, size_t offset, size_t size);
        // these are internal functions used to set up preview buffers
        status_t                registerPreviewBuffers();
        status_t                setOverlay();

        // camera operation mode
        enum camera_mode {
            CAMERA_PREVIEW_MODE   = 0,  // frame automatically released
            CAMERA_RECORDING_MODE = 1,  // frame has to be explicitly released by releaseRecordingFrame()
        };
        // these are internal functions used for preview/recording
        status_t                startCameraMode(camera_mode mode);
        status_t                startPreviewMode();
        status_t                startRecordingMode();
        status_t                setOverlay();
        status_t                registerPreviewBuffers();

        // Ensures atomicity among the public methods
        mutable     Mutex                       mLock;

        // mSurfaceLock synchronizes access to mSurface between
        // setPreviewSurface() and postPreviewFrame().  Note that among
        // the public methods, all accesses to mSurface are
        // syncrhonized by mLock.  However, postPreviewFrame() is called
        // by the CameraHardwareInterface callback, and needs to
        // access mSurface.  It cannot hold mLock, however, because
        // stopPreview() may be holding that lock while attempting
        // to stop preview, and stopPreview itself will block waiting
        // for a callback from CameraHardwareInterface.  If this
        // happens, it will cause a deadlock.
        mutable     Mutex                       mSurfaceLock;
        mutable     Condition                   mReady;
                    sp<CameraService>           mCameraService;
                    sp<ISurface>                mSurface;
                    int                         mPreviewCallbackFlag;
                    int                         mOrientation;

                    sp<MediaPlayer>             mMediaPlayerClick;
                    sp<MediaPlayer>             mMediaPlayerBeep;

                    // these are immutable once the object is created,
                    // they don't need to be protected by a lock
        // these are static callback functions
        static void             notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
        static void             dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
        static void             dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
        // convert client from cookie
        static sp<Client>       getClientFromCookie(void* user);
        // handlers for messages
        void                    handleShutter(image_rect_type *size);
        void                    handlePreviewData(const sp<IMemory>& mem);
        void                    handlePostview(const sp<IMemory>& mem);
        void                    handleRawPicture(const sp<IMemory>& mem);
        void                    handleCompressedPicture(const sp<IMemory>& mem);
        void                    handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
        void                    handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr);
        void                    handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);

        void                    copyFrameAndPostCopiedFrame(
                                    const sp<ICameraClient>& client,
                                    const sp<IMemoryHeap>& heap,
                                    size_t offset, size_t size);

        // these are initialized in the constructor.
        sp<CameraService>               mCameraService;  // immutable after constructor
        sp<ICameraClient>               mCameraClient;
                    sp<CameraHardwareInterface> mHardware;
        int                             mCameraId;       // immutable after constructor
        pid_t                           mClientPid;
                    bool                        mUseOverlay;

        sp<CameraHardwareInterface>     mHardware;       // cleared after disconnect()
        bool                            mUseOverlay;     // immutable after constructor
        sp<OverlayRef>                  mOverlayRef;
        int                             mOverlayW;
        int                             mOverlayH;
        int                             mPreviewCallbackFlag;
        int                             mOrientation;

        mutable     Mutex                       mPreviewLock;
                    sp<MemoryHeapBase>          mPreviewBuffer;
    };

// ----------------------------------------------------------------------------

                            CameraService();
    virtual                 ~CameraService();

    // We use a count for number of clients (shoule only be 0 or 1).
    volatile    int32_t                     mUsers;
    virtual     void                        incUsers();
    virtual     void                        decUsers();
        // Ensures atomicity among the public methods
        mutable Mutex                   mLock;
        sp<ISurface>                    mSurface;

    mutable     Mutex                       mServiceLock;
                wp<Client>                  mClient;
        // If the user want us to return a copy of the preview frame (instead
        // of the original one), we allocate mPreviewBuffer and reuse it if possible.
        sp<MemoryHeapBase>              mPreviewBuffer;

#if DEBUG_HEAP_LEAKS
                wp<IMemoryHeap>             gWeakHeap;
#endif
        // We need to avoid the deadlock when the incoming command thread and
        // the CameraHardwareInterface callback thread both want to grab mLock.
        // An extra flag is used to tell the callback thread that it should stop
        // trying to deliver the callback messages if the client is not
        // interested in it anymore. For example, if the client is calling
        // stopPreview(), the preview frame messages do not need to be delivered
        // anymore.

        // This function takes the same parameter as the enableMsgType() and
        // disableMsgType() functions in CameraHardwareInterface.
        void                    enableMsgType(int32_t msgType);
        void                    disableMsgType(int32_t msgType);
        volatile int32_t        mMsgEnabled;

        // This function keeps trying to grab mLock, or give up if the message
        // is found to be disabled. It returns true if mLock is grabbed.
        bool                    lockIfMessageWanted(int32_t msgType);
    };
};

// ----------------------------------------------------------------------------

}; // namespace android
} // namespace android

#endif
Loading