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

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

Merge "camera2: add reprocess support"

parents b23cabdb 618ff8a4
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -81,6 +81,13 @@ status_t CaptureRequest::readFromParcel(Parcel* parcel) {
        mSurfaceList.push_back(surface);
    }

    int isReprocess = 0;
    if ((err = parcel->readInt32(&isReprocess)) != OK) {
        ALOGE("%s: Failed to read reprocessing from parcel", __FUNCTION__);
        return err;
    }
    mIsReprocess = (isReprocess != 0);

    return OK;
}

@@ -118,6 +125,8 @@ status_t CaptureRequest::writeToParcel(Parcel* parcel) const {
        parcel->writeStrongBinder(binder);
    }

    parcel->writeInt32(mIsReprocess ? 1 : 0);

    return OK;
}

+74 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ enum {
    END_CONFIGURE,
    DELETE_STREAM,
    CREATE_STREAM,
    CREATE_INPUT_STREAM,
    GET_INPUT_SURFACE,
    CREATE_DEFAULT_REQUEST,
    GET_CAMERA_INFO,
    WAIT_UNTIL_IDLE,
@@ -225,6 +227,50 @@ public:
        return reply.readInt32();
    }

    virtual status_t createInputStream(int width, int height, int format)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());
        data.writeInt32(width);
        data.writeInt32(height);
        data.writeInt32(format);

        remote()->transact(CREATE_INPUT_STREAM, data, &reply);

        reply.readExceptionCode();
        return reply.readInt32();
    }

    // get the buffer producer of the input stream
    virtual status_t getInputBufferProducer(
            sp<IGraphicBufferProducer> *producer) {
        if (producer == NULL) {
            return BAD_VALUE;
        }

        Parcel data, reply;
        data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor());

        remote()->transact(GET_INPUT_SURFACE, data, &reply);

        reply.readExceptionCode();
        status_t result = reply.readInt32() ;
        if (result != OK) {
            return result;
        }

        sp<IGraphicBufferProducer> bp = NULL;
        if (reply.readInt32() != 0) {
            String16 name = readMaybeEmptyString16(reply);
            bp = interface_cast<IGraphicBufferProducer>(
                    reply.readStrongBinder());
        }

        *producer = bp;

        return *producer == NULL ? INVALID_OPERATION : OK;
    }

    // Create a request object from a template.
    virtual status_t createDefaultRequest(int templateId,
                                          /*out*/
@@ -409,7 +455,35 @@ status_t BnCameraDeviceUser::onTransact(

            return NO_ERROR;
        } break;
        case CREATE_INPUT_STREAM: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int width, height, format;

            width = data.readInt32();
            height = data.readInt32();
            format = data.readInt32();
            status_t ret = createInputStream(width, height, format);

            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;

        } break;
        case GET_INPUT_SURFACE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            sp<IGraphicBufferProducer> bp;
            status_t ret = getInputBufferProducer(&bp);
            sp<IBinder> b(IInterface::asBinder(ret == OK ? bp : NULL));

            reply->writeNoException();
            reply->writeInt32(ret);
            reply->writeInt32(1);
            reply->writeString16(String16("camera input")); // name of surface
            reply->writeStrongBinder(b);

            return NO_ERROR;
        } break;
        case CREATE_DEFAULT_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ public:

    CameraMetadata          mMetadata;
    Vector<sp<Surface> >    mSurfaceList;
    bool                    mIsReprocess;

    /**
     * Keep impl up-to-date with CaptureRequest.java in frameworks/base
+13 −0
Original line number Diff line number Diff line
@@ -103,6 +103,19 @@ public:

    virtual status_t        createStream(const OutputConfiguration& outputConfiguration) = 0;

    /**
     * Create an input stream of width, height, and format (one of
     * HAL_PIXEL_FORMAT_*)
     *
     * Return stream ID if it's a non-negative value. status_t if it's a
     * negative value.
     */
    virtual status_t        createInputStream(int width, int height, int format) = 0;

    // get the buffer producer of the input stream
    virtual status_t        getInputBufferProducer(
            sp<IGraphicBufferProducer> *producer) = 0;

    // Create a request object from a template.
    virtual status_t        createDefaultRequest(int templateId,
                                                 /*out*/
+101 −16
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
                                   int servicePid) :
    Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
    mInputStream(),
    mRequestIdCounter(0) {

    ATRACE_CALL();
@@ -127,6 +128,7 @@ status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > request
    List<const CameraMetadata> metadataRequestList;
    int32_t requestId = mRequestIdCounter;
    uint32_t loopCounter = 0;
    bool isReprocess = false;

    for (List<sp<CaptureRequest> >::iterator it = requests.begin(); it != requests.end(); ++it) {
        sp<CaptureRequest> request = *it;
@@ -134,6 +136,18 @@ status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > request
            ALOGE("%s: Camera %d: Sent null request.",
                    __FUNCTION__, mCameraId);
            return BAD_VALUE;
        } else if (it == requests.begin()) {
            isReprocess = request->mIsReprocess;
            if (isReprocess && !mInputStream.configured) {
                ALOGE("%s: Camera %d: no input stream is configured.");
                return BAD_VALUE;
            } else if (isReprocess && streaming) {
                ALOGE("%s: Camera %d: streaming reprocess requests not supported.");
                return BAD_VALUE;
            }
        } else if (isReprocess != request->mIsReprocess) {
            ALOGE("%s: Camera %d: Sent regular and reprocess requests.");
            return BAD_VALUE;
        }

        CameraMetadata metadata(request->mMetadata);
@@ -182,6 +196,10 @@ status_t CameraDeviceClient::submitRequestList(List<sp<CaptureRequest> > request
        metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS, &outputStreamIds[0],
                        outputStreamIds.size());

        if (isReprocess) {
            metadata.update(ANDROID_REQUEST_INPUT_STREAMS, &mInputStream.id, 1);
        }

        metadata.update(ANDROID_REQUEST_ID, &requestId, /*size*/1);
        loopCounter++; // loopCounter starts from 1
        ALOGV("%s: Camera %d: Creating request with ID %d (%d of %zu)",
@@ -260,8 +278,8 @@ status_t CameraDeviceClient::beginConfigure() {
}

status_t CameraDeviceClient::endConfigure() {
    ALOGV("%s: ending configure (%zu streams)",
            __FUNCTION__, mStreamMap.size());
    ALOGV("%s: ending configure (%d input stream, %zu output streams)",
            __FUNCTION__, mInputStream.configured ? 1 : 0, mStreamMap.size());

    status_t res;
    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
@@ -284,8 +302,13 @@ status_t CameraDeviceClient::deleteStream(int streamId) {

    if (!mDevice.get()) return DEAD_OBJECT;

    // Guard against trying to delete non-created streams
    bool isInput = false;
    ssize_t index = NAME_NOT_FOUND;

    if (mInputStream.configured && mInputStream.id == streamId) {
        isInput = true;
    } else {
        // Guard against trying to delete non-created streams
        for (size_t i = 0; i < mStreamMap.size(); ++i) {
            if (streamId == mStreamMap.valueAt(i)) {
                index = i;
@@ -298,6 +321,7 @@ status_t CameraDeviceClient::deleteStream(int streamId) {
                  "created yet", __FUNCTION__, mCameraId, streamId);
            return BAD_VALUE;
        }
    }

    // Also returns BAD_VALUE if stream ID was not valid
    res = mDevice->deleteStream(streamId);
@@ -307,8 +331,11 @@ status_t CameraDeviceClient::deleteStream(int streamId) {
              " already checked and the stream ID (%d) should be valid.",
              __FUNCTION__, mCameraId, streamId);
    } else if (res == OK) {
        if (isInput) {
            mInputStream.configured = false;
        } else {
            mStreamMap.removeItemsAt(index);

        }
    }

    return res;
@@ -450,6 +477,58 @@ status_t CameraDeviceClient::createStream(const OutputConfiguration &outputConfi
}


status_t CameraDeviceClient::createInputStream(int width, int height,
        int format) {

    ATRACE_CALL();
    ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);

    status_t res;
    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    Mutex::Autolock icl(mBinderSerializationLock);
    if (!mDevice.get()) return DEAD_OBJECT;

    if (mInputStream.configured) {
        ALOGE("%s: Camera %d: Already has an input stream "
                " configuration. (ID %zd)", __FUNCTION__, mCameraId,
                mInputStream.id);
        return ALREADY_EXISTS;
    }

    int streamId = -1;
    res = mDevice->createInputStream(width, height, format, &streamId);
    if (res == OK) {
        mInputStream.configured = true;
        mInputStream.width = width;
        mInputStream.height = height;
        mInputStream.format = format;
        mInputStream.id = streamId;

        ALOGV("%s: Camera %d: Successfully created a new input stream ID %d",
              __FUNCTION__, mCameraId, streamId);

        return streamId;
    }

    return res;
}

status_t CameraDeviceClient::getInputBufferProducer(
        /*out*/sp<IGraphicBufferProducer> *producer) {
    status_t res;
    if ( (res = checkPid(__FUNCTION__) ) != OK) return res;

    if (producer == NULL) {
        return BAD_VALUE;
    }

    Mutex::Autolock icl(mBinderSerializationLock);
    if (!mDevice.get()) return DEAD_OBJECT;

    return mDevice->getInputBufferProducer(producer);
}

bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height,
        int32_t format, android_dataspace dataSpace, const CameraMetadata& info,
        /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) {
@@ -602,13 +681,19 @@ status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {

    result.append("  State:\n");
    result.appendFormat("    Request ID counter: %d\n", mRequestIdCounter);
    if (mInputStream.configured) {
        result.appendFormat("    Current input stream ID: %d\n",
                    mInputStream.id);
    } else {
        result.append("    No input stream configured.\n");
    }
    if (!mStreamMap.isEmpty()) {
        result.append("    Current stream IDs:\n");
        result.append("    Current output stream IDs:\n");
        for (size_t i = 0; i < mStreamMap.size(); i++) {
            result.appendFormat("      Stream %d\n", mStreamMap.valueAt(i));
        }
    } else {
        result.append("    No streams configured.\n");
        result.append("    No output streams configured.\n");
    }
    write(fd, result.string(), result.size());
    // TODO: print dynamic/request section from most recent requests
Loading