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 
44 static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
45 static mm_jpeg_obj* g_jpeg_obj = NULL;
46 
47 static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
48 static uint16_t g_handler_history_count = 0; /* history count for handler */
49 volatile 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  **/
mm_jpeg_util_generate_handler(uint8_t index)63 uint32_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  **/
mm_jpeg_util_get_index_by_handler(uint32_t handler)89 uint8_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  **/
mm_jpeg_intf_start_job(mm_jpeg_job_t * job,uint32_t * job_id)108 static 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  **/
mm_jpeg_intf_create_session(uint32_t client_hdl,mm_jpeg_encode_params_t * p_params,uint32_t * p_session_id)144 static 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  **/
mm_jpeg_intf_destroy_session(uint32_t session_id)180 static 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  **/
mm_jpeg_intf_abort_job(uint32_t job_id)214 static 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  **/
mm_jpeg_intf_close(uint32_t client_hdl)248 static 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  **/
jpeg_open(mm_jpeg_ops_t * ops,mm_dimension picture_size)292 uint32_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