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