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