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