Commit | Line | Data |
---|---|---|
13d8c7b4 SK |
1 | /* |
2 | * Copyright Samsung Electronics Co.,LTD. | |
3 | * Copyright (C) 2010 The Android Open Source Project | |
4 | * | |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
be8daa96 | 18 | #define LOG_TAG "ExynosJpegForCamera" |
13d8c7b4 | 19 | #include <utils/Log.h> |
bb99f0ed | 20 | #include <string.h> |
13d8c7b4 SK |
21 | |
22 | #include "ExynosJpegEncoderForCamera.h" | |
23 | ||
24 | static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; | |
25 | ||
69d1e6e9 | 26 | #define JPEG_ERROR_LOG ALOGE |
177dd33d | 27 | #define JPEG_WARNING_LOG ALOGW |
13d8c7b4 SK |
28 | |
29 | #define JPEG_THUMBNAIL_QUALITY (60) | |
30 | #define EXIF_LIMIT_SIZE (64*1024) | |
31 | #define THUMBNAIL_IMAGE_PIXEL_SIZE (4) | |
32 | #define MAX_JPG_WIDTH (8192) | |
33 | #define MAX_JPG_HEIGHT (8192) | |
34 | ||
35 | #define MAX_INPUT_BUFFER_PLANE_NUM (1) | |
36 | #define MAX_OUTPUT_BUFFER_PLANE_NUM (1) | |
37 | ||
38 | ExynosJpegEncoderForCamera::ExynosJpegEncoderForCamera() | |
39 | { | |
40 | m_flagCreate = false; | |
41 | m_jpegMain = NULL; | |
42 | m_jpegThumb = NULL; | |
43 | m_thumbnailW = 0; | |
44 | m_thumbnailH = 0; | |
45 | m_thumbnailQuality = JPEG_THUMBNAIL_QUALITY; | |
177dd33d | 46 | m_ionJpegClient = -1; |
13d8c7b4 SK |
47 | initJpegMemory(&m_stThumbInBuf, MAX_IMAGE_PLANE_NUM); |
48 | initJpegMemory(&m_stThumbOutBuf, MAX_IMAGE_PLANE_NUM); | |
eed7ed1b SK |
49 | initJpegMemory(&m_stMainInBuf, MAX_IMAGE_PLANE_NUM); |
50 | initJpegMemory(&m_stMainOutBuf, MAX_IMAGE_PLANE_NUM); | |
13d8c7b4 SK |
51 | } |
52 | ||
53 | ExynosJpegEncoderForCamera::~ExynosJpegEncoderForCamera() | |
54 | { | |
55 | if (m_flagCreate == true) { | |
56 | this->destroy(); | |
57 | } | |
58 | } | |
59 | ||
60 | bool ExynosJpegEncoderForCamera::flagCreate(void) | |
61 | { | |
62 | return m_flagCreate; | |
63 | } | |
64 | ||
65 | int ExynosJpegEncoderForCamera::create(void) | |
66 | { | |
67 | int ret = ERROR_NONE; | |
68 | if (m_flagCreate == true) { | |
69 | return ERROR_ALREADY_CREATE; | |
70 | } | |
71 | ||
72 | if (m_jpegMain == NULL) { | |
73 | m_jpegMain = new ExynosJpegEncoder; | |
74 | ||
75 | if (m_jpegMain == NULL) { | |
76 | JPEG_ERROR_LOG("ERR(%s):Cannot create ExynosJpegEncoder class\n", __func__); | |
77 | return ERROR_CANNOT_CREATE_EXYNOS_JPEG_ENC_HAL; | |
78 | } | |
79 | ||
80 | ret = m_jpegMain->create(); | |
81 | if (ret) { | |
82 | return ret; | |
83 | } | |
84 | ||
85 | ret = m_jpegMain->setCache(JPEG_CACHE_ON); | |
86 | ||
87 | if (ret) { | |
88 | m_jpegMain->destroy(); | |
89 | return ret; | |
90 | } | |
91 | } | |
92 | ||
177dd33d MS |
93 | m_ionJpegClient = |
94 | m_stMainOutBuf.ionClient = | |
95 | m_stMainInBuf.ionClient = | |
96 | m_stThumbInBuf.ionClient = | |
97 | m_stThumbOutBuf.ionClient = | |
98 | createIonClient(m_ionJpegClient); | |
99 | if(m_ionJpegClient < 0) { | |
13d8c7b4 SK |
100 | return ERROR_CANNOT_CREATE_EXYNOS_JPEG_ENC_HAL; |
101 | } | |
13d8c7b4 SK |
102 | |
103 | m_flagCreate = true; | |
104 | ||
105 | return ERROR_NONE; | |
106 | } | |
107 | ||
108 | int ExynosJpegEncoderForCamera::destroy(void) | |
109 | { | |
110 | if (m_flagCreate == false) { | |
111 | return ERROR_ALREADY_DESTROY; | |
112 | } | |
113 | ||
114 | if (m_jpegMain != NULL) { | |
115 | m_jpegMain->destroy(); | |
116 | delete m_jpegMain; | |
117 | m_jpegMain = NULL; | |
118 | } | |
119 | ||
120 | if (m_jpegThumb != NULL) { | |
121 | int iSize = sizeof(char)*m_thumbnailW*m_thumbnailH*4; | |
122 | ||
123 | freeJpegMemory(&m_stThumbInBuf, MAX_IMAGE_PLANE_NUM); | |
124 | freeJpegMemory(&m_stThumbOutBuf, MAX_IMAGE_PLANE_NUM); | |
eed7ed1b SK |
125 | initJpegMemory(&m_stMainInBuf, MAX_IMAGE_PLANE_NUM); |
126 | initJpegMemory(&m_stMainOutBuf, MAX_IMAGE_PLANE_NUM); | |
177dd33d MS |
127 | m_ionJpegClient = |
128 | m_stMainOutBuf.ionClient = | |
129 | m_stMainInBuf.ionClient = | |
130 | m_stThumbInBuf.ionClient = | |
131 | m_stThumbOutBuf.ionClient = | |
132 | deleteIonClient(m_ionJpegClient); | |
13d8c7b4 SK |
133 | m_jpegThumb->destroy(); |
134 | delete m_jpegThumb; | |
135 | m_jpegThumb = NULL; | |
136 | } | |
177dd33d MS |
137 | if (m_ionJpegClient >= 0) { |
138 | JPEG_WARNING_LOG("WARNING(%s):Ion Client created outside of m_jpegThumb\n", __func__); | |
139 | m_ionJpegClient = | |
140 | m_stMainOutBuf.ionClient = | |
141 | m_stMainInBuf.ionClient = | |
142 | m_stThumbInBuf.ionClient = | |
143 | m_stThumbOutBuf.ionClient = | |
144 | deleteIonClient(m_ionJpegClient); | |
145 | } | |
13d8c7b4 SK |
146 | |
147 | m_flagCreate = false; | |
148 | m_thumbnailW = 0; | |
149 | m_thumbnailH = 0; | |
150 | m_thumbnailQuality = JPEG_THUMBNAIL_QUALITY; | |
151 | return ERROR_NONE; | |
152 | } | |
153 | ||
154 | int ExynosJpegEncoderForCamera::setSize(int w, int h) | |
155 | { | |
156 | if (m_flagCreate == false) { | |
157 | return ERROR_NOT_YET_CREATED; | |
158 | } | |
159 | ||
160 | return m_jpegMain->setSize(w, h); | |
161 | } | |
162 | ||
163 | ||
164 | int ExynosJpegEncoderForCamera::setQuality(int quality) | |
165 | { | |
166 | if (m_flagCreate == false) { | |
167 | return ERROR_NOT_YET_CREATED; | |
168 | } | |
169 | ||
170 | return m_jpegMain->setQuality(quality); | |
171 | } | |
172 | ||
173 | int ExynosJpegEncoderForCamera::setColorFormat(int colorFormat) | |
174 | { | |
175 | if (m_flagCreate == false) { | |
176 | return ERROR_NOT_YET_CREATED; | |
177 | } | |
178 | ||
179 | return m_jpegMain->setColorFormat(colorFormat); | |
180 | } | |
181 | ||
182 | int ExynosJpegEncoderForCamera::setJpegFormat(int jpegFormat) | |
183 | { | |
184 | if (m_flagCreate == false) { | |
185 | return ERROR_NOT_YET_CREATED; | |
186 | } | |
187 | ||
188 | return m_jpegMain->setJpegFormat(jpegFormat); | |
189 | } | |
190 | ||
191 | int ExynosJpegEncoderForCamera::updateConfig(void) | |
192 | { | |
193 | if (m_flagCreate == false) { | |
194 | return ERROR_NOT_YET_CREATED; | |
195 | } | |
196 | ||
197 | return m_jpegMain->updateConfig(); | |
198 | } | |
199 | ||
eed7ed1b | 200 | int ExynosJpegEncoderForCamera::setInBuf(int *buf, char** vBuf, int *size) |
13d8c7b4 SK |
201 | { |
202 | if (m_flagCreate == false) { | |
203 | return ERROR_NOT_YET_CREATED; | |
204 | } | |
205 | ||
206 | if (buf == NULL) { | |
207 | return ERROR_BUFFR_IS_NULL; | |
208 | } | |
209 | ||
210 | if (size == NULL) { | |
211 | return ERROR_BUFFR_IS_NULL; | |
212 | } | |
213 | ||
214 | int ret = ERROR_NONE; | |
215 | ||
216 | ret = m_jpegMain->setInBuf(buf, size); | |
217 | if (ret) { | |
218 | JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__); | |
219 | return ret; | |
220 | } | |
eed7ed1b SK |
221 | m_stMainInBuf.ionBuffer[0] = buf[0]; |
222 | m_stMainInBuf.iSize[0] = size[0]; | |
223 | m_stMainInBuf.pcBuf[0] = vBuf[0]; | |
13d8c7b4 SK |
224 | |
225 | return ERROR_NONE; | |
226 | } | |
227 | ||
eed7ed1b | 228 | int ExynosJpegEncoderForCamera::setOutBuf(int buf, char* vBuf, int size) |
13d8c7b4 SK |
229 | { |
230 | if (m_flagCreate == false) { | |
231 | return ERROR_NOT_YET_CREATED; | |
232 | } | |
233 | ||
be8daa96 | 234 | if (!buf) { |
13d8c7b4 SK |
235 | return ERROR_BUFFR_IS_NULL; |
236 | } | |
237 | ||
238 | if (size<=0) { | |
239 | return ERROR_BUFFER_TOO_SMALL; | |
240 | } | |
241 | ||
242 | int ret = ERROR_NONE; | |
243 | ret = m_jpegMain->setOutBuf(buf, size); | |
244 | if (ret) { | |
245 | JPEG_ERROR_LOG("%s::Fail to JPEG output buffer!!\n", __func__); | |
246 | return ret; | |
247 | } | |
eed7ed1b SK |
248 | m_stMainOutBuf.ionBuffer[0] = buf; |
249 | m_stMainOutBuf.iSize[0] = size; | |
250 | m_stMainOutBuf.pcBuf[0] = vBuf; | |
13d8c7b4 SK |
251 | |
252 | return ERROR_NONE; | |
253 | } | |
254 | ||
255 | int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo) | |
256 | { | |
257 | int ret = ERROR_NONE; | |
258 | unsigned char *exifOut = NULL; | |
259 | ||
260 | if (m_flagCreate == false) { | |
261 | return ERROR_NOT_YET_CREATED; | |
262 | } | |
263 | ||
264 | ||
265 | ret = m_jpegMain->encode(); | |
266 | if (ret) { | |
267 | JPEG_ERROR_LOG("encode failed\n"); | |
268 | return ret; | |
269 | } | |
270 | ||
271 | int iJpegSize = m_jpegMain->getJpegSize(); | |
272 | ||
273 | if (iJpegSize<=0) { | |
274 | JPEG_ERROR_LOG("%s:: output_size is too small(%d)!!\n", __func__, iJpegSize); | |
275 | return ERROR_OUT_BUFFER_SIZE_TOO_SMALL; | |
276 | } | |
277 | ||
eed7ed1b SK |
278 | int iOutputSize = m_stMainOutBuf.iSize[0]; |
279 | int iJpegBuffer = m_stMainOutBuf.ionBuffer[0]; | |
280 | char *pcJpegBuffer = m_stMainOutBuf.pcBuf[0]; | |
13d8c7b4 | 281 | |
be8daa96 | 282 | if (!pcJpegBuffer[0]) { |
13d8c7b4 SK |
283 | JPEG_ERROR_LOG("%s::pcJpegBuffer[0] is null!!\n", __func__); |
284 | return ERROR_OUT_BUFFER_CREATE_FAIL; | |
285 | } | |
286 | ||
287 | if (exifInfo != NULL) { | |
288 | unsigned int thumbLen, exifLen; | |
289 | ||
290 | unsigned int bufSize = 0; | |
291 | if (exifInfo->enableThumb) { | |
292 | if (encodeThumbnail(&thumbLen)) { | |
293 | bufSize = EXIF_FILE_SIZE; | |
294 | exifInfo->enableThumb = false; | |
295 | } else { | |
296 | if (thumbLen > EXIF_LIMIT_SIZE) { | |
297 | bufSize = EXIF_FILE_SIZE; | |
298 | exifInfo->enableThumb = false; | |
299 | } | |
300 | else { | |
301 | bufSize = EXIF_FILE_SIZE + thumbLen; | |
302 | } | |
303 | } | |
304 | } else { | |
305 | bufSize = EXIF_FILE_SIZE; | |
306 | exifInfo->enableThumb = false; | |
307 | } | |
308 | ||
309 | exifOut = new unsigned char[bufSize]; | |
310 | if (exifOut == NULL) { | |
311 | JPEG_ERROR_LOG("%s::Failed to allocate for exifOut\n", __func__); | |
312 | delete[] exifOut; | |
313 | return ERROR_EXIFOUT_ALLOC_FAIL; | |
314 | } | |
315 | memset(exifOut, 0, bufSize); | |
316 | ||
317 | if (makeExif (exifOut, exifInfo, &exifLen)) { | |
318 | JPEG_ERROR_LOG("%s::Failed to make EXIF\n", __func__); | |
319 | delete[] exifOut; | |
320 | return ERROR_MAKE_EXIF_FAIL; | |
321 | } | |
322 | ||
323 | if (exifLen <= EXIF_LIMIT_SIZE) { | |
324 | memmove(pcJpegBuffer+exifLen+2, pcJpegBuffer+2, iJpegSize - 2); | |
325 | memcpy(pcJpegBuffer+2, exifOut, exifLen); | |
326 | iJpegSize += exifLen; | |
327 | } | |
328 | ||
329 | delete[] exifOut; | |
330 | } | |
331 | ||
13d8c7b4 SK |
332 | *size = iJpegSize; |
333 | ||
334 | return ERROR_NONE; | |
335 | } | |
336 | ||
337 | int ExynosJpegEncoderForCamera::makeExif (unsigned char *exifOut, | |
338 | exif_attribute_t *exifInfo, | |
339 | unsigned int *size, | |
340 | bool useMainbufForThumb) | |
341 | { | |
342 | unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset; | |
343 | unsigned int tmp, LongerTagOffest = 0, exifSizeExceptThumb; | |
344 | pApp1Start = pCur = exifOut; | |
345 | ||
346 | //2 Exif Identifier Code & TIFF Header | |
347 | pCur += 4; // Skip 4 Byte for APP1 marker and length | |
348 | unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; | |
349 | memcpy(pCur, ExifIdentifierCode, 6); | |
350 | pCur += 6; | |
351 | ||
352 | /* Byte Order - little endian, Offset of IFD - 0x00000008.H */ | |
353 | unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 }; | |
354 | memcpy(pCur, TiffHeader, 8); | |
355 | pIfdStart = pCur; | |
356 | pCur += 8; | |
357 | ||
358 | //2 0th IFD TIFF Tags | |
359 | if (exifInfo->enableGps) | |
360 | tmp = NUM_0TH_IFD_TIFF; | |
361 | else | |
362 | tmp = NUM_0TH_IFD_TIFF - 1; | |
363 | ||
364 | memcpy(pCur, &tmp, NUM_SIZE); | |
365 | pCur += NUM_SIZE; | |
366 | ||
367 | LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; | |
368 | ||
369 | writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, | |
370 | 1, exifInfo->width); | |
371 | writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, | |
372 | 1, exifInfo->height); | |
373 | writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII, | |
374 | strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart); | |
375 | writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII, | |
376 | strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart); | |
377 | writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, | |
378 | 1, exifInfo->orientation); | |
379 | writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII, | |
380 | strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart); | |
381 | writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII, | |
382 | 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); | |
be8daa96 MS |
383 | writeExifIfd(&pCur, EXIF_TAG_SUBSEC_TIME, EXIF_TYPE_ASCII, |
384 | sizeof(exifInfo->sub_sec), exifInfo->sub_sec); | |
13d8c7b4 SK |
385 | writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT, |
386 | 1, exifInfo->ycbcr_positioning); | |
387 | writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG, | |
388 | 1, LongerTagOffest); | |
389 | if (exifInfo->enableGps) { | |
390 | pGpsIfdPtr = pCur; | |
391 | pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer | |
392 | } | |
393 | ||
394 | pNextIfdOffset = pCur; // Skip a offset size for next IFD offset | |
395 | pCur += OFFSET_SIZE; | |
396 | ||
397 | //2 0th IFD Exif Private Tags | |
398 | pCur = pIfdStart + LongerTagOffest; | |
399 | ||
400 | tmp = NUM_0TH_IFD_EXIF; | |
401 | memcpy(pCur, &tmp , NUM_SIZE); | |
402 | pCur += NUM_SIZE; | |
403 | ||
404 | LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE; | |
405 | ||
406 | writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL, | |
407 | 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart); | |
408 | writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL, | |
409 | 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart); | |
410 | writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT, | |
411 | 1, exifInfo->exposure_program); | |
412 | writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT, | |
413 | 1, exifInfo->iso_speed_rating); | |
414 | writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED, | |
415 | 4, exifInfo->exif_version); | |
416 | writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII, | |
417 | 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); | |
be8daa96 MS |
418 | writeExifIfd(&pCur, EXIF_TAG_SUBSEC_TIME_ORG, EXIF_TYPE_ASCII, |
419 | sizeof(exifInfo->sub_sec), exifInfo->sub_sec); | |
13d8c7b4 SK |
420 | writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII, |
421 | 20, exifInfo->date_time, &LongerTagOffest, pIfdStart); | |
be8daa96 MS |
422 | writeExifIfd(&pCur, EXIF_TAG_SUBSEC_TIME_DIGITIZE, EXIF_TYPE_ASCII, |
423 | sizeof(exifInfo->sub_sec), exifInfo->sub_sec); | |
13d8c7b4 SK |
424 | writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL, |
425 | 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart); | |
426 | writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL, | |
427 | 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart); | |
428 | writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL, | |
429 | 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart); | |
430 | writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL, | |
431 | 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart); | |
432 | writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL, | |
433 | 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart); | |
434 | writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT, | |
435 | 1, exifInfo->metering_mode); | |
436 | writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT, | |
437 | 1, exifInfo->flash); | |
438 | writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL, | |
439 | 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart); | |
440 | char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 }; | |
441 | int commentsLen = strlen((char *)exifInfo->user_comment) + 1; | |
442 | memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen); | |
443 | memcpy(exifInfo->user_comment, code, sizeof(code)); | |
444 | writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED, | |
445 | commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart); | |
446 | writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT, | |
447 | 1, exifInfo->color_space); | |
448 | writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG, | |
449 | 1, exifInfo->width); | |
450 | writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG, | |
451 | 1, exifInfo->height); | |
452 | writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG, | |
453 | 1, exifInfo->exposure_mode); | |
454 | writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG, | |
455 | 1, exifInfo->white_balance); | |
456 | writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG, | |
457 | 1, exifInfo->scene_capture_type); | |
458 | tmp = 0; | |
459 | memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset | |
460 | pCur += OFFSET_SIZE; | |
461 | ||
462 | //2 0th IFD GPS Info Tags | |
463 | if (exifInfo->enableGps) { | |
464 | writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG, | |
465 | 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD | |
466 | ||
467 | pCur = pIfdStart + LongerTagOffest; | |
468 | ||
469 | if (exifInfo->gps_processing_method[0] == 0) { | |
470 | // don't create GPS_PROCESSING_METHOD tag if there isn't any | |
471 | tmp = NUM_0TH_IFD_GPS - 1; | |
472 | } else { | |
473 | tmp = NUM_0TH_IFD_GPS; | |
474 | } | |
475 | memcpy(pCur, &tmp, NUM_SIZE); | |
476 | pCur += NUM_SIZE; | |
477 | ||
478 | LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE; | |
479 | ||
480 | writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE, | |
481 | 4, exifInfo->gps_version_id); | |
482 | writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII, | |
483 | 2, exifInfo->gps_latitude_ref); | |
484 | writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL, | |
485 | 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart); | |
486 | writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII, | |
487 | 2, exifInfo->gps_longitude_ref); | |
488 | writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL, | |
489 | 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart); | |
490 | writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE, | |
491 | 1, exifInfo->gps_altitude_ref); | |
492 | writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL, | |
493 | 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart); | |
494 | writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL, | |
495 | 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart); | |
496 | tmp = strlen((char*)exifInfo->gps_processing_method); | |
497 | if (tmp > 0) { | |
498 | if (tmp > 100) { | |
499 | tmp = 100; | |
500 | } | |
501 | unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)]; | |
502 | memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix)); | |
503 | memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp); | |
504 | writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED, | |
505 | tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart); | |
506 | } | |
507 | writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII, | |
508 | 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart); | |
509 | tmp = 0; | |
510 | memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset | |
511 | pCur += OFFSET_SIZE; | |
512 | } | |
513 | ||
514 | //2 1th IFD TIFF Tags | |
515 | int iThumbFd = 0; | |
516 | char *thumbBuf = NULL; | |
517 | unsigned int thumbSize = 0; | |
518 | int thumbBufSize = 0; | |
519 | int ret = ERROR_NONE; | |
520 | ||
521 | if (useMainbufForThumb) { | |
522 | if (m_jpegMain) { | |
523 | ret = m_jpegMain->getOutBuf((int *)&iThumbFd, (int *)&thumbBufSize); | |
524 | if (ret != ERROR_NONE) { | |
525 | iThumbFd = -1; | |
526 | } | |
527 | thumbSize = (unsigned int)m_jpegMain->getJpegSize(); | |
eed7ed1b | 528 | thumbBuf = m_stMainOutBuf.pcBuf[0]; |
13d8c7b4 SK |
529 | } |
530 | } else { | |
531 | if (m_jpegThumb) { | |
532 | ret = m_jpegThumb->getOutBuf((int *)&iThumbFd, (int *)&thumbBufSize); | |
533 | if (ret != ERROR_NONE) { | |
534 | iThumbFd = -1; | |
535 | } | |
536 | thumbSize = (unsigned int)m_jpegThumb->getJpegSize(); | |
eed7ed1b | 537 | thumbBuf = m_stThumbOutBuf.pcBuf[0]; |
13d8c7b4 SK |
538 | } |
539 | } | |
540 | ||
13d8c7b4 SK |
541 | if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize != 0)) { |
542 | exifSizeExceptThumb = tmp = LongerTagOffest; | |
543 | memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD | |
544 | ||
545 | pCur = pIfdStart + LongerTagOffest; | |
546 | ||
547 | tmp = NUM_1TH_IFD_TIFF; | |
548 | memcpy(pCur, &tmp, NUM_SIZE); | |
549 | pCur += NUM_SIZE; | |
550 | ||
551 | LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE; | |
552 | ||
553 | writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG, | |
554 | 1, exifInfo->widthThumb); | |
555 | writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG, | |
556 | 1, exifInfo->heightThumb); | |
557 | writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT, | |
558 | 1, exifInfo->compression_scheme); | |
559 | writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, | |
560 | 1, exifInfo->orientation); | |
561 | writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL, | |
562 | 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart); | |
563 | writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL, | |
564 | 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart); | |
565 | writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT, | |
566 | 1, exifInfo->resolution_unit); | |
567 | writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG, | |
568 | 1, LongerTagOffest); | |
569 | writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG, | |
570 | 1, thumbSize); | |
571 | ||
572 | tmp = 0; | |
573 | memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset | |
574 | pCur += OFFSET_SIZE; | |
575 | ||
576 | memcpy(pIfdStart + LongerTagOffest, | |
577 | thumbBuf, thumbSize); | |
578 | LongerTagOffest += thumbSize; | |
579 | if (LongerTagOffest > EXIF_LIMIT_SIZE) { | |
580 | LongerTagOffest = exifSizeExceptThumb; | |
581 | tmp = 0; | |
582 | memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD | |
583 | } | |
584 | } else { | |
585 | tmp = 0; | |
586 | memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD | |
587 | } | |
588 | ||
be8daa96 MS |
589 | *(pApp1Start++) = 0xff; |
590 | *(pApp1Start++) = 0xe1; | |
13d8c7b4 SK |
591 | |
592 | *size = 10 + LongerTagOffest; | |
593 | tmp = *size - 2; // APP1 Maker isn't counted | |
be8daa96 MS |
594 | *(pApp1Start++) = (tmp >> 8) & 0xFF; |
595 | *(pApp1Start++) = tmp & 0xFF; | |
13d8c7b4 | 596 | |
13d8c7b4 SK |
597 | return ERROR_NONE; |
598 | } | |
599 | ||
600 | /* | |
601 | * private member functions | |
602 | */ | |
603 | inline void ExynosJpegEncoderForCamera::writeExifIfd(unsigned char **pCur, | |
604 | unsigned short tag, | |
605 | unsigned short type, | |
606 | unsigned int count, | |
607 | unsigned int value) | |
608 | { | |
609 | memcpy(*pCur, &tag, 2); | |
610 | *pCur += 2; | |
611 | memcpy(*pCur, &type, 2); | |
612 | *pCur += 2; | |
613 | memcpy(*pCur, &count, 4); | |
614 | *pCur += 4; | |
615 | memcpy(*pCur, &value, 4); | |
616 | *pCur += 4; | |
617 | } | |
618 | ||
619 | inline void ExynosJpegEncoderForCamera::writeExifIfd(unsigned char **pCur, | |
620 | unsigned short tag, | |
621 | unsigned short type, | |
622 | unsigned int count, | |
623 | unsigned char *pValue) | |
624 | { | |
625 | char buf[4] = { 0,}; | |
626 | ||
627 | memcpy(buf, pValue, count); | |
628 | memcpy(*pCur, &tag, 2); | |
629 | *pCur += 2; | |
630 | memcpy(*pCur, &type, 2); | |
631 | *pCur += 2; | |
632 | memcpy(*pCur, &count, 4); | |
633 | *pCur += 4; | |
634 | memcpy(*pCur, buf, 4); | |
635 | *pCur += 4; | |
636 | } | |
637 | ||
638 | inline void ExynosJpegEncoderForCamera::writeExifIfd(unsigned char **pCur, | |
639 | unsigned short tag, | |
640 | unsigned short type, | |
641 | unsigned int count, | |
642 | unsigned char *pValue, | |
643 | unsigned int *offset, | |
644 | unsigned char *start) | |
645 | { | |
646 | memcpy(*pCur, &tag, 2); | |
647 | *pCur += 2; | |
648 | memcpy(*pCur, &type, 2); | |
649 | *pCur += 2; | |
650 | memcpy(*pCur, &count, 4); | |
651 | *pCur += 4; | |
652 | memcpy(*pCur, offset, 4); | |
653 | *pCur += 4; | |
654 | memcpy(start + *offset, pValue, count); | |
655 | *offset += count; | |
656 | } | |
657 | ||
658 | inline void ExynosJpegEncoderForCamera::writeExifIfd(unsigned char **pCur, | |
659 | unsigned short tag, | |
660 | unsigned short type, | |
661 | unsigned int count, | |
662 | rational_t *pValue, | |
663 | unsigned int *offset, | |
664 | unsigned char *start) | |
665 | { | |
666 | memcpy(*pCur, &tag, 2); | |
667 | *pCur += 2; | |
668 | memcpy(*pCur, &type, 2); | |
669 | *pCur += 2; | |
670 | memcpy(*pCur, &count, 4); | |
671 | *pCur += 4; | |
672 | memcpy(*pCur, offset, 4); | |
673 | *pCur += 4; | |
674 | memcpy(start + *offset, pValue, 8 * count); | |
675 | *offset += 8 * count; | |
676 | } | |
677 | ||
678 | int ExynosJpegEncoderForCamera::scaleDownYuv422(char **srcBuf, unsigned int srcW, unsigned int srcH, char **dstBuf, unsigned int dstW, unsigned int dstH) | |
679 | { | |
680 | int step_x, step_y; | |
681 | int src_y_start_pos, dst_pos, src_pos; | |
682 | char *src_buf = srcBuf[0]; | |
683 | char *dst_buf = dstBuf[0]; | |
684 | ||
685 | if (dstW & 0x01 || dstH & 0x01) { | |
686 | return ERROR_INVALID_SCALING_WIDTH_HEIGHT; | |
687 | } | |
688 | ||
689 | step_x = srcW / dstW; | |
690 | step_y = srcH / dstH; | |
691 | ||
692 | unsigned int srcWStride = srcW * 2; | |
693 | unsigned int stepXStride = step_x * 2; | |
694 | ||
695 | dst_pos = 0; | |
696 | for (unsigned int y = 0; y < dstH; y++) { | |
697 | src_y_start_pos = srcWStride * step_y * y; | |
698 | ||
699 | for (unsigned int x = 0; x < dstW; x += 2) { | |
700 | src_pos = src_y_start_pos + (stepXStride * x); | |
701 | ||
702 | dst_buf[dst_pos++] = src_buf[src_pos ]; | |
703 | dst_buf[dst_pos++] = src_buf[src_pos + 1]; | |
704 | dst_buf[dst_pos++] = src_buf[src_pos + 2]; | |
705 | dst_buf[dst_pos++] = src_buf[src_pos + 3]; | |
706 | } | |
707 | } | |
708 | ||
709 | return ERROR_NONE; | |
710 | } | |
711 | ||
712 | int ExynosJpegEncoderForCamera::scaleDownYuv422_2p(char **srcBuf, unsigned int srcW, unsigned int srcH, char **dstBuf, unsigned int dstW, unsigned int dstH) | |
713 | { | |
714 | int32_t step_x, step_y; | |
715 | int32_t src_y_start_pos, dst_pos, src_pos; | |
716 | int32_t src_Y_offset; | |
717 | char *src_buf; | |
718 | char *dst_buf; | |
719 | ||
720 | if (dstW % 2 != 0 || dstH % 2 != 0) { | |
721 | return ERROR_INVALID_SCALING_WIDTH_HEIGHT; | |
722 | } | |
723 | ||
724 | step_x = srcW / dstW; | |
725 | step_y = srcH / dstH; | |
726 | ||
727 | // Y scale down | |
728 | src_buf = srcBuf[0]; | |
729 | dst_buf = dstBuf[0]; | |
730 | dst_pos = 0; | |
731 | for (uint32_t y = 0; y < dstH; y++) { | |
732 | src_y_start_pos = y * step_y * srcW; | |
733 | ||
734 | for (uint32_t x = 0; x < dstW; x++) { | |
735 | src_pos = src_y_start_pos + (x * step_x); | |
736 | ||
737 | dst_buf[dst_pos++] = src_buf[src_pos]; | |
738 | } | |
739 | } | |
740 | ||
741 | // UV scale down | |
742 | for (uint32_t i = 0; i < dstH; i++) { | |
743 | src_y_start_pos = i * step_y * srcW + (srcW*srcH); | |
744 | ||
745 | for (uint32_t j = 0; j < dstW; j += 2) { | |
746 | src_pos = src_y_start_pos + (j * step_x); | |
747 | ||
748 | dst_buf[dst_pos++] = src_buf[src_pos ]; | |
749 | dst_buf[dst_pos++] = src_buf[src_pos + 1]; | |
750 | } | |
751 | } | |
752 | ||
753 | return ERROR_NONE; | |
754 | } | |
755 | ||
756 | // thumbnail | |
757 | int ExynosJpegEncoderForCamera::setThumbnailSize(int w, int h) | |
758 | { | |
759 | if (m_flagCreate == false) { | |
760 | return ERROR_CANNOT_CREATE_EXYNOS_JPEG_ENC_HAL; | |
761 | } | |
762 | ||
763 | if (w < 0 || MAX_JPG_WIDTH < w) { | |
764 | return false; | |
765 | } | |
766 | ||
767 | if (h < 0 || MAX_JPG_HEIGHT < h) { | |
768 | return false; | |
769 | } | |
770 | ||
771 | m_thumbnailW = w; | |
772 | m_thumbnailH = h; | |
773 | return ERROR_NONE; | |
774 | } | |
775 | ||
776 | int ExynosJpegEncoderForCamera::setThumbnailQuality(int quality) | |
777 | { | |
778 | if (m_flagCreate == false) { | |
779 | return ERROR_CANNOT_CREATE_EXYNOS_JPEG_ENC_HAL; | |
780 | } | |
781 | ||
782 | if (quality < 1 || 100 < quality) { | |
783 | return false; | |
784 | } | |
785 | ||
786 | m_thumbnailQuality = quality; | |
787 | return ERROR_NONE; | |
788 | } | |
789 | ||
790 | int ExynosJpegEncoderForCamera::encodeThumbnail(unsigned int *size, bool useMain) | |
791 | { | |
792 | int ret = ERROR_NONE; | |
793 | ||
794 | if (m_flagCreate == false) { | |
795 | return ERROR_CANNOT_CREATE_EXYNOS_JPEG_ENC_HAL; | |
796 | } | |
797 | ||
798 | // create jpeg thumbnail class | |
799 | if (m_jpegThumb == NULL) { | |
800 | m_jpegThumb = new ExynosJpegEncoder; | |
801 | ||
802 | if (m_jpegThumb == NULL) { | |
803 | JPEG_ERROR_LOG("ERR(%s):Cannot open a jpeg device file\n", __func__); | |
804 | return ERROR_CANNOT_CREATE_SEC_THUMB; | |
805 | } | |
806 | } | |
807 | ||
808 | ret = m_jpegThumb->create(); | |
809 | if (ret) { | |
810 | JPEG_ERROR_LOG("ERR(%s):Fail create\n", __func__); | |
811 | return ret; | |
812 | } | |
813 | ||
814 | ret = m_jpegThumb->setCache(JPEG_CACHE_ON); | |
815 | if (ret) { | |
816 | JPEG_ERROR_LOG("ERR(%s):Fail cache set\n", __func__); | |
817 | return ret; | |
818 | } | |
819 | ||
820 | void *pConfig = m_jpegMain->getJpegConfig(); | |
821 | if (pConfig == NULL) { | |
822 | JPEG_ERROR_LOG("ERR(%s):Fail getJpegConfig\n", __func__); | |
823 | return ERROR_BUFFR_IS_NULL; | |
824 | } | |
825 | ||
826 | ret = m_jpegThumb->setJpegConfig(pConfig); | |
827 | if (ret) { | |
828 | JPEG_ERROR_LOG("ERR(%s):Fail setJpegConfig\n", __func__); | |
829 | return ret; | |
830 | } | |
831 | ||
832 | /* TODO: Currently we fix the thumbnail quality */ | |
833 | ret = m_jpegThumb->setQuality(JPEG_THUMBNAIL_QUALITY); | |
834 | if (ret) { | |
835 | JPEG_ERROR_LOG("ERR(%s):Fail setQuality\n", __func__); | |
836 | return ret; | |
837 | } | |
838 | ||
839 | ret = m_jpegThumb->setSize(m_thumbnailW, m_thumbnailH); | |
840 | if (ret) { | |
841 | JPEG_ERROR_LOG("ERR(%s):Fail setSize\n", __func__); | |
842 | return ret; | |
843 | } | |
844 | ||
845 | freeJpegMemory(&m_stThumbInBuf, MAX_IMAGE_PLANE_NUM); | |
846 | freeJpegMemory(&m_stThumbOutBuf, MAX_IMAGE_PLANE_NUM); | |
847 | ||
848 | if (m_jpegThumb->setColorBufSize(m_stThumbInBuf.iSize, MAX_IMAGE_PLANE_NUM) != ERROR_NONE) { | |
849 | return ERROR_INVALID_COLOR_FORMAT; | |
850 | } | |
851 | m_stThumbOutBuf.iSize[0] = sizeof(char)*m_thumbnailW*m_thumbnailH*THUMBNAIL_IMAGE_PIXEL_SIZE; | |
852 | ||
853 | ||
854 | if (allocJpegMemory(&m_stThumbInBuf, MAX_IMAGE_PLANE_NUM) != ERROR_NONE) { | |
855 | return ERROR_MEM_ALLOC_FAIL; | |
856 | } | |
857 | ||
858 | if (allocJpegMemory(&m_stThumbOutBuf, MAX_IMAGE_PLANE_NUM) != ERROR_NONE) { | |
859 | return ERROR_MEM_ALLOC_FAIL; | |
860 | } | |
861 | ||
862 | ret = m_jpegThumb->setInBuf(m_stThumbInBuf.ionBuffer, m_stThumbInBuf.iSize); | |
863 | if (ret) { | |
864 | JPEG_ERROR_LOG("ERR(%s):Fail setInBuf\n", __func__); | |
865 | return ret; | |
866 | } | |
867 | ||
868 | ret = m_jpegThumb->setOutBuf(m_stThumbOutBuf.ionBuffer[0], m_stThumbOutBuf.iSize[0]); | |
869 | if (ret) { | |
870 | JPEG_ERROR_LOG("ERR(%s):Fail setOutBuf\n", __func__); | |
871 | return ret; | |
872 | } | |
873 | ||
874 | ret = m_jpegThumb->updateConfig(); | |
875 | if (ret) { | |
876 | JPEG_ERROR_LOG("update config failed\n"); | |
877 | return ret; | |
878 | } | |
879 | ||
880 | if (useMain) { | |
881 | int iTempWidth=0; | |
882 | int iTempHeight=0; | |
13d8c7b4 SK |
883 | int iTempColorformat = 0; |
884 | ||
885 | iTempColorformat = m_jpegMain->getColorFormat(); | |
886 | ||
887 | ret = m_jpegMain->getSize(&iTempWidth, &iTempHeight); | |
888 | if (ret) { | |
889 | JPEG_ERROR_LOG("ERR(%s):Fail getSize\n", __func__); | |
890 | return ret; | |
891 | } | |
892 | ||
13d8c7b4 SK |
893 | switch (iTempColorformat) { |
894 | case V4L2_PIX_FMT_YUYV: | |
eed7ed1b | 895 | ret = scaleDownYuv422(m_stMainInBuf.pcBuf, |
13d8c7b4 SK |
896 | iTempWidth, |
897 | iTempHeight, | |
898 | m_stThumbInBuf.pcBuf, | |
899 | m_thumbnailW, | |
900 | m_thumbnailH); | |
901 | break; | |
902 | case V4L2_PIX_FMT_NV16: | |
eed7ed1b | 903 | ret = scaleDownYuv422_2p(m_stMainInBuf.pcBuf, |
13d8c7b4 SK |
904 | iTempWidth, |
905 | iTempHeight, | |
906 | m_stThumbInBuf.pcBuf, | |
907 | m_thumbnailW, | |
908 | m_thumbnailH); | |
909 | break; | |
910 | default: | |
911 | return ERROR_INVALID_COLOR_FORMAT; | |
912 | break; | |
913 | } | |
914 | ||
13d8c7b4 SK |
915 | if (ret) { |
916 | JPEG_ERROR_LOG("%s::scaleDown(%d, %d, %d, %d) fail", __func__, iTempWidth, iTempHeight, m_thumbnailW, m_thumbnailH); | |
917 | return ret; | |
918 | } | |
919 | } | |
920 | else { | |
921 | return ERROR_IMPLEMENT_NOT_YET; | |
922 | } | |
923 | ||
924 | int iOutSizeThumb; | |
925 | ||
926 | ret = m_jpegThumb->encode(); | |
927 | if (ret) { | |
928 | JPEG_ERROR_LOG("encode failed\n"); | |
929 | return ret; | |
930 | } | |
931 | ||
932 | iOutSizeThumb = m_jpegThumb->getJpegSize(); | |
933 | if (iOutSizeThumb<=0) { | |
934 | JPEG_ERROR_LOG("jpeg size is too small\n"); | |
935 | return ERROR_THUMB_JPEG_SIZE_TOO_SMALL; | |
936 | } | |
937 | ||
938 | *size = (unsigned int)iOutSizeThumb; | |
939 | ||
940 | return ERROR_NONE; | |
941 | ||
942 | } | |
943 | ||
944 | int ExynosJpegEncoderForCamera::createIonClient(ion_client ionClient) | |
945 | { | |
177dd33d | 946 | if (ionClient < 0) { |
13d8c7b4 SK |
947 | ionClient = ion_client_create(); |
948 | if (ionClient < 0) { | |
949 | JPEG_ERROR_LOG("[%s]src ion client create failed, value = %d\n", __func__, ionClient); | |
13d8c7b4 SK |
950 | } |
951 | } | |
952 | ||
953 | return ionClient; | |
954 | } | |
955 | ||
956 | int ExynosJpegEncoderForCamera::deleteIonClient(ion_client ionClient) | |
957 | { | |
177dd33d MS |
958 | if (ionClient >= 0) { |
959 | ion_client_destroy(ionClient); | |
13d8c7b4 | 960 | } |
177dd33d | 961 | ionClient = -1; |
13d8c7b4 SK |
962 | return ionClient; |
963 | } | |
964 | ||
965 | int ExynosJpegEncoderForCamera::allocJpegMemory(struct stJpegMem *pstMem, int iMemoryNum) | |
966 | { | |
967 | int ret = ERROR_NONE; | |
968 | int i = 0; | |
969 | ||
177dd33d MS |
970 | if (pstMem->ionClient < 0) { |
971 | JPEG_ERROR_LOG("[%s] i = %d , ionClient is closed (%d)\n", __func__, i, pstMem->ionClient); | |
13d8c7b4 SK |
972 | return ERROR_BUFFR_IS_NULL; |
973 | } | |
974 | ||
975 | for (i=0;i<iMemoryNum;i++) { | |
976 | if (pstMem->iSize[i] == 0) { | |
977 | break; | |
978 | } | |
979 | ||
980 | pstMem->ionBuffer[i] = ion_alloc(pstMem->ionClient, \ | |
981 | pstMem->iSize[i], 0, ION_HEAP_SYSTEM_MASK, 0); | |
982 | if ((pstMem->ionBuffer[i] == -1) ||(pstMem->ionBuffer[i] == 0)) { | |
983 | JPEG_ERROR_LOG("[%s]ion_alloc(%d) failed\n", __func__, pstMem->iSize[i]); | |
984 | pstMem->ionBuffer[i] = -1; | |
985 | freeJpegMemory(pstMem, iMemoryNum); | |
986 | return ERROR_MEM_ALLOC_FAIL; | |
987 | } | |
988 | ||
989 | pstMem->pcBuf[i] = (char *)ion_map(pstMem->ionBuffer[i], \ | |
990 | pstMem->iSize[i], 0); | |
991 | if ((pstMem->pcBuf[i] == (char *)MAP_FAILED) || (pstMem->pcBuf[i] == NULL)) { | |
992 | JPEG_ERROR_LOG("[%s]src ion map failed(%d)\n", __func__, pstMem->iSize[i]); | |
993 | pstMem->pcBuf[i] = (char *)MAP_FAILED; | |
994 | freeJpegMemory(pstMem, iMemoryNum); | |
995 | return ERROR_MEM_ALLOC_FAIL; | |
996 | } | |
997 | } | |
998 | ||
999 | return ERROR_NONE; | |
1000 | } | |
1001 | ||
1002 | void ExynosJpegEncoderForCamera::freeJpegMemory(struct stJpegMem *pstMem, int iMemoryNum) | |
1003 | { | |
177dd33d MS |
1004 | int i = 0; |
1005 | if (pstMem->ionClient < 0) { | |
13d8c7b4 SK |
1006 | return; |
1007 | } | |
1008 | ||
1009 | ||
1010 | for (i=0;i<iMemoryNum;i++) { | |
1011 | if (pstMem->ionBuffer[i] != -1) { | |
1012 | if (pstMem->pcBuf[i] != (char *)MAP_FAILED) { | |
1013 | ion_unmap(pstMem->pcBuf[i], pstMem->iSize[i]); | |
1014 | } | |
1015 | ion_free(pstMem->ionBuffer[i]); | |
1016 | } | |
1017 | pstMem->ionBuffer[i] = -1; | |
1018 | pstMem->pcBuf[i] = (char *)MAP_FAILED; | |
1019 | pstMem->iSize[i] = 0; | |
1020 | } | |
1021 | } | |
1022 | ||
1023 | void ExynosJpegEncoderForCamera::initJpegMemory(struct stJpegMem *pstMem, int iMemoryNum) | |
1024 | { | |
1025 | int i =0 ; | |
1026 | for (i=0;i<iMemoryNum;i++) { | |
1027 | pstMem->pcBuf[i] = (char *)MAP_FAILED; | |
1028 | pstMem->ionBuffer[i] = -1; | |
1029 | pstMem->iSize[i] = 0; | |
1030 | } | |
177dd33d | 1031 | pstMem->ionClient = -1; |
13d8c7b4 | 1032 | } |
2ed2aecf | 1033 |