Fail if there's problem with tmp buffer during JPEG capture
... instead of producing black image.
Bug: 301023410
Test: atest virtual_camera_tests
Test: atest VirtualCameraTest
Change-Id: Iffc56d59799f2b5f877926e7ad21354aeb3e2e1c
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index 8bd8c9b..9b0fc07 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -581,37 +581,36 @@
std::shared_ptr<AHardwareBuffer> inHwBuffer = framebuffer->getHardwareBuffer();
GraphicBuffer* gBuffer = GraphicBuffer::fromAHardwareBuffer(inHwBuffer.get());
- std::optional<size_t> compressedSize;
- if (gBuffer != nullptr) {
- if (gBuffer->getPixelFormat() != HAL_PIXEL_FORMAT_YCbCr_420_888) {
- // This should never happen since we're allocating the temporary buffer
- // with YUV420 layout above.
- ALOGE("%s: Cannot compress non-YUV buffer (pixelFormat %d)", __func__,
- gBuffer->getPixelFormat());
- return cameraStatus(Status::INTERNAL_ERROR);
- }
-
- YCbCrLockGuard yCbCrLock(inHwBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN);
- if (yCbCrLock.getStatus() != OK) {
- return cameraStatus(Status::INTERNAL_ERROR);
- }
-
- std::vector<uint8_t> app1ExifData =
- createExif(Resolution(stream->width, stream->height),
- createThumbnail(requestSettings.thumbnailResolution,
- requestSettings.thumbnailJpegQuality));
- compressedSize = compressJpeg(
- gBuffer->getWidth(), gBuffer->getHeight(), requestSettings.jpegQuality,
- *yCbCrLock, app1ExifData, stream->bufferSize - sizeof(CameraBlob),
- (*planesLock).planes[0].data);
- } else {
- std::vector<uint8_t> app1ExifData =
- createExif(Resolution(stream->width, stream->height));
- compressedSize = compressBlackJpeg(
- stream->width, stream->height, requestSettings.jpegQuality, app1ExifData,
- stream->bufferSize - sizeof(CameraBlob), (*planesLock).planes[0].data);
+ if (gBuffer == nullptr) {
+ ALOGE(
+ "%s: Encountered invalid temporary buffer while rendering JPEG "
+ "into BLOB stream",
+ __func__);
+ return cameraStatus(Status::INTERNAL_ERROR);
}
+ if (gBuffer->getPixelFormat() != HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ // This should never happen since we're allocating the temporary buffer
+ // with YUV420 layout above.
+ ALOGE("%s: Cannot compress non-YUV buffer (pixelFormat %d)", __func__,
+ gBuffer->getPixelFormat());
+ return cameraStatus(Status::INTERNAL_ERROR);
+ }
+
+ YCbCrLockGuard yCbCrLock(inHwBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN);
+ if (yCbCrLock.getStatus() != OK) {
+ return cameraStatus(Status::INTERNAL_ERROR);
+ }
+
+ std::vector<uint8_t> app1ExifData =
+ createExif(Resolution(stream->width, stream->height),
+ createThumbnail(requestSettings.thumbnailResolution,
+ requestSettings.thumbnailJpegQuality));
+ std::optional<size_t> compressedSize = compressJpeg(
+ gBuffer->getWidth(), gBuffer->getHeight(), requestSettings.jpegQuality,
+ *yCbCrLock, app1ExifData, stream->bufferSize - sizeof(CameraBlob),
+ (*planesLock).planes[0].data);
+
if (!compressedSize.has_value()) {
ALOGE("%s: Failed to compress JPEG image", __func__);
return cameraStatus(Status::INTERNAL_ERROR);
diff --git a/services/camera/virtualcamera/util/JpegUtil.cc b/services/camera/virtualcamera/util/JpegUtil.cc
index 98f2448..8569eff 100644
--- a/services/camera/virtualcamera/util/JpegUtil.cc
+++ b/services/camera/virtualcamera/util/JpegUtil.cc
@@ -153,18 +153,6 @@
return compress(yLines, cbLines, crLines);
}
- std::optional<size_t> compressBlackImage() {
- // We only really need to prepare one scanline for Y and one shared scanline
- // for Cb & Cr.
- std::vector<uint8_t> yLine(mWidth, 0);
- std::vector<uint8_t> chromaLine(mWidth / 2, 0xff / 2);
-
- std::vector<JSAMPROW> yLines(mHeight, yLine.data());
- std::vector<JSAMPROW> cLines(mHeight / 2, chromaLine.data());
-
- return compress(yLines, cLines, cLines);
- }
-
private:
void setSuccess(const boolean success) {
mSuccess = success;
@@ -279,17 +267,6 @@
return context.compress(ycbcr);
}
-std::optional<size_t> compressBlackJpeg(const int width, const int height,
- const int quality,
- const std::vector<uint8_t>& app1ExifData,
- size_t outBufferSize, void* outBuffer) {
- LibJpegContext context(width, height, quality, outBufferSize, outBuffer);
- if (!app1ExifData.empty()) {
- context.setApp1Data(app1ExifData.data(), app1ExifData.size());
- }
- return context.compressBlackImage();
-}
-
} // namespace virtualcamera
} // namespace companion
} // namespace android
diff --git a/services/camera/virtualcamera/util/JpegUtil.h b/services/camera/virtualcamera/util/JpegUtil.h
index e64fb4f..83ed74b 100644
--- a/services/camera/virtualcamera/util/JpegUtil.h
+++ b/services/camera/virtualcamera/util/JpegUtil.h
@@ -17,10 +17,8 @@
#ifndef ANDROID_COMPANION_VIRTUALCAMERA_JPEGUTIL_H
#define ANDROID_COMPANION_VIRTUALCAMERA_JPEGUTIL_H
-#include <memory>
#include <optional>
-#include "android/hardware_buffer.h"
#include "system/graphics.h"
namespace android {
@@ -43,20 +41,6 @@
const std::vector<uint8_t>& app1ExifData,
size_t outBufferSize, void* outBuffer);
-// Jpeg-compress all-black image into the output buffer.
-// * width - width of the image
-// * heigh - height of the image
-// * quality - 0-100, higher number corresponds to higher quality.
-// * app1ExifData - vector containing data to be included in APP1
-// segment. Can be empty.
-// * outBufferSize - capacity of the output buffer.
-// * outBuffer - output buffer to write compressed data into.
-// Returns size of compressed data if the compression was successful,
-// empty optional otherwise.
-std::optional<size_t> compressBlackJpeg(int width, int height, int quality,
- const std::vector<uint8_t>& app1ExifData,
- size_t outBufferSize, void* outBuffer);
-
} // namespace virtualcamera
} // namespace companion
} // namespace android