1/* Copyright (c) 2012-2016, 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// To remove
31#include <cutils/properties.h>
32
33// System dependencies
34#include <stdlib.h>
35#include <pthread.h>
36
37// JPEG dependencies
38#include "mm_jpeg_dbg.h"
39#include "mm_jpeg_interface.h"
40#include "mm_jpeg.h"
41#include "mm_jpeg_mpo.h"
42
43static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
44static mm_jpeg_obj* g_jpeg_obj = NULL;
45
46static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
47static uint16_t g_handler_history_count = 0; /* history count for handler */
48volatile uint32_t gKpiDebugLevel = 0;
49
50/** mm_jpeg_util_generate_handler:
51 *
52 *  Arguments:
53 *    @index: client index
54 *
55 *  Return:
56 *       handle value
57 *
58 *  Description:
59 *       utility function to generate handler
60 *
61 **/
62uint32_t mm_jpeg_util_generate_handler(uint8_t index)
63{
64  uint32_t handler = 0;
65  pthread_mutex_lock(&g_handler_lock);
66  g_handler_history_count++;
67  if (0 == g_handler_history_count) {
68    g_handler_history_count++;
69  }
70  handler = g_handler_history_count;
71  handler = (handler<<8) | index;
72  pthread_mutex_unlock(&g_handler_lock);
73  return handler;
74}
75
76/** mm_jpeg_util_get_index_by_handler:
77 *
78 *  Arguments:
79 *    @handler: handle value
80 *
81 *  Return:
82 *       client index
83 *
84 *  Description:
85 *       get client index
86 *
87 **/
88uint8_t mm_jpeg_util_get_index_by_handler(uint32_t handler)
89{
90  return (handler & 0x000000ff);
91}
92
93/** mm_jpeg_intf_start_job:
94 *
95 *  Arguments:
96 *    @client_hdl: client handle
97 *    @job: jpeg job object
98 *    @jobId: job id
99 *
100 *  Return:
101 *       0 success, failure otherwise
102 *
103 *  Description:
104 *       start the jpeg job
105 *
106 **/
107static int32_t mm_jpeg_intf_start_job(mm_jpeg_job_t* job, uint32_t* job_id)
108{
109  int32_t rc = -1;
110
111  if (NULL == job ||
112    NULL == job_id) {
113    LOGE("invalid parameters for job or jobId");
114    return rc;
115  }
116
117  pthread_mutex_lock(&g_intf_lock);
118  if (NULL == g_jpeg_obj) {
119    /* mm_jpeg obj not exists, return error */
120    LOGE("mm_jpeg is not opened yet");
121    pthread_mutex_unlock(&g_intf_lock);
122    return rc;
123  }
124  rc = mm_jpeg_start_job(g_jpeg_obj, job, job_id);
125  pthread_mutex_unlock(&g_intf_lock);
126  return rc;
127}
128
129/** mm_jpeg_intf_create_session:
130 *
131 *  Arguments:
132 *    @client_hdl: client handle
133 *    @p_params: encode parameters
134 *    @p_session_id: session id
135 *
136 *  Return:
137 *       0 success, failure otherwise
138 *
139 *  Description:
140 *       Create new jpeg session
141 *
142 **/
143static int32_t mm_jpeg_intf_create_session(uint32_t client_hdl,
144    mm_jpeg_encode_params_t *p_params,
145    uint32_t *p_session_id)
146{
147  int32_t rc = -1;
148
149  if (0 == client_hdl || NULL == p_params || NULL == p_session_id) {
150    LOGE("invalid client_hdl or jobId");
151    return rc;
152  }
153
154  pthread_mutex_lock(&g_intf_lock);
155  if (NULL == g_jpeg_obj) {
156    /* mm_jpeg obj not exists, return error */
157    LOGE("mm_jpeg is not opened yet");
158    pthread_mutex_unlock(&g_intf_lock);
159    return rc;
160  }
161
162 rc = mm_jpeg_create_session(g_jpeg_obj, client_hdl, p_params, p_session_id);
163  pthread_mutex_unlock(&g_intf_lock);
164  return rc;
165}
166
167/** mm_jpeg_intf_destroy_session:
168 *
169 *  Arguments:
170 *    @session_id: session id
171 *
172 *  Return:
173 *       0 success, failure otherwise
174 *
175 *  Description:
176 *       Destroy jpeg session
177 *
178 **/
179static int32_t mm_jpeg_intf_destroy_session(uint32_t session_id)
180{
181  int32_t rc = -1;
182
183  if (0 == session_id) {
184    LOGE("invalid client_hdl or jobId");
185    return rc;
186  }
187
188  pthread_mutex_lock(&g_intf_lock);
189  if (NULL == g_jpeg_obj) {
190    /* mm_jpeg obj not exists, return error */
191    LOGE("mm_jpeg is not opened yet");
192    pthread_mutex_unlock(&g_intf_lock);
193    return rc;
194  }
195
196  rc = mm_jpeg_destroy_session_by_id(g_jpeg_obj, session_id);
197  pthread_mutex_unlock(&g_intf_lock);
198  return rc;
199}
200
201/** mm_jpeg_intf_abort_job:
202 *
203 *  Arguments:
204 *    @jobId: job id
205 *
206 *  Return:
207 *       0 success, failure otherwise
208 *
209 *  Description:
210 *       Abort the jpeg job
211 *
212 **/
213static int32_t mm_jpeg_intf_abort_job(uint32_t job_id)
214{
215  int32_t rc = -1;
216
217  if (0 == job_id) {
218    LOGE("invalid jobId");
219    return rc;
220  }
221
222  pthread_mutex_lock(&g_intf_lock);
223  if (NULL == g_jpeg_obj) {
224    /* mm_jpeg obj not exists, return error */
225    LOGE("mm_jpeg is not opened yet");
226    pthread_mutex_unlock(&g_intf_lock);
227    return rc;
228  }
229
230  rc = mm_jpeg_abort_job(g_jpeg_obj, job_id);
231  pthread_mutex_unlock(&g_intf_lock);
232  return rc;
233}
234
235/** mm_jpeg_intf_close:
236 *
237 *  Arguments:
238 *    @client_hdl: client handle
239 *
240 *  Return:
241 *       0 success, failure otherwise
242 *
243 *  Description:
244 *       Close the jpeg job
245 *
246 **/
247static int32_t mm_jpeg_intf_close(uint32_t client_hdl)
248{
249  int32_t rc = -1;
250
251  if (0 == client_hdl) {
252    LOGE("invalid client_hdl");
253    return rc;
254  }
255
256  pthread_mutex_lock(&g_intf_lock);
257  if (NULL == g_jpeg_obj) {
258    /* mm_jpeg obj not exists, return error */
259    LOGE("mm_jpeg is not opened yet");
260    pthread_mutex_unlock(&g_intf_lock);
261    return rc;
262  }
263
264  rc = mm_jpeg_close(g_jpeg_obj, client_hdl);
265  g_jpeg_obj->num_clients--;
266  if(0 == rc) {
267    if (0 == g_jpeg_obj->num_clients) {
268      /* No client, close jpeg internally */
269      rc = mm_jpeg_deinit(g_jpeg_obj);
270      free(g_jpeg_obj);
271      g_jpeg_obj = NULL;
272    }
273  }
274
275  pthread_mutex_unlock(&g_intf_lock);
276  return rc;
277}
278
279/** mm_jpeg_intf_compose_mpo:
280 *
281 *  Arguments:
282 *    @mpo_info : MPO Information
283 *
284 *  Return:
285 *       0 success, failure otherwise
286 *
287 *  Description:
288 *       Compose MPO image from jpeg images
289 *
290 **/
291static int32_t mm_jpeg_intf_compose_mpo(mm_jpeg_mpo_info_t *mpo_info)
292{
293  int32_t rc = -1;
294  if (!mpo_info) {
295    LOGE("Invalid input");
296    return rc;
297  }
298
299  if (mpo_info->num_of_images > MM_JPEG_MAX_MPO_IMAGES) {
300    LOGE("Num of images exceeds max supported images in MPO");
301    return rc;
302  }
303  //Call MPo composition
304  rc = mm_jpeg_mpo_compose(mpo_info);
305
306  return rc;
307}
308
309/** jpeg_open:
310 *
311 *  Arguments:
312 *    @ops: ops table pointer
313 *    @mpo_ops: mpo ops table ptr
314 *    @picture_size: Max available dim
315 *    @jpeg_metadata: Jpeg meta data
316 *
317 *  Return:
318 *       0 failure, success otherwise
319 *
320 *  Description:
321 *       Open a jpeg client. Jpeg meta data will be cached
322 *       but memory manegement has to be done by the cient.
323 *
324 **/
325uint32_t jpeg_open(mm_jpeg_ops_t *ops, mm_jpeg_mpo_ops_t *mpo_ops,
326  mm_dimension picture_size,
327  cam_jpeg_metadata_t *jpeg_metadata)
328{
329  int32_t rc = 0;
330  uint32_t clnt_hdl = 0;
331  mm_jpeg_obj* jpeg_obj = NULL;
332  char prop[PROPERTY_VALUE_MAX];
333
334  property_get("persist.camera.kpi.debug", prop, "0");
335  gKpiDebugLevel = atoi(prop);
336
337  pthread_mutex_lock(&g_intf_lock);
338  /* first time open */
339  if(NULL == g_jpeg_obj) {
340    jpeg_obj = (mm_jpeg_obj *)malloc(sizeof(mm_jpeg_obj));
341    if(NULL == jpeg_obj) {
342      LOGE("no mem");
343      pthread_mutex_unlock(&g_intf_lock);
344      return clnt_hdl;
345    }
346
347    /* initialize jpeg obj */
348    memset(jpeg_obj, 0, sizeof(mm_jpeg_obj));
349
350    /* by default reuse reproc source buffer if available */
351    if (mpo_ops == NULL) {
352      jpeg_obj->reuse_reproc_buffer = 1;
353    } else {
354      jpeg_obj->reuse_reproc_buffer = 0;
355    }
356   LOGH("reuse_reproc_buffer %d ",
357      jpeg_obj->reuse_reproc_buffer);
358
359    /* used for work buf calculation */
360    jpeg_obj->max_pic_w = picture_size.w;
361    jpeg_obj->max_pic_h = picture_size.h;
362
363    /*Cache OTP Data for the session*/
364    if (NULL != jpeg_metadata) {
365      jpeg_obj->jpeg_metadata = jpeg_metadata;
366    }
367
368    rc = mm_jpeg_init(jpeg_obj);
369    if(0 != rc) {
370      LOGE("mm_jpeg_init err = %d", rc);
371      free(jpeg_obj);
372      pthread_mutex_unlock(&g_intf_lock);
373      return clnt_hdl;
374    }
375
376    /* remember in global variable */
377    g_jpeg_obj = jpeg_obj;
378  }
379
380  /* open new client */
381  clnt_hdl = mm_jpeg_new_client(g_jpeg_obj);
382  if (clnt_hdl > 0) {
383    /* valid client */
384    if (NULL != ops) {
385      /* fill in ops tbl if ptr not NULL */
386      ops->start_job = mm_jpeg_intf_start_job;
387      ops->abort_job = mm_jpeg_intf_abort_job;
388      ops->create_session = mm_jpeg_intf_create_session;
389      ops->destroy_session = mm_jpeg_intf_destroy_session;
390      ops->close = mm_jpeg_intf_close;
391    }
392    if (NULL != mpo_ops) {
393      mpo_ops->compose_mpo = mm_jpeg_intf_compose_mpo;
394    }
395  } else {
396    /* failed new client */
397    LOGE("mm_jpeg_new_client failed");
398
399    if (0 == g_jpeg_obj->num_clients) {
400      /* no client, close jpeg */
401      mm_jpeg_deinit(g_jpeg_obj);
402      free(g_jpeg_obj);
403      g_jpeg_obj = NULL;
404    }
405  }
406
407  pthread_mutex_unlock(&g_intf_lock);
408  return clnt_hdl;
409}
410