/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// To remove
#include <cutils/properties.h>
// System dependencies
#include <stdlib.h>
#include <pthread.h>
// JPEG dependencies
#include "mm_jpeg_dbg.h"
#include "mm_jpeg_interface.h"
#include "mm_jpeg.h"
#include "mm_jpeg_mpo.h"
static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
static mm_jpeg_obj* g_jpeg_obj = NULL;
static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
static uint16_t g_handler_history_count = 0; /* history count for handler */
volatile uint32_t gKpiDebugLevel = 0;
/** mm_jpeg_util_generate_handler:
*
* Arguments:
* @index: client index
*
* Return:
* handle value
*
* Description:
* utility function to generate handler
*
**/
uint32_t mm_jpeg_util_generate_handler(uint8_t index)
{
uint32_t handler = 0;
pthread_mutex_lock(&g_handler_lock);
g_handler_history_count++;
if (0 == g_handler_history_count) {
g_handler_history_count++;
}
handler = g_handler_history_count;
handler = (handler<<8) | index;
pthread_mutex_unlock(&g_handler_lock);
return handler;
}
/** mm_jpeg_util_get_index_by_handler:
*
* Arguments:
* @handler: handle value
*
* Return:
* client index
*
* Description:
* get client index
*
**/
uint8_t mm_jpeg_util_get_index_by_handler(uint32_t handler)
{
return (handler & 0x000000ff);
}
/** mm_jpeg_intf_start_job:
*
* Arguments:
* @client_hdl: client handle
* @job: jpeg job object
* @jobId: job id
*
* Return:
* 0 success, failure otherwise
*
* Description:
* start the jpeg job
*
**/
static int32_t mm_jpeg_intf_start_job(mm_jpeg_job_t* job, uint32_t* job_id)
{
int32_t rc = -1;
if (NULL == job ||
NULL == job_id) {
LOGE("invalid parameters for job or jobId");
return rc;
}
pthread_mutex_lock(&g_intf_lock);
if (NULL == g_jpeg_obj) {
/* mm_jpeg obj not exists, return error */
LOGE("mm_jpeg is not opened yet");
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
rc = mm_jpeg_start_job(g_jpeg_obj, job, job_id);
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
/** mm_jpeg_intf_create_session:
*
* Arguments:
* @client_hdl: client handle
* @p_params: encode parameters
* @p_session_id: session id
*
* Return:
* 0 success, failure otherwise
*
* Description:
* Create new jpeg session
*
**/
static int32_t mm_jpeg_intf_create_session(uint32_t client_hdl,
mm_jpeg_encode_params_t *p_params,
uint32_t *p_session_id)
{
int32_t rc = -1;
if (0 == client_hdl || NULL == p_params || NULL == p_session_id) {
LOGE("invalid client_hdl or jobId");
return rc;
}
pthread_mutex_lock(&g_intf_lock);
if (NULL == g_jpeg_obj) {
/* mm_jpeg obj not exists, return error */
LOGE("mm_jpeg is not opened yet");
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
rc = mm_jpeg_create_session(g_jpeg_obj, client_hdl, p_params, p_session_id);
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
/** mm_jpeg_intf_destroy_session:
*
* Arguments:
* @session_id: session id
*
* Return:
* 0 success, failure otherwise
*
* Description:
* Destroy jpeg session
*
**/
static int32_t mm_jpeg_intf_destroy_session(uint32_t session_id)
{
int32_t rc = -1;
if (0 == session_id) {
LOGE("invalid client_hdl or jobId");
return rc;
}
pthread_mutex_lock(&g_intf_lock);
if (NULL == g_jpeg_obj) {
/* mm_jpeg obj not exists, return error */
LOGE("mm_jpeg is not opened yet");
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
rc = mm_jpeg_destroy_session_by_id(g_jpeg_obj, session_id);
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
/** mm_jpeg_intf_abort_job:
*
* Arguments:
* @jobId: job id
*
* Return:
* 0 success, failure otherwise
*
* Description:
* Abort the jpeg job
*
**/
static int32_t mm_jpeg_intf_abort_job(uint32_t job_id)
{
int32_t rc = -1;
if (0 == job_id) {
LOGE("invalid jobId");
return rc;
}
pthread_mutex_lock(&g_intf_lock);
if (NULL == g_jpeg_obj) {
/* mm_jpeg obj not exists, return error */
LOGE("mm_jpeg is not opened yet");
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
rc = mm_jpeg_abort_job(g_jpeg_obj, job_id);
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
/** mm_jpeg_intf_close:
*
* Arguments:
* @client_hdl: client handle
*
* Return:
* 0 success, failure otherwise
*
* Description:
* Close the jpeg job
*
**/
static int32_t mm_jpeg_intf_close(uint32_t client_hdl)
{
int32_t rc = -1;
if (0 == client_hdl) {
LOGE("invalid client_hdl");
return rc;
}
pthread_mutex_lock(&g_intf_lock);
if (NULL == g_jpeg_obj) {
/* mm_jpeg obj not exists, return error */
LOGE("mm_jpeg is not opened yet");
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
rc = mm_jpeg_close(g_jpeg_obj, client_hdl);
g_jpeg_obj->num_clients--;
if(0 == rc) {
if (0 == g_jpeg_obj->num_clients) {
/* No client, close jpeg internally */
rc = mm_jpeg_deinit(g_jpeg_obj);
free(g_jpeg_obj);
g_jpeg_obj = NULL;
}
}
pthread_mutex_unlock(&g_intf_lock);
return rc;
}
/** mm_jpeg_intf_compose_mpo:
*
* Arguments:
* @mpo_info : MPO Information
*
* Return:
* 0 success, failure otherwise
*
* Description:
* Compose MPO image from jpeg images
*
**/
static int32_t mm_jpeg_intf_compose_mpo(mm_jpeg_mpo_info_t *mpo_info)
{
int32_t rc = -1;
if (!mpo_info) {
LOGE("Invalid input");
return rc;
}
if (mpo_info->num_of_images > MM_JPEG_MAX_MPO_IMAGES) {
LOGE("Num of images exceeds max supported images in MPO");
return rc;
}
//Call MPo composition
rc = mm_jpeg_mpo_compose(mpo_info);
return rc;
}
/** jpeg_open:
*
* Arguments:
* @ops: ops table pointer
* @mpo_ops: mpo ops table ptr
* @picture_size: Max available dim
* @jpeg_metadata: Jpeg meta data
*
* Return:
* 0 failure, success otherwise
*
* Description:
* Open a jpeg client. Jpeg meta data will be cached
* but memory manegement has to be done by the cient.
*
**/
uint32_t jpeg_open(mm_jpeg_ops_t *ops, mm_jpeg_mpo_ops_t *mpo_ops,
mm_dimension picture_size,
cam_jpeg_metadata_t *jpeg_metadata)
{
int32_t rc = 0;
uint32_t clnt_hdl = 0;
mm_jpeg_obj* jpeg_obj = NULL;
char prop[PROPERTY_VALUE_MAX];
property_get("persist.camera.kpi.debug", prop, "0");
gKpiDebugLevel = atoi(prop);
pthread_mutex_lock(&g_intf_lock);
/* first time open */
if(NULL == g_jpeg_obj) {
jpeg_obj = (mm_jpeg_obj *)malloc(sizeof(mm_jpeg_obj));
if(NULL == jpeg_obj) {
LOGE("no mem");
pthread_mutex_unlock(&g_intf_lock);
return clnt_hdl;
}
/* initialize jpeg obj */
memset(jpeg_obj, 0, sizeof(mm_jpeg_obj));
/* by default reuse reproc source buffer if available */
if (mpo_ops == NULL) {
jpeg_obj->reuse_reproc_buffer = 1;
} else {
jpeg_obj->reuse_reproc_buffer = 0;
}
LOGH("reuse_reproc_buffer %d ",
jpeg_obj->reuse_reproc_buffer);
/* used for work buf calculation */
jpeg_obj->max_pic_w = picture_size.w;
jpeg_obj->max_pic_h = picture_size.h;
/*Cache OTP Data for the session*/
if (NULL != jpeg_metadata) {
jpeg_obj->jpeg_metadata = jpeg_metadata;
}
rc = mm_jpeg_init(jpeg_obj);
if(0 != rc) {
LOGE("mm_jpeg_init err = %d", rc);
free(jpeg_obj);
pthread_mutex_unlock(&g_intf_lock);
return clnt_hdl;
}
/* remember in global variable */
g_jpeg_obj = jpeg_obj;
}
/* open new client */
clnt_hdl = mm_jpeg_new_client(g_jpeg_obj);
if (clnt_hdl > 0) {
/* valid client */
if (NULL != ops) {
/* fill in ops tbl if ptr not NULL */
ops->start_job = mm_jpeg_intf_start_job;
ops->abort_job = mm_jpeg_intf_abort_job;
ops->create_session = mm_jpeg_intf_create_session;
ops->destroy_session = mm_jpeg_intf_destroy_session;
ops->close = mm_jpeg_intf_close;
}
if (NULL != mpo_ops) {
mpo_ops->compose_mpo = mm_jpeg_intf_compose_mpo;
}
} else {
/* failed new client */
LOGE("mm_jpeg_new_client failed");
if (0 == g_jpeg_obj->num_clients) {
/* no client, close jpeg */
mm_jpeg_deinit(g_jpeg_obj);
free(g_jpeg_obj);
g_jpeg_obj = NULL;
}
}
pthread_mutex_unlock(&g_intf_lock);
return clnt_hdl;
}