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

Commit f69c70de authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera service: Initialization for camera2 clients and devices

- Refactor initialization code to hide device type from CameraService
- Add metadata queue class to Camera2Device
- Initialization of Camera2Device, Camera2Client
- Conversion from HAL2 device static metadata to camera API
  parameters.

Bug: 6243944
Change-Id: I524145b45438e906d8493dae202704ce8f090aeb
parent dd72c301
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -21,7 +21,8 @@ LOCAL_SHARED_LIBRARIES:= \
    libmedia_native \
    libcamera_client \
    libgui \
    libhardware
    libhardware \
    libcamera_metadata

LOCAL_C_INCLUDES += \
    system/media/camera/include
+698 −8

File changed.

Preview size limit exceeded, changes collapsed.

+10 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include "Camera2Device.h"
#include "CameraService.h"
#include "camera/CameraParameters.h"

namespace android {

@@ -55,17 +56,25 @@ public:
    // Interface used by CameraService
    Camera2Client(const sp<CameraService>& cameraService,
            const sp<ICameraClient>& cameraClient,
            const sp<Camera2Device>& device,
            int cameraId,
            int cameraFacing,
            int clientPid);
    ~Camera2Client();

    status_t initialize(camera_module_t *module);

    virtual status_t dump(int fd, const Vector<String16>& args);

private:
    CameraParameters *mParams;
    sp<Camera2Device> mDevice;

    // Convert static camera info from a camera2 device to the
    // old API parameter map.
    status_t buildDefaultParameters();

    // Free parameters for mapping from new to old HAL
    static const unsigned int kNumZoomSteps = 10;
};

}; // namespace android
+285 −10
Original line number Diff line number Diff line
@@ -22,8 +22,8 @@

namespace android {

Camera2Device::Camera2Device(const char *name):
        mName(name),
Camera2Device::Camera2Device(int id):
        mId(id),
        mDevice(NULL)
{

@@ -35,32 +35,307 @@ Camera2Device::~Camera2Device()
        status_t res;
        res = mDevice->common.close(&mDevice->common);
        if (res != OK) {
            ALOGE("Could not close camera2 %s: %s (%d)",
                    mName, strerror(-res), res);
            ALOGE("%s: Could not close camera %d: %s (%d)",
                    __FUNCTION__,
                    mId, strerror(-res), res);
        }
        mDevice = NULL;
    }
}

status_t Camera2Device::initialize(hw_module_t *module)
status_t Camera2Device::initialize(camera_module_t *module)
{
    status_t res;
    res = module->methods->open(module, mName,
    char name[10];
    snprintf(name, sizeof(name), "%d", mId);

    res = module->common.methods->open(&module->common, name,
            reinterpret_cast<hw_device_t**>(&mDevice));

    if (res != OK) {
        ALOGE("Could not open camera %s: %s (%d)", mName, strerror(-res), res);
        ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
                mId, strerror(-res), res);
        return res;
    }

    if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
        ALOGE("Could not open camera %s: "
                "Camera device is not version 2.0, reports %x instead",
                mName, mDevice->common.version);
        ALOGE("%s: Could not open camera %d: "
                "Camera device is not version %x, reports %x instead",
                __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
                mDevice->common.version);
        return BAD_VALUE;
    }

    camera_info info;
    res = module->get_camera_info(mId, &info);
    if (res != OK ) return res;

    if (info.device_version != mDevice->common.version) {
        ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
                " and device version (%x).", __FUNCTION__,
                mDevice->common.version, info.device_version);
        return BAD_VALUE;
    }

    mDeviceInfo = info.static_camera_characteristics;

    res = mDevice->ops->set_request_queue_src_ops(mDevice,
            mRequestQueue.getToConsumerInterface());
    if (res != OK) return res;

    res = mDevice->ops->set_frame_queue_dst_ops(mDevice,
            mFrameQueue.getToProducerInterface());
    if (res != OK) return res;

    res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
    if (res != OK ) return res;

    return OK;
}

status_t Camera2Device::setStreamingRequest(camera_metadata_t* request)
{
    mRequestQueue.setStreamSlot(request);
    return OK;
}

/**
 * Camera2Device::MetadataQueue
 */

Camera2Device::MetadataQueue::MetadataQueue():
            mDevice(NULL),
            mFrameCount(0),
            mCount(0),
            mStreamSlotCount(0),
            mSignalConsumer(true)
{
    camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
    camera2_request_queue_src_ops::request_count = consumer_buffer_count;
    camera2_request_queue_src_ops::free_request = consumer_free;

    camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
    camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
    camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
}

Camera2Device::MetadataQueue::~MetadataQueue() {
    Mutex::Autolock l(mMutex);
    freeBuffers(mEntries.begin(), mEntries.end());
    freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
}

// Interface to camera2 HAL as consumer (input requests/reprocessing)
const camera2_request_queue_src_ops_t*
Camera2Device::MetadataQueue::getToConsumerInterface() {
    return static_cast<camera2_request_queue_src_ops_t*>(this);
}

void Camera2Device::MetadataQueue::setFromConsumerInterface(camera2_device_t *d) {
    Mutex::Autolock l(mMutex);
    mDevice = d;
}

const camera2_frame_queue_dst_ops_t*
Camera2Device::MetadataQueue::getToProducerInterface() {
    return static_cast<camera2_frame_queue_dst_ops_t*>(this);
}

// Real interfaces
status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
    Mutex::Autolock l(mMutex);

    mCount++;
    mEntries.push_back(buf);
    notEmpty.signal();

    if (mSignalConsumer && mDevice != NULL) {
        mSignalConsumer = false;

        mMutex.unlock();
        ALOGV("%s: Signaling consumer", __FUNCTION__);
        mDevice->ops->notify_request_queue_not_empty(mDevice);
        mMutex.lock();
    }
    return OK;
}

int Camera2Device::MetadataQueue::getBufferCount() {
    Mutex::Autolock l(mMutex);
    if (mStreamSlotCount > 0) {
        return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
    }
    return mCount;
}

status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
        bool incrementCount)
{
    Mutex::Autolock l(mMutex);

    if (mCount == 0) {
        if (mStreamSlotCount == 0) {
            ALOGV("%s: Empty", __FUNCTION__);
            *buf = NULL;
            mSignalConsumer = true;
            return OK;
        }
        ALOGV("%s: Streaming %d frames to queue", __FUNCTION__,
              mStreamSlotCount);

        for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
                slotEntry != mStreamSlot.end();
                slotEntry++ ) {
            size_t entries = get_camera_metadata_entry_count(*slotEntry);
            size_t dataBytes = get_camera_metadata_data_count(*slotEntry);

            camera_metadata_t *copy =
                    allocate_camera_metadata(entries, dataBytes);
            append_camera_metadata(copy, *slotEntry);
            mEntries.push_back(copy);
        }
        mCount = mStreamSlotCount;
    }
    ALOGV("MetadataQueue: deque (%d buffers)", mCount);
    camera_metadata_t *b = *(mEntries.begin());
    mEntries.erase(mEntries.begin());

    if (incrementCount) {
        add_camera_metadata_entry(b,
                ANDROID_REQUEST_FRAME_COUNT,
                (void**)&mFrameCount, 1);
        mFrameCount++;
    }

    *buf = b;
    mCount--;

    return OK;
}

status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
{
    Mutex::Autolock l(mMutex);
    status_t res;
    while (mCount == 0) {
        res = notEmpty.waitRelative(mMutex,timeout);
        if (res != OK) return res;
    }
    return OK;
}

status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
{
    Mutex::Autolock l(mMutex);
    if (buf == NULL) {
        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
        mStreamSlotCount = 0;
        return OK;
    }
    if (mStreamSlotCount > 1) {
        List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
        freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
        mStreamSlotCount = 1;
    }
    if (mStreamSlotCount == 1) {
        free_camera_metadata( *(mStreamSlot.begin()) );
        *(mStreamSlot.begin()) = buf;
    } else {
        mStreamSlot.push_front(buf);
        mStreamSlotCount = 1;
    }
    return OK;
}

status_t Camera2Device::MetadataQueue::setStreamSlot(
        const List<camera_metadata_t*> &bufs)
{
    Mutex::Autolock l(mMutex);
    if (mStreamSlotCount > 0) {
        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
    }
    mStreamSlot = bufs;
    mStreamSlotCount = mStreamSlot.size();

    return OK;
}

status_t Camera2Device::MetadataQueue::freeBuffers(
        List<camera_metadata_t*>::iterator start,
        List<camera_metadata_t*>::iterator end)
{
    while (start != end) {
        free_camera_metadata(*start);
        start = mStreamSlot.erase(start);
    }
    return OK;
}

Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
        const camera2_request_queue_src_ops_t *q)
{
    const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
    return const_cast<MetadataQueue*>(cmq);
}

Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
        const camera2_frame_queue_dst_ops_t *q)
{
    const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
    return const_cast<MetadataQueue*>(cmq);
}

int Camera2Device::MetadataQueue::consumer_buffer_count(
        const camera2_request_queue_src_ops_t *q)
{
    MetadataQueue *queue = getInstance(q);
    return queue->getBufferCount();
}

int Camera2Device::MetadataQueue::consumer_dequeue(
        const camera2_request_queue_src_ops_t *q,
        camera_metadata_t **buffer)
{
    MetadataQueue *queue = getInstance(q);
    return queue->dequeue(buffer, true);
}

int Camera2Device::MetadataQueue::consumer_free(
        const camera2_request_queue_src_ops_t *q,
        camera_metadata_t *old_buffer)
{
    MetadataQueue *queue = getInstance(q);
    free_camera_metadata(old_buffer);
    return OK;
}

int Camera2Device::MetadataQueue::producer_dequeue(
        const camera2_frame_queue_dst_ops_t *q,
        size_t entries, size_t bytes,
        camera_metadata_t **buffer)
{
    camera_metadata_t *new_buffer =
            allocate_camera_metadata(entries, bytes);
    if (new_buffer == NULL) return NO_MEMORY;
    *buffer = new_buffer;
        return OK;
}

int Camera2Device::MetadataQueue::producer_cancel(
        const camera2_frame_queue_dst_ops_t *q,
        camera_metadata_t *old_buffer)
{
    free_camera_metadata(old_buffer);
    return OK;
}

int Camera2Device::MetadataQueue::producer_enqueue(
        const camera2_frame_queue_dst_ops_t *q,
        camera_metadata_t *filled_buffer)
{
    MetadataQueue *queue = getInstance(q);
    return queue->enqueue(filled_buffer);
}


}; // namespace android
+94 −4
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#define ANDROID_SERVERS_CAMERA_CAMERA2DEVICE_H

#include <utils/RefBase.h>
#include <utils/List.h>
#include <utils/Mutex.h>
#include <utils/Condition.h>
#include <utils/Errors.h>
#include "hardware/camera2.h"

@@ -25,17 +28,104 @@ namespace android {

class Camera2Device : public virtual RefBase {
  public:
    Camera2Device(const char *name);
    Camera2Device(int id);

    ~Camera2Device();

    status_t initialize(hw_module_t *module);
    status_t initialize(camera_module_t *module);

    status_t setStreamingRequest(camera_metadata_t* request);

    camera_metadata_t* info() {
        return mDeviceInfo;
    }

  private:

    const int mId;
    camera2_device_t *mDevice;

    camera_metadata_t *mDeviceInfo;
    vendor_tag_query_ops_t *mVendorTagOps;

    /**
     * Queue class for both sending requests to a camera2 device, and for
     * receiving frames from a camera2 device.
     */
    class MetadataQueue: public camera2_request_queue_src_ops_t,
                         public camera2_frame_queue_dst_ops_t {
      public:
        MetadataQueue();
        ~MetadataQueue();

        // Interface to camera2 HAL device, either for requests (device is
        // consumer) or for frames (device is producer)
        const camera2_request_queue_src_ops_t*   getToConsumerInterface();
        void setFromConsumerInterface(camera2_device_t *d);

        const camera2_frame_queue_dst_ops_t* getToProducerInterface();

        // Real interfaces. On enqueue, queue takes ownership of buffer pointer
        // On dequeue, user takes ownership of buffer pointer.
        status_t enqueue(camera_metadata_t *buf);
        status_t dequeue(camera_metadata_t **buf, bool incrementCount = true);
        int      getBufferCount();
        status_t waitForBuffer(nsecs_t timeout);

        // Set repeating buffer(s); if the queue is empty on a dequeue call, the
        // queue copies the contents of the stream slot into the queue, and then
        // dequeues the first new entry.
        status_t setStreamSlot(camera_metadata_t *buf);
        status_t setStreamSlot(const List<camera_metadata_t*> &bufs);

      private:
        status_t freeBuffers(List<camera_metadata_t*>::iterator start,
                List<camera_metadata_t*>::iterator end);

    const char *mName;
        camera2_device_t *mDevice;

};
        Mutex mMutex;
        Condition notEmpty;

        int mFrameCount;

        int mCount;
        List<camera_metadata_t*> mEntries;
        int mStreamSlotCount;
        List<camera_metadata_t*> mStreamSlot;

        bool mSignalConsumer;

        static MetadataQueue* getInstance(
            const camera2_frame_queue_dst_ops_t *q);
        static MetadataQueue* getInstance(
            const camera2_request_queue_src_ops_t *q);

        static int consumer_buffer_count(
            const camera2_request_queue_src_ops_t *q);

        static int consumer_dequeue(const camera2_request_queue_src_ops_t *q,
            camera_metadata_t **buffer);

        static int consumer_free(const camera2_request_queue_src_ops_t *q,
                camera_metadata_t *old_buffer);

        static int producer_dequeue(const camera2_frame_queue_dst_ops_t *q,
                size_t entries, size_t bytes,
                camera_metadata_t **buffer);

        static int producer_cancel(const camera2_frame_queue_dst_ops_t *q,
            camera_metadata_t *old_buffer);

        static int producer_enqueue(const camera2_frame_queue_dst_ops_t *q,
                camera_metadata_t *filled_buffer);

    }; // class MetadataQueue

    MetadataQueue mRequestQueue;
    MetadataQueue mFrameQueue;

}; // class Camera2Device

}; // namespace android

Loading