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