128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan/*
228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan * Copyright 2017 The Chromium OS Authors. All rights reserved.
328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan * Use of this source code is governed by a BSD-style license that can be
428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan * found in the LICENSE file.
528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan */
628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include "arc/jpeg_compressor.h"
828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <memory>
1028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
1128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <errno.h>
1228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
1328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include "arc/common.h"
1428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
1528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathannamespace arc {
1628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
1728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// The destination manager that can access |result_buffer_| in JpegCompressor.
1828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanstruct destination_mgr {
1928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan public:
2028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  struct jpeg_destination_mgr mgr;
2128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  JpegCompressor* compressor;
2228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan};
2328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
2428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth SwaminathanJpegCompressor::JpegCompressor() {}
2528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
2628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth SwaminathanJpegCompressor::~JpegCompressor() {}
2728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
2828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanbool JpegCompressor::CompressImage(const void* image, int width, int height,
2928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan                                   int quality, const void* app1Buffer,
3028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan                                   unsigned int app1Size) {
3128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  if (width % 8 != 0 || height % 2 != 0) {
3228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    LOGF(ERROR) << "Image size can not be handled: " << width << "x" << height;
3328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    return false;
3428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  }
3528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
3628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  result_buffer_.clear();
3728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  if (!Encode(image, width, height, quality, app1Buffer, app1Size)) {
3828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    return false;
3928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  }
4028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  LOGF(INFO) << "Compressed JPEG: " << (width * height * 12) / 8 << "[" << width
4128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan             << "x" << height << "] -> " << result_buffer_.size() << " bytes";
4228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  return true;
4328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
4428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
4528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanconst void* JpegCompressor::GetCompressedImagePtr() {
4628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  return result_buffer_.data();
4728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
4828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
4928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathansize_t JpegCompressor::GetCompressedImageSize() {
5028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  return result_buffer_.size();
5128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
5228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
5328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanvoid JpegCompressor::InitDestination(j_compress_ptr cinfo) {
5428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
5528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  std::vector<JOCTET>& buffer = dest->compressor->result_buffer_;
5628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  buffer.resize(kBlockSize);
5728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.next_output_byte = &buffer[0];
5828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.free_in_buffer = buffer.size();
5928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
6028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
6128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanboolean JpegCompressor::EmptyOutputBuffer(j_compress_ptr cinfo) {
6228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
6328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  std::vector<JOCTET>& buffer = dest->compressor->result_buffer_;
6428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  size_t oldsize = buffer.size();
6528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  buffer.resize(oldsize + kBlockSize);
6628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.next_output_byte = &buffer[oldsize];
6728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.free_in_buffer = kBlockSize;
6828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  return true;
6928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
7028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
7128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanvoid JpegCompressor::TerminateDestination(j_compress_ptr cinfo) {
7228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  destination_mgr* dest = reinterpret_cast<destination_mgr*>(cinfo->dest);
7328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  std::vector<JOCTET>& buffer = dest->compressor->result_buffer_;
7428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  buffer.resize(buffer.size() - dest->mgr.free_in_buffer);
7528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
7628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
7728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanvoid JpegCompressor::OutputErrorMessage(j_common_ptr cinfo) {
7828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  char buffer[JMSG_LENGTH_MAX];
7928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
8028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  /* Create the message */
8128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  (*cinfo->err->format_message)(cinfo, buffer);
8228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  LOGF(ERROR) << buffer;
8328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
8428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
8528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanbool JpegCompressor::Encode(const void* inYuv, int width, int height,
8628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan                            int jpegQuality, const void* app1Buffer,
8728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan                            unsigned int app1Size) {
8828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_compress_struct cinfo;
8928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_error_mgr jerr;
9028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
9128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo.err = jpeg_std_error(&jerr);
9228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  // Override output_message() to print error log with ALOGE().
9328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo.err->output_message = &OutputErrorMessage;
9428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_create_compress(&cinfo);
9528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  SetJpegDestination(&cinfo);
9628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
9728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  SetJpegCompressStruct(width, height, jpegQuality, &cinfo);
9828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_start_compress(&cinfo, TRUE);
9928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
10028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  if (app1Buffer != nullptr && app1Size > 0) {
10128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    jpeg_write_marker(&cinfo, JPEG_APP0 + 1,
10228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan                      static_cast<const JOCTET*>(app1Buffer), app1Size);
10328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  }
10428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
10528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  if (!Compress(&cinfo, static_cast<const uint8_t*>(inYuv))) {
10628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    return false;
10728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  }
10828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_finish_compress(&cinfo);
10928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  return true;
11028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
11128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
11228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanvoid JpegCompressor::SetJpegDestination(jpeg_compress_struct* cinfo) {
11328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  destination_mgr* dest =
11428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      static_cast<struct destination_mgr*>((*cinfo->mem->alloc_small)(
11528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan          (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(destination_mgr)));
11628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->compressor = this;
11728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.init_destination = &InitDestination;
11828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.empty_output_buffer = &EmptyOutputBuffer;
11928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  dest->mgr.term_destination = &TerminateDestination;
12028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->dest = reinterpret_cast<struct jpeg_destination_mgr*>(dest);
12128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
12228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
12328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanvoid JpegCompressor::SetJpegCompressStruct(int width, int height, int quality,
12428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan                                           jpeg_compress_struct* cinfo) {
12528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->image_width = width;
12628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->image_height = height;
12728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->input_components = 3;
12828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->in_color_space = JCS_YCbCr;
12928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_set_defaults(cinfo);
13028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
13128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_set_quality(cinfo, quality, TRUE);
13228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  jpeg_set_colorspace(cinfo, JCS_YCbCr);
13328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->raw_data_in = TRUE;
13428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->dct_method = JDCT_IFAST;
13528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
13628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  // Configure sampling factors. The sampling factor is JPEG subsampling 420
13728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  // because the source format is YUV420.
13828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->comp_info[0].h_samp_factor = 2;
13928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->comp_info[0].v_samp_factor = 2;
14028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->comp_info[1].h_samp_factor = 1;
14128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->comp_info[1].v_samp_factor = 1;
14228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->comp_info[2].h_samp_factor = 1;
14328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  cinfo->comp_info[2].v_samp_factor = 1;
14428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
14528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
14628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanbool JpegCompressor::Compress(jpeg_compress_struct* cinfo, const uint8_t* yuv) {
14728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  JSAMPROW y[kCompressBatchSize];
14828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  JSAMPROW cb[kCompressBatchSize / 2];
14928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  JSAMPROW cr[kCompressBatchSize / 2];
15028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  JSAMPARRAY planes[3]{y, cb, cr};
15128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
15228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  size_t y_plane_size = cinfo->image_width * cinfo->image_height;
15328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  size_t uv_plane_size = y_plane_size / 4;
15428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  uint8_t* y_plane = const_cast<uint8_t*>(yuv);
15528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  uint8_t* u_plane = const_cast<uint8_t*>(yuv + y_plane_size);
15628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  uint8_t* v_plane = const_cast<uint8_t*>(yuv + y_plane_size + uv_plane_size);
15728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  std::unique_ptr<uint8_t[]> empty(new uint8_t[cinfo->image_width]);
15828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  memset(empty.get(), 0, cinfo->image_width);
15928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
16028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  while (cinfo->next_scanline < cinfo->image_height) {
16128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    for (int i = 0; i < kCompressBatchSize; ++i) {
16228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      size_t scanline = cinfo->next_scanline + i;
16328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      if (scanline < cinfo->image_height) {
16428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan        y[i] = y_plane + scanline * cinfo->image_width;
16528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      } else {
16628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan        y[i] = empty.get();
16728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      }
16828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    }
16928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    // cb, cr only have half scanlines
17028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    for (int i = 0; i < kCompressBatchSize / 2; ++i) {
17128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      size_t scanline = cinfo->next_scanline / 2 + i;
17228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      if (scanline < cinfo->image_height / 2) {
17328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan        int offset = scanline * (cinfo->image_width / 2);
17428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan        cb[i] = u_plane + offset;
17528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan        cr[i] = v_plane + offset;
17628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      } else {
17728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan        cb[i] = cr[i] = empty.get();
17828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      }
17928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    }
18028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
18128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    int processed = jpeg_write_raw_data(cinfo, planes, kCompressBatchSize);
18228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    if (processed != kCompressBatchSize) {
18328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      LOGF(ERROR) << "Number of processed lines does not equal input lines.";
18428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan      return false;
18528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan    }
18628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  }
18728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan  return true;
18828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}
18928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan
19028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}  // namespace arc
191