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