blob: e5247e3bfc70690a5c33e8b050058507a1304da6 [file] [log] [blame]
codeworkxf1be2fe2012-03-24 17:38:29 +01001/*
2**
3** Copyright 2008, The Android Open Source Project
4** Copyright 2010, Samsung Electronics Co. LTD
5**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
Daniel Hillenbrand353fecb2012-07-22 16:14:08 +020019//#define LOG_NDEBUG 0
20#define LOG_TAG "Jpeg-api"
codeworkxf1be2fe2012-03-24 17:38:29 +010021
22#include <utils/Log.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/ioctl.h>
28#include <fcntl.h>
29#include <ctype.h>
30#include <unistd.h>
31#include <sys/mman.h>
32#include <string.h>
33#include <errno.h>
34#include <sys/time.h>
35#include <signal.h>
36#include <math.h>
37#include <sys/poll.h>
38
39#ifdef S5P_VMEM
40#include "s5p_vmem_api.h"
41#endif
42#include "jpeg_api.h"
43
44static struct jpeg_lib *jpeg_ctx = NULL;
45#ifdef S5P_VMEM
46static int mem_fp;
47unsigned int cookie;
48#endif /* S5P_VMEM */
49
50static unsigned int get_yuv_size(enum jpeg_frame_format out_format,
51 unsigned int width, unsigned int height)
52{
53 switch (out_format) {
54 case YUV_422 :
55 if (width % 16 != 0)
56 width += 16 - (width % 16);
57 if (height % 8 != 0)
58 height += 8 - (height % 8);
59 break;
60
61 case YUV_420 :
62 if (width % 16 != 0)
63 width += 16 - (width % 16);
64 if (height % 16 != 0)
65 height += 16 - (height % 16);
66 break;
67
68 default:
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +020069 ALOGV("get_yuv_size return fmt(%d)\n", out_format);
codeworkxf1be2fe2012-03-24 17:38:29 +010070 return(0);
71 }
72
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +020073 ALOGV("get_yuv_size width(%d) height(%d)\n", width, height);
codeworkxf1be2fe2012-03-24 17:38:29 +010074
75 switch (out_format) {
76 case YUV_422 :
77 return(width*height*2);
78 case YUV_420 :
79 return((width*height) + (width*height >> 1));
80 default :
81 return(0);
82 }
83}
84
85static int check_input_size(unsigned int width, unsigned int height)
86{
87 if ((width % 16) != 0 || (height % 8) != 0)
88 return -1;
89
90 return 0;
91}
92
93static void init_decode_param(void)
94{
95 jpeg_ctx = (struct jpeg_lib *)malloc(sizeof(struct jpeg_lib));
96 memset(jpeg_ctx, 0x00, sizeof(struct jpeg_lib));
97
98 jpeg_ctx->args.dec_param = (struct jpeg_dec_param *)malloc(sizeof(struct jpeg_dec_param));
99 memset(jpeg_ctx->args.dec_param, 0x00, sizeof(struct jpeg_dec_param));
100}
101
102static void init_encode_param(void)
103{
104 jpeg_ctx = (struct jpeg_lib *)malloc(sizeof(struct jpeg_lib));
105 memset(jpeg_ctx, 0x00, sizeof(struct jpeg_lib));
106
107 jpeg_ctx->args.enc_param = (struct jpeg_enc_param *)malloc(sizeof(struct jpeg_enc_param));
108 memset(jpeg_ctx->args.enc_param, 0x00, sizeof(struct jpeg_enc_param));
109}
110
111int api_jpeg_decode_init()
112{
113 init_decode_param();
114 jpeg_ctx->jpeg_fd = open(JPEG_DRIVER_NAME, O_RDWR);
115
116 if (jpeg_ctx->jpeg_fd < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200117 ALOGE("JPEG driver open failed\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100118 return -1;
119 }
120
121#ifdef S5P_VMEM
122 mem_fp = s5p_vmem_open();
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200123 ALOGV("s5p_vmem_open\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100124#else
125 jpeg_ctx->args.mmapped_addr = (char *) mmap(0,
126 JPEG_TOTAL_BUF_SIZE,
127 PROT_READ | PROT_WRITE,
128 MAP_SHARED,
129 jpeg_ctx->jpeg_fd, 0);
130
131 if (jpeg_ctx->args.mmapped_addr == NULL) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200132 ALOGE("JPEG mmap failed\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100133 return -1;
134 }
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200135 ALOGV("api_jpeg_decode_init jpeg_ctx->args.mmapped_addr 0x%08x\n",
codeworkxf1be2fe2012-03-24 17:38:29 +0100136 jpeg_ctx->args.mmapped_addr);
137#endif /* S5P_VMEM */
138
139 return jpeg_ctx->jpeg_fd;
140}
141
142int api_jpeg_encode_init()
143{
144 init_encode_param();
145 jpeg_ctx->jpeg_fd = open(JPEG_DRIVER_NAME, O_RDWR);
146
147 if (jpeg_ctx->jpeg_fd < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200148 ALOGE("JPEG driver open failed %d\n", jpeg_ctx->jpeg_fd);
codeworkxf1be2fe2012-03-24 17:38:29 +0100149 return -1;
150 }
151
152#ifdef S5P_VMEM
153 mem_fp = s5p_vmem_open();
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200154 ALOGI("s5p_vmem_open\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100155#else
156
157 jpeg_ctx->args.mmapped_addr = (char *) mmap(0,
158 JPEG_TOTAL_BUF_SIZE,
159 PROT_READ | PROT_WRITE,
160 MAP_SHARED,
161 jpeg_ctx->jpeg_fd, 0);
162
163 if (jpeg_ctx->args.mmapped_addr == NULL) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200164 ALOGE("JPEG mmap failed\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100165 return -1;
166 }
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200167 ALOGV("api_jpeg_encode_init jpeg_ctx->args.mmapped_addr 0x%08x\n",
codeworkxf1be2fe2012-03-24 17:38:29 +0100168 jpeg_ctx->args.mmapped_addr);
169#endif /* S5P_VMEM */
170 return jpeg_ctx->jpeg_fd;
171}
172
173int api_jpeg_decode_deinit(int dev_fd)
174{
175 if (jpeg_ctx->args.mmapped_addr != NULL)
176 munmap(jpeg_ctx->args.mmapped_addr, JPEG_TOTAL_BUF_SIZE);
177
178#ifdef S5P_VMEM
179 s5p_free_share(mem_fp, jpeg_ctx->args.in_cookie, jpeg_ctx->args.in_buf);
180 s5p_free_share(mem_fp, jpeg_ctx->args.out_cookie, jpeg_ctx->args.out_buf);
181 s5p_vmem_close(mem_fp);
182#endif
183
184 close(jpeg_ctx->jpeg_fd);
185
186 if (jpeg_ctx->args.dec_param != NULL)
187 free(jpeg_ctx->args.dec_param);
188
189 free(jpeg_ctx);
190
191 return JPEG_OK;
192}
193
194int api_jpeg_encode_deinit(int dev_fd)
195{
196 if (jpeg_ctx->args.mmapped_addr != NULL)
197 munmap(jpeg_ctx->args.mmapped_addr, JPEG_TOTAL_BUF_SIZE);
198
199#ifdef S5P_VMEM
200 s5p_free_share(mem_fp, jpeg_ctx->args.in_cookie, jpeg_ctx->args.in_buf);
201 s5p_free_share(mem_fp, jpeg_ctx->args.out_cookie, jpeg_ctx->args.out_buf);
202 s5p_vmem_close(mem_fp);
203#endif
204 close(jpeg_ctx->jpeg_fd);
205
206 if (jpeg_ctx->args.enc_param != NULL)
207 free(jpeg_ctx->args.enc_param);
208
209 free(jpeg_ctx);
210
211 return JPEG_OK;
212}
213
214void *api_jpeg_get_decode_in_buf(int dev_fd, unsigned int size)
215{
216 if (size < 0 || size > MAX_JPEG_RES) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200217 ALOGE("Invalid decode input buffer size\r\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100218 return NULL;
219 }
220#ifdef S5P_VMEM
221 jpeg_ctx->args.in_cookie = (unsigned int)ioctl(jpeg_ctx->jpeg_fd,
222 IOCTL_GET_DEC_IN_BUF, size);
223 jpeg_ctx->args.in_buf = s5p_malloc_share(mem_fp,
224 jpeg_ctx->args.in_cookie,
225 &jpeg_ctx->args.in_buf_size);
226#else
227 jpeg_ctx->args.in_buf = (char *)ioctl(jpeg_ctx->jpeg_fd,
228 IOCTL_GET_DEC_IN_BUF,
229 jpeg_ctx->args.mmapped_addr);
230#endif /* S5P_VMEM */
231 return (void *)(jpeg_ctx->args.in_buf);
232}
233
234void *api_jpeg_get_encode_in_buf(int dev_fd, unsigned int size)
235{
236#ifdef S5P_VMEM
237 jpeg_ctx->args.in_cookie = (unsigned int)ioctl(jpeg_ctx->jpeg_fd,
238 IOCTL_GET_ENC_IN_BUF, (size*3));
239 jpeg_ctx->args.in_buf = s5p_malloc_share(mem_fp,
240 jpeg_ctx->args.in_cookie,
241 &jpeg_ctx->args.in_buf_size);
242#else
243 jpeg_ctx->args.enc_param->size = size;
244 jpeg_ctx->args.in_buf = (char *)ioctl(jpeg_ctx->jpeg_fd,
245 IOCTL_GET_ENC_IN_BUF,
246 jpeg_ctx->args.mmapped_addr);
247#endif
248
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200249 ALOGV("api_jpeg_get_encode_in_buf: 0x%x\n",
codeworkxf1be2fe2012-03-24 17:38:29 +0100250 jpeg_ctx->args.in_buf);
251
252 return (void *)(jpeg_ctx->args.in_buf);
253}
254
255void *api_jpeg_get_decode_out_buf(int dev_fd)
256{
257#ifdef S5P_VMEM
258 jpeg_ctx->args.out_cookie = (unsigned int)ioctl(jpeg_ctx->jpeg_fd,
259 IOCTL_GET_DEC_OUT_BUF, JPEG_FRAME_BUF_SIZE);
260 jpeg_ctx->args.out_buf = s5p_malloc_share(mem_fp,
261 jpeg_ctx->args.out_cookie,
262 &jpeg_ctx->args.out_buf_size);
263#else
264 jpeg_ctx->args.out_buf = (char *)ioctl(jpeg_ctx->jpeg_fd,
265 IOCTL_GET_DEC_OUT_BUF,
266 jpeg_ctx->args.mmapped_addr);
267#endif /* S5P_VMEM */
268 /*
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200269 ALOGV("api_jpeg_get_decode_out_buf: 0x%x\n",
codeworkxf1be2fe2012-03-24 17:38:29 +0100270 jpeg_ctx->args.out_buf);
271 */
272 return (void *)(jpeg_ctx->args.out_buf);
273}
274
275void *api_jpeg_get_encode_out_buf(int dev_fd)
276{
277#ifdef S5P_VMEM
278 jpeg_ctx->args.out_cookie = (unsigned int)ioctl(jpeg_ctx->jpeg_fd,
279 IOCTL_GET_ENC_OUT_BUF, JPEG_STREAM_BUF_SIZE);
280 jpeg_ctx->args.out_buf = s5p_malloc_share(mem_fp,
281 jpeg_ctx->args.out_cookie,
282 &jpeg_ctx->args.out_buf_size);
283#else
284 jpeg_ctx->args.out_buf = (char *)ioctl(jpeg_ctx->jpeg_fd,
285 IOCTL_GET_ENC_OUT_BUF,
286 jpeg_ctx->args.mmapped_addr);
287#endif /* S5P_VMEM */
288
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200289 ALOGV("api_jpeg_get_encode_out_buf: 0x%x\n",
codeworkxf1be2fe2012-03-24 17:38:29 +0100290 jpeg_ctx->args.out_buf);
291
292 return (void *)(jpeg_ctx->args.out_buf);
293}
294
295void api_jpeg_set_decode_param(struct jpeg_dec_param *param)
296{
297 memcpy(jpeg_ctx->args.dec_param, param, sizeof(struct jpeg_dec_param));
298 ioctl(jpeg_ctx->jpeg_fd, IOCTL_SET_DEC_PARAM, jpeg_ctx->args.dec_param);
299}
300
301void api_jpeg_set_encode_param(struct jpeg_enc_param *param)
302{
303 memcpy(jpeg_ctx->args.enc_param, param, sizeof(struct jpeg_enc_param));
304 ioctl(jpeg_ctx->jpeg_fd, IOCTL_SET_ENC_PARAM, jpeg_ctx->args.enc_param);
305}
306
307enum jpeg_ret_type api_jpeg_decode_exe(int dev_fd,
308 struct jpeg_dec_param *dec_param)
309{
310 struct jpeg_args *arg;
311
312 arg = &(jpeg_ctx->args);
313
314 ioctl(jpeg_ctx->jpeg_fd, IOCTL_JPEG_DEC_EXE, arg->dec_param);
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200315 ALOGV("api_jpeg_decode_exe dec_param->out_fmt :%d \
codeworkxf1be2fe2012-03-24 17:38:29 +0100316 dec_param->width : %d dec_param->height : %d\n",
317 arg->dec_param->out_fmt,
318 arg->dec_param->width,
319 arg->dec_param->height);
320 dec_param->width = arg->dec_param->width;
321 dec_param->height = arg->dec_param->height;
322 dec_param->size = get_yuv_size(arg->dec_param->out_fmt,
323 arg->dec_param->width,
324 arg->dec_param->height);
325
326 return JPEG_DECODE_OK;
327}
328
329enum jpeg_ret_type api_jpeg_encode_exe(int dev_fd,
330 struct jpeg_enc_param *enc_param)
331{
332 struct jpeg_args *arg;
333 arg = &(jpeg_ctx->args);
334
335 // check MCU validation width & height & sampling mode
336 if (check_input_size(jpeg_ctx->args.enc_param->width,
337 jpeg_ctx->args.enc_param->height) < 0) {
Daniel Hillenbrand0fdadca2012-07-22 15:45:33 +0200338 ALOGV("width/height doesn't match with MCU\r\n");
codeworkxf1be2fe2012-03-24 17:38:29 +0100339 return JPEG_FAIL;
340 }
341
342 ioctl(jpeg_ctx->jpeg_fd, IOCTL_JPEG_ENC_EXE, arg->enc_param);
343
344 enc_param->size = arg->enc_param->size;
345
346 return JPEG_ENCODE_OK;
347}