Loading camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -121,4 +121,6 @@ interface ICameraDeviceUser void tearDown(int streamId); void prepare2(int maxCount, int streamId); void setDeferredConfiguration(int streamId, in OutputConfiguration outputConfiguration); } camera/camera2/OutputConfiguration.cpp +59 −5 Original line number Diff line number Diff line Loading @@ -42,9 +42,24 @@ int OutputConfiguration::getSurfaceSetID() const { return mSurfaceSetID; } int OutputConfiguration::getSurfaceType() const { return mSurfaceType; } int OutputConfiguration::getWidth() const { return mWidth; } int OutputConfiguration::getHeight() const { return mHeight; } OutputConfiguration::OutputConfiguration() : mRotation(INVALID_ROTATION), mSurfaceSetID(INVALID_SET_ID) { mSurfaceSetID(INVALID_SET_ID), mSurfaceType(SURFACE_TYPE_UNKNOWN), mWidth(0), mHeight(0) { } OutputConfiguration::OutputConfiguration(const Parcel& parcel) : Loading @@ -70,18 +85,48 @@ status_t OutputConfiguration::readFromParcel(const Parcel* parcel) { return err; } int surfaceType = SURFACE_TYPE_UNKNOWN; if ((err = parcel->readInt32(&surfaceType)) != OK) { ALOGE("%s: Failed to read surface type from parcel", __FUNCTION__); return err; } int width = 0; if ((err = parcel->readInt32(&width)) != OK) { ALOGE("%s: Failed to read surface width from parcel", __FUNCTION__); return err; } int height = 0; if ((err = parcel->readInt32(&height)) != OK) { ALOGE("%s: Failed to read surface height from parcel", __FUNCTION__); return err; } view::Surface surfaceShim; if ((err = surfaceShim.readFromParcel(parcel)) != OK) { // Read surface failure for deferred surface configuration is expected. if (surfaceType == SURFACE_TYPE_SURFACE_VIEW || surfaceType == SURFACE_TYPE_SURFACE_TEXTURE) { ALOGV("%s: Get null surface from a deferred surface configuration (%dx%d)", __FUNCTION__, width, height); err = OK; } else { ALOGE("%s: Failed to read surface from parcel", __FUNCTION__); return err; } } mGbp = surfaceShim.graphicBufferProducer; mRotation = rotation; mSurfaceSetID = setID; mSurfaceType = surfaceType; mWidth = width; mHeight = height; ALOGV("%s: OutputConfiguration: bp = %p, name = %s, rotation = %d, setId = %d", __FUNCTION__, mGbp.get(), String8(surfaceShim.name).string(), mRotation, mSurfaceSetID); ALOGV("%s: OutputConfiguration: bp = %p, name = %s, rotation = %d, setId = %d," "surfaceType = %d", __FUNCTION__, mGbp.get(), String8(surfaceShim.name).string(), mRotation, mSurfaceSetID, mSurfaceType); return err; } Loading @@ -104,6 +149,15 @@ status_t OutputConfiguration::writeToParcel(Parcel* parcel) const { err = parcel->writeInt32(mSurfaceSetID); if (err != OK) return err; err = parcel->writeInt32(mSurfaceType); if (err != OK) return err; err = parcel->writeInt32(mWidth); if (err != OK) return err; err = parcel->writeInt32(mHeight); if (err != OK) return err; view::Surface surfaceShim; surfaceShim.name = String16("unknown_name"); // name of surface surfaceShim.graphicBufferProducer = mGbp; Loading include/camera/camera2/OutputConfiguration.h +25 −2 Original line number Diff line number Diff line Loading @@ -33,10 +33,17 @@ public: static const int INVALID_ROTATION; static const int INVALID_SET_ID; enum SurfaceType{ SURFACE_TYPE_UNKNOWN = -1, SURFACE_TYPE_SURFACE_VIEW = 0, SURFACE_TYPE_SURFACE_TEXTURE = 1 }; sp<IGraphicBufferProducer> getGraphicBufferProducer() const; int getRotation() const; int getSurfaceSetID() const; int getSurfaceType() const; int getWidth() const; int getHeight() const; /** * Keep impl up-to-date with OutputConfiguration.java in frameworks/base */ Loading @@ -60,7 +67,10 @@ public: bool operator == (const OutputConfiguration& other) const { return (mGbp == other.mGbp && mRotation == other.mRotation && mSurfaceSetID == other.mSurfaceSetID); mSurfaceSetID == other.mSurfaceSetID && mSurfaceType == other.mSurfaceType && mWidth == other.mWidth && mHeight == other.mHeight); } bool operator != (const OutputConfiguration& other) const { return !(*this == other); Loading @@ -71,6 +81,16 @@ public: if (mSurfaceSetID != other.mSurfaceSetID) { return mSurfaceSetID < other.mSurfaceSetID; } if (mSurfaceType != other.mSurfaceType) { return mSurfaceType < other.mSurfaceType; } if (mWidth != other.mWidth) { return mWidth < other.mWidth; } if (mHeight != other.mHeight) { return mHeight < other.mHeight; } return mRotation < other.mRotation; } bool operator > (const OutputConfiguration& other) const { Loading @@ -81,6 +101,9 @@ private: sp<IGraphicBufferProducer> mGbp; int mRotation; int mSurfaceSetID; int mSurfaceType; int mWidth; int mHeight; // helper function static String16 readMaybeEmptyString16(const Parcel* parcel); }; Loading services/camera/libcameraservice/api2/CameraDeviceClient.cpp +200 −40 Original line number Diff line number Diff line Loading @@ -338,13 +338,15 @@ binder::Status CameraDeviceClient::endConfigure(bool isConstrainedHighSpeed) { status_t err = mDevice->configureStreams(isConstrainedHighSpeed); if (err == BAD_VALUE) { res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT, "Camera %d: Unsupported set of inputs/outputs provided", String8 msg = String8::format("Camera %d: Unsupported set of inputs/outputs provided", mCameraId); ALOGE("%s: %s", __FUNCTION__, msg.string()); res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); } else if (err != OK) { res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION, "Camera %d: Error configuring streams: %s (%d)", String8 msg = String8::format("Camera %d: Error configuring streams: %s (%d)", mCameraId, strerror(-err), err); ALOGE("%s: %s", __FUNCTION__, msg.string()); res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string()); } return res; Loading @@ -365,6 +367,7 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) { bool isInput = false; ssize_t index = NAME_NOT_FOUND; ssize_t dIndex = NAME_NOT_FOUND; if (mInputStream.configured && mInputStream.id == streamId) { isInput = true; Loading @@ -378,12 +381,21 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) { } if (index == NAME_NOT_FOUND) { // See if this stream is one of the deferred streams. for (size_t i = 0; i < mDeferredStreams.size(); ++i) { if (streamId == mDeferredStreams[i]) { dIndex = i; break; } } if (dIndex == NAME_NOT_FOUND) { String8 msg = String8::format("Camera %d: Invalid stream ID (%d) specified, no such" " stream created yet", mCameraId, streamId); ALOGW("%s: %s", __FUNCTION__, msg.string()); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); } } } // Also returns BAD_VALUE if stream ID was not valid status_t err = mDevice->deleteStream(streamId); Loading @@ -396,8 +408,10 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) { } else { if (isInput) { mInputStream.configured = false; } else { } else if (index != NAME_NOT_FOUND) { mStreamMap.removeItemsAt(index); } else { mDeferredStreams.removeItemsAt(dIndex); } } Loading @@ -416,14 +430,30 @@ binder::Status CameraDeviceClient::createStream( Mutex::Autolock icl(mBinderSerializationLock); sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer(); if (bufferProducer == NULL) { ALOGE("%s: bufferProducer must not be null", __FUNCTION__); bool deferredConsumer = bufferProducer == NULL; int surfaceType = outputConfiguration.getSurfaceType(); bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) || (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE)); if (deferredConsumer && !validSurfaceType) { ALOGE("%s: Target surface is invalid: bufferProducer = %p, surfaceType = %d.", __FUNCTION__, bufferProducer.get(), surfaceType); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid"); } if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } int width, height, format; int32_t consumerUsage; android_dataspace dataSpace; status_t err; // Create stream for deferred surface case. if (deferredConsumer) { return createDeferredSurfaceStreamLocked(outputConfiguration, newStreamId); } // Don't create multiple streams for the same target surface { ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer)); Loading @@ -435,13 +465,10 @@ binder::Status CameraDeviceClient::createStream( } } status_t err; // HACK b/10949105 // Query consumer usage bits to set async operation mode for // GLConsumer using controlledByApp parameter. bool useAsync = false; int32_t consumerUsage; if ((err = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage)) != OK) { String8 msg = String8::format("Camera %d: Failed to query Surface consumer usage: %s (%d)", Loading @@ -450,8 +477,8 @@ binder::Status CameraDeviceClient::createStream( return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string()); } if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) { ALOGW("%s: Camera %d: Forcing asynchronous mode for stream", __FUNCTION__, mCameraId); ALOGW("%s: Camera %d with consumer usage flag: 0x%x: Forcing asynchronous mode for stream", __FUNCTION__, mCameraId, consumerUsage); useAsync = true; } Loading @@ -467,9 +494,6 @@ binder::Status CameraDeviceClient::createStream( sp<Surface> surface = new Surface(bufferProducer, useAsync); ANativeWindow *anw = surface.get(); int width, height, format; android_dataspace dataSpace; if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) { String8 msg = String8::format("Camera %d: Failed to query Surface width: %s (%d)", mCameraId, strerror(-err), err); Loading Loading @@ -526,16 +550,81 @@ binder::Status CameraDeviceClient::createStream( } else { mStreamMap.add(binder, streamId); ALOGV("%s: Camera %d: Successfully created a new stream ID %d", __FUNCTION__, mCameraId, streamId); ALOGV("%s: Camera %d: Successfully created a new stream ID %d for output surface" " (%d x %d) with format 0x%x.", __FUNCTION__, mCameraId, streamId, width, height, format); /** * Set the stream transform flags to automatically * rotate the camera stream for preview use cases. */ // Set transform flags to ensure preview to be rotated correctly. res = setStreamTransformLocked(streamId); *newStreamId = streamId; } return res; } binder::Status CameraDeviceClient::createDeferredSurfaceStreamLocked( const hardware::camera2::params::OutputConfiguration &outputConfiguration, /*out*/ int* newStreamId) { int width, height, format, surfaceType; int32_t consumerUsage; android_dataspace dataSpace; status_t err; binder::Status res; if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } // Infer the surface info for deferred surface stream creation. width = outputConfiguration.getWidth(); height = outputConfiguration.getHeight(); surfaceType = outputConfiguration.getSurfaceType(); format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN; // Hardcode consumer usage flags: SurfaceView--0x900, SurfaceTexture--0x100. consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE; if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) { consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER; } int streamId = camera3::CAMERA3_STREAM_ID_INVALID; err = mDevice->createStream(/*surface*/nullptr, width, height, format, dataSpace, static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()), &streamId, outputConfiguration.getSurfaceSetID(), consumerUsage); if (err != OK) { res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION, "Camera %d: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)", mCameraId, width, height, format, dataSpace, strerror(-err), err); } else { // Can not add streamId to mStreamMap here, as the surface is deferred. Add it to // a separate list to track. Once the deferred surface is set, this id will be // relocated to mStreamMap. mDeferredStreams.push_back(streamId); ALOGV("%s: Camera %d: Successfully created a new stream ID %d for a deferred surface" " (%d x %d) stream with format 0x%x.", __FUNCTION__, mCameraId, streamId, width, height, format); // Set transform flags to ensure preview to be rotated correctly. res = setStreamTransformLocked(streamId); *newStreamId = streamId; } return res; } binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId) { int32_t transform = 0; err = getRotationTransformLocked(&transform); status_t err; binder::Status res; if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } err = getRotationTransformLocked(&transform); if (err != OK) { // Error logged by getRotationTransformLocked. return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, Loading @@ -550,13 +639,9 @@ binder::Status CameraDeviceClient::createStream( return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string()); } *newStreamId = streamId; } return res; } binder::Status CameraDeviceClient::createInputStream( int width, int height, int format, /*out*/ Loading Loading @@ -934,6 +1019,76 @@ binder::Status CameraDeviceClient::tearDown(int streamId) { return res; } binder::Status CameraDeviceClient::setDeferredConfiguration(int32_t streamId, const hardware::camera2::params::OutputConfiguration &outputConfiguration) { ATRACE_CALL(); binder::Status res; if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res; Mutex::Autolock icl(mBinderSerializationLock); sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer(); // Client code should guarantee that the surface is from SurfaceView or SurfaceTexture. if (bufferProducer == NULL) { ALOGE("%s: bufferProducer must not be null", __FUNCTION__); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid"); } // Check if this stram id is one of the deferred streams ssize_t index = NAME_NOT_FOUND; for (size_t i = 0; i < mDeferredStreams.size(); i++) { if (streamId == mDeferredStreams[i]) { index = i; break; } } if (index == NAME_NOT_FOUND) { String8 msg = String8::format("Camera %d: deferred surface is set to a unknown stream" "(ID %d)", mCameraId, streamId); ALOGW("%s: %s", __FUNCTION__, msg.string()); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); } if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } // Don't create multiple streams for the same target surface { ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer)); if (index != NAME_NOT_FOUND) { String8 msg = String8::format("Camera %d: Surface already has a stream created " " for it (ID %zd)", mCameraId, index); ALOGW("%s: %s", __FUNCTION__, msg.string()); return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string()); } } status_t err; // Always set to async, as we know the deferred surface is for preview streaming. sp<Surface> consumerSurface = new Surface(bufferProducer, /*useAsync*/true); // Finish the deferred stream configuration with the surface. err = mDevice->setConsumerSurface(streamId, consumerSurface); if (err == OK) { sp<IBinder> binder = IInterface::asBinder(bufferProducer); mStreamMap.add(binder, streamId); mDeferredStreams.removeItemsAt(index); } else if (err == NO_INIT) { res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT, "Camera %d: Deferred surface is invalid: %s (%d)", mCameraId, strerror(-err), err); } else { res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION, "Camera %d: Error setting output stream deferred surface: %s (%d)", mCameraId, strerror(-err), err); } return res; } status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) { return BasicClient::dump(fd, args); } Loading @@ -959,6 +1114,11 @@ status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) { for (size_t i = 0; i < mStreamMap.size(); i++) { result.appendFormat(" Stream %d\n", mStreamMap.valueAt(i)); } } else if (!mDeferredStreams.isEmpty()) { result.append(" Current deferred surface output stream IDs:\n"); for (auto& streamId : mDeferredStreams) { result.appendFormat(" Stream %d\n", streamId); } } else { result.append(" No output streams configured.\n"); } Loading services/camera/libcameraservice/api2/CameraDeviceClient.h +17 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ public: // Prepare stream by preallocating up to maxCount of its buffers virtual binder::Status prepare2(int32_t maxCount, int32_t streamId); // Set the deferred surface for a stream. virtual binder::Status setDeferredConfiguration(int32_t streamId, const hardware::camera2::params::OutputConfiguration &outputConfiguration); /** * Interface used by CameraService */ Loading Loading @@ -188,6 +192,15 @@ private: // Find the square of the euclidean distance between two points static int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1); // Create an output stream with surface deferred for future. binder::Status createDeferredSurfaceStreamLocked( const hardware::camera2::params::OutputConfiguration &outputConfiguration, int* newStreamId = NULL); // Set the stream transform flags to automatically rotate the camera stream for preview use // cases. binder::Status setStreamTransformLocked(int streamId); // Find the closest dimensions for a given format in available stream configurations with // a width <= ROUNDING_WIDTH_CAP static const int32_t ROUNDING_WIDTH_CAP = 1920; Loading @@ -213,6 +226,10 @@ private: int32_t mRequestIdCounter; // The list of output streams whose surfaces are deferred. We have to track them separately // as there are no surfaces available and can not be put into mStreamMap. Once the deferred // Surface is configured, the stream id will be moved to mStreamMap. Vector<int32_t> mDeferredStreams; }; }; // namespace android Loading Loading
camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -121,4 +121,6 @@ interface ICameraDeviceUser void tearDown(int streamId); void prepare2(int maxCount, int streamId); void setDeferredConfiguration(int streamId, in OutputConfiguration outputConfiguration); }
camera/camera2/OutputConfiguration.cpp +59 −5 Original line number Diff line number Diff line Loading @@ -42,9 +42,24 @@ int OutputConfiguration::getSurfaceSetID() const { return mSurfaceSetID; } int OutputConfiguration::getSurfaceType() const { return mSurfaceType; } int OutputConfiguration::getWidth() const { return mWidth; } int OutputConfiguration::getHeight() const { return mHeight; } OutputConfiguration::OutputConfiguration() : mRotation(INVALID_ROTATION), mSurfaceSetID(INVALID_SET_ID) { mSurfaceSetID(INVALID_SET_ID), mSurfaceType(SURFACE_TYPE_UNKNOWN), mWidth(0), mHeight(0) { } OutputConfiguration::OutputConfiguration(const Parcel& parcel) : Loading @@ -70,18 +85,48 @@ status_t OutputConfiguration::readFromParcel(const Parcel* parcel) { return err; } int surfaceType = SURFACE_TYPE_UNKNOWN; if ((err = parcel->readInt32(&surfaceType)) != OK) { ALOGE("%s: Failed to read surface type from parcel", __FUNCTION__); return err; } int width = 0; if ((err = parcel->readInt32(&width)) != OK) { ALOGE("%s: Failed to read surface width from parcel", __FUNCTION__); return err; } int height = 0; if ((err = parcel->readInt32(&height)) != OK) { ALOGE("%s: Failed to read surface height from parcel", __FUNCTION__); return err; } view::Surface surfaceShim; if ((err = surfaceShim.readFromParcel(parcel)) != OK) { // Read surface failure for deferred surface configuration is expected. if (surfaceType == SURFACE_TYPE_SURFACE_VIEW || surfaceType == SURFACE_TYPE_SURFACE_TEXTURE) { ALOGV("%s: Get null surface from a deferred surface configuration (%dx%d)", __FUNCTION__, width, height); err = OK; } else { ALOGE("%s: Failed to read surface from parcel", __FUNCTION__); return err; } } mGbp = surfaceShim.graphicBufferProducer; mRotation = rotation; mSurfaceSetID = setID; mSurfaceType = surfaceType; mWidth = width; mHeight = height; ALOGV("%s: OutputConfiguration: bp = %p, name = %s, rotation = %d, setId = %d", __FUNCTION__, mGbp.get(), String8(surfaceShim.name).string(), mRotation, mSurfaceSetID); ALOGV("%s: OutputConfiguration: bp = %p, name = %s, rotation = %d, setId = %d," "surfaceType = %d", __FUNCTION__, mGbp.get(), String8(surfaceShim.name).string(), mRotation, mSurfaceSetID, mSurfaceType); return err; } Loading @@ -104,6 +149,15 @@ status_t OutputConfiguration::writeToParcel(Parcel* parcel) const { err = parcel->writeInt32(mSurfaceSetID); if (err != OK) return err; err = parcel->writeInt32(mSurfaceType); if (err != OK) return err; err = parcel->writeInt32(mWidth); if (err != OK) return err; err = parcel->writeInt32(mHeight); if (err != OK) return err; view::Surface surfaceShim; surfaceShim.name = String16("unknown_name"); // name of surface surfaceShim.graphicBufferProducer = mGbp; Loading
include/camera/camera2/OutputConfiguration.h +25 −2 Original line number Diff line number Diff line Loading @@ -33,10 +33,17 @@ public: static const int INVALID_ROTATION; static const int INVALID_SET_ID; enum SurfaceType{ SURFACE_TYPE_UNKNOWN = -1, SURFACE_TYPE_SURFACE_VIEW = 0, SURFACE_TYPE_SURFACE_TEXTURE = 1 }; sp<IGraphicBufferProducer> getGraphicBufferProducer() const; int getRotation() const; int getSurfaceSetID() const; int getSurfaceType() const; int getWidth() const; int getHeight() const; /** * Keep impl up-to-date with OutputConfiguration.java in frameworks/base */ Loading @@ -60,7 +67,10 @@ public: bool operator == (const OutputConfiguration& other) const { return (mGbp == other.mGbp && mRotation == other.mRotation && mSurfaceSetID == other.mSurfaceSetID); mSurfaceSetID == other.mSurfaceSetID && mSurfaceType == other.mSurfaceType && mWidth == other.mWidth && mHeight == other.mHeight); } bool operator != (const OutputConfiguration& other) const { return !(*this == other); Loading @@ -71,6 +81,16 @@ public: if (mSurfaceSetID != other.mSurfaceSetID) { return mSurfaceSetID < other.mSurfaceSetID; } if (mSurfaceType != other.mSurfaceType) { return mSurfaceType < other.mSurfaceType; } if (mWidth != other.mWidth) { return mWidth < other.mWidth; } if (mHeight != other.mHeight) { return mHeight < other.mHeight; } return mRotation < other.mRotation; } bool operator > (const OutputConfiguration& other) const { Loading @@ -81,6 +101,9 @@ private: sp<IGraphicBufferProducer> mGbp; int mRotation; int mSurfaceSetID; int mSurfaceType; int mWidth; int mHeight; // helper function static String16 readMaybeEmptyString16(const Parcel* parcel); }; Loading
services/camera/libcameraservice/api2/CameraDeviceClient.cpp +200 −40 Original line number Diff line number Diff line Loading @@ -338,13 +338,15 @@ binder::Status CameraDeviceClient::endConfigure(bool isConstrainedHighSpeed) { status_t err = mDevice->configureStreams(isConstrainedHighSpeed); if (err == BAD_VALUE) { res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT, "Camera %d: Unsupported set of inputs/outputs provided", String8 msg = String8::format("Camera %d: Unsupported set of inputs/outputs provided", mCameraId); ALOGE("%s: %s", __FUNCTION__, msg.string()); res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); } else if (err != OK) { res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION, "Camera %d: Error configuring streams: %s (%d)", String8 msg = String8::format("Camera %d: Error configuring streams: %s (%d)", mCameraId, strerror(-err), err); ALOGE("%s: %s", __FUNCTION__, msg.string()); res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string()); } return res; Loading @@ -365,6 +367,7 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) { bool isInput = false; ssize_t index = NAME_NOT_FOUND; ssize_t dIndex = NAME_NOT_FOUND; if (mInputStream.configured && mInputStream.id == streamId) { isInput = true; Loading @@ -378,12 +381,21 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) { } if (index == NAME_NOT_FOUND) { // See if this stream is one of the deferred streams. for (size_t i = 0; i < mDeferredStreams.size(); ++i) { if (streamId == mDeferredStreams[i]) { dIndex = i; break; } } if (dIndex == NAME_NOT_FOUND) { String8 msg = String8::format("Camera %d: Invalid stream ID (%d) specified, no such" " stream created yet", mCameraId, streamId); ALOGW("%s: %s", __FUNCTION__, msg.string()); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); } } } // Also returns BAD_VALUE if stream ID was not valid status_t err = mDevice->deleteStream(streamId); Loading @@ -396,8 +408,10 @@ binder::Status CameraDeviceClient::deleteStream(int streamId) { } else { if (isInput) { mInputStream.configured = false; } else { } else if (index != NAME_NOT_FOUND) { mStreamMap.removeItemsAt(index); } else { mDeferredStreams.removeItemsAt(dIndex); } } Loading @@ -416,14 +430,30 @@ binder::Status CameraDeviceClient::createStream( Mutex::Autolock icl(mBinderSerializationLock); sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer(); if (bufferProducer == NULL) { ALOGE("%s: bufferProducer must not be null", __FUNCTION__); bool deferredConsumer = bufferProducer == NULL; int surfaceType = outputConfiguration.getSurfaceType(); bool validSurfaceType = ((surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) || (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_TEXTURE)); if (deferredConsumer && !validSurfaceType) { ALOGE("%s: Target surface is invalid: bufferProducer = %p, surfaceType = %d.", __FUNCTION__, bufferProducer.get(), surfaceType); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid"); } if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } int width, height, format; int32_t consumerUsage; android_dataspace dataSpace; status_t err; // Create stream for deferred surface case. if (deferredConsumer) { return createDeferredSurfaceStreamLocked(outputConfiguration, newStreamId); } // Don't create multiple streams for the same target surface { ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer)); Loading @@ -435,13 +465,10 @@ binder::Status CameraDeviceClient::createStream( } } status_t err; // HACK b/10949105 // Query consumer usage bits to set async operation mode for // GLConsumer using controlledByApp parameter. bool useAsync = false; int32_t consumerUsage; if ((err = bufferProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage)) != OK) { String8 msg = String8::format("Camera %d: Failed to query Surface consumer usage: %s (%d)", Loading @@ -450,8 +477,8 @@ binder::Status CameraDeviceClient::createStream( return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string()); } if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) { ALOGW("%s: Camera %d: Forcing asynchronous mode for stream", __FUNCTION__, mCameraId); ALOGW("%s: Camera %d with consumer usage flag: 0x%x: Forcing asynchronous mode for stream", __FUNCTION__, mCameraId, consumerUsage); useAsync = true; } Loading @@ -467,9 +494,6 @@ binder::Status CameraDeviceClient::createStream( sp<Surface> surface = new Surface(bufferProducer, useAsync); ANativeWindow *anw = surface.get(); int width, height, format; android_dataspace dataSpace; if ((err = anw->query(anw, NATIVE_WINDOW_WIDTH, &width)) != OK) { String8 msg = String8::format("Camera %d: Failed to query Surface width: %s (%d)", mCameraId, strerror(-err), err); Loading Loading @@ -526,16 +550,81 @@ binder::Status CameraDeviceClient::createStream( } else { mStreamMap.add(binder, streamId); ALOGV("%s: Camera %d: Successfully created a new stream ID %d", __FUNCTION__, mCameraId, streamId); ALOGV("%s: Camera %d: Successfully created a new stream ID %d for output surface" " (%d x %d) with format 0x%x.", __FUNCTION__, mCameraId, streamId, width, height, format); /** * Set the stream transform flags to automatically * rotate the camera stream for preview use cases. */ // Set transform flags to ensure preview to be rotated correctly. res = setStreamTransformLocked(streamId); *newStreamId = streamId; } return res; } binder::Status CameraDeviceClient::createDeferredSurfaceStreamLocked( const hardware::camera2::params::OutputConfiguration &outputConfiguration, /*out*/ int* newStreamId) { int width, height, format, surfaceType; int32_t consumerUsage; android_dataspace dataSpace; status_t err; binder::Status res; if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } // Infer the surface info for deferred surface stream creation. width = outputConfiguration.getWidth(); height = outputConfiguration.getHeight(); surfaceType = outputConfiguration.getSurfaceType(); format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; dataSpace = android_dataspace_t::HAL_DATASPACE_UNKNOWN; // Hardcode consumer usage flags: SurfaceView--0x900, SurfaceTexture--0x100. consumerUsage = GraphicBuffer::USAGE_HW_TEXTURE; if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) { consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER; } int streamId = camera3::CAMERA3_STREAM_ID_INVALID; err = mDevice->createStream(/*surface*/nullptr, width, height, format, dataSpace, static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()), &streamId, outputConfiguration.getSurfaceSetID(), consumerUsage); if (err != OK) { res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION, "Camera %d: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)", mCameraId, width, height, format, dataSpace, strerror(-err), err); } else { // Can not add streamId to mStreamMap here, as the surface is deferred. Add it to // a separate list to track. Once the deferred surface is set, this id will be // relocated to mStreamMap. mDeferredStreams.push_back(streamId); ALOGV("%s: Camera %d: Successfully created a new stream ID %d for a deferred surface" " (%d x %d) stream with format 0x%x.", __FUNCTION__, mCameraId, streamId, width, height, format); // Set transform flags to ensure preview to be rotated correctly. res = setStreamTransformLocked(streamId); *newStreamId = streamId; } return res; } binder::Status CameraDeviceClient::setStreamTransformLocked(int streamId) { int32_t transform = 0; err = getRotationTransformLocked(&transform); status_t err; binder::Status res; if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } err = getRotationTransformLocked(&transform); if (err != OK) { // Error logged by getRotationTransformLocked. return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, Loading @@ -550,13 +639,9 @@ binder::Status CameraDeviceClient::createStream( return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string()); } *newStreamId = streamId; } return res; } binder::Status CameraDeviceClient::createInputStream( int width, int height, int format, /*out*/ Loading Loading @@ -934,6 +1019,76 @@ binder::Status CameraDeviceClient::tearDown(int streamId) { return res; } binder::Status CameraDeviceClient::setDeferredConfiguration(int32_t streamId, const hardware::camera2::params::OutputConfiguration &outputConfiguration) { ATRACE_CALL(); binder::Status res; if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res; Mutex::Autolock icl(mBinderSerializationLock); sp<IGraphicBufferProducer> bufferProducer = outputConfiguration.getGraphicBufferProducer(); // Client code should guarantee that the surface is from SurfaceView or SurfaceTexture. if (bufferProducer == NULL) { ALOGE("%s: bufferProducer must not be null", __FUNCTION__); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Target Surface is invalid"); } // Check if this stram id is one of the deferred streams ssize_t index = NAME_NOT_FOUND; for (size_t i = 0; i < mDeferredStreams.size(); i++) { if (streamId == mDeferredStreams[i]) { index = i; break; } } if (index == NAME_NOT_FOUND) { String8 msg = String8::format("Camera %d: deferred surface is set to a unknown stream" "(ID %d)", mCameraId, streamId); ALOGW("%s: %s", __FUNCTION__, msg.string()); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string()); } if (!mDevice.get()) { return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive"); } // Don't create multiple streams for the same target surface { ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer)); if (index != NAME_NOT_FOUND) { String8 msg = String8::format("Camera %d: Surface already has a stream created " " for it (ID %zd)", mCameraId, index); ALOGW("%s: %s", __FUNCTION__, msg.string()); return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string()); } } status_t err; // Always set to async, as we know the deferred surface is for preview streaming. sp<Surface> consumerSurface = new Surface(bufferProducer, /*useAsync*/true); // Finish the deferred stream configuration with the surface. err = mDevice->setConsumerSurface(streamId, consumerSurface); if (err == OK) { sp<IBinder> binder = IInterface::asBinder(bufferProducer); mStreamMap.add(binder, streamId); mDeferredStreams.removeItemsAt(index); } else if (err == NO_INIT) { res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT, "Camera %d: Deferred surface is invalid: %s (%d)", mCameraId, strerror(-err), err); } else { res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION, "Camera %d: Error setting output stream deferred surface: %s (%d)", mCameraId, strerror(-err), err); } return res; } status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) { return BasicClient::dump(fd, args); } Loading @@ -959,6 +1114,11 @@ status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) { for (size_t i = 0; i < mStreamMap.size(); i++) { result.appendFormat(" Stream %d\n", mStreamMap.valueAt(i)); } } else if (!mDeferredStreams.isEmpty()) { result.append(" Current deferred surface output stream IDs:\n"); for (auto& streamId : mDeferredStreams) { result.appendFormat(" Stream %d\n", streamId); } } else { result.append(" No output streams configured.\n"); } Loading
services/camera/libcameraservice/api2/CameraDeviceClient.h +17 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ public: // Prepare stream by preallocating up to maxCount of its buffers virtual binder::Status prepare2(int32_t maxCount, int32_t streamId); // Set the deferred surface for a stream. virtual binder::Status setDeferredConfiguration(int32_t streamId, const hardware::camera2::params::OutputConfiguration &outputConfiguration); /** * Interface used by CameraService */ Loading Loading @@ -188,6 +192,15 @@ private: // Find the square of the euclidean distance between two points static int64_t euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1); // Create an output stream with surface deferred for future. binder::Status createDeferredSurfaceStreamLocked( const hardware::camera2::params::OutputConfiguration &outputConfiguration, int* newStreamId = NULL); // Set the stream transform flags to automatically rotate the camera stream for preview use // cases. binder::Status setStreamTransformLocked(int streamId); // Find the closest dimensions for a given format in available stream configurations with // a width <= ROUNDING_WIDTH_CAP static const int32_t ROUNDING_WIDTH_CAP = 1920; Loading @@ -213,6 +226,10 @@ private: int32_t mRequestIdCounter; // The list of output streams whose surfaces are deferred. We have to track them separately // as there are no surfaces available and can not be put into mStreamMap. Once the deferred // Surface is configured, the stream id will be moved to mStreamMap. Vector<int32_t> mDeferredStreams; }; }; // namespace android Loading