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
32static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
33
34namespace android {
35JpegEncoder::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        ALOGE("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        ALOGE("Failed to mmap");
56        return;
57    }
58
59    mArgs.enc_param = new jpg_enc_proc_param;
60    if (mArgs.enc_param == NULL) {
61        ALOGE("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        ALOGE("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
82JpegEncoder::~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
95jpg_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        ALOGE("Invalid Config type");
158        ret = ERR_UNKNOWN;
159    }
160
161    if (ret == JPG_FAIL)
162        ALOGE("Invalid value(%d) for %d type", value, type);
163
164    return ret;
165}
166
167void* JpegEncoder::getInBuf(uint64_t size)
168{
169    if (!available)
170        return NULL;
171
172    if (size > JPG_FRAME_BUF_SIZE) {
173        ALOGE("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
180void* JpegEncoder::getOutBuf(uint64_t *size)
181{
182    if (!available)
183        return NULL;
184
185    if (mArgs.enc_param->file_size <= 0) {
186        ALOGE("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
194void* JpegEncoder::getThumbInBuf(uint64_t size)
195{
196    if (!available)
197        return NULL;
198
199    if (size > JPG_FRAME_THUMB_BUF_SIZE) {
200        ALOGE("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
207void* JpegEncoder::getThumbOutBuf(uint64_t *size)
208{
209    if (!available)
210        return NULL;
211
212    if (mArgs.thumb_enc_param->file_size <= 0) {
213        ALOGE("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
221jpg_return_status JpegEncoder::encode(unsigned int *size, exif_attribute_t *exifInfo)
222{
223    if (!available)
224        return JPG_FAIL;
225
226    ALOGD("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        ALOGE("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                ALOGE("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            ALOGE("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            ALOGE("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    ALOGD("encode X");
299
300    return ret;
301}
302
303jpg_return_status JpegEncoder::encodeThumbImg(unsigned int *size, bool useMain)
304{
305    if (!available)
306        return JPG_FAIL;
307
308    ALOGD("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            ALOGE("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        ALOGE("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    ALOGD("encodeThumbImg X");
354
355    return JPG_SUCCESS;
356}
357
358jpg_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    ALOGD("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    ALOGD("makeExif X");
599
600    return JPG_SUCCESS;
601}
602
603jpg_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        ALOGE("Invaild sample mode");
629        return JPG_FAIL;
630    }
631
632    if (expectedWidth == width && expectedHeight == height)
633        return JPG_SUCCESS;
634
635    ALOGW("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        ALOGE("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
658bool 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        ALOGE("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        ALOGE("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
685bool 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        ALOGE("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
720inline 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
736inline 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
756inline 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
776inline 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