Manta: exynos: libcamera2: plug /dev/ion file descriptor leak
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos5.git] / libcamera2 / ExynosJpegEncoderForCamera.cpp
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
18 #define LOG_TAG "ExynosJpegForCamera"
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
25 #define JPEG_ERROR_LOG ALOGE
26 #define JPEG_WARNING_LOG ALOGW
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;
45 m_ionJpegClient = -1;
46 initJpegMemory(&m_stThumbInBuf, MAX_IMAGE_PLANE_NUM);
47 initJpegMemory(&m_stThumbOutBuf, MAX_IMAGE_PLANE_NUM);
48 initJpegMemory(&m_stMainInBuf, MAX_IMAGE_PLANE_NUM);
49 initJpegMemory(&m_stMainOutBuf, MAX_IMAGE_PLANE_NUM);
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
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) {
99 return ERROR_CANNOT_CREATE_EXYNOS_JPEG_ENC_HAL;
100 }
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);
124 initJpegMemory(&m_stMainInBuf, MAX_IMAGE_PLANE_NUM);
125 initJpegMemory(&m_stMainOutBuf, MAX_IMAGE_PLANE_NUM);
126 m_ionJpegClient =
127 m_stMainOutBuf.ionClient =
128 m_stMainInBuf.ionClient =
129 m_stThumbInBuf.ionClient =
130 m_stThumbOutBuf.ionClient =
131 deleteIonClient(m_ionJpegClient);
132 m_jpegThumb->destroy();
133 delete m_jpegThumb;
134 m_jpegThumb = NULL;
135 }
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 }
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
199 int ExynosJpegEncoderForCamera::setInBuf(int *buf, char** vBuf, int *size)
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 }
220 m_stMainInBuf.ionBuffer[0] = buf[0];
221 m_stMainInBuf.iSize[0] = size[0];
222 m_stMainInBuf.pcBuf[0] = vBuf[0];
223
224 return ERROR_NONE;
225 }
226
227 int ExynosJpegEncoderForCamera::setOutBuf(int buf, char* vBuf, int size)
228 {
229 if (m_flagCreate == false) {
230 return ERROR_NOT_YET_CREATED;
231 }
232
233 if (!buf) {
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 }
247 m_stMainOutBuf.ionBuffer[0] = buf;
248 m_stMainOutBuf.iSize[0] = size;
249 m_stMainOutBuf.pcBuf[0] = vBuf;
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
277 int iOutputSize = m_stMainOutBuf.iSize[0];
278 int iJpegBuffer = m_stMainOutBuf.ionBuffer[0];
279 char *pcJpegBuffer = m_stMainOutBuf.pcBuf[0];
280
281 if (!pcJpegBuffer[0]) {
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
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);
382 writeExifIfd(&pCur, EXIF_TAG_SUBSEC_TIME, EXIF_TYPE_ASCII,
383 sizeof(exifInfo->sub_sec), exifInfo->sub_sec);
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);
417 writeExifIfd(&pCur, EXIF_TAG_SUBSEC_TIME_ORG, EXIF_TYPE_ASCII,
418 sizeof(exifInfo->sub_sec), exifInfo->sub_sec);
419 writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII,
420 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
421 writeExifIfd(&pCur, EXIF_TAG_SUBSEC_TIME_DIGITIZE, EXIF_TYPE_ASCII,
422 sizeof(exifInfo->sub_sec), exifInfo->sub_sec);
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();
527 thumbBuf = m_stMainOutBuf.pcBuf[0];
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();
536 thumbBuf = m_stThumbOutBuf.pcBuf[0];
537 }
538 }
539
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
588 *(pApp1Start++) = 0xff;
589 *(pApp1Start++) = 0xe1;
590
591 *size = 10 + LongerTagOffest;
592 tmp = *size - 2; // APP1 Maker isn't counted
593 *(pApp1Start++) = (tmp >> 8) & 0xFF;
594 *(pApp1Start++) = tmp & 0xFF;
595
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;
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
892 switch (iTempColorformat) {
893 case V4L2_PIX_FMT_YUYV:
894 ret = scaleDownYuv422(m_stMainInBuf.pcBuf,
895 iTempWidth,
896 iTempHeight,
897 m_stThumbInBuf.pcBuf,
898 m_thumbnailW,
899 m_thumbnailH);
900 break;
901 case V4L2_PIX_FMT_NV16:
902 ret = scaleDownYuv422_2p(m_stMainInBuf.pcBuf,
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
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 {
945 if (ionClient < 0) {
946 ionClient = ion_client_create();
947 if (ionClient < 0) {
948 JPEG_ERROR_LOG("[%s]src ion client create failed, value = %d\n", __func__, ionClient);
949 }
950 }
951
952 return ionClient;
953 }
954
955 int ExynosJpegEncoderForCamera::deleteIonClient(ion_client ionClient)
956 {
957 if (ionClient >= 0) {
958 ion_client_destroy(ionClient);
959 }
960 ionClient = -1;
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
969 if (pstMem->ionClient < 0) {
970 JPEG_ERROR_LOG("[%s] i = %d , ionClient is closed (%d)\n", __func__, i, pstMem->ionClient);
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 {
1003 int i = 0;
1004 if (pstMem->ionClient < 0) {
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 }
1030 pstMem->ionClient = -1;
1031 }
1032