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

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

Camera service: Minimally functional preview for camera 2 devices.

- Camera app starts up
- Basic preview operation with defaults
- Shutdown sequence is very minimal

Bug: 6243944

Change-Id: I67673b7c1fc08956d218d99f9171e74a7a82bf07
parent 611f6199
Loading
Loading
Loading
Loading
+145 −15
Original line number Diff line number Diff line
@@ -57,7 +57,10 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
        int clientPid):
        Client(cameraService, cameraClient,
                cameraId, cameraFacing, clientPid),
        mParams(NULL)
        mState(NOT_INITIALIZED),
        mParams(NULL),
        mPreviewStreamId(NO_PREVIEW_STREAM),
        mPreviewRequest(NULL)
{
    ALOG1_ENTRY;

@@ -90,6 +93,8 @@ status_t Camera2Client::initialize(camera_module_t *module)
        mParams->dump();
    }

    mState = STOPPED;

    ALOG1_EXIT;
    return OK;
}
@@ -118,7 +123,12 @@ void Camera2Client::disconnect() {

    if (mDevice == 0) return;

    mDevice->setStreamingRequest(NULL);
    stopPreview();

    if (mPreviewStreamId != NO_PREVIEW_STREAM) {
        mDevice->deleteStream(mPreviewStreamId);
        mPreviewStreamId = NO_PREVIEW_STREAM;
    }

    CameraService::Client::disconnect();
}
@@ -135,12 +145,67 @@ status_t Camera2Client::unlock() {
    return BAD_VALUE;
}

status_t Camera2Client::setPreviewDisplay(const sp<Surface>& surface) {
    return BAD_VALUE;
status_t Camera2Client::setPreviewDisplay(
        const sp<Surface>& surface) {
    ALOG1_ENTRY;
    if (mState == PREVIEW) return INVALID_OPERATION;

    sp<IBinder> binder;
    sp<ANativeWindow> window;
    if (surface != 0) {
        binder = surface->asBinder();
        window = surface;
    }

status_t Camera2Client::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) {
    return BAD_VALUE;
    return setPreviewWindow(binder,window);
}

status_t Camera2Client::setPreviewTexture(
        const sp<ISurfaceTexture>& surfaceTexture) {
    ALOG1_ENTRY;
    if (mState == PREVIEW) return INVALID_OPERATION;

    sp<IBinder> binder;
    sp<ANativeWindow> window;
    if (surfaceTexture != 0) {
        binder = surfaceTexture->asBinder();
        window = new SurfaceTextureClient(surfaceTexture);
    }
    return setPreviewWindow(binder, window);
}

status_t Camera2Client::setPreviewWindow(const sp<IBinder>& binder,
        const sp<ANativeWindow>& window) {
    ALOG1_ENTRY;
    status_t res;

    if (binder == mPreviewSurface) {
        return NO_ERROR;
    }

    if (mPreviewStreamId != NO_PREVIEW_STREAM) {
        res = mDevice->deleteStream(mPreviewStreamId);
        if (res != OK) {
            return res;
        }
    }

    int previewWidth, previewHeight;
    mParams->getPreviewSize(&previewWidth, &previewHeight);

    res = mDevice->createStream(window,
            previewWidth, previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE,
            &mPreviewStreamId);
    if (res != OK) {
        return res;
    }

    if (mState == WAITING_FOR_PREVIEW_WINDOW) {
        return startPreview();
    }

    ALOG1_EXIT;
    return OK;
}

void Camera2Client::setPreviewCallbackFlag(int flag) {
@@ -148,15 +213,63 @@ void Camera2Client::setPreviewCallbackFlag(int flag) {
}

status_t Camera2Client::startPreview() {
    return BAD_VALUE;
    ALOG1_ENTRY;
    status_t res;
    if (mState == PREVIEW) return INVALID_OPERATION;

    if (mPreviewStreamId == NO_PREVIEW_STREAM) {
        mState = WAITING_FOR_PREVIEW_WINDOW;
        return OK;
    }

    if (mPreviewRequest == NULL) {
        updatePreviewRequest();
    }

    uint8_t outputStream = mPreviewStreamId;

    camera_metadata_entry_t outputStreams;
    res = find_camera_metadata_entry(mPreviewRequest,
            ANDROID_REQUEST_OUTPUT_STREAMS,
            &outputStreams);
    if (res == NAME_NOT_FOUND) {
        res = add_camera_metadata_entry(mPreviewRequest,
                ANDROID_REQUEST_OUTPUT_STREAMS,
                &outputStream, 1);
    } else if (res == OK) {
        res = update_camera_metadata_entry(mPreviewRequest,
                outputStreams.index, &outputStream, 1, NULL);
    }

    if (res != OK) {
        ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mState = STOPPED;
        return res;
    }

    res = mDevice->setStreamingRequest(mPreviewRequest);
    if (res != OK) {
        ALOGE("%s: Camera %d: Unable to set preview request to start preview: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mState = STOPPED;
        return res;
    }
    mState = PREVIEW;

    return OK;
}

void Camera2Client::stopPreview() {
    ALOG1_ENTRY;
    if (mState != PREVIEW) return;

    mDevice->setStreamingRequest(NULL);
    mState = STOPPED;
}

bool Camera2Client::previewEnabled() {
    return false;
    return mState == PREVIEW;
}

status_t Camera2Client::storeMetaDataInBuffers(bool enabled) {
@@ -179,11 +292,11 @@ void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
}

status_t Camera2Client::autoFocus() {
    return BAD_VALUE;
    return OK;
}

status_t Camera2Client::cancelAutoFocus() {
    return BAD_VALUE;
    return OK;
}

status_t Camera2Client::takePicture(int msgType) {
@@ -191,7 +304,7 @@ status_t Camera2Client::takePicture(int msgType) {
}

status_t Camera2Client::setParameters(const String8& params) {
    return BAD_VALUE;
    return OK;
}

String8 Camera2Client::getParameters() const {
@@ -199,7 +312,7 @@ String8 Camera2Client::getParameters() const {
}

status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
    return BAD_VALUE;
    return OK;
}

// private methods
@@ -781,7 +894,7 @@ status_t Camera2Client::buildDefaultParameters() {
            "(0,0,0,0,0)");

    mParams->set(CameraParameters::KEY_ZOOM, 0);
    mParams->set(CameraParameters::KEY_MAX_ZOOM, kNumZoomSteps - 1);
    mParams->set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);

    camera_metadata_entry_t maxDigitalZoom;
    res = find_camera_metadata_entry(mDevice->info(),
@@ -792,9 +905,9 @@ status_t Camera2Client::buildDefaultParameters() {
        String8 zoomRatios;
        float zoom = 1.f;
        float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
                (kNumZoomSteps-1);
                (NUM_ZOOM_STEPS-1);
        bool addComma = false;
        for (size_t i=0; i < kNumZoomSteps; i++) {
        for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
            if (addComma) zoomRatios += ",";
            addComma = true;
            zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
@@ -846,4 +959,21 @@ status_t Camera2Client::buildDefaultParameters() {
    return OK;
}

status_t Camera2Client::updatePreviewRequest() {
    ALOG1_ENTRY
    status_t res;
    if (mPreviewRequest == NULL) {
        res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
                &mPreviewRequest);
        if (res != OK) {
            ALOGE("%s: Camera %d: Unable to create default preview request: "
                    "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
            return res;
        }
    }
    // TODO: Adjust for mParams changes
    ALOG1_EXIT
    return OK;
}

} // namespace android
+25 −4
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ public:
    virtual status_t        lock();
    virtual status_t        unlock();
    virtual status_t        setPreviewDisplay(const sp<Surface>& surface);
    virtual status_t        setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
    virtual status_t        setPreviewTexture(
        const sp<ISurfaceTexture>& surfaceTexture);
    virtual void            setPreviewCallbackFlag(int flag);
    virtual status_t        startPreview();
    virtual void            stopPreview();
@@ -66,15 +67,35 @@ public:
    virtual status_t dump(int fd, const Vector<String16>& args);

private:
    CameraParameters *mParams;
    // Number of zoom steps to simulate
    static const unsigned int NUM_ZOOM_STEPS = 10;
    // Used with mPreviewStreamId
    static const int NO_PREVIEW_STREAM = -1;

    enum {
        NOT_INITIALIZED,
        STOPPED,
        WAITING_FOR_PREVIEW_WINDOW,
        PREVIEW
    } mState;

    sp<Camera2Device> mDevice;

    CameraParameters *mParams;

    sp<IBinder> mPreviewSurface;
    int mPreviewStreamId;
    camera_metadata_t *mPreviewRequest;

    status_t setPreviewWindow(const sp<IBinder>& binder,
            const sp<ANativeWindow>& window);

    // 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;
    // Update preview request based on mParams
    status_t updatePreviewRequest();
};

}; // namespace android
+381 −34
Original line number Diff line number Diff line
@@ -26,11 +26,12 @@ Camera2Device::Camera2Device(int id):
        mId(id),
        mDevice(NULL)
{

    ALOGV("%s: E", __FUNCTION__);
}

Camera2Device::~Camera2Device()
{
    ALOGV("%s: E", __FUNCTION__);
    if (mDevice) {
        status_t res;
        res = mDevice->common.close(&mDevice->common);
@@ -45,6 +46,8 @@ Camera2Device::~Camera2Device()

status_t Camera2Device::initialize(camera_module_t *module)
{
    ALOGV("%s: E", __FUNCTION__);

    status_t res;
    char name[10];
    snprintf(name, sizeof(name), "%d", mId);
@@ -79,26 +82,90 @@ status_t Camera2Device::initialize(camera_module_t *module)

    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 = mRequestQueue.setConsumerDevice(mDevice);
    if (res != OK) {
        ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
                __FUNCTION__, mId, strerror(-res), res);
        return res;
    }
    res = mFrameQueue.setProducerDevice(mDevice);
    if (res != OK) {
        ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
                __FUNCTION__, mId, strerror(-res), res);
        return res;
    }

    res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
    if (res != OK ) return res;
    if (res != OK ) {
        ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
                __FUNCTION__, mId, strerror(-res), res);
        return res;
    }

    return OK;
}

camera_metadata_t *Camera2Device::info() {
    ALOGV("%s: E", __FUNCTION__);

    return mDeviceInfo;
}

status_t Camera2Device::setStreamingRequest(camera_metadata_t* request)
{
    ALOGV("%s: E", __FUNCTION__);

    mRequestQueue.setStreamSlot(request);
    return OK;
}

status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
        uint32_t width, uint32_t height, int format, int *id) {
    status_t res;
    ALOGV("%s: E", __FUNCTION__);

    sp<StreamAdapter> stream = new StreamAdapter(mDevice);

    res = stream->connectToDevice(consumer, width, height, format);
    if (res != OK) {
        ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
                "%s (%d)",
                __FUNCTION__, mId, width, height, format, strerror(-res), res);
        return res;
    }

    *id = stream->getId();

    mStreams.push_back(stream);
    return OK;
}

status_t Camera2Device::deleteStream(int id) {
    ALOGV("%s: E", __FUNCTION__);

    bool found = false;
    for (StreamList::iterator streamI = mStreams.begin();
         streamI != mStreams.end(); streamI++) {
        if ((*streamI)->getId() == id) {
            mStreams.erase(streamI);
            found = true;
            break;
        }
    }
    if (!found) {
        ALOGE("%s: Camera %d: Unable to find stream %d to delete",
                __FUNCTION__, mId, id);
        return BAD_VALUE;
    }
    return OK;
}

status_t Camera2Device::createDefaultRequest(int templateId,
        camera_metadata_t **request) {
    ALOGV("%s: E", __FUNCTION__);
    return mDevice->ops->construct_default_request(mDevice, templateId, request);
}

/**
 * Camera2Device::MetadataQueue
 */
@@ -125,39 +192,32 @@ Camera2Device::MetadataQueue::~MetadataQueue() {
    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);
// Connect to camera2 HAL as consumer (input requests/reprocessing)
status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
    status_t res;
    res = d->ops->set_request_queue_src_ops(d,
            this);
    if (res != OK) return res;
    mDevice = d;
    return OK;
}

const camera2_frame_queue_dst_ops_t*
Camera2Device::MetadataQueue::getToProducerInterface() {
    return static_cast<camera2_frame_queue_dst_ops_t*>(this);
status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
    status_t res;
    res = d->ops->set_frame_queue_dst_ops(d,
            this);
    return res;
}

// Real interfaces
status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
    ALOGV("%s: E", __FUNCTION__);
    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;
    return signalConsumerLocked();
}

int Camera2Device::MetadataQueue::getBufferCount() {
@@ -171,6 +231,8 @@ int Camera2Device::MetadataQueue::getBufferCount() {
status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
        bool incrementCount)
{
    ALOGV("%s: E", __FUNCTION__);
    status_t res;
    Mutex::Autolock l(mMutex);

    if (mCount == 0) {
@@ -201,9 +263,16 @@ status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
    mEntries.erase(mEntries.begin());

    if (incrementCount) {
        add_camera_metadata_entry(b,
        camera_metadata_entry_t frameCount;
        res = find_camera_metadata_entry(b,
                ANDROID_REQUEST_FRAME_COUNT,
                (void**)&mFrameCount, 1);
                &frameCount);
        if (res != OK) {
            ALOGE("%s: Unable to add frame count: %s (%d)",
                    __FUNCTION__, strerror(-res), res);
        } else {
            *frameCount.data.i32 = mFrameCount;
        }
        mFrameCount++;
    }

@@ -226,6 +295,7 @@ status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)

status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
{
    ALOGV("%s: E", __FUNCTION__);
    Mutex::Autolock l(mMutex);
    if (buf == NULL) {
        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
@@ -244,20 +314,34 @@ status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
        mStreamSlot.push_front(buf);
        mStreamSlotCount = 1;
    }
    return OK;
    return signalConsumerLocked();
}

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

    return OK;
status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
    status_t res = OK;
    notEmpty.signal();
    if (mSignalConsumer && mDevice != NULL) {
        mSignalConsumer = false;

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

status_t Camera2Device::MetadataQueue::freeBuffers(
@@ -337,5 +421,268 @@ int Camera2Device::MetadataQueue::producer_enqueue(
    return queue->enqueue(filled_buffer);
}

/**
 * Camera2Device::StreamAdapter
 */

#ifndef container_of
#define container_of(ptr, type, member) \
    (type *)((char*)(ptr) - offsetof(type, member))
#endif

Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
        mState(DISCONNECTED),
        mDevice(d),
        mId(-1),
        mWidth(0), mHeight(0), mFormatRequested(0)
{
    camera2_stream_ops::dequeue_buffer = dequeue_buffer;
    camera2_stream_ops::enqueue_buffer = enqueue_buffer;
    camera2_stream_ops::cancel_buffer = cancel_buffer;
    camera2_stream_ops::set_crop = set_crop;
}

Camera2Device::StreamAdapter::~StreamAdapter() {
    disconnect();
}

status_t Camera2Device::StreamAdapter::connectToDevice(sp<ANativeWindow> consumer,
        uint32_t width, uint32_t height, int format) {
    status_t res;

    if (mState != DISCONNECTED) return INVALID_OPERATION;
    if (consumer == NULL) {
        ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
        return BAD_VALUE;
    }

    mConsumerInterface = consumer;
    mWidth = width;
    mHeight = height;
    mFormatRequested = format;

    // Allocate device-side stream interface

    uint32_t id;
    uint32_t formatActual;
    uint32_t usage;
    uint32_t maxBuffers = 2;
    res = mDevice->ops->allocate_stream(mDevice,
            mWidth, mHeight, mFormatRequested, getStreamOps(),
            &id, &formatActual, &usage, &maxBuffers);
    if (res != OK) {
        ALOGE("%s: Device stream allocation failed: %s (%d)",
                __FUNCTION__, strerror(-res), res);
        return res;
    }

    mId = id;
    mFormat = formatActual;
    mUsage = usage;
    mMaxProducerBuffers = maxBuffers;

    mState = ALLOCATED;

    // Configure consumer-side ANativeWindow interface
    res = native_window_api_connect(mConsumerInterface.get(),
            NATIVE_WINDOW_API_CAMERA);
    if (res != OK) {
        ALOGE("%s: Unable to connect to native window for stream %d",
                __FUNCTION__, mId);

        return res;
    }

    mState = CONNECTED;

    res = native_window_set_usage(mConsumerInterface.get(), mUsage);
    if (res != OK) {
        ALOGE("%s: Unable to configure usage %08x for stream %d",
                __FUNCTION__, mUsage, mId);
        return res;
    }

    res = native_window_set_buffers_geometry(mConsumerInterface.get(),
            mWidth, mHeight, mFormat);
    if (res != OK) {
        ALOGE("%s: Unable to configure buffer geometry"
                " %d x %d, format 0x%x for stream %d",
                __FUNCTION__, mWidth, mHeight, mFormat, mId);
        return res;
    }

    int maxConsumerBuffers;
    res = mConsumerInterface->query(mConsumerInterface.get(),
            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
    if (res != OK) {
        ALOGE("%s: Unable to query consumer undequeued"
                " buffer count for stream %d", __FUNCTION__, mId);
        return res;
    }
    mMaxConsumerBuffers = maxConsumerBuffers;

    ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
            mMaxProducerBuffers, mMaxConsumerBuffers);

    int totalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;

    res = native_window_set_buffer_count(mConsumerInterface.get(),
            totalBuffers);
    if (res != OK) {
        ALOGE("%s: Unable to set buffer count for stream %d",
                __FUNCTION__, mId);
        return res;
    }

    // Register allocated buffers with HAL device
    buffer_handle_t *buffers = new buffer_handle_t[totalBuffers];
    ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[totalBuffers];
    int bufferIdx = 0;
    for (; bufferIdx < totalBuffers; bufferIdx++) {
        res = mConsumerInterface->dequeueBuffer(mConsumerInterface.get(),
                &anwBuffers[bufferIdx]);
        if (res != OK) {
            ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
                    "stream %d", __FUNCTION__, bufferIdx, mId);
            goto cleanUpBuffers;
        }

        res = mConsumerInterface->lockBuffer(mConsumerInterface.get(),
                anwBuffers[bufferIdx]);
        if (res != OK) {
            ALOGE("%s: Unable to lock buffer %d for initial registration for"
                    "stream %d", __FUNCTION__, bufferIdx, mId);
            bufferIdx++;
            goto cleanUpBuffers;
        }

        buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
    }

    res = mDevice->ops->register_stream_buffers(mDevice,
            mId,
            totalBuffers,
            buffers);
    if (res != OK) {
        ALOGE("%s: Unable to register buffers with HAL device for stream %d",
                __FUNCTION__, mId);
    } else {
        mState = ACTIVE;
    }

cleanUpBuffers:
    for (int i = 0; i < bufferIdx; i++) {
        res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
                anwBuffers[i]);
        if (res != OK) {
            ALOGE("%s: Unable to cancel buffer %d after registration",
                    __FUNCTION__, i);
        }
    }
    delete anwBuffers;
    delete buffers;

    return res;
}

status_t Camera2Device::StreamAdapter::disconnect() {
    status_t res;
    if (mState >= ALLOCATED) {
        res = mDevice->ops->release_stream(mDevice, mId);
        if (res != OK) {
            ALOGE("%s: Unable to release stream %d",
                    __FUNCTION__, mId);
            return res;
        }
    }
    if (mState >= CONNECTED) {
        res = native_window_api_disconnect(mConsumerInterface.get(),
                NATIVE_WINDOW_API_CAMERA);
        if (res != OK) {
            ALOGE("%s: Unable to disconnect stream %d from native window",
                    __FUNCTION__, mId);
            return res;
        }
    }
    mId = -1;
    mState = DISCONNECTED;
    return OK;
}

int Camera2Device::StreamAdapter::getId() {
    return mId;
}

const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
    return static_cast<camera2_stream_ops *>(this);
}

ANativeWindow* Camera2Device::StreamAdapter::toANW(
        const camera2_stream_ops_t *w) {
    return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
}

int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
        buffer_handle_t** buffer) {
    int res;
    int state = static_cast<const StreamAdapter*>(w)->mState;
    if (state != ACTIVE) {
        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
        return INVALID_OPERATION;
    }

    ANativeWindow *a = toANW(w);
    ANativeWindowBuffer* anb;
    res = a->dequeueBuffer(a, &anb);
    if (res != OK) return res;
    res = a->lockBuffer(a, anb);
    if (res != OK) return res;

    *buffer = &(anb->handle);
    ALOGV("%s: Buffer %p", __FUNCTION__, *buffer);
    return res;
}

int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
        int64_t timestamp,
        buffer_handle_t* buffer) {
    ALOGV("%s: Buffer %p captured at %lld ns", __FUNCTION__, buffer, timestamp);
    int state = static_cast<const StreamAdapter*>(w)->mState;
    if (state != ACTIVE) {
        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
        return INVALID_OPERATION;
    }
    ANativeWindow *a = toANW(w);
    status_t err;
    err = native_window_set_buffers_timestamp(a, timestamp);
    if (err != OK) return err;
    return a->queueBuffer(a,
            container_of(buffer, ANativeWindowBuffer, handle));
}

int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
        buffer_handle_t* buffer) {
    int state = static_cast<const StreamAdapter*>(w)->mState;
    if (state != ACTIVE) {
        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
        return INVALID_OPERATION;
    }
    ANativeWindow *a = toANW(w);
    return a->cancelBuffer(a,
            container_of(buffer, ANativeWindowBuffer, handle));
}

int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
        int left, int top, int right, int bottom) {
    int state = static_cast<const StreamAdapter*>(w)->mState;
    if (state != ACTIVE) {
        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
        return INVALID_OPERATION;
    }
    ANativeWindow *a = toANW(w);
    android_native_rect_t crop = { left, top, right, bottom };
    return native_window_set_crop(a, &crop);
}


}; // namespace android
+78 −3

File changed.

Preview size limit exceeded, changes collapsed.