• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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