/*
 * Copyright (C) 2011 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.
 */

/*
 * Contains implementation of a class CallbackNotifier that manages callbacks set
 * via set_callbacks, enable_msg_type, and disable_msg_type camera HAL API.
 */

#define LOG_NDEBUG 0
#define LOG_TAG "EmulatedCamera_CallbackNotifier"
#include <log/log.h>
#include <media/hardware/MetadataBufferType.h>
#include "EmulatedCameraDevice.h"
#undef min
#undef max
#include "CallbackNotifier.h"
#include "Exif.h"
#include "JpegCompressor.h"
#include "Thumbnail.h"

namespace android {

/* String representation of camera messages. */
static const char* lCameraMessages[] =
{
    "CAMERA_MSG_ERROR",
    "CAMERA_MSG_SHUTTER",
    "CAMERA_MSG_FOCUS",
    "CAMERA_MSG_ZOOM",
    "CAMERA_MSG_PREVIEW_FRAME",
    "CAMERA_MSG_VIDEO_FRAME",
    "CAMERA_MSG_POSTVIEW_FRAME",
    "CAMERA_MSG_RAW_IMAGE",
    "CAMERA_MSG_COMPRESSED_IMAGE",
    "CAMERA_MSG_RAW_IMAGE_NOTIFY",
    "CAMERA_MSG_PREVIEW_METADATA"
};
static const int lCameraMessagesNum = sizeof(lCameraMessages) / sizeof(char*);

/* Builds an array of strings for the given set of messages.
 * Param:
 *  msg - Messages to get strings for,
 *  strings - Array where to save strings
 *  max - Maximum number of entries in the array.
 * Return:
 *  Number of strings saved into the 'strings' array.
 */
static int GetMessageStrings(uint32_t msg, const char** strings, int max)
{
    int index = 0;
    int out = 0;
    while (msg != 0 && out < max && index < lCameraMessagesNum) {
        while ((msg & 0x1) == 0 && index < lCameraMessagesNum) {
            msg >>= 1;
            index++;
        }
        if ((msg & 0x1) != 0 && index < lCameraMessagesNum) {
            strings[out] = lCameraMessages[index];
            out++;
            msg >>= 1;
            index++;
        }
    }

    return out;
}

/* Logs messages, enabled by the mask. */
static void PrintMessages(uint32_t msg)
{
    const char* strs[lCameraMessagesNum];
    const int translated = GetMessageStrings(msg, strs, lCameraMessagesNum);
    for (int n = 0; n < translated; n++) {
        ALOGV("    %s", strs[n]);
    }
}

CallbackNotifier::CallbackNotifier()
    : mNotifyCB(NULL),
      mDataCB(NULL),
      mDataCBTimestamp(NULL),
      mGetMemoryCB(NULL),
      mCBOpaque(NULL),
      mLastFrameTimestamp(0),
      mFrameRefreshFreq(0),
      mMessageEnabler(0),
      mJpegQuality(90),
      mVideoRecEnabled(false),
      mTakingPicture(false)
{
}

CallbackNotifier::~CallbackNotifier()
{
}

/****************************************************************************
 * Camera API
 ***************************************************************************/

void CallbackNotifier::setCallbacks(camera_notify_callback notify_cb,
                                    camera_data_callback data_cb,
                                    camera_data_timestamp_callback data_cb_timestamp,
                                    camera_request_memory get_memory,
                                    void* user)
{
    ALOGV("%s: %p, %p, %p, %p (%p)",
         __FUNCTION__, notify_cb, data_cb, data_cb_timestamp, get_memory, user);

    Mutex::Autolock locker(&mObjectLock);
    mNotifyCB = notify_cb;
    mDataCB = data_cb;
    mDataCBTimestamp = data_cb_timestamp;
    mGetMemoryCB = get_memory;
    mCBOpaque = user;
}

void CallbackNotifier::enableMessage(uint msg_type)
{
    ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
    PrintMessages(msg_type);

    Mutex::Autolock locker(&mObjectLock);
    mMessageEnabler |= msg_type;
    ALOGV("**** Currently enabled messages:");
    PrintMessages(mMessageEnabler);
}

void CallbackNotifier::disableMessage(uint msg_type)
{
    ALOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
    PrintMessages(msg_type);

    Mutex::Autolock locker(&mObjectLock);
    mMessageEnabler &= ~msg_type;
    ALOGV("**** Currently enabled messages:");
    PrintMessages(mMessageEnabler);
}

status_t CallbackNotifier::enableVideoRecording(int fps)
{
    ALOGV("%s: FPS = %d", __FUNCTION__, fps);

    Mutex::Autolock locker(&mObjectLock);
    mVideoRecEnabled = true;
    mLastFrameTimestamp = 0;
    mFrameRefreshFreq = 1000000000LL / fps;

    return NO_ERROR;
}

void CallbackNotifier::disableVideoRecording()
{
    ALOGV("%s:", __FUNCTION__);

    Mutex::Autolock locker(&mObjectLock);
    mVideoRecEnabled = false;
    mLastFrameTimestamp = 0;
    mFrameRefreshFreq = 0;
}

void CallbackNotifier::releaseRecordingFrame(const void* opaque)
{
    List<camera_memory_t*>::iterator it = mCameraMemoryTs.begin();
    for( ; it != mCameraMemoryTs.end(); ++it ) {
        if ( (*it)->data == opaque ) {
            (*it)->release( *it );
            mCameraMemoryTs.erase(it);
            break;
        }
    }
}

void CallbackNotifier::autoFocusComplete() {
    // Even though we don't support auto-focus we are expected to send a fake
    // success message according to the documentation.
    // https://developer.android.com/reference/android/hardware/Camera.AutoFocusCallback.html
    mNotifyCB(CAMERA_MSG_FOCUS, true, 0, mCBOpaque);
}

status_t CallbackNotifier::storeMetaDataInBuffers(bool enable)
{
    // Return error if metadata is request, otherwise silently agree.
    return enable ? INVALID_OPERATION : NO_ERROR;
}

/****************************************************************************
 * Public API
 ***************************************************************************/

void CallbackNotifier::cleanupCBNotifier()
{
    Mutex::Autolock locker(&mObjectLock);
    mMessageEnabler = 0;
    mNotifyCB = NULL;
    mDataCB = NULL;
    mDataCBTimestamp = NULL;
    mGetMemoryCB = NULL;
    mCBOpaque = NULL;
    mLastFrameTimestamp = 0;
    mFrameRefreshFreq = 0;
    mJpegQuality = 90;
    mVideoRecEnabled = false;
    mTakingPicture = false;
}

void CallbackNotifier::onNextFrameAvailable(nsecs_t timestamp,
                                            EmulatedCameraDevice* camera_dev)
{
    if (isMessageEnabled(CAMERA_MSG_VIDEO_FRAME) && isVideoRecordingEnabled() &&
            isNewVideoFrameTime(timestamp)) {
        // This is the path for video frames, the format used here is not
        // exposed to external users so it can be whatever the camera and the
        // encoder can agree upon. The emulator system images use software
        // encoders that expect a YUV420 format but the camera parameter
        // constants cannot represent this. The closest we have is YV12 which is
        // YVU420. So we produce YV12 frames so that we can serve those through
        // the preview callback below and then we convert from YV12 to YUV420
        // here. This is a pretty cheap conversion in most cases since we have
        // to copy the frame here anyway. In the best (and most common) cases
        // the conversion is just copying the U and V parts of the frame in
        // different order. A slightly more expensive case is when the YV12
        // frame has padding to ensure that rows are aligned to 16-byte
        // boundaries. The YUV420 format expected by the encoders do not have
        // this alignment so it has to be removed. This way the encoder gets the
        // format it expects and the preview callback (or data callback) below
        // gets the format that is configured in camera parameters.
        const size_t frameSize = camera_dev->getVideoFrameBufferSize();
        camera_memory_t* cam_buff = mGetMemoryCB(-1, frameSize, 1, mCBOpaque);
        if (NULL != cam_buff && NULL != cam_buff->data) {
            int64_t frame_timestamp = 0L;
            camera_dev->getCurrentFrame(cam_buff->data, V4L2_PIX_FMT_YUV420,
                                        &frame_timestamp);
            mDataCBTimestamp(frame_timestamp != 0L ? frame_timestamp : timestamp,
                             CAMERA_MSG_VIDEO_FRAME, cam_buff, 0, mCBOpaque);
            mCameraMemoryTs.push_back( cam_buff );
        } else {
            ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
        }
    }

    if (isMessageEnabled(CAMERA_MSG_PREVIEW_FRAME)) {
        camera_memory_t* cam_buff =
            mGetMemoryCB(-1, camera_dev->getFrameBufferSize(), 1, mCBOpaque);
        if (NULL != cam_buff && NULL != cam_buff->data) {
            int64_t frame_timestamp = 0L;
            camera_dev->getCurrentFrame(cam_buff->data,
                                        camera_dev->getOriginalPixelFormat(),
                                        &frame_timestamp);
            mDataCB(CAMERA_MSG_PREVIEW_FRAME, cam_buff, 0, NULL, mCBOpaque);
            cam_buff->release(cam_buff);
        } else {
            ALOGE("%s: Memory failure in CAMERA_MSG_PREVIEW_FRAME", __FUNCTION__);
        }
    }

    if (mTakingPicture) {
        /* This happens just once. */
        mTakingPicture = false;
        /* The sequence of callbacks during picture taking is:
         *  - CAMERA_MSG_SHUTTER
         *  - CAMERA_MSG_RAW_IMAGE_NOTIFY
         *  - CAMERA_MSG_COMPRESSED_IMAGE
         */
        if (isMessageEnabled(CAMERA_MSG_SHUTTER)) {
            mNotifyCB(CAMERA_MSG_SHUTTER, 0, 0, mCBOpaque);
        }
        if (isMessageEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
            mNotifyCB(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCBOpaque);
        }
        if (isMessageEnabled(CAMERA_MSG_COMPRESSED_IMAGE)) {
            // Create EXIF data from the camera parameters, this includes things
            // like EXIF default fields, a timestamp and GPS information.
            ExifData* exifData = createExifData(mCameraParameters);

            // Hold the frame lock while accessing the current frame to prevent
            // concurrent modifications. Then create our JPEG from that frame.
            EmulatedCameraDevice::FrameLock lock(*camera_dev);
            const void* frame = camera_dev->getCurrentFrame();

            // Create a thumbnail and place the pointer and size in the EXIF
            // data structure. This transfers ownership to the EXIF data and
            // the memory will be deallocated in the freeExifData call below.
            int width = camera_dev->getFrameWidth();
            int height = camera_dev->getFrameHeight();
            int thumbWidth = mCameraParameters.getInt(
                    CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
            int thumbHeight = mCameraParameters.getInt(
                    CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
            if (thumbWidth > 0 && thumbHeight > 0) {
                if (!createThumbnail(static_cast<const unsigned char*>(frame),
                                     width, height, thumbWidth, thumbHeight,
                                     mJpegQuality, exifData)) {
                    // Not really a fatal error, we'll just keep going
                    ALOGE("%s: Failed to create thumbnail for image",
                          __FUNCTION__);
                }
            }

            /* Compress the frame to JPEG. Note that when taking pictures, we
             * have requested camera device to provide us with NV21 frames. */
            NV21JpegCompressor compressor;
            status_t res = compressor.compressRawImage(frame, width, height,
                                                       mJpegQuality, exifData);
            if (res == NO_ERROR) {
                camera_memory_t* jpeg_buff =
                    mGetMemoryCB(-1, compressor.getCompressedSize(), 1, mCBOpaque);
                if (NULL != jpeg_buff && NULL != jpeg_buff->data) {
                    compressor.getCompressedImage(jpeg_buff->data);
                    mDataCB(CAMERA_MSG_COMPRESSED_IMAGE, jpeg_buff, 0, NULL, mCBOpaque);
                    jpeg_buff->release(jpeg_buff);
                } else {
                    ALOGE("%s: Memory failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
                }
            } else {
                ALOGE("%s: Compression failure in CAMERA_MSG_VIDEO_FRAME", __FUNCTION__);
            }
            // The EXIF data has been consumed, free it
            freeExifData(exifData);
        }
    }
}

void CallbackNotifier::onCameraDeviceError(int err)
{
    if (isMessageEnabled(CAMERA_MSG_ERROR) && mNotifyCB != NULL) {
        mNotifyCB(CAMERA_MSG_ERROR, err, 0, mCBOpaque);
    }
}

/****************************************************************************
 * Private API
 ***************************************************************************/

bool CallbackNotifier::isNewVideoFrameTime(nsecs_t timestamp)
{
    Mutex::Autolock locker(&mObjectLock);
    if ((timestamp - mLastFrameTimestamp) >= mFrameRefreshFreq) {
        mLastFrameTimestamp = timestamp;
        return true;
    }
    return false;
}

}; /* namespace android */
