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