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 <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <cutils/properties.h>
37 
38 #include "mm_jpeg_dbg.h"
39 #include "mm_jpeg_interface.h"
40 #include "mm_jpeg.h"
41 
42 static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
43 static mm_jpeg_obj* g_jpeg_obj = NULL;
44 
45 static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
46 static uint16_t g_handler_history_count = 0; /* history count for handler */
47 volatile uint32_t gMmJpegIntfLogLevel = 1;
48 
49 /** mm_jpeg_util_generate_handler:
50  *
51  *  Arguments:
52  *    @index: client index
53  *
54  *  Return:
55  *       handle value
56  *
57  *  Description:
58  *       utility function to generate handler
59  *
60  **/
mm_jpeg_util_generate_handler(uint8_t index)61 uint32_t mm_jpeg_util_generate_handler(uint8_t index)
62 {
63   uint32_t handler = 0;
64   pthread_mutex_lock(&g_handler_lock);
65   g_handler_history_count++;
66   if (0 == g_handler_history_count) {
67     g_handler_history_count++;
68   }
69   handler = g_handler_history_count;
70   handler = (handler<<8) | index;
71   pthread_mutex_unlock(&g_handler_lock);
72   return handler;
73 }
74 
75 /** mm_jpeg_util_get_index_by_handler:
76  *
77  *  Arguments:
78  *    @handler: handle value
79  *
80  *  Return:
81  *       client index
82  *
83  *  Description:
84  *       get client index
85  *
86  **/
mm_jpeg_util_get_index_by_handler(uint32_t handler)87 uint8_t mm_jpeg_util_get_index_by_handler(uint32_t handler)
88 {
89   return (handler & 0x000000ff);
90 }
91 
92 /** mm_jpeg_intf_start_job:
93  *
94  *  Arguments:
95  *    @client_hdl: client handle
96  *    @job: jpeg job object
97  *    @jobId: job id
98  *
99  *  Return:
100  *       0 success, failure otherwise
101  *
102  *  Description:
103  *       start the jpeg job
104  *
105  **/
mm_jpeg_intf_start_job(mm_jpeg_job_t * job,uint32_t * job_id)106 static int32_t mm_jpeg_intf_start_job(mm_jpeg_job_t* job, uint32_t* job_id)
107 {
108   int32_t rc = -1;
109 
110   if (NULL == job ||
111     NULL == job_id) {
112     CDBG_ERROR("%s:%d] invalid parameters for job or jobId", __func__, __LINE__);
113     return rc;
114   }
115 
116   pthread_mutex_lock(&g_intf_lock);
117   if (NULL == g_jpeg_obj) {
118     /* mm_jpeg obj not exists, return error */
119     CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__);
120     pthread_mutex_unlock(&g_intf_lock);
121     return rc;
122   }
123   rc = mm_jpeg_start_job(g_jpeg_obj, job, job_id);
124   pthread_mutex_unlock(&g_intf_lock);
125   return rc;
126 }
127 
128 /** mm_jpeg_intf_create_session:
129  *
130  *  Arguments:
131  *    @client_hdl: client handle
132  *    @p_params: encode parameters
133  *    @p_session_id: session id
134  *
135  *  Return:
136  *       0 success, failure otherwise
137  *
138  *  Description:
139  *       Create new jpeg session
140  *
141  **/
mm_jpeg_intf_create_session(uint32_t client_hdl,mm_jpeg_encode_params_t * p_params,uint32_t * p_session_id)142 static int32_t mm_jpeg_intf_create_session(uint32_t client_hdl,
143     mm_jpeg_encode_params_t *p_params,
144     uint32_t *p_session_id)
145 {
146   int32_t rc = -1;
147 
148   if (0 == client_hdl || NULL == p_params || NULL == p_session_id) {
149     CDBG_ERROR("%s:%d] invalid client_hdl or jobId", __func__, __LINE__);
150     return rc;
151   }
152 
153   pthread_mutex_lock(&g_intf_lock);
154   if (NULL == g_jpeg_obj) {
155     /* mm_jpeg obj not exists, return error */
156     CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__);
157     pthread_mutex_unlock(&g_intf_lock);
158     return rc;
159   }
160 
161  rc = mm_jpeg_create_session(g_jpeg_obj, client_hdl, p_params, p_session_id);
162   pthread_mutex_unlock(&g_intf_lock);
163   return rc;
164 }
165 
166 /** mm_jpeg_intf_destroy_session:
167  *
168  *  Arguments:
169  *    @session_id: session id
170  *
171  *  Return:
172  *       0 success, failure otherwise
173  *
174  *  Description:
175  *       Destroy jpeg session
176  *
177  **/
mm_jpeg_intf_destroy_session(uint32_t session_id)178 static int32_t mm_jpeg_intf_destroy_session(uint32_t session_id)
179 {
180   int32_t rc = -1;
181 
182   if (0 == session_id) {
183     CDBG_ERROR("%s:%d] invalid client_hdl or jobId", __func__, __LINE__);
184     return rc;
185   }
186 
187   pthread_mutex_lock(&g_intf_lock);
188   if (NULL == g_jpeg_obj) {
189     /* mm_jpeg obj not exists, return error */
190     CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__);
191     pthread_mutex_unlock(&g_intf_lock);
192     return rc;
193   }
194 
195   rc = mm_jpeg_destroy_session_by_id(g_jpeg_obj, session_id);
196   pthread_mutex_unlock(&g_intf_lock);
197   return rc;
198 }
199 
200 /** mm_jpeg_intf_abort_job:
201  *
202  *  Arguments:
203  *    @jobId: job id
204  *
205  *  Return:
206  *       0 success, failure otherwise
207  *
208  *  Description:
209  *       Abort the jpeg job
210  *
211  **/
mm_jpeg_intf_abort_job(uint32_t job_id)212 static int32_t mm_jpeg_intf_abort_job(uint32_t job_id)
213 {
214   int32_t rc = -1;
215 
216   if (0 == job_id) {
217     CDBG_ERROR("%s:%d] invalid jobId", __func__, __LINE__);
218     return rc;
219   }
220 
221   pthread_mutex_lock(&g_intf_lock);
222   if (NULL == g_jpeg_obj) {
223     /* mm_jpeg obj not exists, return error */
224     CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__);
225     pthread_mutex_unlock(&g_intf_lock);
226     return rc;
227   }
228 
229   rc = mm_jpeg_abort_job(g_jpeg_obj, job_id);
230   pthread_mutex_unlock(&g_intf_lock);
231   return rc;
232 }
233 
234 /** mm_jpeg_intf_close:
235  *
236  *  Arguments:
237  *    @client_hdl: client handle
238  *
239  *  Return:
240  *       0 success, failure otherwise
241  *
242  *  Description:
243  *       Close the jpeg job
244  *
245  **/
mm_jpeg_intf_close(uint32_t client_hdl)246 static int32_t mm_jpeg_intf_close(uint32_t client_hdl)
247 {
248   int32_t rc = -1;
249 
250   if (0 == client_hdl) {
251     CDBG_ERROR("%s:%d] invalid client_hdl", __func__, __LINE__);
252     return rc;
253   }
254 
255   pthread_mutex_lock(&g_intf_lock);
256   if (NULL == g_jpeg_obj) {
257     /* mm_jpeg obj not exists, return error */
258     CDBG_ERROR("%s:%d] mm_jpeg is not opened yet", __func__, __LINE__);
259     pthread_mutex_unlock(&g_intf_lock);
260     return rc;
261   }
262 
263   rc = mm_jpeg_close(g_jpeg_obj, client_hdl);
264   g_jpeg_obj->num_clients--;
265   if(0 == rc) {
266     if (0 == g_jpeg_obj->num_clients) {
267       /* No client, close jpeg internally */
268       rc = mm_jpeg_deinit(g_jpeg_obj);
269       free(g_jpeg_obj);
270       g_jpeg_obj = NULL;
271     }
272   }
273 
274   pthread_mutex_unlock(&g_intf_lock);
275   return rc;
276 }
277 
278 /** jpeg_open:
279  *
280  *  Arguments:
281  *    @ops: ops table pointer
282  *
283  *  Return:
284  *       0 failure, success otherwise
285  *
286  *  Description:
287  *       Open a jpeg client
288  *
289  **/
jpeg_open(mm_jpeg_ops_t * ops,mm_dimension picture_size)290 uint32_t jpeg_open(mm_jpeg_ops_t *ops, mm_dimension picture_size)
291 {
292   int32_t rc = 0;
293   uint32_t clnt_hdl = 0;
294   mm_jpeg_obj* jpeg_obj = NULL;
295   char prop[PROPERTY_VALUE_MAX];
296 
297   property_get("persist.camera.logs", prop, "0");
298   gMmJpegIntfLogLevel = atoi(prop);
299 
300   pthread_mutex_lock(&g_intf_lock);
301   /* first time open */
302   if(NULL == g_jpeg_obj) {
303     jpeg_obj = (mm_jpeg_obj *)malloc(sizeof(mm_jpeg_obj));
304     if(NULL == jpeg_obj) {
305       CDBG_ERROR("%s:%d] no mem", __func__, __LINE__);
306       pthread_mutex_unlock(&g_intf_lock);
307       return clnt_hdl;
308     }
309 
310     /* initialize jpeg obj */
311     memset(jpeg_obj, 0, sizeof(mm_jpeg_obj));
312 
313     /* used for work buf calculation */
314     jpeg_obj->max_pic_w = picture_size.w;
315     jpeg_obj->max_pic_h = picture_size.h;
316 
317     rc = mm_jpeg_init(jpeg_obj);
318     if(0 != rc) {
319       CDBG_ERROR("%s:%d] mm_jpeg_init err = %d", __func__, __LINE__, rc);
320       free(jpeg_obj);
321       pthread_mutex_unlock(&g_intf_lock);
322       return clnt_hdl;
323     }
324 
325     /* remember in global variable */
326     g_jpeg_obj = jpeg_obj;
327   }
328 
329   /* open new client */
330   clnt_hdl = mm_jpeg_new_client(g_jpeg_obj);
331   if (clnt_hdl > 0) {
332     /* valid client */
333     if (NULL != ops) {
334       /* fill in ops tbl if ptr not NULL */
335       ops->start_job = mm_jpeg_intf_start_job;
336       ops->abort_job = mm_jpeg_intf_abort_job;
337       ops->create_session = mm_jpeg_intf_create_session;
338       ops->destroy_session = mm_jpeg_intf_destroy_session;
339       ops->close = mm_jpeg_intf_close;
340     }
341   } else {
342     /* failed new client */
343     CDBG_ERROR("%s:%d] mm_jpeg_new_client failed", __func__, __LINE__);
344 
345     if (0 == g_jpeg_obj->num_clients) {
346       /* no client, close jpeg */
347       mm_jpeg_deinit(g_jpeg_obj);
348       free(g_jpeg_obj);
349       g_jpeg_obj = NULL;
350     }
351   }
352 
353   pthread_mutex_unlock(&g_intf_lock);
354   return clnt_hdl;
355 }
356