1/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30#include <stdlib.h> 31#include <pthread.h> 32#include <errno.h> 33#include <sys/ioctl.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <fcntl.h> 37#include <cutils/properties.h> 38#include <stdlib.h> 39 40#include "mm_jpeg_dbg.h" 41#include "mm_jpeg_interface.h" 42#include "mm_jpeg.h" 43 44static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER; 45static mm_jpeg_obj* g_jpeg_obj = NULL; 46 47static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER; 48static uint16_t g_handler_history_count = 0; /* history count for handler */ 49volatile uint32_t gMmJpegIntfLogLevel = 1; 50 51/** mm_jpeg_util_generate_handler: 52 * 53 * Arguments: 54 * @index: client index 55 * 56 * Return: 57 * handle value 58 * 59 * Description: 60 * utility function to generate handler 61 * 62 **/ 63uint32_t mm_jpeg_util_generate_handler(uint8_t index) 64{ 65 uint32_t handler = 0; 66 pthread_mutex_lock(&g_handler_lock); 67 g_handler_history_count++; 68 if (0 == g_handler_history_count) { 69 g_handler_history_count++; 70 } 71 handler = g_handler_history_count; 72 handler = (handler<<8) | index; 73 pthread_mutex_unlock(&g_handler_lock); 74 return handler; 75} 76 77/** mm_jpeg_util_get_index_by_handler: 78 * 79 * Arguments: 80 * @handler: handle value 81 * 82 * Return: 83 * client index 84 * 85 * Description: 86 * get client index 87 * 88 **/ 89uint8_t mm_jpeg_util_get_index_by_handler(uint32_t handler) 90{ 91 return (handler & 0x000000ff); 92} 93 94/** mm_jpeg_intf_start_job: 95 * 96 * Arguments: 97 * @client_hdl: client handle 98 * @job: jpeg job object 99 * @jobId: job id 100 * 101 * Return: 102 * 0 success, failure otherwise 103 * 104 * Description: 105 * start the jpeg job 106 * 107 **/ 108static int32_t mm_jpeg_intf_start_job(mm_jpeg_job_t* job, uint32_t* job_id) 109{ 110 int32_t rc = -1; 111 112 if (NULL == job || 113 NULL == job_id) { 114 CDBG_ERROR("%s:%d] invalid parameters for job or jobId", __func__, __LINE__); 115 return rc; 116 } 117 118 pthread_mutex_lock(&g_intf_lock); 119 if (NULL == g_jpeg_obj) { 120 /* mm_jpeg obj not exists, return error */ 121 CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__); 122 pthread_mutex_unlock(&g_intf_lock); 123 return rc; 124 } 125 rc = mm_jpeg_start_job(g_jpeg_obj, job, job_id); 126 pthread_mutex_unlock(&g_intf_lock); 127 return rc; 128} 129 130/** mm_jpeg_intf_create_session: 131 * 132 * Arguments: 133 * @client_hdl: client handle 134 * @p_params: encode parameters 135 * @p_session_id: session id 136 * 137 * Return: 138 * 0 success, failure otherwise 139 * 140 * Description: 141 * Create new jpeg session 142 * 143 **/ 144static int32_t mm_jpeg_intf_create_session(uint32_t client_hdl, 145 mm_jpeg_encode_params_t *p_params, 146 uint32_t *p_session_id) 147{ 148 int32_t rc = -1; 149 150 if (0 == client_hdl || NULL == p_params || NULL == p_session_id) { 151 CDBG_ERROR("%s:%d] invalid client_hdl or jobId", __func__, __LINE__); 152 return rc; 153 } 154 155 pthread_mutex_lock(&g_intf_lock); 156 if (NULL == g_jpeg_obj) { 157 /* mm_jpeg obj not exists, return error */ 158 CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__); 159 pthread_mutex_unlock(&g_intf_lock); 160 return rc; 161 } 162 163 rc = mm_jpeg_create_session(g_jpeg_obj, client_hdl, p_params, p_session_id); 164 pthread_mutex_unlock(&g_intf_lock); 165 return rc; 166} 167 168/** mm_jpeg_intf_destroy_session: 169 * 170 * Arguments: 171 * @session_id: session id 172 * 173 * Return: 174 * 0 success, failure otherwise 175 * 176 * Description: 177 * Destroy jpeg session 178 * 179 **/ 180static int32_t mm_jpeg_intf_destroy_session(uint32_t session_id) 181{ 182 int32_t rc = -1; 183 184 if (0 == session_id) { 185 CDBG_ERROR("%s:%d] invalid client_hdl or jobId", __func__, __LINE__); 186 return rc; 187 } 188 189 pthread_mutex_lock(&g_intf_lock); 190 if (NULL == g_jpeg_obj) { 191 /* mm_jpeg obj not exists, return error */ 192 CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__); 193 pthread_mutex_unlock(&g_intf_lock); 194 return rc; 195 } 196 197 rc = mm_jpeg_destroy_session_by_id(g_jpeg_obj, session_id); 198 pthread_mutex_unlock(&g_intf_lock); 199 return rc; 200} 201 202/** mm_jpeg_intf_abort_job: 203 * 204 * Arguments: 205 * @jobId: job id 206 * 207 * Return: 208 * 0 success, failure otherwise 209 * 210 * Description: 211 * Abort the jpeg job 212 * 213 **/ 214static int32_t mm_jpeg_intf_abort_job(uint32_t job_id) 215{ 216 int32_t rc = -1; 217 218 if (0 == job_id) { 219 CDBG_ERROR("%s:%d] invalid jobId", __func__, __LINE__); 220 return rc; 221 } 222 223 pthread_mutex_lock(&g_intf_lock); 224 if (NULL == g_jpeg_obj) { 225 /* mm_jpeg obj not exists, return error */ 226 CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__); 227 pthread_mutex_unlock(&g_intf_lock); 228 return rc; 229 } 230 231 rc = mm_jpeg_abort_job(g_jpeg_obj, job_id); 232 pthread_mutex_unlock(&g_intf_lock); 233 return rc; 234} 235 236/** mm_jpeg_intf_close: 237 * 238 * Arguments: 239 * @client_hdl: client handle 240 * 241 * Return: 242 * 0 success, failure otherwise 243 * 244 * Description: 245 * Close the jpeg job 246 * 247 **/ 248static int32_t mm_jpeg_intf_close(uint32_t client_hdl) 249{ 250 int32_t rc = -1; 251 252 if (0 == client_hdl) { 253 CDBG_ERROR("%s:%d] invalid client_hdl", __func__, __LINE__); 254 return rc; 255 } 256 257 pthread_mutex_lock(&g_intf_lock); 258 if (NULL == g_jpeg_obj) { 259 /* mm_jpeg obj not exists, return error */ 260 CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__); 261 pthread_mutex_unlock(&g_intf_lock); 262 return rc; 263 } 264 265 rc = mm_jpeg_close(g_jpeg_obj, client_hdl); 266 g_jpeg_obj->num_clients--; 267 if(0 == rc) { 268 if (0 == g_jpeg_obj->num_clients) { 269 /* No client, close jpeg internally */ 270 rc = mm_jpeg_deinit(g_jpeg_obj); 271 free(g_jpeg_obj); 272 g_jpeg_obj = NULL; 273 } 274 } 275 276 pthread_mutex_unlock(&g_intf_lock); 277 return rc; 278} 279 280/** jpeg_open: 281 * 282 * Arguments: 283 * @ops: ops table pointer 284 * 285 * Return: 286 * 0 failure, success otherwise 287 * 288 * Description: 289 * Open a jpeg client 290 * 291 **/ 292uint32_t jpeg_open(mm_jpeg_ops_t *ops, mm_dimension picture_size) 293{ 294 int32_t rc = 0; 295 uint32_t clnt_hdl = 0; 296 mm_jpeg_obj* jpeg_obj = NULL; 297 char prop[PROPERTY_VALUE_MAX]; 298 uint32_t globalLogLevel = 0; 299 300 memset(prop, 0x0, sizeof(prop)); 301 property_get("persist.camera.hal.debug", prop, "0"); 302 int val = atoi(prop); 303 if (0 <= val) { 304 gMmJpegIntfLogLevel = (uint32_t)val; 305 } 306 property_get("persist.camera.global.debug", prop, "0"); 307 val = atoi(prop); 308 if (0 <= val) { 309 globalLogLevel = (uint32_t)val; 310 } 311 312 /* Highest log level among hal.logs and global.logs is selected */ 313 if (gMmJpegIntfLogLevel < globalLogLevel) 314 gMmJpegIntfLogLevel = globalLogLevel; 315 if (gMmJpegIntfLogLevel < MINIMUM_JPEG_LOG_LEVEL) 316 gMmJpegIntfLogLevel = MINIMUM_JPEG_LOG_LEVEL; 317 318 pthread_mutex_lock(&g_intf_lock); 319 /* first time open */ 320 if(NULL == g_jpeg_obj) { 321 jpeg_obj = (mm_jpeg_obj *)malloc(sizeof(mm_jpeg_obj)); 322 if(NULL == jpeg_obj) { 323 CDBG_ERROR("%s:%d] no mem", __func__, __LINE__); 324 pthread_mutex_unlock(&g_intf_lock); 325 return clnt_hdl; 326 } 327 328 /* initialize jpeg obj */ 329 memset(jpeg_obj, 0, sizeof(mm_jpeg_obj)); 330 331 /* used for work buf calculation */ 332 jpeg_obj->max_pic_w = picture_size.w; 333 jpeg_obj->max_pic_h = picture_size.h; 334 335 rc = mm_jpeg_init(jpeg_obj); 336 if(0 != rc) { 337 CDBG_ERROR("%s:%d] mm_jpeg_init err = %d", __func__, __LINE__, rc); 338 free(jpeg_obj); 339 pthread_mutex_unlock(&g_intf_lock); 340 return clnt_hdl; 341 } 342 343 /* remember in global variable */ 344 g_jpeg_obj = jpeg_obj; 345 } 346 347 /* open new client */ 348 clnt_hdl = mm_jpeg_new_client(g_jpeg_obj); 349 if (clnt_hdl > 0) { 350 /* valid client */ 351 if (NULL != ops) { 352 /* fill in ops tbl if ptr not NULL */ 353 ops->start_job = mm_jpeg_intf_start_job; 354 ops->abort_job = mm_jpeg_intf_abort_job; 355 ops->create_session = mm_jpeg_intf_create_session; 356 ops->destroy_session = mm_jpeg_intf_destroy_session; 357 ops->close = mm_jpeg_intf_close; 358 } 359 } else { 360 /* failed new client */ 361 CDBG_ERROR("%s:%d] mm_jpeg_new_client failed", __func__, __LINE__); 362 363 if (0 == g_jpeg_obj->num_clients) { 364 /* no client, close jpeg */ 365 mm_jpeg_deinit(g_jpeg_obj); 366 free(g_jpeg_obj); 367 g_jpeg_obj = NULL; 368 } 369 } 370 371 pthread_mutex_unlock(&g_intf_lock); 372 return clnt_hdl; 373} 374