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