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 
ExynosJpegEncoderForCamera()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 
~ExynosJpegEncoderForCamera()52 ExynosJpegEncoderForCamera::~ExynosJpegEncoderForCamera()
53 {
54     if (m_flagCreate == true) {
55         this->destroy();
56     }
57 }
58 
flagCreate(void)59 bool ExynosJpegEncoderForCamera::flagCreate(void)
60 {
61     return m_flagCreate;
62 }
63 
create(void)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 
destroy(void)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 
setSize(int w,int h)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 
setQuality(int quality)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 
setColorFormat(int colorFormat)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 
setJpegFormat(int jpegFormat)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 
updateConfig(void)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 
setInBuf(int * buf,char ** vBuf,int * size)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 
setOutBuf(int buf,char * vBuf,int size)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 
encode(int * size,exif_attribute_t * exifInfo)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 
makeExif(unsigned char * exifOut,exif_attribute_t * exifInfo,unsigned int * size,bool useMainbufForThumb)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 */
writeExifIfd(unsigned char ** pCur,unsigned short tag,unsigned short type,unsigned int count,unsigned int value)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 
writeExifIfd(unsigned char ** pCur,unsigned short tag,unsigned short type,unsigned int count,unsigned char * pValue)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 
writeExifIfd(unsigned char ** pCur,unsigned short tag,unsigned short type,unsigned int count,unsigned char * pValue,unsigned int * offset,unsigned char * start)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 
writeExifIfd(unsigned char ** pCur,unsigned short tag,unsigned short type,unsigned int count,rational_t * pValue,unsigned int * offset,unsigned char * start)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 
scaleDownYuv422(char ** srcBuf,unsigned int srcW,unsigned int srcH,char ** dstBuf,unsigned int dstW,unsigned int dstH)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 
scaleDownYuv422_2p(char ** srcBuf,unsigned int srcW,unsigned int srcH,char ** dstBuf,unsigned int dstW,unsigned int dstH)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
setThumbnailSize(int w,int h)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 
setThumbnailQuality(int quality)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 
encodeThumbnail(unsigned int * size,bool useMain)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 
createIonClient(ion_client ionClient)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 
deleteIonClient(ion_client ionClient)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 
allocJpegMemory(struct stJpegMem * pstMem,int iMemoryNum)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 
freeJpegMemory(struct stJpegMem * pstMem,int iMemoryNum)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 
initJpegMemory(struct stJpegMem * pstMem,int iMemoryNum)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 
1033