From bba75576c3bc5a90cd8e14bd053ab2d74a6c7e9d Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Thu, 20 Nov 2014 17:29:50 -0800 Subject: Camera2: Round unsupported surface sizes in configure. Bug: 16030677 Change-Id: Ida04e04f41983b9126609522dd12064a7bf9645f --- .../libcameraservice/api2/CameraDeviceClient.cpp | 76 ++++++++++++++++++++-- .../libcameraservice/api2/CameraDeviceClient.h | 9 +++ 2 files changed, 81 insertions(+), 4 deletions(-) (limited to 'services') diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index e3301aa..e6865bb 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -353,6 +353,14 @@ status_t CameraDeviceClient::createStream(int width, int height, int format, useAsync = true; } + int32_t disallowedFlags = GraphicBuffer::USAGE_HW_VIDEO_ENCODER | + GRALLOC_USAGE_RENDERSCRIPT; + int32_t allowedFlags = GraphicBuffer::USAGE_SW_READ_MASK | + GraphicBuffer::USAGE_HW_TEXTURE | + GraphicBuffer::USAGE_HW_COMPOSER; + bool flexibleConsumer = (consumerUsage & disallowedFlags) == 0 && + (consumerUsage & allowedFlags) != 0; + sp binder; sp anw; if (bufferProducer != 0) { @@ -382,14 +390,18 @@ status_t CameraDeviceClient::createStream(int width, int height, int format, // IMPLEMENTATION_DEFINED. b/9487482 if (format >= HAL_PIXEL_FORMAT_RGBA_8888 && format <= HAL_PIXEL_FORMAT_BGRA_8888) { - ALOGW("%s: Camera %d: Overriding format 0x%x to IMPLEMENTATION_DEFINED", + ALOGW("%s: Camera %d: Overriding format %#x to IMPLEMENTATION_DEFINED", __FUNCTION__, mCameraId, format); format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; } - // TODO: add startConfigure/stopConfigure call to CameraDeviceBase - // this will make it so Camera3Device doesn't call configure_streams - // after each call, but only once we are done with all. + // Round dimensions to the nearest dimensions available for this format + if (flexibleConsumer && !CameraDeviceClient::roundBufferDimensionNearest(width, height, + format, mDevice->info(), /*out*/&width, /*out*/&height)) { + ALOGE("%s: No stream configurations with the format %#x defined, failed to create stream.", + __FUNCTION__, format); + return BAD_VALUE; + } int streamId = -1; res = mDevice->createStream(anw, width, height, format, &streamId); @@ -425,6 +437,62 @@ status_t CameraDeviceClient::createStream(int width, int height, int format, return res; } + +bool CameraDeviceClient::roundBufferDimensionNearest(int32_t width, int32_t height, + int32_t format, const CameraMetadata& info, + /*out*/int32_t* outWidth, /*out*/int32_t* outHeight) { + + camera_metadata_ro_entry streamConfigs = + info.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS); + + int32_t bestWidth = -1; + int32_t bestHeight = -1; + + // Iterate through listed stream configurations and find the one with the smallest euclidean + // distance from the given dimensions for the given format. + for (size_t i = 0; i < streamConfigs.count; i += 4) { + int32_t fmt = streamConfigs.data.i32[i]; + int32_t w = streamConfigs.data.i32[i + 1]; + int32_t h = streamConfigs.data.i32[i + 2]; + + // Ignore input/output type for now + if (fmt == format) { + if (w == width && h == height) { + bestWidth = width; + bestHeight = height; + break; + } else if (w <= ROUNDING_WIDTH_CAP && (bestWidth == -1 || + CameraDeviceClient::euclidDistSquare(w, h, width, height) < + CameraDeviceClient::euclidDistSquare(bestWidth, bestHeight, width, height))) { + bestWidth = w; + bestHeight = h; + } + } + } + + if (bestWidth == -1) { + // Return false if no configurations for this format were listed + return false; + } + + // Set the outputs to the closet width/height + if (outWidth != NULL) { + *outWidth = bestWidth; + } + if (outHeight != NULL) { + *outHeight = bestHeight; + } + + // Return true if at least one configuration for this format was listed + return true; +} + +int64_t CameraDeviceClient::euclidDistSquare(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { + int64_t d0 = x0 - x1; + int64_t d1 = y0 - y1; + return d0 * d0 + d1 * d1; +} + // Create a request object from a template. status_t CameraDeviceClient::createDefaultRequest(int templateId, /*out*/ diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index 9981dfe..84e46b7 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -154,6 +154,15 @@ private: /** Utility members */ bool enforceRequestPermissions(CameraMetadata& metadata); + // 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); + + // 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 = 1080; + static bool roundBufferDimensionNearest(int32_t width, int32_t height, int32_t format, + const CameraMetadata& info, /*out*/int32_t* outWidth, /*out*/int32_t* outHeight); + // IGraphicsBufferProducer binder -> Stream ID KeyedVector, int> mStreamMap; -- cgit v1.1