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