Home | History | Annotate | Download | only in libs3cjpeg
      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  * JPEG DRIVER MODULE (JpegEncoder.cpp)
     18  * Author  : ge.lee       -- initial version
     19  * Date    : 03 June 2010
     20  * Purpose : This file implements the JPEG encoder APIs as needed by Camera HAL
     21  */
     22 #define LOG_TAG "JpegEncoder"
     23 #define MAIN_DUMP  0
     24 #define THUMB_DUMP 0
     25 
     26 #include <utils/Log.h>
     27 #include <sys/mman.h>
     28 #include <fcntl.h>
     29 
     30 #include "JpegEncoder.h"
     31 
     32 static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
     33 
     34 namespace android {
     35 JpegEncoder::JpegEncoder() : available(false)
     36 {
     37     mArgs.mmapped_addr = (char *)MAP_FAILED;
     38     mArgs.enc_param       = NULL;
     39     mArgs.thumb_enc_param = NULL;
     40 
     41     mDevFd = open(JPG_DRIVER_NAME, O_RDWR);
     42     if (mDevFd < 0) {
     43         LOGE("Failed to open the device");
     44         return;
     45     }
     46 
     47     mArgs.mmapped_addr = (char *)mmap(0,
     48                                       JPG_TOTAL_BUF_SIZE,
     49                                       PROT_READ | PROT_WRITE,
     50                                       MAP_SHARED,
     51                                       mDevFd,
     52                                       0);
     53 
     54     if (mArgs.mmapped_addr == MAP_FAILED) {
     55         LOGE("Failed to mmap");
     56         return;
     57     }
     58 
     59     mArgs.enc_param = new jpg_enc_proc_param;
     60     if (mArgs.enc_param == NULL) {
     61         LOGE("Failed to allocate the memory for enc_param");
     62         return;
     63     }
     64     memset(mArgs.enc_param, 0, sizeof(jpg_enc_proc_param));
     65 
     66     mArgs.thumb_enc_param = new jpg_enc_proc_param;
     67     if (mArgs.thumb_enc_param == NULL) {
     68         LOGE("Failed to allocate the memory for thumb_enc_param");
     69     delete mArgs.enc_param;
     70         return;
     71     }
     72     memset(mArgs.thumb_enc_param, 0, sizeof(jpg_enc_proc_param));
     73 
     74     mArgs.enc_param->sample_mode = JPG_420;
     75     mArgs.enc_param->enc_type = JPG_MAIN;
     76     mArgs.thumb_enc_param->sample_mode = JPG_420;
     77     mArgs.thumb_enc_param->enc_type = JPG_THUMBNAIL;
     78 
     79     available = true;
     80 }
     81 
     82 JpegEncoder::~JpegEncoder()
     83 {
     84     if (mArgs.mmapped_addr != (char*)MAP_FAILED)
     85         munmap(mArgs.mmapped_addr, JPG_TOTAL_BUF_SIZE);
     86 
     87     delete mArgs.enc_param;
     88 
     89     delete mArgs.thumb_enc_param;
     90 
     91     if (mDevFd > 0)
     92         close(mDevFd);
     93 }
     94 
     95 jpg_return_status JpegEncoder::setConfig(jpeg_conf type, int32_t value)
     96 {
     97     if (!available)
     98         return JPG_FAIL;
     99 
    100     jpg_return_status ret = JPG_SUCCESS;
    101 
    102     switch (type) {
    103     case JPEG_SET_ENCODE_WIDTH:
    104         if (value < 0 || value > MAX_JPG_WIDTH)
    105             ret = JPG_FAIL;
    106         else
    107             mArgs.enc_param->width = value;
    108         break;
    109 
    110     case JPEG_SET_ENCODE_HEIGHT:
    111         if (value < 0 || value > MAX_JPG_HEIGHT)
    112             ret = JPG_FAIL;
    113         else
    114             mArgs.enc_param->height = value;
    115         break;
    116 
    117     case JPEG_SET_ENCODE_QUALITY:
    118         if (value < JPG_QUALITY_LEVEL_1 || value > JPG_QUALITY_LEVEL_4)
    119             ret = JPG_FAIL;
    120         else
    121             mArgs.enc_param->quality = (image_quality_type_t)value;
    122         break;
    123 
    124     case JPEG_SET_ENCODE_IN_FORMAT:
    125         if (value != JPG_MODESEL_YCBCR && value != JPG_MODESEL_RGB) {
    126             ret = JPG_FAIL;
    127         } else {
    128             mArgs.enc_param->in_format = (in_mode_t)value;
    129             mArgs.thumb_enc_param->in_format = (in_mode_t)value;
    130         }
    131         break;
    132 
    133     case JPEG_SET_SAMPING_MODE:
    134         if (value != JPG_420 && value != JPG_422) {
    135             ret = JPG_FAIL;
    136         } else {
    137             mArgs.enc_param->sample_mode = (sample_mode_t)value;
    138             mArgs.thumb_enc_param->sample_mode = (sample_mode_t)value;
    139         }
    140         break;
    141 
    142     case JPEG_SET_THUMBNAIL_WIDTH:
    143         if (value < 0 || value > MAX_JPG_THUMBNAIL_WIDTH)
    144             ret = JPG_FAIL;
    145         else
    146             mArgs.thumb_enc_param->width = value;
    147         break;
    148 
    149     case JPEG_SET_THUMBNAIL_HEIGHT:
    150         if (value < 0 || value > MAX_JPG_THUMBNAIL_HEIGHT)
    151             ret = JPG_FAIL;
    152         else
    153             mArgs.thumb_enc_param->height = value;
    154         break;
    155 
    156     default:
    157         LOGE("Invalid Config type");
    158         ret = ERR_UNKNOWN;
    159     }
    160 
    161     if (ret == JPG_FAIL)
    162         LOGE("Invalid value(%d) for %d type", value, type);
    163 
    164     return ret;
    165 }
    166 
    167 void* JpegEncoder::getInBuf(uint64_t size)
    168 {
    169     if (!available)
    170         return NULL;
    171 
    172     if (size > JPG_FRAME_BUF_SIZE) {
    173         LOGE("The buffer size requested is too large");
    174         return NULL;
    175     }
    176     mArgs.in_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_FRMBUF, mArgs.mmapped_addr);
    177     return (void *)(mArgs.in_buf);
    178 }
    179 
    180 void* JpegEncoder::getOutBuf(uint64_t *size)
    181 {
    182     if (!available)
    183         return NULL;
    184 
    185     if (mArgs.enc_param->file_size <= 0) {
    186         LOGE("The buffer requested doesn't have data");
    187         return NULL;
    188     }
    189     mArgs.out_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_STRBUF, mArgs.mmapped_addr);
    190     *size = mArgs.enc_param->file_size;
    191     return (void *)(mArgs.out_buf);
    192 }
    193 
    194 void* JpegEncoder::getThumbInBuf(uint64_t size)
    195 {
    196     if (!available)
    197         return NULL;
    198 
    199     if (size > JPG_FRAME_THUMB_BUF_SIZE) {
    200         LOGE("The buffer size requested is too large");
    201         return NULL;
    202     }
    203     mArgs.in_thumb_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_THUMB_FRMBUF, mArgs.mmapped_addr);
    204     return (void *)(mArgs.in_thumb_buf);
    205 }
    206 
    207 void* JpegEncoder::getThumbOutBuf(uint64_t *size)
    208 {
    209     if (!available)
    210         return NULL;
    211 
    212     if (mArgs.thumb_enc_param->file_size <= 0) {
    213         LOGE("The buffer requested doesn't have data");
    214         return NULL;
    215     }
    216     mArgs.out_thumb_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_THUMB_STRBUF, mArgs.mmapped_addr);
    217     *size = mArgs.thumb_enc_param->file_size;
    218     return (void *)(mArgs.out_thumb_buf);
    219 }
    220 
    221 jpg_return_status JpegEncoder::encode(unsigned int *size, exif_attribute_t *exifInfo)
    222 {
    223     if (!available)
    224         return JPG_FAIL;
    225 
    226     LOGD("encode E");
    227 
    228     jpg_return_status ret = JPG_FAIL;
    229     unsigned char *exifOut = NULL;
    230     jpg_enc_proc_param *param = mArgs.enc_param;
    231 
    232     ret = checkMcu(param->sample_mode, param->width, param->height, false);
    233     if (ret != JPG_SUCCESS)
    234         return ret;
    235 
    236     param->enc_type = JPG_MAIN;
    237     ret = (jpg_return_status)ioctl(mDevFd, IOCTL_JPG_ENCODE, &mArgs);
    238     if (ret != JPG_SUCCESS) {
    239         LOGE("Failed to encode main image");
    240         return ret;
    241     }
    242 
    243     mArgs.out_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_STRBUF, mArgs.mmapped_addr);
    244 
    245     if (exifInfo) {
    246         unsigned int thumbLen, exifLen;
    247 
    248         uint_t bufSize = 0;
    249         if (exifInfo->enableThumb) {
    250             ret = encodeThumbImg(&thumbLen);
    251             if (ret != JPG_SUCCESS) {
    252                 LOGE("Failed to encode for thumbnail image");
    253                 bufSize = EXIF_FILE_SIZE;
    254                 exifInfo->enableThumb = false;
    255             } else {
    256                 bufSize = EXIF_FILE_SIZE + thumbLen;
    257             }
    258         } else {
    259             bufSize = EXIF_FILE_SIZE;
    260         }
    261 
    262         if (mArgs.enc_param->file_size + bufSize > JPG_TOTAL_BUF_SIZE)
    263             return ret;
    264 
    265         exifOut = new unsigned char[bufSize];
    266         if (exifOut == NULL) {
    267             LOGE("Failed to allocate for exifOut");
    268             return ret;
    269         }
    270         memset(exifOut, 0, bufSize);
    271 
    272         ret = makeExif (exifOut, exifInfo, &exifLen);
    273         if (ret != JPG_SUCCESS) {
    274             LOGE("Failed to make EXIF");
    275             delete[] exifOut;
    276             return ret;
    277         }
    278 
    279         memmove(&mArgs.out_buf[exifLen + 2], &mArgs.out_buf[2], param->file_size - 2);
    280         memcpy(&mArgs.out_buf[2], exifOut, exifLen);
    281         param->file_size += exifLen;
    282     }
    283 
    284     delete[] exifOut;
    285 
    286     *size = param->file_size;
    287 
    288 #if MAIN_DUMP
    289     FILE *fout = NULL;
    290     char file_name[50] = "/data/main.jpg";
    291     fout = fopen(file_name, "wb");
    292     if (!fout)
    293         perror(&file_name[0]);
    294     size_t nwrite = fwrite(mArgs.out_buf, sizeof(char), param->file_size, fout);
    295     fclose(fout);
    296 #endif
    297 
    298     LOGD("encode X");
    299 
    300     return ret;
    301 }
    302 
    303 jpg_return_status JpegEncoder::encodeThumbImg(unsigned int *size, bool useMain)
    304 {
    305     if (!available)
    306         return JPG_FAIL;
    307 
    308     LOGD("encodeThumbImg E");
    309 
    310     jpg_return_status ret = JPG_FAIL;
    311     jpg_enc_proc_param *param = mArgs.thumb_enc_param;
    312 
    313     if (useMain) {
    314         mArgs.in_thumb_buf = (char *)getThumbInBuf(param->width*param->height*2);
    315         if (mArgs.in_thumb_buf == NULL) {
    316             LOGE("Failed to get the buffer for thumbnail");
    317             return JPG_FAIL;
    318         }
    319 
    320         ret = (jpg_return_status)scaleDownYuv422(mArgs.in_buf,
    321                                                  mArgs.enc_param->width,
    322                                                  mArgs.enc_param->height,
    323                                                  mArgs.in_thumb_buf,
    324                                                  param->width,
    325                                                  param->height);
    326         if (ret != JPG_SUCCESS)
    327             return JPG_FAIL;
    328     }
    329 
    330     ret = checkMcu(param->sample_mode, param->width, param->height, true);
    331     if (ret != JPG_SUCCESS)
    332         return JPG_FAIL;
    333 
    334     mArgs.enc_param->enc_type = JPG_THUMBNAIL;
    335     ret = (jpg_return_status)ioctl(mDevFd, IOCTL_JPG_ENCODE, &mArgs);
    336     if (ret != JPG_SUCCESS) {
    337         LOGE("Failed to encode for thumbnail");
    338         return JPG_FAIL;
    339     }
    340 
    341     mArgs.out_thumb_buf = (char *)ioctl(mDevFd, IOCTL_JPG_GET_THUMB_STRBUF, mArgs.mmapped_addr);
    342 
    343 #if THUMB_DUMP
    344     FILE *fout = NULL;
    345     char file_name[50] = "/data/thumb.jpg";
    346     fout = fopen(file_name, "wb");
    347     if (!fout)
    348         perror(&file_name[0]);
    349     size_t nwrite = fwrite(mArgs.out_thumb_buf, sizeof(char), param->file_size, fout);
    350     fclose(fout);
    351 #endif
    352 
    353     LOGD("encodeThumbImg X");
    354 
    355     return JPG_SUCCESS;
    356 }
    357 
    358 jpg_return_status JpegEncoder::makeExif (unsigned char *exifOut,
    359                                         exif_attribute_t *exifInfo,
    360                                         unsigned int *size,
    361                                         bool useMainbufForThumb)
    362 {
    363     if (!available)
    364         return JPG_FAIL;
    365 
    366     LOGD("makeExif E");
    367 
    368     unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset;
    369     unsigned int tmp, LongerTagOffest = 0;
    370     pApp1Start = pCur = exifOut;
    371 
    372     //2 Exif Identifier Code & TIFF Header
    373     pCur += 4;  // Skip 4 Byte for APP1 marker and length
    374     unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
    375     memcpy(pCur, ExifIdentifierCode, 6);
    376     pCur += 6;
    377 
    378     /* Byte Order - little endian, Offset of IFD - 0x00000008.H */
    379     unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 };
    380     memcpy(pCur, TiffHeader, 8);
    381     pIfdStart = pCur;
    382     pCur += 8;
    383 
    384     //2 0th IFD TIFF Tags
    385     if (exifInfo->enableGps)
    386         tmp = NUM_0TH_IFD_TIFF;
    387     else
    388         tmp = NUM_0TH_IFD_TIFF - 1;
    389 
    390     memcpy(pCur, &tmp, NUM_SIZE);
    391     pCur += NUM_SIZE;
    392 
    393     LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
    394 
    395     writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
    396                  1, exifInfo->width);
    397     writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
    398                  1, exifInfo->height);
    399     writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII,
    400                  strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart);
    401     writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII,
    402                  strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart);
    403     writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
    404                  1, exifInfo->orientation);
    405     writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII,
    406                  strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart);
    407     writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII,
    408                  20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
    409     writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT,
    410                  1, exifInfo->ycbcr_positioning);
    411     writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG,
    412                  1, LongerTagOffest);
    413     if (exifInfo->enableGps) {
    414         pGpsIfdPtr = pCur;
    415         pCur += IFD_SIZE;   // Skip a ifd size for gps IFD pointer
    416     }
    417 
    418     pNextIfdOffset = pCur;  // Skip a offset size for next IFD offset
    419     pCur += OFFSET_SIZE;
    420 
    421     //2 0th IFD Exif Private Tags
    422     pCur = pIfdStart + LongerTagOffest;
    423 
    424     tmp = NUM_0TH_IFD_EXIF;
    425     memcpy(pCur, &tmp , NUM_SIZE);
    426     pCur += NUM_SIZE;
    427 
    428     LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE;
    429 
    430     writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL,
    431                  1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart);
    432     writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL,
    433                  1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart);
    434     writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT,
    435                  1, exifInfo->exposure_program);
    436     writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT,
    437                  1, exifInfo->iso_speed_rating);
    438     writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED,
    439                  4, exifInfo->exif_version);
    440     writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII,
    441                  20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
    442     writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII,
    443                  20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
    444     writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL,
    445                  1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart);
    446     writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL,
    447                  1, &exifInfo->aperture, &LongerTagOffest, pIfdStart);
    448     writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL,
    449                  1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart);
    450     writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL,
    451                  1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart);
    452     writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL,
    453                  1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart);
    454     writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT,
    455                  1, exifInfo->metering_mode);
    456     writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT,
    457                  1, exifInfo->flash);
    458     writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL,
    459                  1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart);
    460     char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 };
    461     int commentsLen = strlen((char *)exifInfo->user_comment) + 1;
    462     memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen);
    463     memcpy(exifInfo->user_comment, code, sizeof(code));
    464     writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED,
    465                  commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart);
    466     writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT,
    467                  1, exifInfo->color_space);
    468     writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG,
    469                  1, exifInfo->width);
    470     writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG,
    471                  1, exifInfo->height);
    472     writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG,
    473                  1, exifInfo->exposure_mode);
    474     writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG,
    475                  1, exifInfo->white_balance);
    476     writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG,
    477                  1, exifInfo->scene_capture_type);
    478     tmp = 0;
    479     memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
    480     pCur += OFFSET_SIZE;
    481 
    482     //2 0th IFD GPS Info Tags
    483     if (exifInfo->enableGps) {
    484         writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG,
    485                      1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD
    486 
    487         pCur = pIfdStart + LongerTagOffest;
    488 
    489         if (exifInfo->gps_processing_method[0] == 0) {
    490             // don't create GPS_PROCESSING_METHOD tag if there isn't any
    491             tmp = NUM_0TH_IFD_GPS - 1;
    492         } else {
    493             tmp = NUM_0TH_IFD_GPS;
    494         }
    495         memcpy(pCur, &tmp, NUM_SIZE);
    496         pCur += NUM_SIZE;
    497 
    498         LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
    499 
    500         writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE,
    501                      4, exifInfo->gps_version_id);
    502         writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII,
    503                      2, exifInfo->gps_latitude_ref);
    504         writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL,
    505                      3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart);
    506         writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII,
    507                      2, exifInfo->gps_longitude_ref);
    508         writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL,
    509                      3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart);
    510         writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE,
    511                      1, exifInfo->gps_altitude_ref);
    512         writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL,
    513                      1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart);
    514         writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL,
    515                      3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart);
    516         tmp = strlen((char*)exifInfo->gps_processing_method);
    517 	if (tmp > 0) {
    518             if (tmp > 100) {
    519                 tmp = 100;
    520             }
    521             unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)];
    522             memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
    523             memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp);
    524             writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED,
    525                          tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart);
    526         }
    527         writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII,
    528                      11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart);
    529         tmp = 0;
    530         memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
    531         pCur += OFFSET_SIZE;
    532     }
    533 
    534     //2 1th IFD TIFF Tags
    535     char *thumbBuf;
    536     int thumbSize;
    537 
    538     if (useMainbufForThumb) {
    539         thumbBuf = mArgs.out_buf;
    540         thumbSize = mArgs.enc_param->file_size;
    541     } else {
    542         thumbBuf = mArgs.out_thumb_buf;
    543         thumbSize = mArgs.thumb_enc_param->file_size;
    544     }
    545 
    546     if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize > 0)) {
    547         tmp = LongerTagOffest;
    548         memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE);  // NEXT IFD offset skipped on 0th IFD
    549 
    550         pCur = pIfdStart + LongerTagOffest;
    551 
    552         tmp = NUM_1TH_IFD_TIFF;
    553         memcpy(pCur, &tmp, NUM_SIZE);
    554         pCur += NUM_SIZE;
    555 
    556         LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE;
    557 
    558         writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
    559                      1, exifInfo->widthThumb);
    560         writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
    561                      1, exifInfo->heightThumb);
    562         writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT,
    563                      1, exifInfo->compression_scheme);
    564         writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
    565                      1, exifInfo->orientation);
    566         writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL,
    567                      1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart);
    568         writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL,
    569                      1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart);
    570         writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT,
    571                      1, exifInfo->resolution_unit);
    572         writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG,
    573                      1, LongerTagOffest);
    574         writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG,
    575                      1, thumbSize);
    576 
    577         tmp = 0;
    578         memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
    579         pCur += OFFSET_SIZE;
    580 
    581         memcpy(pIfdStart + LongerTagOffest,
    582                thumbBuf, thumbSize);
    583         LongerTagOffest += thumbSize;
    584     } else {
    585         tmp = 0;
    586         memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE);  // NEXT IFD offset skipped on 0th IFD
    587     }
    588 
    589     unsigned char App1Marker[2] = { 0xff, 0xe1 };
    590     memcpy(pApp1Start, App1Marker, 2);
    591     pApp1Start += 2;
    592 
    593     *size = 10 + LongerTagOffest;
    594     tmp = *size - 2;    // APP1 Maker isn't counted
    595     unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF};
    596     memcpy(pApp1Start, size_mm, 2);
    597 
    598     LOGD("makeExif X");
    599 
    600     return JPG_SUCCESS;
    601 }
    602 
    603 jpg_return_status JpegEncoder::checkMcu(sample_mode_t sampleMode,
    604                                         uint32_t width, uint32_t height, bool isThumb)
    605 {
    606     if (!available)
    607         return JPG_FAIL;
    608 
    609     uint32_t expectedWidth = width;
    610     uint32_t expectedHeight = height;
    611 
    612     switch (sampleMode){
    613     case JPG_422:
    614         if (width % 16 != 0)
    615             expectedWidth = width + 16 - (width % 16);
    616         if (height % 8 != 0)
    617             expectedHeight = height + 8 - (height % 8);
    618         break;
    619 
    620     case JPG_420:
    621         if (width % 16 != 0)
    622             expectedWidth = width + 16 - (width % 16);
    623         if (height % 16 != 0)
    624             expectedHeight = height + 16 - (height % 16);
    625         break;
    626 
    627     default:
    628         LOGE("Invaild sample mode");
    629         return JPG_FAIL;
    630     }
    631 
    632     if (expectedWidth == width && expectedHeight == height)
    633         return JPG_SUCCESS;
    634 
    635     LOGW("The image is not matched for MCU");
    636 
    637     uint32_t size = width*height * 2;
    638     char *srcBuf, *dstBuf;
    639 
    640     if ((srcBuf = new char[size]) == NULL) {
    641         LOGE("Failed to allocate for srcBuf");
    642         return JPG_FAIL;
    643     }
    644 
    645     if (!isThumb)
    646         dstBuf = mArgs.in_buf;
    647     else
    648         dstBuf = mArgs.in_thumb_buf;
    649 
    650     memcpy(srcBuf, dstBuf, size);
    651     bool ret = pad(srcBuf, width, height, dstBuf, expectedWidth, expectedHeight);
    652 
    653     delete[] srcBuf;
    654 
    655     return JPG_SUCCESS;
    656 }
    657 
    658 bool JpegEncoder::pad(char *srcBuf, uint32_t srcWidth, uint32_t srcHight,
    659                         char *dstBuf, uint32_t dstWidth, uint32_t dstHight)
    660 {
    661     if (!available)
    662         return false;
    663 
    664     if (srcBuf == NULL || dstBuf == NULL) {
    665         LOGE("srcBuf or dstBuf is NULL");
    666         return false;
    667     }
    668 
    669     int padW = dstWidth - srcWidth;
    670     int padH = dstHight - srcHight;
    671 
    672     if ((int)(dstWidth - srcWidth) < 0 ||
    673             (int)(dstHight - srcHight) < 0) {
    674         LOGE("dstSize is smaller than srcSize");
    675         return false;
    676     }
    677     memset(dstBuf, 0, dstWidth*dstHight * 2);
    678 
    679     for (uint32_t i = 0; i < srcHight; i++)
    680         memcpy(dstBuf + i * dstWidth * 2, srcBuf + i * srcWidth * 2, srcWidth * 2);
    681 
    682     return true;
    683 }
    684 
    685 bool JpegEncoder::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHight,
    686                                   char *dstBuf, uint32_t dstWidth, uint32_t dstHight)
    687 {
    688     if (!available)
    689         return false;
    690 
    691     int32_t step_x, step_y;
    692     int32_t iXsrc, iXdst;
    693     int32_t x, y, src_y_start_pos, dst_pos, src_pos;
    694 
    695     if (dstWidth % 2 != 0 || dstHight % 2 != 0){
    696         LOGE("scale_down_yuv422: invalid width, height for scaling");
    697         return false;
    698     }
    699 
    700     step_x = srcWidth / dstWidth;
    701     step_y = srcHight / dstHight;
    702 
    703     dst_pos = 0;
    704     for (uint32_t y = 0; y < dstHight; y++) {
    705         src_y_start_pos = (y * step_y * (srcWidth * 2));
    706 
    707         for (uint32_t x = 0; x < dstWidth; x += 2) {
    708             src_pos = src_y_start_pos + (x * (step_x * 2));
    709 
    710             dstBuf[dst_pos++] = srcBuf[src_pos    ];
    711             dstBuf[dst_pos++] = srcBuf[src_pos + 1];
    712             dstBuf[dst_pos++] = srcBuf[src_pos + 2];
    713             dstBuf[dst_pos++] = srcBuf[src_pos + 3];
    714         }
    715     }
    716 
    717     return true;
    718 }
    719 
    720 inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
    721                                          unsigned short tag,
    722                                          unsigned short type,
    723                                          unsigned int count,
    724                                          uint32_t value)
    725 {
    726     memcpy(*pCur, &tag, 2);
    727     *pCur += 2;
    728     memcpy(*pCur, &type, 2);
    729     *pCur += 2;
    730     memcpy(*pCur, &count, 4);
    731     *pCur += 4;
    732     memcpy(*pCur, &value, 4);
    733     *pCur += 4;
    734 }
    735 
    736 inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
    737                                          unsigned short tag,
    738                                          unsigned short type,
    739                                          unsigned int count,
    740                                          unsigned char *pValue)
    741 {
    742     char buf[4] = { 0,};
    743 
    744     memcpy(buf, pValue, count);
    745     memcpy(*pCur, &tag, 2);
    746     *pCur += 2;
    747     memcpy(*pCur, &type, 2);
    748     *pCur += 2;
    749     memcpy(*pCur, &count, 4);
    750     *pCur += 4;
    751     memcpy(*pCur, buf, 4);
    752     *pCur += 4;
    753 }
    754 
    755 
    756 inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
    757                                          unsigned short tag,
    758                                          unsigned short type,
    759                                          unsigned int count,
    760                                          unsigned char *pValue,
    761                                          unsigned int *offset,
    762                                          unsigned char *start)
    763 {
    764     memcpy(*pCur, &tag, 2);
    765     *pCur += 2;
    766     memcpy(*pCur, &type, 2);
    767     *pCur += 2;
    768     memcpy(*pCur, &count, 4);
    769     *pCur += 4;
    770     memcpy(*pCur, offset, 4);
    771     *pCur += 4;
    772     memcpy(start + *offset, pValue, count);
    773     *offset += count;
    774 }
    775 
    776 inline void JpegEncoder::writeExifIfd(unsigned char **pCur,
    777                                          unsigned short tag,
    778                                          unsigned short type,
    779                                          unsigned int count,
    780                                          rational_t *pValue,
    781                                          unsigned int *offset,
    782                                          unsigned char *start)
    783 {
    784     memcpy(*pCur, &tag, 2);
    785     *pCur += 2;
    786     memcpy(*pCur, &type, 2);
    787     *pCur += 2;
    788     memcpy(*pCur, &count, 4);
    789     *pCur += 4;
    790     memcpy(*pCur, offset, 4);
    791     *pCur += 4;
    792     memcpy(start + *offset, pValue, 8 * count);
    793     *offset += 8 * count;
    794 }
    795 
    796 };
    797