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