Home | History | Annotate | Download | only in libcamera2
      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 
     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 
     51 ExynosJpegEncoderForCamera::~ExynosJpegEncoderForCamera()
     52 {
     53     if (m_flagCreate == true) {
     54         this->destroy();
     55     }
     56 }
     57 
     58 bool ExynosJpegEncoderForCamera::flagCreate(void)
     59 {
     60     return m_flagCreate;
     61 }
     62 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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