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