/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "EmulatedCamera2_JpegCompressor"

#include <utils/Log.h>

#include "../EmulatedFakeCamera2.h"
#include "../EmulatedFakeCamera3.h"
#include "JpegCompressor.h"

namespace android {

JpegCompressor::JpegCompressor()
    : Thread(false),
      mIsBusy(false),
      mSynchronous(false),
      mBuffers(NULL),
      mListener(NULL),
      mFoundAux(false) {}

JpegCompressor::~JpegCompressor() { Mutex::Autolock lock(mMutex); }

status_t JpegCompressor::reserve() {
  Mutex::Autolock busyLock(mBusyMutex);
  if (mIsBusy) {
    ALOGE("%s: Already processing a buffer!", __FUNCTION__);
    return INVALID_OPERATION;
  }
  mIsBusy = true;
  return OK;
}

status_t JpegCompressor::start(Buffers *buffers, JpegListener *listener) {
  if (listener == NULL) {
    ALOGE("%s: NULL listener not allowed!", __FUNCTION__);
    return BAD_VALUE;
  }
  ALOGV("%s: Starting JPEG compression thread", __FUNCTION__);
  Mutex::Autolock lock(mMutex);
  {
    Mutex::Autolock busyLock(mBusyMutex);

    if (!mIsBusy) {
      ALOGE("Called start without reserve() first!");
      return INVALID_OPERATION;
    }
    mSynchronous = false;
    mBuffers = buffers;
    mListener = listener;
  }

  status_t res;
  res = run("EmulatedFakeCamera2::JpegCompressor");
  if (res != OK) {
    ALOGE("%s: Unable to start up compression thread: %s (%d)", __FUNCTION__,
          strerror(-res), res);
    delete mBuffers;
  }
  return res;
}

status_t JpegCompressor::compressSynchronous(Buffers *buffers) {
  status_t res;

  Mutex::Autolock lock(mMutex);
  {
    Mutex::Autolock busyLock(mBusyMutex);

    if (mIsBusy) {
      ALOGE("%s: Already processing a buffer!", __FUNCTION__);
      return INVALID_OPERATION;
    }

    mIsBusy = true;
    mSynchronous = true;
    mBuffers = buffers;
  }

  res = compress();

  cleanUp();

  return res;
}

status_t JpegCompressor::cancel() {
  requestExitAndWait();
  return OK;
}

status_t JpegCompressor::readyToRun() { return OK; }

bool JpegCompressor::threadLoop() {
  status_t res;
  ALOGV("%s: Starting compression thread", __FUNCTION__);

  res = compress();

  mListener->onJpegDone(mJpegBuffer, res == OK);

  cleanUp();

  return false;
}

status_t JpegCompressor::compress() {
  // Find source and target buffers. Assumes only one buffer matches
  // each condition!
  ALOGV("%s: Compressing start", __FUNCTION__);
  for (size_t i = 0; i < mBuffers->size(); i++) {
    const StreamBuffer &b = (*mBuffers)[i];
    if (b.format == HAL_PIXEL_FORMAT_BLOB) {
      mJpegBuffer = b;
      mFoundJpeg = true;
    } else if (b.streamId <= 0) {
      mAuxBuffer = b;
      mFoundAux = true;
    }
    if (mFoundJpeg && mFoundAux) break;
  }
  if (!mFoundJpeg || !mFoundAux) {
    ALOGE("%s: Unable to find buffers for JPEG source/destination",
          __FUNCTION__);
    return BAD_VALUE;
  }

  // Set up error management

  mJpegErrorInfo = NULL;
  JpegError error;
  error.parent = this;

  mCInfo.err = jpeg_std_error(&error);
  mCInfo.err->error_exit = jpegErrorHandler;

  jpeg_create_compress(&mCInfo);
  if (checkError("Error initializing compression")) return NO_INIT;

  // Route compressed data straight to output stream buffer

  JpegDestination jpegDestMgr;
  jpegDestMgr.parent = this;
  jpegDestMgr.init_destination = jpegInitDestination;
  jpegDestMgr.empty_output_buffer = jpegEmptyOutputBuffer;
  jpegDestMgr.term_destination = jpegTermDestination;

  mCInfo.dest = &jpegDestMgr;

  // Set up compression parameters

  mCInfo.image_width = mAuxBuffer.width;
  mCInfo.image_height = mAuxBuffer.height;
  mCInfo.input_components = 3;
  mCInfo.in_color_space = JCS_RGB;

  jpeg_set_defaults(&mCInfo);
  if (checkError("Error configuring defaults")) return NO_INIT;

  // Do compression

  jpeg_start_compress(&mCInfo, TRUE);
  if (checkError("Error starting compression")) return NO_INIT;

  size_t rowStride = mAuxBuffer.stride * 3;
  const size_t kChunkSize = 32;
  while (mCInfo.next_scanline < mCInfo.image_height) {
    JSAMPROW chunk[kChunkSize];
    for (size_t i = 0; i < kChunkSize; i++) {
      chunk[i] =
          (JSAMPROW)(mAuxBuffer.img + (i + mCInfo.next_scanline) * rowStride);
    }
    jpeg_write_scanlines(&mCInfo, chunk, kChunkSize);
    if (checkError("Error while compressing")) return NO_INIT;
    if (exitPending()) {
      ALOGV("%s: Cancel called, exiting early", __FUNCTION__);
      return TIMED_OUT;
    }
  }

  jpeg_finish_compress(&mCInfo);
  if (checkError("Error while finishing compression")) return NO_INIT;

  // All done
  ALOGV("%s: Compressing done", __FUNCTION__);

  return OK;
}

bool JpegCompressor::isBusy() {
  Mutex::Autolock busyLock(mBusyMutex);
  return mIsBusy;
}

bool JpegCompressor::isStreamInUse(uint32_t id) {
  Mutex::Autolock lock(mBusyMutex);

  if (mBuffers && mIsBusy) {
    for (size_t i = 0; i < mBuffers->size(); i++) {
      if ((*mBuffers)[i].streamId == (int)id) return true;
    }
  }
  return false;
}

bool JpegCompressor::waitForDone(nsecs_t timeout) {
  Mutex::Autolock lock(mBusyMutex);
  while (mIsBusy) {
    status_t res = mDone.waitRelative(mBusyMutex, timeout);
    if (res != OK) return false;
  }
  return true;
}

bool JpegCompressor::checkError(const char *msg) {
  if (mJpegErrorInfo) {
    char errBuffer[JMSG_LENGTH_MAX];
    mJpegErrorInfo->err->format_message(mJpegErrorInfo, errBuffer);
    ALOGE("%s: %s: %s", __FUNCTION__, msg, errBuffer);
    mJpegErrorInfo = NULL;
    return true;
  }
  return false;
}

void JpegCompressor::cleanUp() {
  jpeg_destroy_compress(&mCInfo);
  Mutex::Autolock lock(mBusyMutex);

  if (mFoundAux) {
    if (mAuxBuffer.streamId == 0) {
      delete[] mAuxBuffer.img;
    } else if (!mSynchronous) {
      mListener->onJpegInputDone(mAuxBuffer);
    }
  }
  if (!mSynchronous) {
    delete mBuffers;
  }

  mBuffers = NULL;

  mIsBusy = false;
  mDone.signal();
}

void JpegCompressor::jpegErrorHandler(j_common_ptr cinfo) {
  JpegError *error = static_cast<JpegError *>(cinfo->err);
  error->parent->mJpegErrorInfo = cinfo;
}

void JpegCompressor::jpegInitDestination(j_compress_ptr cinfo) {
  JpegDestination *dest = static_cast<JpegDestination *>(cinfo->dest);
  ALOGV("%s: Setting destination to %p, size %zu", __FUNCTION__,
        dest->parent->mJpegBuffer.img, kMaxJpegSize);
  dest->next_output_byte = (JOCTET *)(dest->parent->mJpegBuffer.img);
  dest->free_in_buffer = kMaxJpegSize;
}

boolean JpegCompressor::jpegEmptyOutputBuffer(j_compress_ptr /*cinfo*/) {
  ALOGE("%s: JPEG destination buffer overflow!", __FUNCTION__);
  return true;
}

void JpegCompressor::jpegTermDestination(j_compress_ptr cinfo) {
  ALOGV("%s: Done writing JPEG data. %zu bytes left in buffer", __FUNCTION__,
        cinfo->dest->free_in_buffer);
}

JpegCompressor::JpegListener::~JpegListener() {}

}  // namespace android
