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

Commit 5c789e42 authored by Jan Sebechlebsky's avatar Jan Sebechlebsky
Browse files

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
parent 4c9bb1eb
Loading
Loading
Loading
Loading
+26 −27
Original line number Diff line number Diff line
@@ -581,8 +581,14 @@ ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoBlobStreamBuffer(
  std::shared_ptr<AHardwareBuffer> inHwBuffer = framebuffer->getHardwareBuffer();
  GraphicBuffer* gBuffer = GraphicBuffer::fromAHardwareBuffer(inHwBuffer.get());

  std::optional<size_t> compressedSize;
  if (gBuffer != nullptr) {
  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.
@@ -600,17 +606,10 @@ ndk::ScopedAStatus VirtualCameraRenderThread::renderIntoBlobStreamBuffer(
      createExif(Resolution(stream->width, stream->height),
                 createThumbnail(requestSettings.thumbnailResolution,
                                 requestSettings.thumbnailJpegQuality));
    compressedSize = compressJpeg(
  std::optional<size_t> 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 (!compressedSize.has_value()) {
    ALOGE("%s: Failed to compress JPEG image", __func__);
+0 −23
Original line number Diff line number Diff line
@@ -153,18 +153,6 @@ class LibJpegContext {
    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 @@ std::optional<size_t> compressJpeg(const int width, const int height,
  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
+0 −16
Original line number Diff line number Diff line
@@ -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 @@ std::optional<size_t> compressJpeg(int width, int height, int quality,
                                   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