/*
 * 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 "gralloc_cb.h"
#include "JpegCompressor.h"
#include "../EmulatedFakeCamera2.h"
#include "../EmulatedFakeCamera3.h"
#include "../Exif.h"
#include "../Thumbnail.h"
#include "hardware/camera3.h"

namespace android {

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

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, CameraMetadata* settings) {
    if (listener == NULL) {
        ALOGE("%s: NULL listener not allowed!", __FUNCTION__);
        return BAD_VALUE;
    }
    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;
        if (settings) {
              mSettings = *settings;
        }
    }

    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!
    bool foundJpeg = false, mFoundAux = false;
    int thumbWidth = 0, thumbHeight = 0;
    unsigned char thumbJpegQuality = 90;
    unsigned char jpegQuality = 90;
    camera_metadata_entry_t entry;

    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;
    }

    // Create EXIF data and compress thumbnail
    ExifData* exifData = createExifData(mSettings, mAuxBuffer.width, mAuxBuffer.height);
    entry = mSettings.find(ANDROID_JPEG_THUMBNAIL_SIZE);
    if (entry.count > 0) {
        thumbWidth = entry.data.i32[0];
        thumbHeight = entry.data.i32[1];
    }
    entry = mSettings.find(ANDROID_JPEG_THUMBNAIL_QUALITY);
    if (entry.count > 0) {
        thumbJpegQuality = entry.data.u8[0];
    }
    if (thumbWidth > 0 && thumbHeight > 0) {
        createThumbnail(static_cast<const unsigned char*>(mAuxBuffer.img),
                        mAuxBuffer.width, mAuxBuffer.height,
                        thumbWidth, thumbHeight,
                        thumbJpegQuality, exifData);
    }

    // Compress the image
    entry = mSettings.find(ANDROID_JPEG_QUALITY);
    if (entry.count > 0) {
        jpegQuality = entry.data.u8[0];
    }
    NV21JpegCompressor nV21JpegCompressor;
    nV21JpegCompressor.compressRawImage((void*)mAuxBuffer.img,
                                         mAuxBuffer.width,
                                         mAuxBuffer.height,
                                         jpegQuality, exifData);
    nV21JpegCompressor.getCompressedImage((void*)mJpegBuffer.img);

    // Refer to /hardware/libhardware/include/hardware/camera3.h
    // Transport header for compressed JPEG buffers in output streams.
    camera3_jpeg_blob_t jpeg_blob;
    cb_handle_t *cb = (cb_handle_t *)(*mJpegBuffer.buffer);
    jpeg_blob.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
    jpeg_blob.jpeg_size = nV21JpegCompressor.getCompressedSize();
    memcpy(mJpegBuffer.img + cb->width - sizeof(camera3_jpeg_blob_t),
           &jpeg_blob, sizeof(camera3_jpeg_blob_t));

    freeExifData(exifData);
    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;
}

void JpegCompressor::cleanUp() {
    status_t res;
    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();
}

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

} // namespace android
