Home | History | Annotate | Download | only in libcamera
      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(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 
     33 ExynosJpegEncoderForCamera::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 
     56 ExynosJpegEncoderForCamera::~ExynosJpegEncoderForCamera()
     57 {
     58     if (m_flagCreate == true) {
     59         this->destroy();
     60     }
     61 }
     62 
     63 bool ExynosJpegEncoderForCamera::flagCreate(void)
     64 {
     65     return m_flagCreate;
     66 }
     67 
     68 int 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 
    101 int 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 
    141 int 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 
    151 int 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 
    160 int 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 
    169 int 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 
    178 int ExynosJpegEncoderForCamera::updateConfig(void)
    179 {
    180     if (m_flagCreate == false) {
    181         return ERROR_NOT_YET_CREATED;
    182     }
    183 
    184     return m_jpegMain->updateConfig();
    185 }
    186 
    187 int  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 
    242 int  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 
    266 int 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 
    359 int 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 */
    616 inline 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 
    632 inline 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 
    651 inline 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 
    671 inline 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 
    691 int 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 
    725 int 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
    773 int 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 
    792 int 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 
    806 int 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 
   1003 int 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 
   1031 void 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