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