/*
 * Copyright 2021 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "common/still_capture_processor_impl.h"

#include <algorithm>
#include <utility>

#include <libyuv/scale.h>
#include <linux/videodev2.h>

#include "cros-camera/camera_metadata_utils.h"
#include "cros-camera/common.h"
#include "cros-camera/exif_utils.h"

namespace cros {

namespace {

constexpr size_t kJpegMarkerSize = 2;
constexpr size_t kJpegLengthSize = 2;
constexpr uint16_t kJpegSOF0 = 0xFFC0;
constexpr uint16_t kJpegSOF2 = 0xFFC2;
constexpr uint16_t kJpegDHT = 0xFFC4;
constexpr uint16_t kJpegRST0 = 0xFFD0;
constexpr uint16_t kJpegRST1 = 0xFFD1;
constexpr uint16_t kJpegRST2 = 0xFFD2;
constexpr uint16_t kJpegRST3 = 0xFFD3;
constexpr uint16_t kJpegRST4 = 0xFFD4;
constexpr uint16_t kJpegRST5 = 0xFFD5;
constexpr uint16_t kJpegRST6 = 0xFFD6;
constexpr uint16_t kJpegRST7 = 0xFFD7;
constexpr uint16_t kJpegSOF = 0xFFD8;
constexpr uint16_t kJpegEOI = 0xFFD9;
constexpr uint16_t kJpegSOS = 0xFFDA;
constexpr uint16_t kJpegDQT = 0xFFDB;
constexpr uint16_t kJpegDRI = 0xFFDD;
constexpr uint16_t kJpegAPP0 = 0xFFE0;
constexpr uint16_t kJpegAPP1 = 0xFFE1;
constexpr uint16_t kJpegAPP2 = 0xFFE2;
constexpr uint16_t kJpegAPP3 = 0xFFE3;
constexpr uint16_t kJpegAPP4 = 0xFFE4;
constexpr uint16_t kJpegAPP5 = 0xFFE5;
constexpr uint16_t kJpegAPP6 = 0xFFE6;
constexpr uint16_t kJpegAPP7 = 0xFFE7;
constexpr uint16_t kJpegAPP8 = 0xFFE8;
constexpr uint16_t kJpegAPP9 = 0xFFE9;
constexpr uint16_t kJpegAPP10 = 0xFFEA;
constexpr uint16_t kJpegAPP11 = 0xFFEB;
constexpr uint16_t kJpegAPP12 = 0xFFEC;
constexpr uint16_t kJpegAPP13 = 0xFFED;
constexpr uint16_t kJpegAPP14 = 0xFFEE;
constexpr uint16_t kJpegAPP15 = 0xFFEF;
constexpr uint16_t kJpegCOM = 0xFFFE;

void InsertJpegBlobDescriptor(buffer_handle_t jpeg_blob,
                              uint32_t jpeg_data_size) {
  ScopedMapping mapping(jpeg_blob);
  size_t buffer_size = CameraBufferManager::GetPlaneSize(jpeg_blob, 0);
  camera3_jpeg_blob_t* blob = reinterpret_cast<camera3_jpeg_blob_t*>(
      static_cast<uint8_t*>(mapping.plane(0).addr) + buffer_size -
      sizeof(camera3_jpeg_blob_t));
  blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
  blob->jpeg_size = jpeg_data_size;
}

bool ParseAppSections(base::span<uint8_t> blob,
                      std::vector<uint8_t>* out_buffer,
                      std::map<uint16_t, base::span<uint8_t>>* out_index) {
  if (blob.empty())
    return false;
  out_buffer->resize(blob.size());
  uint8_t* src_addr = blob.data();
  const uint8_t* src_end = blob.data() + blob.size();
  size_t dst_offset = 0;
  while (src_addr < src_end) {
    auto parse_word = [](uint8_t* addr) -> uint16_t {
      return (*addr << 8) + *(addr + 1);
    };

    if (src_addr + 2 > src_end) {
      LOGF(ERROR) << "Incomplete marker";
      return false;
    }
    uint16_t marker = parse_word(src_addr);
    VLOGF(2) << "Marker: " << std::hex << marker;
    switch (marker) {
      case kJpegSOF:
      case kJpegRST0:
      case kJpegRST1:
      case kJpegRST2:
      case kJpegRST3:
      case kJpegRST4:
      case kJpegRST5:
      case kJpegRST6:
      case kJpegRST7:
      case kJpegEOI:
        // Skip the marker as there's no payload.
        src_addr += kJpegMarkerSize;
        break;

      case kJpegSOF0:
      case kJpegSOF2:
      case kJpegDHT:
      case kJpegDQT:
      case kJpegDRI:
      case kJpegSOS:
        // Skip the marker and the payload.
        if (src_addr + kJpegMarkerSize + kJpegLengthSize > src_end) {
          LOGF(ERROR) << "Invalid JPEG header";
          return false;
        }
        src_addr += (kJpegMarkerSize + parse_word(src_addr + kJpegMarkerSize));
        break;

      case kJpegAPP0:
      case kJpegAPP1:
      case kJpegAPP2:
      case kJpegAPP3:
      case kJpegAPP4:
      case kJpegAPP5:
      case kJpegAPP6:
      case kJpegAPP7:
      case kJpegAPP8:
      case kJpegAPP9:
      case kJpegAPP10:
      case kJpegAPP11:
      case kJpegAPP12:
      case kJpegAPP13:
      case kJpegAPP14:
      case kJpegAPP15:
      case kJpegCOM: {
        // Copy out the APPn/COM marker and payload.
        if (src_addr + kJpegMarkerSize + kJpegLengthSize > src_end) {
          LOGF(ERROR) << "Invalid JPEG header";
          return false;
        }
        size_t segment_size =
            kJpegMarkerSize + parse_word(src_addr + kJpegMarkerSize);
        if (src_addr + segment_size > src_end) {
          LOGF(ERROR) << "Invalid JPEG header";
          return false;
        }
        std::copy(src_addr, src_addr + segment_size,
                  out_buffer->data() + dst_offset);
        if (out_index->count(marker)) {
          LOGF(ERROR) << "Found duplicated JPEG marker: 0x" << std::hex
                      << marker;
        }
        out_index->insert(
            {marker, {out_buffer->data() + dst_offset, segment_size}});
        dst_offset += segment_size;
        src_addr += segment_size;
        break;
      }

      default:
        LOGF(ERROR) << "Invalid JPEG marker: 0x" << std::hex << marker;
        return false;
    }

    // Assuming that the APPn markers always appear before SOS.
    if (marker == kJpegSOS || marker == kJpegEOI) {
      break;
    }
  }

  out_buffer->resize(dst_offset);
  return true;
}

bool ExtractAppSections(buffer_handle_t blob_buffer,
                        std::vector<uint8_t>* out_buffer,
                        std::map<uint16_t, base::span<uint8_t>>* out_index) {
  ScopedMapping mapping(blob_buffer);
  return ParseAppSections(
      base::make_span(mapping.plane(0).addr, mapping.plane(0).size), out_buffer,
      out_index);
}

// Compupte the cropped region of size (|out_width|, |out_height|) out of the
// src region (|src_width|, |src_height|) such that (|out_width|, |out_height|)
// has the same aspect ratio as (|dst_width|, |dst_height|). The out region can
// be obtained by reading out the |src_width| x |src_height| region from the
// starting coordinate (|out_start_x|, |out_start_y|).
void GetCropSizeAndXySkips(int src_width,
                           int src_height,
                           int dst_width,
                           int dst_height,
                           int* out_width,
                           int* out_height,
                           int* out_start_x,
                           int* out_start_y) {
  CHECK_GE(src_width, dst_width);
  CHECK_GE(src_height, dst_height);
  if (src_width * dst_height == src_height * dst_width) {
    *out_width = src_width;
    *out_height = src_height;
    *out_start_x = 0;
    *out_start_y = 0;
  } else if (static_cast<float>(src_width) / src_height >
             static_cast<float>(dst_width) / dst_height) {
    // Crop left and right of the src.
    *out_width = dst_width * src_height / dst_height;
    *out_height = src_height;  // dst_height * src_height / dst_height
    *out_start_x = (src_width - *out_width) / 2;
    *out_start_y = 0;
  } else {
    // Crop top and bottom of the src.
    *out_width = src_width;  // dst_width * src_width / dst_width
    *out_height = dst_height * src_width / dst_width;
    *out_start_x = 0;
    *out_start_y = (src_height - *out_height) / 2;
  }
}

inline uint8_t HighByte(uint16_t value) {
  return (value >> 8) & 0xFF;
}

inline uint8_t LowByte(uint16_t value) {
  return value & 0xFF;
}

inline uint8_t* WriteTwoBytes(uint8_t* dst, uint16_t value) {
  dst[0] = HighByte(value);
  dst[1] = LowByte(value);
  return dst + 2;
}

}  // namespace

StillCaptureProcessorImpl::StillCaptureProcessorImpl(
    std::unique_ptr<JpegCompressor> jpeg_compressor)
    : thread_("StillCaptureProcessorImplThread"),
      jpeg_compressor_(std::move(jpeg_compressor)) {}

StillCaptureProcessorImpl::~StillCaptureProcessorImpl() {
  Reset();
}

void StillCaptureProcessorImpl::Initialize(
    const camera3_stream_t* const still_capture_stream,
    CaptureResultCallback result_callback) {
  blob_stream_ = still_capture_stream;
  result_callback_ = std::move(result_callback);
  request_contexts_.clear();
  CHECK(thread_.Start());
}

void StillCaptureProcessorImpl::Reset() {
  thread_.Stop();
  blob_stream_ = nullptr;
  result_callback_ = base::NullCallback();
  request_contexts_.clear();
}

void StillCaptureProcessorImpl::QueuePendingOutputBuffer(
    int frame_number,
    camera3_stream_buffer_t output_buffer,
    const camera_metadata_t* request_settings) {
  auto buf_mgr = CameraBufferManager::GetInstance();
  RequestContext req = {
      .jpeg_blob = buf_mgr->AllocateScopedBuffer(
          CameraBufferManager::GetPlaneSize(*output_buffer.buffer, 0), 1,
          HAL_PIXEL_FORMAT_BLOB, output_buffer.stream->usage),
      .client_requested_buffer = output_buffer,
  };
  if (!req.jpeg_blob) {
    LOGF(ERROR) << "Cannot allocated JPEG buffer";
    return;
  }
  base::span<const int32_t> thumbnail_size = GetRoMetadataAsSpan<int32_t>(
      request_settings, ANDROID_JPEG_THUMBNAIL_SIZE);
  if (thumbnail_size.size() == 2) {
    req.thumbnail_size = {static_cast<uint32_t>(thumbnail_size[0]),
                          static_cast<uint32_t>(thumbnail_size[1])};
  }
  base::Optional<uint8_t> thumbnail_quality =
      GetRoMetadata<uint8_t>(request_settings, ANDROID_JPEG_THUMBNAIL_QUALITY);
  if (thumbnail_quality) {
    req.thumbnail_quality = *thumbnail_quality;
  }
  base::Optional<uint8_t> jpeg_quality =
      GetRoMetadata<uint8_t>(request_settings, ANDROID_JPEG_QUALITY);
  if (jpeg_quality) {
    req.jpeg_quality = *jpeg_quality;
  }

  VLOGFID(1, frame_number) << "Output buffer queued. thumbnail_size = "
                           << req.thumbnail_size.ToString()
                           << " thumbnail_quality=" << req.thumbnail_quality
                           << " jpeg_quality=" << req.jpeg_quality;
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          &StillCaptureProcessorImpl::QueuePendingOutputBufferOnThread,
          base::Unretained(this), frame_number, std::move(req)));
}

void StillCaptureProcessorImpl::QueuePendingAppsSegments(
    int frame_number, buffer_handle_t blob_buffer) {
  VLOGFID(1, frame_number) << "APPs segments queued";

  std::vector<uint8_t> apps_segments_buffer;
  std::map<uint16_t, base::span<uint8_t>> apps_segments_index;
  // We can't assume anything on the life-time of |blob_buffer|, so we need to
  // copy the data out from the buffer.
  if (!ExtractAppSections(blob_buffer, &apps_segments_buffer,
                          &apps_segments_index)) {
    LOGF(ERROR) << "Cannot extract JPEG APPs segments";
    apps_segments_buffer.clear();
    apps_segments_index.clear();
  }
  // We can still produce the JPEG image without the metadata.
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          &StillCaptureProcessorImpl::QueuePendingAppsSegmentsOnThread,
          base::Unretained(this), frame_number, std::move(apps_segments_buffer),
          std::move(apps_segments_index)));
}

void StillCaptureProcessorImpl::QueuePendingYuvImage(
    int frame_number, buffer_handle_t yuv_buffer) {
  VLOGFID(1, frame_number) << "YUV image queued";
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&StillCaptureProcessorImpl::QueuePendingYuvImageOnThread,
                     base::Unretained(this), frame_number, yuv_buffer));
}

void StillCaptureProcessorImpl::QueuePendingOutputBufferOnThread(
    int frame_number, RequestContext request_context) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());

  request_contexts_.insert({frame_number, std::move(request_context)});
}

void StillCaptureProcessorImpl::QueuePendingAppsSegmentsOnThread(
    int frame_number,
    std::vector<uint8_t> apps_segments_buffer,
    std::map<uint16_t, base::span<uint8_t>> apps_segments_index) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());

  if (request_contexts_.count(frame_number) == 0) {
    LOGF(ERROR) << "No output buffer queued";
    return;
  }

  RequestContext& context = request_contexts_[frame_number];
  context.apps_segments_buffer = std::move(apps_segments_buffer);
  context.apps_segments_index = std::move(apps_segments_index);
  context.has_apps_segments = true;

  MaybeProduceCaptureResultOnThread(frame_number);
}

void StillCaptureProcessorImpl::QueuePendingYuvImageOnThread(
    int frame_number, buffer_handle_t yuv_buffer) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());

  if (request_contexts_.count(frame_number) == 0) {
    LOGF(ERROR) << "No output buffer queued";
    return;
  }

  RequestContext& context = request_contexts_[frame_number];
  if (!jpeg_compressor_->CompressImageFromHandle(
          yuv_buffer, *context.jpeg_blob, blob_stream_->width,
          blob_stream_->height, context.jpeg_quality, nullptr, 0,
          &context.jpeg_blob_size, /*enable_hw_encode=*/false)) {
    LOGF(ERROR) << "Cannot encode YUV image to JPEG";
    // TODO(jcliang): Notify buffer error here.
    return;
  }
  context.has_jpeg = true;
  if (context.thumbnail_size.area() > 0) {
    // Scale down the YUV image and produce JPEG thumbnail.
    ScopedMapping mapping(yuv_buffer);
    std::vector<uint8_t> scaled_nv12(context.thumbnail_size.area() * 3 / 2);
    // If the thumbnail image aspect ratio is different from the primary JPEG
    // image, we need to crop the main image first before scaling.
    int src_width, src_height, src_x_start, src_y_start;
    GetCropSizeAndXySkips(mapping.width(), mapping.height(),
                          context.thumbnail_size.width,
                          context.thumbnail_size.height, &src_width,
                          &src_height, &src_x_start, &src_y_start);
    int y_plane_start = src_x_start + src_y_start * mapping.plane(0).stride;
    // UV plane has 2:1 subsampling with 2 bytes per pixel.
    int uv_plane_start =
        (src_x_start / 2) * 2 + (src_y_start / 2) * mapping.plane(1).stride;
    uint8_t* dst_y = scaled_nv12.data();
    int dst_stride_y = context.thumbnail_size.width;
    uint8_t* dst_uv = scaled_nv12.data() + context.thumbnail_size.area();
    int dst_stride_uv = context.thumbnail_size.width / 2 * 2;
    if (libyuv::NV12Scale(
            mapping.plane(0).addr + y_plane_start, mapping.plane(0).stride,
            mapping.plane(1).addr + uv_plane_start, mapping.plane(1).stride,
            src_width, src_height, dst_y, dst_stride_y, dst_uv, dst_stride_uv,
            context.thumbnail_size.width, context.thumbnail_size.height,
            libyuv::kFilterBilinear)) {
      LOGF(ERROR) << "Cannot downscale YUV image to produce thumbnail";
    }

    // This leaves 15533 bytes of space for other metadata in APP1 segment.
    constexpr int kThumbnailSizeLimit = 50000;
    uint32_t thumbnail_data_size = 0;
    int thumbnail_quality = context.thumbnail_quality;
    context.thumbnail_buffer.resize(context.thumbnail_size.area() * 2);
    do {
      auto ret = jpeg_compressor_->CompressImageFromMemory(
          scaled_nv12.data(), V4L2_PIX_FMT_NV12,
          context.thumbnail_buffer.data(), context.thumbnail_buffer.size(),
          context.thumbnail_size.width, context.thumbnail_size.height,
          thumbnail_quality, nullptr, 0, &thumbnail_data_size);
      if (!ret) {
        LOGF(ERROR) << "Cannot produce JPEG thumbnail image";
        thumbnail_data_size = 0;
        break;
      }
      thumbnail_quality -= 10;
    } while (thumbnail_data_size > kThumbnailSizeLimit &&
             thumbnail_quality > 0);
    context.thumbnail_buffer.resize(thumbnail_data_size);
    VLOGFID(1, frame_number)
        << "Produced thumbnail with size=" << context.thumbnail_size.ToString()
        << " data_length=" << thumbnail_data_size;
  }

  MaybeProduceCaptureResultOnThread(frame_number);
}

void StillCaptureProcessorImpl::MaybeProduceCaptureResultOnThread(
    int frame_number) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
  DCHECK_EQ(request_contexts_.count(frame_number), 1);

  RequestContext& context = request_contexts_.at(frame_number);
  if (!(context.has_apps_segments && context.has_jpeg)) {
    return;
  }

  {
    ScopedMapping result_mapping(*context.client_requested_buffer.buffer);
    uint8_t* dst_start = result_mapping.plane(0).addr;
    uint8_t* dst_addr = dst_start;

    // Write the SOF marker.
    dst_addr = WriteTwoBytes(dst_addr, kJpegSOF);

    // Copy the APPn segments from vendor camera HAL.
    for (auto it = context.apps_segments_index.begin();
         it != context.apps_segments_index.end(); ++it) {
      switch (it->first) {
        case kJpegAPP0:
          // Skip APP0 as we're going to use the one produced by the encoder
          // below.
          break;

        case kJpegAPP1: {
          if (context.thumbnail_size.area() > 0 &&
              context.thumbnail_buffer.size() > 0) {
            VLOGFID(1, frame_number) << "Write JPEG segment 0x" << std::hex
                                     << it->first << " with thumbnail";
            // Thumbnail requested and available, so replace the thumbnail.
            ExifUtils exif_utils;
            if (!exif_utils.InitializeWithData(it->second)) {
              LOGF(ERROR) << "Cannot load APPs segments";
              break;
            }
            if (!exif_utils.GenerateApp1(context.thumbnail_buffer.data(),
                                         context.thumbnail_buffer.size())) {
              LOGF(ERROR) << "Cannot generate APP1 segment with thumbnail";
              break;
            }

            // Write the APP1 marker.
            dst_addr = WriteTwoBytes(dst_addr, kJpegAPP1);

            // Write the segment size of the APP1 segment.
            const uint8_t* app1_buffer = exif_utils.GetApp1Buffer();
            size_t app1_size = exif_utils.GetApp1Length();
            size_t segment_size = app1_size + kJpegLengthSize;
            dst_addr = WriteTwoBytes(dst_addr, segment_size);

            // Copy the APP1 segment with the thumbnail.
            std::copy(app1_buffer, app1_buffer + app1_size, dst_addr);
            dst_addr += app1_size;
            break;
          }
          FALLTHROUGH;
        }

        default:
          VLOGFID(1, frame_number)
              << "Write JPEG segment 0x" << std::hex << it->first;
          std::copy(it->second.begin(), it->second.end(), dst_addr);
          dst_addr += it->second.size();
      }
    }

    // Copy the JPEG image. Skip the SOI in the buffer.
    ScopedMapping jpeg_mapping(*context.jpeg_blob);
    std::copy(jpeg_mapping.plane(0).addr + kJpegMarkerSize,
              jpeg_mapping.plane(0).addr + context.jpeg_blob_size, dst_addr);
    dst_addr += (context.jpeg_blob_size - kJpegMarkerSize);

    InsertJpegBlobDescriptor(*context.client_requested_buffer.buffer,
                             (dst_addr - dst_start));
  }

  VLOGFID(1, frame_number) << "Return BLOB buffer to client";
  Camera3CaptureDescriptor blob_result(camera3_capture_result_t{
      .frame_number = static_cast<uint32_t>(frame_number),
      .num_output_buffers = 1,
      .output_buffers = &context.client_requested_buffer,
      .partial_result = 0,
  });
  result_callback_.Run(std::move(blob_result));
  request_contexts_.erase(frame_number);
}

bool ParseAppSectionsForTesting(
    base::span<uint8_t> blob,
    std::vector<uint8_t>* out_buffer,
    std::map<uint16_t, base::span<uint8_t>>* out_index) {
  return ParseAppSections(blob, out_buffer, out_index);
}

}  // namespace cros
