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

Commit 3a1d8b51 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala Committed by Android (Google) Code Review
Browse files

Merge "Camera: Add input side to camera3 HAL device" into jb-mr2-dev

parents 8fc405ff 3b53bc9b
Loading
Loading
Loading
Loading
+105 −12
Original line number Original line Diff line number Diff line
@@ -23,19 +23,22 @@
namespace android {
namespace android {


CameraMetadata::CameraMetadata() :
CameraMetadata::CameraMetadata() :
        mBuffer(NULL) {
        mBuffer(NULL), mLocked(false) {
}
}


CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity)
CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
        mLocked(false)
{
{
    mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
    mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
}
}


CameraMetadata::CameraMetadata(const CameraMetadata &other) {
CameraMetadata::CameraMetadata(const CameraMetadata &other) :
        mLocked(false) {
    mBuffer = clone_camera_metadata(other.mBuffer);
    mBuffer = clone_camera_metadata(other.mBuffer);
}
}


CameraMetadata::CameraMetadata(camera_metadata_t *buffer) : mBuffer(NULL) {
CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
        mBuffer(NULL), mLocked(false) {
    acquire(buffer);
    acquire(buffer);
}
}


@@ -44,6 +47,11 @@ CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
}
}


CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
    if (mLocked) {
        ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
        return *this;
    }

    if (CC_LIKELY(buffer != mBuffer)) {
    if (CC_LIKELY(buffer != mBuffer)) {
        camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
        camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
        clear();
        clear();
@@ -53,16 +61,44 @@ CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
}
}


CameraMetadata::~CameraMetadata() {
CameraMetadata::~CameraMetadata() {
    mLocked = false;
    clear();
    clear();
}
}


const camera_metadata_t* CameraMetadata::getAndLock() {
    mLocked = true;
    return mBuffer;
}

status_t CameraMetadata::unlock(const camera_metadata_t *buffer) {
    if (!mLocked) {
        ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if (buffer != mBuffer) {
        ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
                __FUNCTION__);
        return BAD_VALUE;
    }
    mLocked = false;
    return OK;
}

camera_metadata_t* CameraMetadata::release() {
camera_metadata_t* CameraMetadata::release() {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return NULL;
    }
    camera_metadata_t *released = mBuffer;
    camera_metadata_t *released = mBuffer;
    mBuffer = NULL;
    mBuffer = NULL;
    return released;
    return released;
}
}


void CameraMetadata::clear() {
void CameraMetadata::clear() {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return;
    }
    if (mBuffer) {
    if (mBuffer) {
        free_camera_metadata(mBuffer);
        free_camera_metadata(mBuffer);
        mBuffer = NULL;
        mBuffer = NULL;
@@ -70,15 +106,27 @@ void CameraMetadata::clear() {
}
}


void CameraMetadata::acquire(camera_metadata_t *buffer) {
void CameraMetadata::acquire(camera_metadata_t *buffer) {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return;
    }
    clear();
    clear();
    mBuffer = buffer;
    mBuffer = buffer;
}
}


void CameraMetadata::acquire(CameraMetadata &other) {
void CameraMetadata::acquire(CameraMetadata &other) {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return;
    }
    acquire(other.release());
    acquire(other.release());
}
}


status_t CameraMetadata::append(const CameraMetadata &other) {
status_t CameraMetadata::append(const CameraMetadata &other) {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    return append_camera_metadata(mBuffer, other.mBuffer);
    return append_camera_metadata(mBuffer, other.mBuffer);
}
}


@@ -92,6 +140,10 @@ bool CameraMetadata::isEmpty() const {
}
}


status_t CameraMetadata::sort() {
status_t CameraMetadata::sort() {
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    return sort_camera_metadata(mBuffer);
    return sort_camera_metadata(mBuffer);
}
}


@@ -115,69 +167,101 @@ status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const int32_t *data, size_t data_count) {
        const int32_t *data, size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_INT32)) != OK) {
    if ( (res = checkType(tag, TYPE_INT32)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)data, data_count);
    return updateImpl(tag, (const void*)data, data_count);
}
}


status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const uint8_t *data, size_t data_count) {
        const uint8_t *data, size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)data, data_count);
    return updateImpl(tag, (const void*)data, data_count);
}
}


status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const float *data, size_t data_count) {
        const float *data, size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
    if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)data, data_count);
    return updateImpl(tag, (const void*)data, data_count);
}
}


status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const int64_t *data, size_t data_count) {
        const int64_t *data, size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_INT64)) != OK) {
    if ( (res = checkType(tag, TYPE_INT64)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)data, data_count);
    return updateImpl(tag, (const void*)data, data_count);
}
}


status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const double *data, size_t data_count) {
        const double *data, size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
    if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)data, data_count);
    return updateImpl(tag, (const void*)data, data_count);
}
}


status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const camera_metadata_rational_t *data, size_t data_count) {
        const camera_metadata_rational_t *data, size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
    if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)data, data_count);
    return updateImpl(tag, (const void*)data, data_count);
}
}


status_t CameraMetadata::update(uint32_t tag,
status_t CameraMetadata::update(uint32_t tag,
        const String8 &string) {
        const String8 &string) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
        return res;
        return res;
    }
    }
    return update(tag, (const void*)string.string(), string.size());
    return updateImpl(tag, (const void*)string.string(), string.size());
}
}


status_t CameraMetadata::update(uint32_t tag, const void *data,
status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
        size_t data_count) {
        size_t data_count) {
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    int type = get_camera_metadata_tag_type(tag);
    int type = get_camera_metadata_tag_type(tag);
    if (type == -1) {
    if (type == -1) {
        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
@@ -216,6 +300,11 @@ bool CameraMetadata::exists(uint32_t tag) const {
camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
    status_t res;
    status_t res;
    camera_metadata_entry entry;
    camera_metadata_entry entry;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        entry.count = 0;
        return entry;
    }
    res = find_camera_metadata_entry(mBuffer, tag, &entry);
    res = find_camera_metadata_entry(mBuffer, tag, &entry);
    if (CC_UNLIKELY( res != OK )) {
    if (CC_UNLIKELY( res != OK )) {
        entry.count = 0;
        entry.count = 0;
@@ -238,6 +327,10 @@ camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
status_t CameraMetadata::erase(uint32_t tag) {
status_t CameraMetadata::erase(uint32_t tag) {
    camera_metadata_entry_t entry;
    camera_metadata_entry_t entry;
    status_t res;
    status_t res;
    if (mLocked) {
        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
        return INVALID_OPERATION;
    }
    res = find_camera_metadata_entry(mBuffer, tag, &entry);
    res = find_camera_metadata_entry(mBuffer, tag, &entry);
    if (res == NAME_NOT_FOUND) {
    if (res == NAME_NOT_FOUND) {
        return OK;
        return OK;
+19 −1
Original line number Original line Diff line number Diff line
@@ -48,6 +48,23 @@ class CameraMetadata {
    CameraMetadata &operator=(const CameraMetadata &other);
    CameraMetadata &operator=(const CameraMetadata &other);
    CameraMetadata &operator=(const camera_metadata_t *buffer);
    CameraMetadata &operator=(const camera_metadata_t *buffer);


    /**
     * Get reference to the underlying metadata buffer. Ownership remains with
     * the CameraMetadata object, but non-const CameraMetadata methods will not
     * work until unlock() is called. Note that the lock has nothing to do with
     * thread-safety, it simply prevents the camera_metadata_t pointer returned
     * here from being accidentally invalidated by CameraMetadata operations.
     */
    const camera_metadata_t* getAndLock();

    /**
     * Unlock the CameraMetadata for use again. After this unlock, the pointer
     * given from getAndLock() may no longer be used. The pointer passed out
     * from getAndLock must be provided to guarantee that the right object is
     * being unlocked.
     */
    status_t unlock(const camera_metadata_t *buffer);

    /**
    /**
     * Release a raw metadata buffer to the caller. After this call,
     * Release a raw metadata buffer to the caller. After this call,
     * CameraMetadata no longer references the buffer, and the caller takes
     * CameraMetadata no longer references the buffer, and the caller takes
@@ -154,6 +171,7 @@ class CameraMetadata {


  private:
  private:
    camera_metadata_t *mBuffer;
    camera_metadata_t *mBuffer;
    bool               mLocked;


    /**
    /**
     * Check if tag has a given type
     * Check if tag has a given type
@@ -163,7 +181,7 @@ class CameraMetadata {
    /**
    /**
     * Base update entry method
     * Base update entry method
     */
     */
    status_t update(uint32_t tag, const void *data, size_t data_count);
    status_t updateImpl(uint32_t tag, const void *data, size_t data_count);


    /**
    /**
     * Resize metadata buffer if needed by reallocating it and copying it over.
     * Resize metadata buffer if needed by reallocating it and copying it over.
+782 −38

File changed.

Preview size limit exceeded, changes collapsed.

+152 −11
Original line number Original line Diff line number Diff line
@@ -14,8 +14,8 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#ifndef ANDROID_SERVERS_CAMERA_CAMERA3DEVICE_H
#ifndef ANDROID_SERVERS_CAMERA3DEVICE_H
#define ANDROID_SERVERS_CAMERA_CAMERA3DEVICE_H
#define ANDROID_SERVERS_CAMERA3DEVICE_H


#include <utils/Condition.h>
#include <utils/Condition.h>
#include <utils/Errors.h>
#include <utils/Errors.h>
@@ -24,6 +24,8 @@
#include <utils/Thread.h>
#include <utils/Thread.h>


#include "CameraDeviceBase.h"
#include "CameraDeviceBase.h"
#include "camera3/Camera3Stream.h"
#include "camera3/Camera3OutputStream.h"


#include "hardware/camera3.h"
#include "hardware/camera3.h"


@@ -55,44 +57,121 @@ class Camera3Device :
    virtual ~Camera3Device();
    virtual ~Camera3Device();


    /**
    /**
     * CameraDevice interface
     * CameraDeviceBase interface
     */
     */

    virtual int      getId() const;
    virtual int      getId() const;

    // Transitions to idle state on success.
    virtual status_t initialize(camera_module_t *module);
    virtual status_t initialize(camera_module_t *module);
    virtual status_t disconnect();
    virtual status_t disconnect();
    virtual status_t dump(int fd, const Vector<String16> &args);
    virtual status_t dump(int fd, const Vector<String16> &args);
    virtual const CameraMetadata& info() const;
    virtual const CameraMetadata& info() const;

    // Capture and setStreamingRequest will configure streams if currently in
    // idle state
    virtual status_t capture(CameraMetadata &request);
    virtual status_t capture(CameraMetadata &request);
    virtual status_t setStreamingRequest(const CameraMetadata &request);
    virtual status_t setStreamingRequest(const CameraMetadata &request);
    virtual status_t clearStreamingRequest();
    virtual status_t clearStreamingRequest();

    virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);
    virtual status_t waitUntilRequestReceived(int32_t requestId, nsecs_t timeout);

    // Actual stream creation/deletion is delayed until first request is submitted
    // If adding streams while actively capturing, will pause device before adding
    // stream, reconfiguring device, and unpausing.
    virtual status_t createStream(sp<ANativeWindow> consumer,
    virtual status_t createStream(sp<ANativeWindow> consumer,
            uint32_t width, uint32_t height, int format, size_t size,
            uint32_t width, uint32_t height, int format, size_t size,
            int *id);
            int *id);
    virtual status_t createReprocessStreamFromStream(int outputId, int *id);
    virtual status_t createReprocessStreamFromStream(int outputId, int *id);

    virtual status_t getStreamInfo(int id,
    virtual status_t getStreamInfo(int id,
            uint32_t *width, uint32_t *height, uint32_t *format);
            uint32_t *width, uint32_t *height, uint32_t *format);
    virtual status_t setStreamTransform(int id, int transform);
    virtual status_t setStreamTransform(int id, int transform);

    virtual status_t deleteStream(int id);
    virtual status_t deleteStream(int id);
    virtual status_t deleteReprocessStream(int id);
    virtual status_t deleteReprocessStream(int id);

    virtual status_t createDefaultRequest(int templateId, CameraMetadata *request);
    virtual status_t createDefaultRequest(int templateId, CameraMetadata *request);

    // Transitions to the idle state on success
    virtual status_t waitUntilDrained();
    virtual status_t waitUntilDrained();

    virtual status_t setNotifyCallback(NotificationListener *listener);
    virtual status_t setNotifyCallback(NotificationListener *listener);
    virtual status_t waitForNextFrame(nsecs_t timeout);
    virtual status_t waitForNextFrame(nsecs_t timeout);
    virtual status_t getNextFrame(CameraMetadata *frame);
    virtual status_t getNextFrame(CameraMetadata *frame);

    virtual status_t triggerAutofocus(uint32_t id);
    virtual status_t triggerAutofocus(uint32_t id);
    virtual status_t triggerCancelAutofocus(uint32_t id);
    virtual status_t triggerCancelAutofocus(uint32_t id);
    virtual status_t triggerPrecaptureMetering(uint32_t id);
    virtual status_t triggerPrecaptureMetering(uint32_t id);

    virtual status_t pushReprocessBuffer(int reprocessStreamId,
    virtual status_t pushReprocessBuffer(int reprocessStreamId,
            buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
            buffer_handle_t *buffer, wp<BufferReleasedListener> listener);


  private:
  private:
    static const nsecs_t       kShutdownTimeout = 5000000000; // 5 sec


    Mutex                      mLock;

    /**** Scope for mLock ****/

    const int                  mId;
    const int                  mId;
    camera3_device_t          *mHal3Device;
    camera3_device_t          *mHal3Device;


    CameraMetadata             mDeviceInfo;
    CameraMetadata             mDeviceInfo;
    vendor_tag_query_ops_t     mVendorTagOps;
    vendor_tag_query_ops_t     mVendorTagOps;


    enum {
        STATUS_ERROR,
        STATUS_UNINITIALIZED,
        STATUS_IDLE,
        STATUS_ACTIVE
    }                          mStatus;

    // Mapping of stream IDs to stream instances
    typedef KeyedVector<int, sp<camera3::Camera3OutputStream> > StreamSet;

    StreamSet                  mOutputStreams;
    sp<camera3::Camera3Stream> mInputStream;
    int                        mNextStreamId;

    // Need to hold on to stream references until configure completes.
    Vector<sp<camera3::Camera3Stream> > mDeletedStreams;

    /**** End scope for mLock ****/

    class CaptureRequest : public LightRefBase<CaptureRequest> {
      public:
        CameraMetadata                      mSettings;
        sp<camera3::Camera3Stream>          mInputStream;
        Vector<sp<camera3::Camera3Stream> > mOutputStreams;
    };
    typedef List<sp<CaptureRequest> > RequestList;

    /**
     * Lock-held version of waitUntilDrained. Will transition to IDLE on
     * success.
     */
    status_t           waitUntilDrainedLocked();

    /**
     * Do common work for setting up a streaming or single capture request.
     * On success, will transition to ACTIVE if in IDLE.
     */
    sp<CaptureRequest> setUpRequestLocked(const CameraMetadata &request);

    /**
     * Build a CaptureRequest request from the CameraDeviceBase request
     * settings.
     */
    sp<CaptureRequest> createCaptureRequest(const CameraMetadata &request);

    /**
     * Take the currently-defined set of streams and configure the HAL to use
     * them. This is a long-running operation (may be several hundered ms).
     */
    status_t           configureStreamsLocked();

    /**
    /**
     * Thread for managing capture request submission to HAL device.
     * Thread for managing capture request submission to HAL device.
     */
     */
@@ -100,18 +179,80 @@ class Camera3Device :


      public:
      public:


        RequestThread(wp<Camera3Device> parent);
        RequestThread(wp<Camera3Device> parent,
                camera3_device_t *hal3Device);

        /**
         * Call after stream (re)-configuration is completed.
         */
        void     configurationComplete();

        /**
         * Set or clear the list of repeating requests. Does not block
         * on either. Use waitUntilPaused to wait until request queue
         * has emptied out.
         */
        status_t setRepeatingRequests(const RequestList& requests);
        status_t clearRepeatingRequests();

        status_t queueRequest(sp<CaptureRequest> request);

        /**
         * Pause/unpause the capture thread. Doesn't block, so use
         * waitUntilPaused to wait until the thread is paused.
         */
        void     setPaused(bool paused);

        /**
         * Wait until thread is paused, either due to setPaused(true)
         * or due to lack of input requests. Returns TIMED_OUT in case
         * the thread does not pause within the timeout.
         */
        status_t waitUntilPaused(nsecs_t timeout);


      protected:
      protected:


        virtual bool threadLoop();
        virtual bool threadLoop();


      private:
      private:
        static const nsecs_t kRequestTimeout = 50e6; // 50 ms

        // Waits for a request, or returns NULL if times out.
        sp<CaptureRequest> waitForNextRequest();

        // Return buffers, etc, for a request that couldn't be fully
        // constructed. The buffers will be returned in the ERROR state
        // to mark them as not having valid data.
        // All arguments will be modified.
        void cleanUpFailedRequest(camera3_capture_request_t &request,
                sp<CaptureRequest> &nextRequest,
                Vector<camera3_stream_buffer_t> &outputBuffers);

        // Pause handling
        bool               waitIfPaused();


        wp<Camera3Device>  mParent;
        wp<Camera3Device>  mParent;
        camera3_device_t  *mHal3Device;

        Mutex              mRequestLock;
        Condition          mRequestSignal;
        RequestList        mRequestQueue;
        RequestList        mRepeatingRequests;

        bool               mReconfigured;

        // Used by waitIfPaused, waitForNextRequest, and waitUntilPaused
        Mutex              mPauseLock;
        bool               mDoPause;
        Condition          mDoPauseSignal;
        bool               mPaused;
        Condition          mPausedSignal;

        sp<CaptureRequest> mPrevRequest;


        int32_t            mFrameNumber;
    };
    };
    sp<RequestThread> requestThread;
    sp<RequestThread> mRequestThread;


    /**
    /**
     * Callback functions from HAL device
     * Callback functions from HAL device