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 
43 static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
44 static mm_jpeg_obj* g_jpeg_obj = NULL;
45 
46 static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
47 static uint16_t g_handler_history_count = 0; /* history count for handler */
48 volatile 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  **/
mm_jpeg_util_generate_handler(uint8_t index)62 uint32_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  **/
mm_jpeg_util_get_index_by_handler(uint32_t handler)88 uint8_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  **/
mm_jpeg_intf_start_job(mm_jpeg_job_t * job,uint32_t * job_id)107 static 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  **/
mm_jpeg_intf_create_session(uint32_t client_hdl,mm_jpeg_encode_params_t * p_params,uint32_t * p_session_id)143 static 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  **/
mm_jpeg_intf_destroy_session(uint32_t session_id)179 static 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  **/
mm_jpeg_intf_abort_job(uint32_t job_id)213 static 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  **/
mm_jpeg_intf_close(uint32_t client_hdl)247 static 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  **/
mm_jpeg_intf_compose_mpo(mm_jpeg_mpo_info_t * mpo_info)291 static 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  **/
jpeg_open(mm_jpeg_ops_t * ops,mm_jpeg_mpo_ops_t * mpo_ops,mm_dimension picture_size,cam_jpeg_metadata_t * jpeg_metadata)325 uint32_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