1 /* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 #define ATRACE_TAG ATRACE_TAG_CAMERA
30
31 #define LOG_TAG "QCamera3PostProc"
32 //#define LOG_NDEBUG 0
33
34 #include <stdlib.h>
35 #include <utils/Errors.h>
36 #include <utils/Trace.h>
37 #include <cutils/properties.h>
38
39 #include "QCamera3PostProc.h"
40 #include "QCamera3HWI.h"
41 #include "QCamera3Channel.h"
42 #include "QCamera3Stream.h"
43
44 namespace qcamera {
45
46 static const char ExifAsciiPrefix[] =
47 { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; // "ASCII\0\0\0"
48 static const char ExifUndefinedPrefix[] =
49 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // "\0\0\0\0\0\0\0\0"
50
51 #define EXIF_ASCII_PREFIX_SIZE 8 //(sizeof(ExifAsciiPrefix))
52 #define FOCAL_LENGTH_DECIMAL_PRECISION 1000
53
54 /*===========================================================================
55 * FUNCTION : QCamera3PostProcessor
56 *
57 * DESCRIPTION: constructor of QCamera3PostProcessor.
58 *
59 * PARAMETERS :
60 * @cam_ctrl : ptr to HWI object
61 *
62 * RETURN : None
63 *==========================================================================*/
QCamera3PostProcessor(QCamera3ProcessingChannel * ch_ctrl)64 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3ProcessingChannel* ch_ctrl)
65 : m_parent(ch_ctrl),
66 mJpegCB(NULL),
67 mJpegUserData(NULL),
68 mJpegClientHandle(0),
69 mJpegSessionId(0),
70 m_bThumbnailNeeded(TRUE),
71 m_pReprocChannel(NULL),
72 m_inputPPQ(releasePPInputData, this),
73 m_inputFWKPPQ(NULL, this),
74 m_ongoingPPQ(releaseOngoingPPData, this),
75 m_inputJpegQ(releaseJpegData, this),
76 m_ongoingJpegQ(releaseJpegData, this),
77 m_inputMetaQ(releaseMetadata, this),
78 m_jpegSettingsQ(NULL, this)
79 {
80 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
81 pthread_mutex_init(&mReprocJobLock, NULL);
82 }
83
84 /*===========================================================================
85 * FUNCTION : ~QCamera3PostProcessor
86 *
87 * DESCRIPTION: deconstructor of QCamera3PostProcessor.
88 *
89 * PARAMETERS : None
90 *
91 * RETURN : None
92 *==========================================================================*/
~QCamera3PostProcessor()93 QCamera3PostProcessor::~QCamera3PostProcessor()
94 {
95 pthread_mutex_destroy(&mReprocJobLock);
96 }
97
98 /*===========================================================================
99 * FUNCTION : init
100 *
101 * DESCRIPTION: initialization of postprocessor
102 *
103 * PARAMETERS :
104 * @memory : output buffer memory
105 * @postprocess_mask : postprocess mask for the buffer
106 *
107 * RETURN : int32_t type of status
108 * NO_ERROR -- success
109 * none-zero failure code
110 *==========================================================================*/
init(QCamera3StreamMem * memory,uint32_t postprocess_mask)111 int32_t QCamera3PostProcessor::init(QCamera3StreamMem *memory,
112 uint32_t postprocess_mask)
113 {
114 ATRACE_CALL();
115 mOutputMem = memory;
116 mPostProcMask = postprocess_mask;
117 m_dataProcTh.launch(dataProcessRoutine, this);
118
119 return NO_ERROR;
120 }
121
122 /*===========================================================================
123 * FUNCTION : deinit
124 *
125 * DESCRIPTION: de-initialization of postprocessor
126 *
127 * PARAMETERS : None
128 *
129 * RETURN : int32_t type of status
130 * NO_ERROR -- success
131 * none-zero failure code
132 *==========================================================================*/
deinit()133 int32_t QCamera3PostProcessor::deinit()
134 {
135 int rc = NO_ERROR;
136 m_dataProcTh.exit();
137
138 if (m_pReprocChannel != NULL) {
139 m_pReprocChannel->stop();
140 delete m_pReprocChannel;
141 m_pReprocChannel = NULL;
142 }
143
144 if(mJpegClientHandle > 0) {
145 rc = mJpegHandle.close(mJpegClientHandle);
146 CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
147 __func__, rc, mJpegClientHandle);
148 mJpegClientHandle = 0;
149 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
150 }
151
152 mOutputMem = NULL;
153 return rc;
154 }
155
156 /*===========================================================================
157 * FUNCTION : initJpeg
158 *
159 * DESCRIPTION: initialization of jpeg through postprocessor
160 *
161 * PARAMETERS :
162 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface
163 * @max_pic_dim : max picture dimensions
164 * @user_data : user data ptr for jpeg callback
165 *
166 * RETURN : int32_t type of status
167 * NO_ERROR -- success
168 * none-zero failure code
169 *==========================================================================*/
initJpeg(jpeg_encode_callback_t jpeg_cb,cam_dimension_t * max_pic_dim,void * user_data)170 int32_t QCamera3PostProcessor::initJpeg(jpeg_encode_callback_t jpeg_cb,
171 cam_dimension_t* max_pic_dim,
172 void *user_data)
173 {
174 ATRACE_CALL();
175 mJpegCB = jpeg_cb;
176 mJpegUserData = user_data;
177 mm_dimension max_size;
178
179 if ((0 > max_pic_dim->width) || (0 > max_pic_dim->height)) {
180 ALOGE("%s : Negative dimension %dx%d", __func__,
181 max_pic_dim->width, max_pic_dim->height);
182 return BAD_VALUE;
183 }
184
185 //set max pic size
186 memset(&max_size, 0, sizeof(mm_dimension));
187 max_size.w = max_pic_dim->width;
188 max_size.h = max_pic_dim->height;
189
190 mJpegClientHandle = jpeg_open(&mJpegHandle, max_size);
191 if(!mJpegClientHandle) {
192 ALOGE("%s : jpeg_open did not work", __func__);
193 return UNKNOWN_ERROR;
194 }
195 return NO_ERROR;
196 }
197
198 /*===========================================================================
199 * FUNCTION : start
200 *
201 * DESCRIPTION: start postprocessor. Data process thread and data notify thread
202 * will be launched.
203 *
204 * PARAMETERS :
205 * @config : reprocess configuration
206 *
207 * RETURN : int32_t type of status
208 * NO_ERROR -- success
209 * none-zero failure code
210 *
211 * NOTE : if any reprocess is needed, a reprocess channel/stream
212 * will be started.
213 *==========================================================================*/
start(const reprocess_config_t & config)214 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config)
215 {
216 int32_t rc = NO_ERROR;
217 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
218
219 if (config.reprocess_type != REPROCESS_TYPE_NONE) {
220 if (m_pReprocChannel != NULL) {
221 m_pReprocChannel->stop();
222 delete m_pReprocChannel;
223 m_pReprocChannel = NULL;
224 }
225
226 // if reprocess is needed, start reprocess channel
227 CDBG("%s: Setting input channel as pInputChannel", __func__);
228 m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent);
229 if (m_pReprocChannel == NULL) {
230 ALOGE("%s: cannot add reprocess channel", __func__);
231 return UNKNOWN_ERROR;
232 }
233 /*start the reprocess channel only if buffers are already allocated, thus
234 only start it in an intermediate reprocess type, defer it for others*/
235 if (config.reprocess_type == REPROCESS_TYPE_JPEG) {
236 rc = m_pReprocChannel->start();
237 if (rc != 0) {
238 ALOGE("%s: cannot start reprocess channel", __func__);
239 delete m_pReprocChannel;
240 m_pReprocChannel = NULL;
241 return rc;
242 }
243 }
244 }
245 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
246
247 return rc;
248 }
249
250 /*===========================================================================
251 * FUNCTION : stop
252 *
253 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
254 *
255 * PARAMETERS : None
256 *
257 * RETURN : int32_t type of status
258 * NO_ERROR -- success
259 * none-zero failure code
260 *
261 * NOTE : reprocess channel will be stopped and deleted if there is any
262 *==========================================================================*/
stop()263 int32_t QCamera3PostProcessor::stop()
264 {
265 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
266
267 if (m_pReprocChannel != NULL) {
268 m_pReprocChannel->stop();
269 delete m_pReprocChannel;
270 m_pReprocChannel = NULL;
271 }
272
273 return NO_ERROR;
274 }
275
276 /*===========================================================================
277 * FUNCTION : getFWKJpegEncodeConfig
278 *
279 * DESCRIPTION: function to prepare encoding job information
280 *
281 * PARAMETERS :
282 * @encode_parm : param to be filled with encoding configuration
283 * @frame : framework input buffer
284 * @jpeg_settings : jpeg settings to be applied for encoding
285 *
286 * RETURN : int32_t type of status
287 * NO_ERROR -- success
288 * none-zero failure code
289 *==========================================================================*/
getFWKJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,qcamera_fwk_input_pp_data_t * frame,jpeg_settings_t * jpeg_settings)290 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
291 mm_jpeg_encode_params_t& encode_parm,
292 qcamera_fwk_input_pp_data_t *frame,
293 jpeg_settings_t *jpeg_settings)
294 {
295 CDBG("%s : E", __func__);
296 int32_t ret = NO_ERROR;
297
298 if ((NULL == frame) || (NULL == jpeg_settings)) {
299 return BAD_VALUE;
300 }
301
302 ssize_t bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
303 if (BAD_INDEX == bufSize) {
304 ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__,
305 jpeg_settings->out_buf_index);
306 return BAD_VALUE;
307 }
308
309 encode_parm.jpeg_cb = mJpegCB;
310 encode_parm.userdata = mJpegUserData;
311
312 if (jpeg_settings->thumbnail_size.width > 0 &&
313 jpeg_settings->thumbnail_size.height > 0)
314 m_bThumbnailNeeded = TRUE;
315 else
316 m_bThumbnailNeeded = FALSE;
317 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
318
319 // get color format
320 cam_format_t img_fmt = frame->reproc_config.stream_format;
321 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
322
323 // get jpeg quality
324 encode_parm.quality = jpeg_settings->jpeg_quality;
325 if (encode_parm.quality <= 0) {
326 encode_parm.quality = 85;
327 }
328
329 // get jpeg thumbnail quality
330 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
331
332 cam_frame_len_offset_t main_offset =
333 frame->reproc_config.input_stream_plane_info.plane_info;
334
335 encode_parm.num_src_bufs = 1;
336 encode_parm.src_main_buf[0].index = 0;
337 encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
338 encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
339 encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
340 encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
341 encode_parm.src_main_buf[0].offset = main_offset;
342
343 //Pass input thumbnail buffer info to encoder.
344 //Note: Use main buffer to encode thumbnail
345 if (m_bThumbnailNeeded == TRUE) {
346 encode_parm.num_tmb_bufs = 1;
347 encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
348 }
349
350 //Pass output jpeg buffer info to encoder.
351 //mOutputMem is allocated by framework.
352 encode_parm.num_dst_bufs = 1;
353 encode_parm.dest_buf[0].index = 0;
354 encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
355 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
356 jpeg_settings->out_buf_index);
357 encode_parm.dest_buf[0].fd = mOutputMem->getFd(
358 jpeg_settings->out_buf_index);
359 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
360 encode_parm.dest_buf[0].offset = main_offset;
361
362 CDBG("%s : X", __func__);
363 return NO_ERROR;
364
365 on_error:
366 CDBG("%s : X with error %d", __func__, ret);
367 return ret;
368 }
369
370 /*===========================================================================
371 * FUNCTION : getJpegEncodeConfig
372 *
373 * DESCRIPTION: function to prepare encoding job information
374 *
375 * PARAMETERS :
376 * @encode_parm : param to be filled with encoding configuration
377 * #main_stream : stream object where the input buffer comes from
378 * @jpeg_settings : jpeg settings to be applied for encoding
379 *
380 * RETURN : int32_t type of status
381 * NO_ERROR -- success
382 * none-zero failure code
383 *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)384 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
385 mm_jpeg_encode_params_t& encode_parm,
386 QCamera3Stream *main_stream,
387 jpeg_settings_t *jpeg_settings)
388 {
389 CDBG("%s : E", __func__);
390 int32_t ret = NO_ERROR;
391 ssize_t bufSize = 0;
392
393 encode_parm.jpeg_cb = mJpegCB;
394 encode_parm.userdata = mJpegUserData;
395
396 if (jpeg_settings->thumbnail_size.width > 0 &&
397 jpeg_settings->thumbnail_size.height > 0)
398 m_bThumbnailNeeded = TRUE;
399 else
400 m_bThumbnailNeeded = FALSE;
401 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
402
403 // get color format
404 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value
405 main_stream->getFormat(img_fmt);
406 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
407
408 // get jpeg quality
409 encode_parm.quality = jpeg_settings->jpeg_quality;
410 if (encode_parm.quality <= 0) {
411 encode_parm.quality = 85;
412 }
413
414 // get jpeg thumbnail quality
415 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
416
417 cam_frame_len_offset_t main_offset;
418 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
419 main_stream->getFrameOffset(main_offset);
420
421 // src buf config
422 //Pass input main image buffer info to encoder.
423 QCamera3StreamMem *pStreamMem = main_stream->getStreamBufs();
424 if (pStreamMem == NULL) {
425 ALOGE("%s: cannot get stream bufs from main stream", __func__);
426 ret = BAD_VALUE;
427 goto on_error;
428 }
429 encode_parm.num_src_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
430 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
431 if (pStreamMem != NULL) {
432 encode_parm.src_main_buf[i].index = i;
433 bufSize = pStreamMem->getSize(i);
434 if (BAD_INDEX == bufSize) {
435 ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
436 ret = BAD_VALUE;
437 goto on_error;
438 }
439 encode_parm.src_main_buf[i].buf_size = (size_t)bufSize;
440 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
441 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
442 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
443 encode_parm.src_main_buf[i].offset = main_offset;
444 }
445 }
446
447 //Pass input thumbnail buffer info to encoder.
448 //Note: Use main buffer to encode thumbnail
449 if (m_bThumbnailNeeded == TRUE) {
450 pStreamMem = main_stream->getStreamBufs();
451 if (pStreamMem == NULL) {
452 ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
453 ret = BAD_VALUE;
454 goto on_error;
455 }
456 cam_frame_len_offset_t thumb_offset;
457 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
458 main_stream->getFrameOffset(thumb_offset);
459 encode_parm.num_tmb_bufs = MIN(pStreamMem->getCnt(), MM_JPEG_MAX_BUF);
460 for (uint32_t i = 0; i < encode_parm.num_tmb_bufs; i++) {
461 if (pStreamMem != NULL) {
462 encode_parm.src_thumb_buf[i].index = i;
463 bufSize = pStreamMem->getSize(i);
464 if (BAD_INDEX == bufSize) {
465 ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
466 ret = BAD_VALUE;
467 goto on_error;
468 }
469 encode_parm.src_thumb_buf[i].buf_size = (uint32_t)bufSize;
470 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
471 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
472 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
473 encode_parm.src_thumb_buf[i].offset = thumb_offset;
474 }
475 }
476 }
477
478 //Pass output jpeg buffer info to encoder.
479 //mJpegMem is allocated by framework.
480 bufSize = mOutputMem->getSize(jpeg_settings->out_buf_index);
481 if (BAD_INDEX == bufSize) {
482 ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__,
483 jpeg_settings->out_buf_index);
484 ret = BAD_VALUE;
485 goto on_error;
486 }
487 encode_parm.num_dst_bufs = 1;
488 encode_parm.dest_buf[0].index = 0;
489 encode_parm.dest_buf[0].buf_size = (size_t)bufSize;
490 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mOutputMem->getPtr(
491 jpeg_settings->out_buf_index);
492 encode_parm.dest_buf[0].fd = mOutputMem->getFd(
493 jpeg_settings->out_buf_index);
494 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
495 encode_parm.dest_buf[0].offset = main_offset;
496
497 CDBG("%s : X", __func__);
498 return NO_ERROR;
499
500 on_error:
501 CDBG("%s : X with error %d", __func__, ret);
502 return ret;
503 }
504
processData(mm_camera_super_buf_t * input)505 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input) {
506 return processData(input, NULL, 0);
507 }
508
509 /*===========================================================================
510 * FUNCTION : processData
511 *
512 * DESCRIPTION: enqueue data into dataProc thread
513 *
514 * PARAMETERS :
515 * @frame : process input frame
516 * @output : process output frame
517 *
518 * RETURN : int32_t type of status
519 * NO_ERROR -- success
520 * none-zero failure code
521 *
522 * NOTE : depends on if offline reprocess is needed, received frame will
523 * be sent to either input queue of postprocess or jpeg encoding
524 *==========================================================================*/
processData(mm_camera_super_buf_t * input,buffer_handle_t * output,uint32_t frameNumber)525 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input,
526 buffer_handle_t *output, uint32_t frameNumber)
527 {
528 CDBG("%s: E", __func__);
529 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
530 pthread_mutex_lock(&mReprocJobLock);
531
532 // enqueue to post proc input queue
533 qcamera_hal3_pp_buffer_t *pp_buffer = (qcamera_hal3_pp_buffer_t *)malloc(
534 sizeof(qcamera_hal3_pp_buffer_t));
535 if (NULL == pp_buffer) {
536 ALOGE("%s: out of memory", __func__);
537 return NO_MEMORY;
538 }
539 memset(pp_buffer, 0, sizeof(*pp_buffer));
540 pp_buffer->input = input;
541 pp_buffer->output = output;
542 pp_buffer->frameNumber = frameNumber;
543 m_inputPPQ.enqueue((void *)pp_buffer);
544 if (!(m_inputMetaQ.isEmpty())) {
545 CDBG("%s: meta queue is not empty, do next job", __func__);
546 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
547 } else
548 CDBG("%s: metadata queue is empty", __func__);
549 pthread_mutex_unlock(&mReprocJobLock);
550
551 return NO_ERROR;
552 }
553
554 /*===========================================================================
555 * FUNCTION : processData
556 *
557 * DESCRIPTION: enqueue data into dataProc thread
558 *
559 * PARAMETERS :
560 * @frame : process frame
561 *
562 * RETURN : int32_t type of status
563 * NO_ERROR -- success
564 * none-zero failure code
565 *
566 * NOTE : depends on if offline reprocess is needed, received frame will
567 * be sent to either input queue of postprocess or jpeg encoding
568 *==========================================================================*/
processData(qcamera_fwk_input_pp_data_t * frame)569 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
570 {
571 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
572 if (frame->reproc_config.reprocess_type != REPROCESS_TYPE_NONE) {
573 pthread_mutex_lock(&mReprocJobLock);
574 // enqueu to post proc input queue
575 m_inputFWKPPQ.enqueue((void *)frame);
576 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
577 pthread_mutex_unlock(&mReprocJobLock);
578 } else {
579 jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
580
581 if (jpeg_settings == NULL) {
582 ALOGE("%s: Cannot find jpeg settings", __func__);
583 return BAD_VALUE;
584 }
585
586 CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
587 qcamera_hal3_jpeg_data_t *jpeg_job =
588 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
589 if (jpeg_job == NULL) {
590 ALOGE("%s: No memory for jpeg job", __func__);
591 return NO_MEMORY;
592 }
593
594 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
595 jpeg_job->fwk_frame = frame;
596 jpeg_job->jpeg_settings = jpeg_settings;
597 jpeg_job->metadata =
598 (metadata_buffer_t *) frame->metadata_buffer.buffer;
599
600 // enqueu to jpeg input queue
601 m_inputJpegQ.enqueue((void *)jpeg_job);
602 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
603 }
604
605 return NO_ERROR;
606 }
607
608 /*===========================================================================
609 * FUNCTION : processPPMetadata
610 *
611 * DESCRIPTION: enqueue data into dataProc thread
612 *
613 * PARAMETERS :
614 * @frame : process metadata frame received from pic channel
615 *
616 * RETURN : int32_t type of status
617 * NO_ERROR -- success
618 * none-zero failure code
619 *
620 *==========================================================================*/
processPPMetadata(mm_camera_super_buf_t * reproc_meta)621 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
622 {
623 CDBG("%s: E", __func__);
624 pthread_mutex_lock(&mReprocJobLock);
625 // enqueue to metadata input queue
626 m_inputMetaQ.enqueue((void *)reproc_meta);
627 if (!(m_inputPPQ.isEmpty())) {
628 CDBG("%s: pp queue is not empty, do next job", __func__);
629 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
630 } else {
631 CDBG("%s: pp queue is empty, not calling do next job", __func__);
632 }
633 pthread_mutex_unlock(&mReprocJobLock);
634 return NO_ERROR;
635 }
636
637 /*===========================================================================
638 * FUNCTION : processJpegSettingData
639 *
640 * DESCRIPTION: enqueue jpegSetting into dataProc thread
641 *
642 * PARAMETERS :
643 * @jpeg_settings : jpeg settings data received from pic channel
644 *
645 * RETURN : int32_t type of status
646 * NO_ERROR -- success
647 * none-zero failure code
648 *
649 *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)650 int32_t QCamera3PostProcessor::processJpegSettingData(
651 jpeg_settings_t *jpeg_settings)
652 {
653 if (!jpeg_settings) {
654 ALOGE("%s: invalid jpeg settings pointer", __func__);
655 return -EINVAL;
656 }
657 return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
658 }
659
660 /*===========================================================================
661 * FUNCTION : processPPData
662 *
663 * DESCRIPTION: process received frame after reprocess.
664 *
665 * PARAMETERS :
666 * @frame : received frame from reprocess channel.
667 *
668 * RETURN : int32_t type of status
669 * NO_ERROR -- success
670 * none-zero failure code
671 *
672 * NOTE : The frame after reprocess need to send to jpeg encoding.
673 *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)674 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
675 {
676 qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
677
678 if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
679 ALOGE("%s: Cannot find reprocess job", __func__);
680 return BAD_VALUE;
681 }
682 if (job->jpeg_settings == NULL) {
683 ALOGE("%s: Cannot find jpeg settings", __func__);
684 return BAD_VALUE;
685 }
686
687 qcamera_hal3_jpeg_data_t *jpeg_job =
688 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
689 if (jpeg_job == NULL) {
690 ALOGE("%s: No memory for jpeg job", __func__);
691 return NO_MEMORY;
692 }
693
694 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
695 jpeg_job->src_frame = frame;
696 if(frame != job->src_frame)
697 jpeg_job->src_reproc_frame = job->src_frame;
698 if (NULL == job->fwk_src_frame) {
699 jpeg_job->metadata = job->metadata;
700 } else {
701 jpeg_job->metadata =
702 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
703 jpeg_job->fwk_src_buffer = job->fwk_src_frame;
704 }
705 jpeg_job->src_metadata = job->src_metadata;
706 jpeg_job->jpeg_settings = job->jpeg_settings;
707
708 // free pp job buf
709 free(job);
710
711 // enqueu reprocessed frame to jpeg input queue
712 m_inputJpegQ.enqueue((void *)jpeg_job);
713
714 // wait up data proc thread
715 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
716
717 return NO_ERROR;
718 }
719
720 /*===========================================================================
721 * FUNCTION : dequeuePPJob
722 *
723 * DESCRIPTION: find a postprocessing job from ongoing pp queue by frame number
724 *
725 * PARAMETERS :
726 * @frameNumber : frame number for the pp job
727 *
728 * RETURN : ptr to a pp job struct. NULL if not found.
729 *==========================================================================*/
dequeuePPJob(uint32_t frameNumber)730 qcamera_hal3_pp_data_t *QCamera3PostProcessor::dequeuePPJob(uint32_t frameNumber) {
731 qcamera_hal3_pp_data_t *pp_job = NULL;
732 pp_job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
733
734 if (pp_job == NULL) {
735 ALOGE("%s: Fatal: ongoing PP queue is empty", __func__);
736 return NULL;
737 }
738 if (pp_job->fwk_src_frame &&
739 (pp_job->fwk_src_frame->frameNumber != frameNumber)) {
740 ALOGE("%s: head of pp queue doesn't match requested frame number", __func__);
741 }
742 return pp_job;
743 }
744
745 /*===========================================================================
746 * FUNCTION : findJpegJobByJobId
747 *
748 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
749 *
750 * PARAMETERS :
751 * @jobId : job Id of the job
752 *
753 * RETURN : ptr to a jpeg job struct. NULL if not found.
754 *
755 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg
756 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue
757 * will serve the purpose to find the jpeg job.
758 *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)759 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
760 {
761 qcamera_hal3_jpeg_data_t * job = NULL;
762 if (jobId == 0) {
763 ALOGE("%s: not a valid jpeg jobId", __func__);
764 return NULL;
765 }
766
767 // currely only one jpeg job ongoing, so simply dequeue the head
768 job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
769 return job;
770 }
771
772 /*===========================================================================
773 * FUNCTION : releasePPInputData
774 *
775 * DESCRIPTION: callback function to release post process input data node
776 *
777 * PARAMETERS :
778 * @data : ptr to post process input data
779 * @user_data : user data ptr (QCamera3Reprocessor)
780 *
781 * RETURN : None
782 *==========================================================================*/
releasePPInputData(void * data,void * user_data)783 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
784 {
785 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
786 if (NULL != pme) {
787 qcamera_hal3_pp_buffer_t *buf = (qcamera_hal3_pp_buffer_t *)data;
788 if (NULL != buf) {
789 if (buf->input) {
790 pme->releaseSuperBuf(buf->input);
791 free(buf->input);
792 buf->input = NULL;
793 }
794 }
795 }
796 }
797
798 /*===========================================================================
799 * FUNCTION : releaseMetaData
800 *
801 * DESCRIPTION: callback function to release metadata camera buffer
802 *
803 * PARAMETERS :
804 * @data : ptr to post process input data
805 * @user_data : user data ptr (QCamera3Reprocessor)
806 *
807 * RETURN : None
808 *==========================================================================*/
releaseMetadata(void * data,void * user_data)809 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
810 {
811 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
812 if (NULL != pme) {
813 pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
814 }
815 }
816
817 /*===========================================================================
818 * FUNCTION : releaseJpegData
819 *
820 * DESCRIPTION: callback function to release jpeg job node
821 *
822 * PARAMETERS :
823 * @data : ptr to ongoing jpeg job data
824 * @user_data : user data ptr (QCamera3Reprocessor)
825 *
826 * RETURN : None
827 *==========================================================================*/
releaseJpegData(void * data,void * user_data)828 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
829 {
830 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
831 if (NULL != pme) {
832 pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
833 }
834 }
835
836 /*===========================================================================
837 * FUNCTION : releaseOngoingPPData
838 *
839 * DESCRIPTION: callback function to release ongoing postprocess job node
840 *
841 * PARAMETERS :
842 * @data : ptr to onging postprocess job
843 * @user_data : user data ptr (QCamera3Reprocessor)
844 *
845 * RETURN : None
846 *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)847 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
848 {
849 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
850 if (NULL != pme) {
851 qcamera_hal3_pp_data_t *pp_data = (qcamera_hal3_pp_data_t *)data;
852
853 if (pp_data && pp_data->src_frame)
854 pme->releaseSuperBuf(pp_data->src_frame);
855
856 pme->releasePPJobData(pp_data);
857
858 }
859 }
860
861 /*===========================================================================
862 * FUNCTION : releaseSuperBuf
863 *
864 * DESCRIPTION: function to release a superbuf frame by returning back to kernel
865 *
866 * PARAMETERS :
867 * @super_buf : ptr to the superbuf frame
868 *
869 * RETURN : None
870 *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)871 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
872 {
873 if (NULL != super_buf) {
874 if (m_parent != NULL) {
875 m_parent->bufDone(super_buf);
876 }
877 }
878 }
879
880 /*===========================================================================
881 * FUNCTION : releaseOfflineBuffers
882 *
883 * DESCRIPTION: function to release/unmap offline buffers if any
884 *
885 * PARAMETERS : None
886 *
887 * RETURN : int32_t type of status
888 * NO_ERROR -- success
889 * none-zero failure code
890 *==========================================================================*/
releaseOfflineBuffers()891 int32_t QCamera3PostProcessor::releaseOfflineBuffers()
892 {
893 int32_t rc = NO_ERROR;
894
895 if(NULL != m_pReprocChannel) {
896 rc = m_pReprocChannel->unmapOfflineBuffers(false);
897 }
898
899 return rc;
900 }
901
902 /*===========================================================================
903 * FUNCTION : releaseJpegJobData
904 *
905 * DESCRIPTION: function to release internal resources in jpeg job struct
906 *
907 * PARAMETERS :
908 * @job : ptr to jpeg job struct
909 *
910 * RETURN : None
911 *
912 * NOTE : original source frame need to be queued back to kernel for
913 * future use. Output buf of jpeg job need to be released since
914 * it's allocated for each job. Exif object need to be deleted.
915 *==========================================================================*/
releaseJpegJobData(qcamera_hal3_jpeg_data_t * job)916 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
917 {
918 ATRACE_CALL();
919 int32_t rc = NO_ERROR;
920 CDBG("%s: E", __func__);
921 if (NULL != job) {
922 if (NULL != job->src_reproc_frame) {
923 free(job->src_reproc_frame);
924 job->src_reproc_frame = NULL;
925 }
926
927 if (NULL != job->src_frame) {
928 if (NULL != m_pReprocChannel) {
929 rc = m_pReprocChannel->bufDone(job->src_frame);
930 if (NO_ERROR != rc)
931 ALOGE("%s: bufDone error: %d", __func__, rc);
932 }
933 free(job->src_frame);
934 job->src_frame = NULL;
935 }
936
937 if (NULL != job->fwk_src_buffer) {
938 free(job->fwk_src_buffer);
939 job->fwk_src_buffer = NULL;
940 } else if (NULL != job->src_metadata) {
941 m_parent->metadataBufDone(job->src_metadata);
942 free(job->src_metadata);
943 job->src_metadata = NULL;
944 }
945
946 if (NULL != job->fwk_frame) {
947 free(job->fwk_frame);
948 job->fwk_frame = NULL;
949 }
950
951 if (NULL != job->pJpegExifObj) {
952 delete job->pJpegExifObj;
953 job->pJpegExifObj = NULL;
954 }
955
956 if (NULL != job->jpeg_settings) {
957 free(job->jpeg_settings);
958 job->jpeg_settings = NULL;
959 }
960 }
961 /* Additional trigger to process any pending jobs in the input queue */
962 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
963 CDBG("%s: X", __func__);
964 }
965
966 /*===========================================================================
967 * FUNCTION : releasePPJobData
968 *
969 * DESCRIPTION: function to release internal resources in p pjob struct
970 *
971 * PARAMETERS :
972 * @job : ptr to pp job struct
973 *
974 * RETURN : None
975 *
976 * NOTE : Original source metadata buffer needs to be released and
977 * queued back to kernel for future use. src_frame, src_metadata,
978 * and fwk_src_frame structures need to be freed.
979 *==========================================================================*/
releasePPJobData(qcamera_hal3_pp_data_t * pp_job)980 void QCamera3PostProcessor::releasePPJobData(qcamera_hal3_pp_data_t *pp_job)
981 {
982 ATRACE_CALL();
983 CDBG("%s: E", __func__);
984 if (NULL != pp_job) {
985 if (NULL != pp_job->src_frame) {
986 free(pp_job->src_frame);
987 if (NULL != pp_job->src_metadata) {
988 m_parent->metadataBufDone(pp_job->src_metadata);
989 free(pp_job->src_metadata);
990 }
991 pp_job->src_frame = NULL;
992 pp_job->metadata = NULL;
993 }
994
995 if (NULL != pp_job->fwk_src_frame) {
996 free(pp_job->fwk_src_frame);
997 pp_job->fwk_src_frame = NULL;
998 }
999 }
1000
1001 /* Additional trigger to process any pending jobs in the input queue */
1002 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1003 CDBG("%s: X", __func__);
1004 }
1005
1006 /*===========================================================================
1007 * FUNCTION : getColorfmtFromImgFmt
1008 *
1009 * DESCRIPTION: function to return jpeg color format based on its image format
1010 *
1011 * PARAMETERS :
1012 * @img_fmt : image format
1013 *
1014 * RETURN : jpeg color format that can be understandable by omx lib
1015 *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)1016 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
1017 {
1018 switch (img_fmt) {
1019 case CAM_FORMAT_YUV_420_NV21:
1020 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1021 case CAM_FORMAT_YUV_420_NV21_ADRENO:
1022 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1023 case CAM_FORMAT_YUV_420_NV12:
1024 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1025 case CAM_FORMAT_YUV_420_YV12:
1026 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1027 case CAM_FORMAT_YUV_422_NV61:
1028 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
1029 case CAM_FORMAT_YUV_422_NV16:
1030 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
1031 default:
1032 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1033 }
1034 }
1035
1036 /*===========================================================================
1037 * FUNCTION : getJpegImgTypeFromImgFmt
1038 *
1039 * DESCRIPTION: function to return jpeg encode image type based on its image format
1040 *
1041 * PARAMETERS :
1042 * @img_fmt : image format
1043 *
1044 * RETURN : return jpeg source image format (YUV or Bitstream)
1045 *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)1046 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
1047 {
1048 switch (img_fmt) {
1049 case CAM_FORMAT_YUV_420_NV21:
1050 case CAM_FORMAT_YUV_420_NV21_ADRENO:
1051 case CAM_FORMAT_YUV_420_NV12:
1052 case CAM_FORMAT_YUV_420_YV12:
1053 case CAM_FORMAT_YUV_422_NV61:
1054 case CAM_FORMAT_YUV_422_NV16:
1055 return MM_JPEG_FMT_YUV;
1056 default:
1057 return MM_JPEG_FMT_YUV;
1058 }
1059 }
1060
1061 /*===========================================================================
1062 * FUNCTION : encodeFWKData
1063 *
1064 * DESCRIPTION: function to prepare encoding job information and send to
1065 * mm-jpeg-interface to do the encoding job
1066 *
1067 * PARAMETERS :
1068 * @jpeg_job_data : ptr to a struct saving job related information
1069 * @needNewSess : flag to indicate if a new jpeg encoding session need
1070 * to be created. After creation, this flag will be toggled
1071 *
1072 * RETURN : int32_t type of status
1073 * NO_ERROR -- success
1074 * none-zero failure code
1075 *==========================================================================*/
encodeFWKData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1076 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1077 uint8_t &needNewSess)
1078 {
1079 CDBG("%s : E", __func__);
1080 int32_t ret = NO_ERROR;
1081 mm_jpeg_job_t jpg_job;
1082 uint32_t jobId = 0;
1083 qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
1084 metadata_buffer_t *metadata = NULL;
1085 jpeg_settings_t *jpeg_settings = NULL;
1086 QCamera3HardwareInterface* hal_obj = NULL;
1087 bool needJpegRotation = false;
1088
1089 if (NULL == jpeg_job_data) {
1090 ALOGE("%s: Invalid jpeg job", __func__);
1091 return BAD_VALUE;
1092 }
1093
1094 recvd_frame = jpeg_job_data->fwk_frame;
1095 if (NULL == recvd_frame) {
1096 ALOGE("%s: Invalid input buffer", __func__);
1097 return BAD_VALUE;
1098 }
1099
1100 metadata = jpeg_job_data->metadata;
1101 if (NULL == metadata) {
1102 ALOGE("%s: Invalid metadata buffer", __func__);
1103 return BAD_VALUE;
1104 }
1105
1106 jpeg_settings = jpeg_job_data->jpeg_settings;
1107 if (NULL == jpeg_settings) {
1108 ALOGE("%s: Invalid jpeg settings buffer", __func__);
1109 return BAD_VALUE;
1110 }
1111
1112 if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
1113 ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!",
1114 __func__);
1115 return BAD_VALUE;
1116 }
1117
1118 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1119
1120 if (mJpegClientHandle <= 0) {
1121 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1122 return UNKNOWN_ERROR;
1123 }
1124
1125 cam_dimension_t src_dim;
1126 memset(&src_dim, 0, sizeof(cam_dimension_t));
1127 src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
1128 src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
1129
1130 cam_dimension_t dst_dim;
1131 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1132 dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
1133 dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
1134
1135 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1136 if (needNewSess) {
1137 //creating a new session, so we must destroy the old one
1138 if ( 0 < mJpegSessionId ) {
1139 ret = mJpegHandle.destroy_session(mJpegSessionId);
1140 if (ret != NO_ERROR) {
1141 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1142 __func__, mJpegSessionId);
1143 return ret;
1144 }
1145 mJpegSessionId = 0;
1146 }
1147 // create jpeg encoding session
1148 mm_jpeg_encode_params_t encodeParam;
1149 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1150 encodeParam.main_dim.src_dim = src_dim;
1151 encodeParam.main_dim.dst_dim = dst_dim;
1152 encodeParam.thumb_dim.src_dim = src_dim;
1153 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1154
1155 getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1156 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1157 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1158
1159 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1160 if (ret != NO_ERROR) {
1161 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1162 return ret;
1163 }
1164 needNewSess = FALSE;
1165 }
1166
1167 // Fill in new job
1168 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1169 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1170 jpg_job.encode_job.session_id = mJpegSessionId;
1171 jpg_job.encode_job.src_index = 0;
1172 jpg_job.encode_job.dst_index = 0;
1173
1174 cam_rect_t crop;
1175 memset(&crop, 0, sizeof(cam_rect_t));
1176 //TBD_later - Zoom event removed in stream
1177 //main_stream->getCropInfo(crop);
1178
1179 // Set main dim job parameters and handle rotation
1180 needJpegRotation = hal_obj->needJpegRotation();
1181 if (!needJpegRotation && (jpeg_settings->jpeg_orientation == 90 ||
1182 jpeg_settings->jpeg_orientation == 270)) {
1183
1184 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1185 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1186
1187 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1188 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1189
1190 jpg_job.encode_job.main_dim.crop.width = crop.height;
1191 jpg_job.encode_job.main_dim.crop.height = crop.width;
1192 jpg_job.encode_job.main_dim.crop.left = crop.top;
1193 jpg_job.encode_job.main_dim.crop.top = crop.left;
1194 } else {
1195 jpg_job.encode_job.main_dim.src_dim = src_dim;
1196 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1197 jpg_job.encode_job.main_dim.crop = crop;
1198 }
1199
1200 QCamera3HardwareInterface* obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1201 // get 3a sw version info
1202 cam_q3a_version_t sw_version;
1203 memset(&sw_version, 0, sizeof(sw_version));
1204 if (obj)
1205 obj->get3AVersion(sw_version);
1206
1207 // get exif data
1208 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings);
1209 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1210 if (pJpegExifObj != NULL) {
1211 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1212 jpg_job.encode_job.exif_info.numOfEntries =
1213 pJpegExifObj->getNumOfEntries();
1214 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1215 sw_version.major_version;
1216 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1217 sw_version.minor_version;
1218 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1219 sw_version.patch_version;
1220 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1221 sw_version.new_feature_des;
1222 }
1223
1224 // thumbnail dim
1225 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1226 if (m_bThumbnailNeeded == TRUE) {
1227 memset(&crop, 0, sizeof(cam_rect_t));
1228 jpg_job.encode_job.thumb_dim.dst_dim =
1229 jpeg_settings->thumbnail_size;
1230
1231 if (needJpegRotation) {
1232 jpg_job.encode_job.rotation = (uint32_t)jpeg_settings->jpeg_orientation;
1233 CDBG_HIGH("%s: jpeg rotation is set to %u", __func__, jpg_job.encode_job.rotation);
1234 } else if (jpeg_settings->jpeg_orientation == 90 ||
1235 jpeg_settings->jpeg_orientation == 270) {
1236 //swap the thumbnail destination width and height if it has
1237 //already been rotated
1238 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1239 jpg_job.encode_job.thumb_dim.dst_dim.width =
1240 jpg_job.encode_job.thumb_dim.dst_dim.height;
1241 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1242 }
1243 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1244 jpg_job.encode_job.thumb_dim.crop = crop;
1245 jpg_job.encode_job.thumb_index = 0;
1246 }
1247
1248 if (metadata != NULL) {
1249 //Fill in the metadata passed as parameter
1250 jpg_job.encode_job.p_metadata = metadata;
1251 } else {
1252 ALOGE("%s: Metadata is null", __func__);
1253 }
1254
1255 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1256
1257 //Start jpeg encoding
1258 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1259 if (ret == NO_ERROR) {
1260 // remember job info
1261 jpeg_job_data->jobId = jobId;
1262 }
1263
1264 CDBG("%s : X", __func__);
1265 return ret;
1266 }
1267
1268 /*===========================================================================
1269 * FUNCTION : encodeData
1270 *
1271 * DESCRIPTION: function to prepare encoding job information and send to
1272 * mm-jpeg-interface to do the encoding job
1273 *
1274 * PARAMETERS :
1275 * @jpeg_job_data : ptr to a struct saving job related information
1276 * @needNewSess : flag to indicate if a new jpeg encoding session need
1277 * to be created. After creation, this flag will be toggled
1278 *
1279 * RETURN : int32_t type of status
1280 * NO_ERROR -- success
1281 * none-zero failure code
1282 *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1283 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1284 uint8_t &needNewSess)
1285 {
1286 ATRACE_CALL();
1287 CDBG("%s : E", __func__);
1288 int32_t ret = NO_ERROR;
1289 mm_jpeg_job_t jpg_job;
1290 uint32_t jobId = 0;
1291 QCamera3Stream *main_stream = NULL;
1292 mm_camera_buf_def_t *main_frame = NULL;
1293 QCamera3Channel *srcChannel = NULL;
1294 mm_camera_super_buf_t *recvd_frame = NULL;
1295 metadata_buffer_t *metadata = NULL;
1296 jpeg_settings_t *jpeg_settings = NULL;
1297 QCamera3HardwareInterface* hal_obj = NULL;
1298 if (m_parent != NULL) {
1299 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1300 } else {
1301 ALOGE("%s: m_parent is NULL, Error",__func__);
1302 return BAD_VALUE;
1303 }
1304 bool needJpegRotation = false;
1305
1306 recvd_frame = jpeg_job_data->src_frame;
1307 metadata = jpeg_job_data->metadata;
1308 jpeg_settings = jpeg_job_data->jpeg_settings;
1309
1310 CDBG("%s: encoding bufIndex: %u", __func__,
1311 jpeg_job_data->src_frame->bufs[0]->buf_idx);
1312
1313 QCamera3Channel *pChannel = NULL;
1314 // first check picture channel
1315 if (m_parent->getMyHandle() == recvd_frame->ch_id) {
1316 pChannel = m_parent;
1317 }
1318 // check reprocess channel if not found
1319 if (pChannel == NULL) {
1320 if (m_pReprocChannel != NULL &&
1321 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1322 pChannel = m_pReprocChannel;
1323 }
1324 }
1325
1326 srcChannel = pChannel;
1327
1328 if (srcChannel == NULL) {
1329 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
1330 __func__, recvd_frame->ch_id);
1331 return BAD_VALUE;
1332 }
1333
1334 // find snapshot frame and thumnail frame
1335 //Note: In this version we will receive only snapshot frame.
1336 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
1337 QCamera3Stream *srcStream =
1338 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1339 if (srcStream != NULL) {
1340 switch (srcStream->getMyType()) {
1341 case CAM_STREAM_TYPE_SNAPSHOT:
1342 case CAM_STREAM_TYPE_OFFLINE_PROC:
1343 main_stream = srcStream;
1344 main_frame = recvd_frame->bufs[i];
1345 break;
1346 default:
1347 break;
1348 }
1349 }
1350 }
1351
1352 if(NULL == main_frame){
1353 ALOGE("%s : Main frame is NULL", __func__);
1354 return BAD_VALUE;
1355 }
1356
1357 QCamera3StreamMem *memObj = (QCamera3StreamMem *)main_frame->mem_info;
1358 if (NULL == memObj) {
1359 ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
1360 return NO_MEMORY;
1361 }
1362
1363 // clean and invalidate cache ops through mem obj of the frame
1364 memObj->cleanInvalidateCache(main_frame->buf_idx);
1365
1366 if (mJpegClientHandle <= 0) {
1367 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1368 return UNKNOWN_ERROR;
1369 }
1370 cam_dimension_t src_dim;
1371 memset(&src_dim, 0, sizeof(cam_dimension_t));
1372 main_stream->getFrameDimension(src_dim);
1373
1374 cam_dimension_t dst_dim;
1375 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1376 if (NO_ERROR != m_parent->getStreamSize(dst_dim)) {
1377 ALOGE("%s: Failed to get size of the JPEG stream", __func__);
1378 return UNKNOWN_ERROR;
1379 }
1380
1381 needJpegRotation = hal_obj->needJpegRotation();
1382 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1383 if (needNewSess) {
1384 //creating a new session, so we must destroy the old one
1385 if ( 0 < mJpegSessionId ) {
1386 ret = mJpegHandle.destroy_session(mJpegSessionId);
1387 if (ret != NO_ERROR) {
1388 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1389 __func__, mJpegSessionId);
1390 return ret;
1391 }
1392 mJpegSessionId = 0;
1393 }
1394 // create jpeg encoding session
1395 mm_jpeg_encode_params_t encodeParam;
1396 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1397 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1398 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1399 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1400 if (!needJpegRotation &&
1401 (jpeg_settings->jpeg_orientation == 90 ||
1402 jpeg_settings->jpeg_orientation == 270)) {
1403 //swap src width and height, stride and scanline due to rotation
1404 encodeParam.main_dim.src_dim.width = src_dim.height;
1405 encodeParam.main_dim.src_dim.height = src_dim.width;
1406 encodeParam.thumb_dim.src_dim.width = src_dim.height;
1407 encodeParam.thumb_dim.src_dim.height = src_dim.width;
1408
1409 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1410 encodeParam.src_main_buf[0].offset.mp[0].stride =
1411 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1412 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1413
1414 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1415 encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1416 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1417 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1418 } else {
1419 encodeParam.main_dim.src_dim = src_dim;
1420 encodeParam.thumb_dim.src_dim = src_dim;
1421 }
1422 encodeParam.main_dim.dst_dim = dst_dim;
1423 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1424 if (needJpegRotation) {
1425 encodeParam.rotation = (uint32_t)jpeg_settings->jpeg_orientation;
1426 }
1427
1428 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1429 if (ret != NO_ERROR) {
1430 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1431 return ret;
1432 }
1433 needNewSess = FALSE;
1434 }
1435
1436 // Fill in new job
1437 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1438 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1439 jpg_job.encode_job.session_id = mJpegSessionId;
1440 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
1441 jpg_job.encode_job.dst_index = 0;
1442
1443 if (needJpegRotation) {
1444 jpg_job.encode_job.rotation = (uint32_t)jpeg_settings->jpeg_orientation;
1445 CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__,
1446 jpg_job.encode_job.rotation);
1447 }
1448
1449 cam_rect_t crop;
1450 memset(&crop, 0, sizeof(cam_rect_t));
1451 //TBD_later - Zoom event removed in stream
1452 //main_stream->getCropInfo(crop);
1453
1454 // Set main dim job parameters and handle rotation
1455 if (!needJpegRotation && (jpeg_settings->jpeg_orientation == 90 ||
1456 jpeg_settings->jpeg_orientation == 270)) {
1457
1458 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1459 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1460
1461 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1462 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1463
1464 jpg_job.encode_job.main_dim.crop.width = crop.height;
1465 jpg_job.encode_job.main_dim.crop.height = crop.width;
1466 jpg_job.encode_job.main_dim.crop.left = crop.top;
1467 jpg_job.encode_job.main_dim.crop.top = crop.left;
1468 } else {
1469 jpg_job.encode_job.main_dim.src_dim = src_dim;
1470 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1471 jpg_job.encode_job.main_dim.crop = crop;
1472 }
1473
1474 QCamera3HardwareInterface* obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1475 // get 3a sw version info
1476 cam_q3a_version_t sw_version;
1477 memset(&sw_version, 0, sizeof(sw_version));
1478
1479 if (obj)
1480 obj->get3AVersion(sw_version);
1481
1482 // get exif data
1483 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings);
1484 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1485 if (pJpegExifObj != NULL) {
1486 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1487 jpg_job.encode_job.exif_info.numOfEntries =
1488 pJpegExifObj->getNumOfEntries();
1489 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1490 sw_version.major_version;
1491 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1492 sw_version.minor_version;
1493 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1494 sw_version.patch_version;
1495 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1496 sw_version.new_feature_des;
1497 }
1498
1499 // thumbnail dim
1500 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1501 if (m_bThumbnailNeeded == TRUE) {
1502 memset(&crop, 0, sizeof(cam_rect_t));
1503 jpg_job.encode_job.thumb_dim.dst_dim =
1504 jpeg_settings->thumbnail_size;
1505
1506 if (!needJpegRotation &&
1507 (jpeg_settings->jpeg_orientation == 90 ||
1508 jpeg_settings->jpeg_orientation == 270)) {
1509 //swap the thumbnail destination width and height if it has
1510 //already been rotated
1511 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1512 jpg_job.encode_job.thumb_dim.dst_dim.width =
1513 jpg_job.encode_job.thumb_dim.dst_dim.height;
1514 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1515
1516 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1517 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1518 } else {
1519 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1520 }
1521 jpg_job.encode_job.thumb_dim.crop = crop;
1522 jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1523 }
1524
1525 jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
1526 jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
1527 if (metadata != NULL) {
1528 //Fill in the metadata passed as parameter
1529 jpg_job.encode_job.p_metadata = metadata;
1530
1531 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
1532 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
1533
1534 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
1535 jpg_job.encode_job.p_metadata->mobicat_aec_params =
1536 jpg_job.encode_job.cam_exif_params.cam_3a_params;
1537 }
1538
1539 /* Save a copy of 3A debug params */
1540 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
1541 jpg_job.encode_job.cam_exif_params.ae_debug_params_valid;
1542 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
1543 jpg_job.encode_job.cam_exif_params.awb_debug_params_valid;
1544 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
1545 jpg_job.encode_job.cam_exif_params.af_debug_params_valid;
1546 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
1547 jpg_job.encode_job.cam_exif_params.asd_debug_params_valid;
1548 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
1549 jpg_job.encode_job.cam_exif_params.stats_debug_params_valid;
1550
1551 if (jpg_job.encode_job.cam_exif_params.ae_debug_params_valid) {
1552 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
1553 jpg_job.encode_job.cam_exif_params.ae_debug_params;
1554 }
1555 if (jpg_job.encode_job.cam_exif_params.awb_debug_params_valid) {
1556 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
1557 jpg_job.encode_job.cam_exif_params.awb_debug_params;
1558 }
1559 if (jpg_job.encode_job.cam_exif_params.af_debug_params_valid) {
1560 jpg_job.encode_job.p_metadata->statsdebug_af_data =
1561 jpg_job.encode_job.cam_exif_params.af_debug_params;
1562 }
1563 if (jpg_job.encode_job.cam_exif_params.asd_debug_params_valid) {
1564 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
1565 jpg_job.encode_job.cam_exif_params.asd_debug_params;
1566 }
1567 if (jpg_job.encode_job.cam_exif_params.stats_debug_params_valid) {
1568 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
1569 jpg_job.encode_job.cam_exif_params.stats_debug_params;
1570 }
1571 } else {
1572 ALOGE("%s: Metadata is null", __func__);
1573 }
1574
1575 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1576
1577 //Start jpeg encoding
1578 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1579 if (ret == NO_ERROR) {
1580 // remember job info
1581 jpeg_job_data->jobId = jobId;
1582 }
1583
1584 CDBG("%s : X", __func__);
1585 return ret;
1586 }
1587
1588 /*===========================================================================
1589 * FUNCTION : dataProcessRoutine
1590 *
1591 * DESCRIPTION: data process routine that handles input data either from input
1592 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1593 * reprocess.
1594 *
1595 * PARAMETERS :
1596 * @data : user data ptr (QCamera3PostProcessor)
1597 *
1598 * RETURN : None
1599 *==========================================================================*/
dataProcessRoutine(void * data)1600 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1601 {
1602 int running = 1;
1603 int ret;
1604 uint8_t is_active = FALSE;
1605 uint8_t needNewSess = TRUE;
1606 mm_camera_super_buf_t *meta_buffer = NULL;
1607 CDBG("%s: E", __func__);
1608 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1609 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1610 cmdThread->setName("cam_data_proc");
1611
1612 do {
1613 do {
1614 ret = cam_sem_wait(&cmdThread->cmd_sem);
1615 if (ret != 0 && errno != EINVAL) {
1616 ALOGE("%s: cam_sem_wait error (%s)",
1617 __func__, strerror(errno));
1618 return NULL;
1619 }
1620 } while (ret != 0);
1621
1622 // we got notified about new cmd avail in cmd queue
1623 camera_cmd_type_t cmd = cmdThread->getCmd();
1624 switch (cmd) {
1625 case CAMERA_CMD_TYPE_START_DATA_PROC:
1626 CDBG_HIGH("%s: start data proc", __func__);
1627 is_active = TRUE;
1628 needNewSess = TRUE;
1629
1630 pme->m_ongoingPPQ.init();
1631 pme->m_inputJpegQ.init();
1632 pme->m_inputPPQ.init();
1633 pme->m_inputFWKPPQ.init();
1634 pme->m_inputMetaQ.init();
1635 cam_sem_post(&cmdThread->sync_sem);
1636
1637 break;
1638 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1639 {
1640 CDBG_HIGH("%s: stop data proc", __func__);
1641 is_active = FALSE;
1642
1643 // cancel all ongoing jpeg jobs
1644 qcamera_hal3_jpeg_data_t *jpeg_job =
1645 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1646 while (jpeg_job != NULL) {
1647 pme->mJpegHandle.abort_job(jpeg_job->jobId);
1648
1649 pme->releaseJpegJobData(jpeg_job);
1650 free(jpeg_job);
1651
1652 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1653 }
1654
1655 // destroy jpeg encoding session
1656 if ( 0 < pme->mJpegSessionId ) {
1657 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
1658 pme->mJpegSessionId = 0;
1659 }
1660
1661 needNewSess = TRUE;
1662
1663 // flush ongoing postproc Queue
1664 pme->m_ongoingPPQ.flush();
1665
1666 // flush input jpeg Queue
1667 pme->m_inputJpegQ.flush();
1668
1669 // flush input Postproc Queue
1670 pme->m_inputPPQ.flush();
1671
1672 // flush framework input Postproc Queue
1673 pme->m_inputFWKPPQ.flush();
1674
1675 pme->m_inputMetaQ.flush();
1676
1677 // signal cmd is completed
1678 cam_sem_post(&cmdThread->sync_sem);
1679 }
1680 break;
1681 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1682 {
1683 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
1684 /* needNewSess is set to TRUE as postproc is not re-STARTed
1685 * anymore for every captureRequest */
1686 needNewSess = TRUE;
1687 if (is_active == TRUE) {
1688 // check if there is any ongoing jpeg jobs
1689 if (pme->m_ongoingJpegQ.isEmpty()) {
1690 CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
1691 // no ongoing jpeg job, we are fine to send jpeg encoding job
1692 qcamera_hal3_jpeg_data_t *jpeg_job =
1693 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1694
1695 if (NULL != jpeg_job) {
1696 // add into ongoing jpeg job Q
1697 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
1698
1699 if (jpeg_job->fwk_frame) {
1700 ret = pme->encodeFWKData(jpeg_job, needNewSess);
1701 } else {
1702 ret = pme->encodeData(jpeg_job, needNewSess);
1703 }
1704 if (NO_ERROR != ret) {
1705 // dequeue the last one
1706 pme->m_ongoingJpegQ.dequeue(false);
1707
1708 pme->releaseJpegJobData(jpeg_job);
1709 free(jpeg_job);
1710 }
1711 }
1712 }
1713
1714 // check if there are any framework pp jobs
1715 if (!pme->m_inputFWKPPQ.isEmpty()) {
1716 qcamera_fwk_input_pp_data_t *fwk_frame =
1717 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1718 if (NULL != fwk_frame) {
1719 qcamera_hal3_pp_data_t *pp_job =
1720 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1721 jpeg_settings_t *jpeg_settings =
1722 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1723 if (pp_job != NULL) {
1724 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1725 pp_job->jpeg_settings = jpeg_settings;
1726 if (pme->m_pReprocChannel != NULL) {
1727 if (NO_ERROR != pme->m_pReprocChannel->overrideFwkMetadata(fwk_frame)) {
1728 ALOGE("%s: Failed to extract output crop", __func__);
1729 }
1730 // add into ongoing PP job Q
1731 pp_job->fwk_src_frame = fwk_frame;
1732 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1733 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
1734 if (NO_ERROR != ret) {
1735 // remove from ongoing PP job Q
1736 pme->m_ongoingPPQ.dequeue(false);
1737 }
1738 } else {
1739 ALOGE("%s: Reprocess channel is NULL", __func__);
1740 ret = -1;
1741 }
1742 } else {
1743 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1744 ret = -1;
1745 }
1746
1747 if (0 != ret) {
1748 // free pp_job
1749 if (pp_job != NULL) {
1750 free(pp_job);
1751 }
1752 // free frame
1753 if (fwk_frame != NULL) {
1754 free(fwk_frame);
1755 }
1756 }
1757 }
1758 }
1759
1760 CDBG_HIGH("%s: dequeuing pp frame", __func__);
1761 pthread_mutex_lock(&pme->mReprocJobLock);
1762 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
1763 qcamera_hal3_pp_buffer_t *pp_buffer =
1764 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
1765 meta_buffer =
1766 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1767 jpeg_settings_t *jpeg_settings =
1768 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1769 pthread_mutex_unlock(&pme->mReprocJobLock);
1770 qcamera_hal3_pp_data_t *pp_job =
1771 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1772 if (pp_job == NULL) {
1773 ALOGE("%s: no mem for qcamera_hal3_pp_data_t",
1774 __func__);
1775 ret = -1;
1776 } else if (meta_buffer == NULL) {
1777 ALOGE("%s: no mem for mm_camera_super_buf_t",
1778 __func__);
1779 ret = -1;
1780 } else {
1781 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1782 pp_job->src_frame = pp_buffer->input;
1783 pp_job->src_metadata = meta_buffer;
1784 if (meta_buffer->bufs[0] != NULL) {
1785 pp_job->metadata = (metadata_buffer_t *)
1786 meta_buffer->bufs[0]->buffer;
1787 }
1788 pp_job->jpeg_settings = jpeg_settings;
1789 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1790 if (pme->m_pReprocChannel != NULL) {
1791 mm_camera_buf_def_t *meta_buffer_arg = NULL;
1792 meta_buffer_arg = meta_buffer->bufs[0];
1793 qcamera_fwk_input_pp_data_t fwk_frame;
1794 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
1795 fwk_frame.frameNumber = pp_buffer->frameNumber;
1796 ret = pme->m_pReprocChannel->overrideMetadata(
1797 pp_buffer, meta_buffer_arg,
1798 pp_job->jpeg_settings,
1799 fwk_frame);
1800 if (NO_ERROR == ret) {
1801 // add into ongoing PP job Q
1802 ret = pme->m_pReprocChannel->doReprocessOffline(
1803 &fwk_frame);
1804 if (NO_ERROR != ret) {
1805 // remove from ongoing PP job Q
1806 pme->m_ongoingPPQ.dequeue(false);
1807 }
1808 }
1809 } else {
1810 ALOGE("%s: No reprocess. Calling processPPData directly",
1811 __func__);
1812 ret = pme->processPPData(pp_buffer->input);
1813 }
1814 }
1815
1816 if (0 != ret) {
1817 // free pp_job
1818 if (pp_job != NULL) {
1819 free(pp_job);
1820 }
1821 // free frame
1822 if (pp_buffer != NULL) {
1823 if (pp_buffer->input) {
1824 pme->releaseSuperBuf(pp_buffer->input);
1825 free(pp_buffer->input);
1826 }
1827 free(pp_buffer);
1828 }
1829 //free metadata
1830 if (NULL != meta_buffer) {
1831 pme->m_parent->metadataBufDone(meta_buffer);
1832 free(meta_buffer);
1833 }
1834 } else {
1835 if (pp_buffer != NULL) {
1836 free(pp_buffer);
1837 }
1838 }
1839 } else {
1840 pthread_mutex_unlock(&pme->mReprocJobLock);
1841 }
1842 } else {
1843 // not active, simply return buf and do no op
1844 qcamera_hal3_jpeg_data_t *jpeg_job =
1845 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1846 if (NULL != jpeg_job) {
1847 free(jpeg_job);
1848 }
1849
1850 qcamera_hal3_pp_buffer_t* pp_buf =
1851 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
1852 if (NULL != pp_buf) {
1853 if (pp_buf->input) {
1854 pme->releaseSuperBuf(pp_buf->input);
1855 free(pp_buf->input);
1856 pp_buf->input = NULL;
1857 }
1858 free(pp_buf);
1859 }
1860 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1861 if (metadata != NULL) {
1862 pme->m_parent->metadataBufDone(metadata);
1863 free(metadata);
1864 }
1865 qcamera_fwk_input_pp_data_t *fwk_frame =
1866 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1867 if (NULL != fwk_frame) {
1868 free(fwk_frame);
1869 }
1870 }
1871 }
1872 break;
1873 case CAMERA_CMD_TYPE_EXIT:
1874 running = 0;
1875 break;
1876 default:
1877 break;
1878 }
1879 } while (running);
1880 CDBG("%s: X", __func__);
1881 return NULL;
1882 }
1883
1884 /* EXIF related helper methods */
1885
1886 /*===========================================================================
1887 * FUNCTION : getRational
1888 *
1889 * DESCRIPTION: compose rational struct
1890 *
1891 * PARAMETERS :
1892 * @rat : ptr to struct to store rational info
1893 * @num :num of the rational
1894 * @denom : denom of the rational
1895 *
1896 * RETURN : int32_t type of status
1897 * NO_ERROR -- success
1898 * none-zero failure code
1899 *==========================================================================*/
getRational(rat_t * rat,int num,int denom)1900 int32_t getRational(rat_t *rat, int num, int denom)
1901 {
1902 if ((0 > num) || (0 >= denom)) {
1903 ALOGE("%s: Negative values", __func__);
1904 return BAD_VALUE;
1905 }
1906 if (NULL == rat) {
1907 ALOGE("%s: NULL rat input", __func__);
1908 return BAD_VALUE;
1909 }
1910 rat->num = (uint32_t)num;
1911 rat->denom = (uint32_t)denom;
1912 return NO_ERROR;
1913 }
1914
1915 /*===========================================================================
1916 * FUNCTION : parseGPSCoordinate
1917 *
1918 * DESCRIPTION: parse GPS coordinate string
1919 *
1920 * PARAMETERS :
1921 * @coord_str : [input] coordinate string
1922 * @coord : [output] ptr to struct to store coordinate
1923 *
1924 * RETURN : int32_t type of status
1925 * NO_ERROR -- success
1926 * none-zero failure code
1927 *==========================================================================*/
parseGPSCoordinate(const char * coord_str,rat_t * coord)1928 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
1929 {
1930 if(coord == NULL) {
1931 ALOGE("%s: error, invalid argument coord == NULL", __func__);
1932 return BAD_VALUE;
1933 }
1934 double degF = atof(coord_str);
1935 if (degF < 0) {
1936 degF = -degF;
1937 }
1938 double minF = (degF - (int) degF) * 60;
1939 double secF = (minF - (int) minF) * 60;
1940
1941 getRational(&coord[0], (int)degF, 1);
1942 getRational(&coord[1], (int)minF, 1);
1943 getRational(&coord[2], (int)(secF * 10000), 10000);
1944 return NO_ERROR;
1945 }
1946
1947 /*===========================================================================
1948 * FUNCTION : getExifDateTime
1949 *
1950 * DESCRIPTION: query exif date time
1951 *
1952 * PARAMETERS :
1953 * @dateTime : string to store exif date time
1954 * @subsecTime : string to store exif subsec time
1955 *
1956 * RETURN : int32_t type of status
1957 * NO_ERROR -- success
1958 * none-zero failure code
1959 *==========================================================================*/
getExifDateTime(String8 & dateTime,String8 & subsecTime)1960 int32_t getExifDateTime(String8 &dateTime, String8 &subsecTime)
1961 {
1962 int32_t ret = NO_ERROR;
1963
1964 //get time and date from system
1965 struct timeval tv;
1966 struct tm timeinfo_data;
1967
1968 int res = gettimeofday(&tv, NULL);
1969 if (0 == res) {
1970 struct tm *timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
1971 if (NULL != timeinfo) {
1972 //Write datetime according to EXIF Spec
1973 //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
1974 dateTime = String8::format("%04d:%02d:%02d %02d:%02d:%02d",
1975 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
1976 timeinfo->tm_mday, timeinfo->tm_hour,
1977 timeinfo->tm_min, timeinfo->tm_sec);
1978 //Write subsec according to EXIF Sepc
1979 subsecTime = String8::format("%06ld", tv.tv_usec);
1980 } else {
1981 ALOGE("%s: localtime_r() error", __func__);
1982 ret = UNKNOWN_ERROR;
1983 }
1984 } else if (-1 == res) {
1985 ALOGE("%s: gettimeofday() error: %s", __func__, strerror(errno));
1986 ret = UNKNOWN_ERROR;
1987 } else {
1988 ALOGE("%s: gettimeofday() unexpected return code: %d", __func__, res);
1989 ret = UNKNOWN_ERROR;
1990 }
1991
1992 return ret;
1993 }
1994
1995 /*===========================================================================
1996 * FUNCTION : getExifFocalLength
1997 *
1998 * DESCRIPTION: get exif focal length
1999 *
2000 * PARAMETERS :
2001 * @focalLength : ptr to rational struct to store focal length
2002 * @value : focal length value
2003 *
2004 * RETURN : int32_t type of status
2005 * NO_ERROR -- success
2006 * none-zero failure code
2007 *==========================================================================*/
getExifFocalLength(rat_t * focalLength,float value)2008 int32_t getExifFocalLength(rat_t *focalLength, float value)
2009 {
2010 int focalLengthValue =
2011 (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
2012 return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
2013 }
2014
2015 /*===========================================================================
2016 * FUNCTION : getExifExpTimeInfo
2017 *
2018 * DESCRIPTION: get exif exposure time information
2019 *
2020 * PARAMETERS :
2021 * @expoTimeInfo : rational exposure time value
2022 * @value : exposure time value
2023 * RETURN : nt32_t type of status
2024 * NO_ERROR -- success
2025 * none-zero failure code
2026 *==========================================================================*/
getExifExpTimeInfo(rat_t * expoTimeInfo,int64_t value)2027 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
2028 {
2029
2030 int64_t cal_exposureTime;
2031 if (value != 0)
2032 cal_exposureTime = value;
2033 else
2034 cal_exposureTime = 60;
2035
2036 return getRational(expoTimeInfo, 1, (int)cal_exposureTime);
2037 }
2038
2039 /*===========================================================================
2040 * FUNCTION : getExifGpsProcessingMethod
2041 *
2042 * DESCRIPTION: get GPS processing method
2043 *
2044 * PARAMETERS :
2045 * @gpsProcessingMethod : string to store GPS process method
2046 * @count : length of the string
2047 * @value : the value of the processing method
2048 *
2049 * RETURN : int32_t type of status
2050 * NO_ERROR -- success
2051 * none-zero failure code
2052 *==========================================================================*/
getExifGpsProcessingMethod(char * gpsProcessingMethod,uint32_t & count,char * value)2053 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
2054 uint32_t &count, char* value)
2055 {
2056 if(value != NULL) {
2057 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
2058 count = EXIF_ASCII_PREFIX_SIZE;
2059 strlcpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE,
2060 value,
2061 strlen(value)+1);
2062 count += (uint32_t)strlen(value);
2063 gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
2064 return NO_ERROR;
2065 } else {
2066 return BAD_VALUE;
2067 }
2068 }
2069
2070 /*===========================================================================
2071 * FUNCTION : getExifLatitude
2072 *
2073 * DESCRIPTION: get exif latitude
2074 *
2075 * PARAMETERS :
2076 * @latitude : ptr to rational struct to store latitude info
2077 * @latRef : character to indicate latitude reference
2078 * @value : value of the latitude
2079 *
2080 * RETURN : int32_t type of status
2081 * NO_ERROR -- success
2082 * none-zero failure code
2083 *==========================================================================*/
getExifLatitude(rat_t * latitude,char * latRef,double value)2084 int32_t getExifLatitude(rat_t *latitude, char *latRef, double value)
2085 {
2086 char str[30];
2087 snprintf(str, sizeof(str), "%f", value);
2088 if(str != NULL) {
2089 parseGPSCoordinate(str, latitude);
2090
2091 //set Latitude Ref
2092 float latitudeValue = strtof(str, 0);
2093 if(latitudeValue < 0.0f) {
2094 latRef[0] = 'S';
2095 } else {
2096 latRef[0] = 'N';
2097 }
2098 latRef[1] = '\0';
2099 return NO_ERROR;
2100 }else{
2101 return BAD_VALUE;
2102 }
2103 }
2104
2105 /*===========================================================================
2106 * FUNCTION : getExifLongitude
2107 *
2108 * DESCRIPTION: get exif longitude
2109 *
2110 * PARAMETERS :
2111 * @longitude : ptr to rational struct to store longitude info
2112 * @lonRef : character to indicate longitude reference
2113 * @value : value of the longitude
2114 *
2115 * RETURN : int32_t type of status
2116 * NO_ERROR -- success
2117 * none-zero failure code
2118 *==========================================================================*/
getExifLongitude(rat_t * longitude,char * lonRef,double value)2119 int32_t getExifLongitude(rat_t *longitude, char *lonRef, double value)
2120 {
2121 char str[30];
2122 snprintf(str, sizeof(str), "%f", value);
2123 if(str != NULL) {
2124 parseGPSCoordinate(str, longitude);
2125
2126 //set Longitude Ref
2127 float longitudeValue = strtof(str, 0);
2128 if(longitudeValue < 0.0f) {
2129 lonRef[0] = 'W';
2130 } else {
2131 lonRef[0] = 'E';
2132 }
2133 lonRef[1] = '\0';
2134 return NO_ERROR;
2135 }else{
2136 return BAD_VALUE;
2137 }
2138 }
2139
2140 /*===========================================================================
2141 * FUNCTION : getExifAltitude
2142 *
2143 * DESCRIPTION: get exif altitude
2144 *
2145 * PARAMETERS :
2146 * @altitude : ptr to rational struct to store altitude info
2147 * @altRef : character to indicate altitude reference
2148 * @argValue : altitude value
2149 *
2150 * RETURN : int32_t type of status
2151 * NO_ERROR -- success
2152 * none-zero failure code
2153 *==========================================================================*/
getExifAltitude(rat_t * altitude,char * altRef,double argValue)2154 int32_t getExifAltitude(rat_t *altitude, char *altRef, double argValue)
2155 {
2156 char str[30];
2157 snprintf(str, sizeof(str), "%f", argValue);
2158 if (str != NULL) {
2159 double value = atof(str);
2160 *altRef = 0;
2161 if(value < 0){
2162 *altRef = 1;
2163 value = -value;
2164 }
2165 return getRational(altitude, (int)(value * 1000), 1000);
2166 } else {
2167 return BAD_VALUE;
2168 }
2169 }
2170
2171 /*===========================================================================
2172 * FUNCTION : getExifGpsDateTimeStamp
2173 *
2174 * DESCRIPTION: get exif GPS date time stamp
2175 *
2176 * PARAMETERS :
2177 * @gpsDateStamp : GPS date time stamp string
2178 * @bufLen : length of the string
2179 * @gpsTimeStamp : ptr to rational struct to store time stamp info
2180 * @value : timestamp value
2181 *
2182 * RETURN : int32_t type of status
2183 * NO_ERROR -- success
2184 * none-zero failure code
2185 *==========================================================================*/
getExifGpsDateTimeStamp(char * gpsDateStamp,uint32_t bufLen,rat_t * gpsTimeStamp,int64_t value)2186 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, uint32_t bufLen,
2187 rat_t *gpsTimeStamp, int64_t value)
2188 {
2189 char str[30];
2190 snprintf(str, sizeof(str), "%lld", (long long int)value);
2191 if(str != NULL) {
2192 time_t unixTime = (time_t)atol(str);
2193 struct tm *UTCTimestamp = gmtime(&unixTime);
2194 if (UTCTimestamp != NULL && gpsDateStamp != NULL
2195 && gpsTimeStamp != NULL) {
2196 strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
2197
2198 getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
2199 getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
2200 getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
2201 return NO_ERROR;
2202 } else {
2203 ALOGE("%s: Could not get the timestamp", __func__);
2204 return BAD_VALUE;
2205 }
2206 } else {
2207 return BAD_VALUE;
2208 }
2209 }
2210
2211 /*===========================================================================
2212 * FUNCTION : getExifExposureValue
2213 *
2214 * DESCRIPTION: get exif GPS date time stamp
2215 *
2216 * PARAMETERS :
2217 * @exposure_val : rational exposure value
2218 * @exposure_comp : exposure compensation
2219 * @step : exposure step
2220 *
2221 * RETURN : int32_t type of status
2222 * NO_ERROR -- success
2223 * none-zero failure code
2224 *==========================================================================*/
getExifExposureValue(srat_t * exposure_val,int32_t exposure_comp,cam_rational_type_t step)2225 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
2226 cam_rational_type_t step)
2227 {
2228 exposure_val->num = exposure_comp * step.numerator;
2229 exposure_val->denom = step.denominator;
2230 return 0;
2231 }
2232
2233 /*===========================================================================
2234 * FUNCTION : getExifData
2235 *
2236 * DESCRIPTION: get exif data to be passed into jpeg encoding
2237 *
2238 * PARAMETERS :
2239 * @metadata : metadata of the encoding request
2240 * @jpeg_settings : jpeg_settings for encoding
2241 *
2242 * RETURN : exif data from user setting and GPS
2243 *==========================================================================*/
getExifData(metadata_buffer_t * metadata,jpeg_settings_t * jpeg_settings)2244 QCamera3Exif *QCamera3PostProcessor::getExifData(metadata_buffer_t *metadata,
2245 jpeg_settings_t *jpeg_settings)
2246 {
2247 QCamera3Exif *exif = new QCamera3Exif();
2248 if (exif == NULL) {
2249 ALOGE("%s: No memory for QCamera3Exif", __func__);
2250 return NULL;
2251 }
2252
2253 int32_t rc = NO_ERROR;
2254 uint32_t count = 0;
2255
2256 // add exif entries
2257 String8 dateTime;
2258 String8 subsecTime;
2259 rc = getExifDateTime(dateTime, subsecTime);
2260 if (rc == NO_ERROR) {
2261 exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII,
2262 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2263 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
2264 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2265 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII,
2266 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2267 exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII,
2268 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2269 exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII,
2270 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2271 exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII,
2272 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2273 } else {
2274 ALOGE("%s: getExifDateTime failed", __func__);
2275 }
2276
2277
2278 if (metadata != NULL) {
2279 IF_META_AVAILABLE(float, focal_length, CAM_INTF_META_LENS_FOCAL_LENGTH, metadata) {
2280 rat_t focalLength;
2281 rc = getExifFocalLength(&focalLength, *focal_length);
2282 if (rc == NO_ERROR) {
2283 exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
2284 EXIF_RATIONAL,
2285 1,
2286 (void *)&(focalLength));
2287 } else {
2288 ALOGE("%s: getExifFocalLength failed", __func__);
2289 }
2290 }
2291
2292 IF_META_AVAILABLE(int32_t, isoSpeed, CAM_INTF_META_SENSOR_SENSITIVITY, metadata) {
2293 int16_t fwk_isoSpeed = (int16_t) *isoSpeed;
2294 exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT, 1, (void *) &(fwk_isoSpeed));
2295 }
2296
2297
2298 IF_META_AVAILABLE(int64_t, sensor_exposure_time,
2299 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata) {
2300 rat_t sensorExpTime;
2301 rc = getExifExpTimeInfo(&sensorExpTime, *sensor_exposure_time);
2302 if (rc == NO_ERROR){
2303 exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
2304 EXIF_RATIONAL,
2305 1,
2306 (void *)&(sensorExpTime));
2307 } else {
2308 ALOGE("%s: getExifExpTimeInfo failed", __func__);
2309 }
2310 }
2311
2312 char* jpeg_gps_processing_method = jpeg_settings->gps_processing_method;
2313 if (strlen(jpeg_gps_processing_method) > 0) {
2314 char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE +
2315 GPS_PROCESSING_METHOD_SIZE];
2316 count = 0;
2317 rc = getExifGpsProcessingMethod(gpsProcessingMethod,
2318 count,
2319 jpeg_gps_processing_method);
2320 if(rc == NO_ERROR) {
2321 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
2322 EXIF_ASCII,
2323 count,
2324 (void *)gpsProcessingMethod);
2325 } else {
2326 ALOGE("%s: getExifGpsProcessingMethod failed", __func__);
2327 }
2328 }
2329
2330 if (jpeg_settings->gps_coordinates_valid) {
2331
2332 //latitude
2333 rat_t latitude[3];
2334 char latRef[2];
2335 rc = getExifLatitude(latitude, latRef,
2336 jpeg_settings->gps_coordinates[0]);
2337 if(rc == NO_ERROR) {
2338 exif->addEntry(EXIFTAGID_GPS_LATITUDE,
2339 EXIF_RATIONAL,
2340 3,
2341 (void *)latitude);
2342 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
2343 EXIF_ASCII,
2344 2,
2345 (void *)latRef);
2346 } else {
2347 ALOGE("%s: getExifLatitude failed", __func__);
2348 }
2349
2350 //longitude
2351 rat_t longitude[3];
2352 char lonRef[2];
2353 rc = getExifLongitude(longitude, lonRef,
2354 jpeg_settings->gps_coordinates[1]);
2355 if(rc == NO_ERROR) {
2356 exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
2357 EXIF_RATIONAL,
2358 3,
2359 (void *)longitude);
2360
2361 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
2362 EXIF_ASCII,
2363 2,
2364 (void *)lonRef);
2365 } else {
2366 ALOGE("%s: getExifLongitude failed", __func__);
2367 }
2368
2369 //altitude
2370 rat_t altitude;
2371 char altRef;
2372 rc = getExifAltitude(&altitude, &altRef,
2373 jpeg_settings->gps_coordinates[2]);
2374 if(rc == NO_ERROR) {
2375 exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
2376 EXIF_RATIONAL,
2377 1,
2378 (void *)&(altitude));
2379
2380 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
2381 EXIF_BYTE,
2382 1,
2383 (void *)&altRef);
2384 } else {
2385 ALOGE("%s: getExifAltitude failed", __func__);
2386 }
2387 }
2388
2389 if (jpeg_settings->gps_timestamp_valid) {
2390
2391 char gpsDateStamp[20];
2392 rat_t gpsTimeStamp[3];
2393 rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
2394 jpeg_settings->gps_timestamp);
2395 if(rc == NO_ERROR) {
2396 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
2397 (uint32_t)(strlen(gpsDateStamp) + 1),
2398 (void *)gpsDateStamp);
2399
2400 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
2401 EXIF_RATIONAL,
2402 3,
2403 (void *)gpsTimeStamp);
2404 } else {
2405 ALOGE("%s: getExifGpsDataTimeStamp failed", __func__);
2406 }
2407 }
2408
2409 IF_META_AVAILABLE(int32_t, exposure_comp, CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) {
2410 IF_META_AVAILABLE(cam_rational_type_t, comp_step, CAM_INTF_PARM_EV_STEP, metadata) {
2411 srat_t exposure_val;
2412 rc = getExifExposureValue(&exposure_val, *exposure_comp, *comp_step);
2413 if(rc == NO_ERROR) {
2414 exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
2415 EXIF_SRATIONAL,
2416 1,
2417 (void *)(&exposure_val));
2418 } else {
2419 ALOGE("%s: getExifExposureValue failed ", __func__);
2420 }
2421 }
2422 }
2423 } else {
2424 ALOGE("%s: no metadata provided ", __func__);
2425 }
2426
2427 bool output_image_desc = true;
2428
2429 #ifdef ENABLE_MODEL_INFO_EXIF
2430
2431 char value[PROPERTY_VALUE_MAX];
2432 if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
2433 exif->addEntry(EXIFTAGID_MAKE, EXIF_ASCII,
2434 (uint32_t)(strlen(value) + 1), (void *)value);
2435 } else {
2436 ALOGE("%s: getExifMaker failed", __func__);
2437 }
2438
2439 if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
2440 exif->addEntry(EXIFTAGID_MODEL, EXIF_ASCII,
2441 (uint32_t)(strlen(value) + 1), (void *)value);
2442 } else {
2443 ALOGE("%s: getExifModel failed", __func__);
2444 }
2445
2446 if (property_get("ro.build.description", value, "QCAM-AA") > 0) {
2447 exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII,
2448 (uint32_t)(strlen(value) + 1), (void *)value);
2449 } else {
2450 ALOGE("%s: getExifSoftware failed", __func__);
2451 }
2452
2453 // Production sw should not enable image description field output
2454 output_image_desc = false;
2455 #endif
2456
2457 if (jpeg_settings->image_desc_valid && output_image_desc) {
2458 if (exif->addEntry(EXIFTAGID_IMAGE_DESCRIPTION, EXIF_ASCII,
2459 strlen(jpeg_settings->image_desc)+1,
2460 (void *)jpeg_settings->image_desc)) {
2461 ALOGE("%s: Adding IMAGE_DESCRIPTION tag failed", __func__);
2462 }
2463 }
2464 return exif;
2465 }
2466
2467 /*===========================================================================
2468 * FUNCTION : QCamera3Exif
2469 *
2470 * DESCRIPTION: constructor of QCamera3Exif
2471 *
2472 * PARAMETERS : None
2473 *
2474 * RETURN : None
2475 *==========================================================================*/
QCamera3Exif()2476 QCamera3Exif::QCamera3Exif()
2477 : m_nNumEntries(0)
2478 {
2479 memset(m_Entries, 0, sizeof(m_Entries));
2480 }
2481
2482 /*===========================================================================
2483 * FUNCTION : ~QCamera3Exif
2484 *
2485 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
2486 *
2487 * PARAMETERS : None
2488 *
2489 * RETURN : None
2490 *==========================================================================*/
~QCamera3Exif()2491 QCamera3Exif::~QCamera3Exif()
2492 {
2493 for (uint32_t i = 0; i < m_nNumEntries; i++) {
2494 switch (m_Entries[i].tag_entry.type) {
2495 case EXIF_BYTE:
2496 {
2497 if (m_Entries[i].tag_entry.count > 1 &&
2498 m_Entries[i].tag_entry.data._bytes != NULL) {
2499 free(m_Entries[i].tag_entry.data._bytes);
2500 m_Entries[i].tag_entry.data._bytes = NULL;
2501 }
2502 }
2503 break;
2504 case EXIF_ASCII:
2505 {
2506 if (m_Entries[i].tag_entry.data._ascii != NULL) {
2507 free(m_Entries[i].tag_entry.data._ascii);
2508 m_Entries[i].tag_entry.data._ascii = NULL;
2509 }
2510 }
2511 break;
2512 case EXIF_SHORT:
2513 {
2514 if (m_Entries[i].tag_entry.count > 1 &&
2515 m_Entries[i].tag_entry.data._shorts != NULL) {
2516 free(m_Entries[i].tag_entry.data._shorts);
2517 m_Entries[i].tag_entry.data._shorts = NULL;
2518 }
2519 }
2520 break;
2521 case EXIF_LONG:
2522 {
2523 if (m_Entries[i].tag_entry.count > 1 &&
2524 m_Entries[i].tag_entry.data._longs != NULL) {
2525 free(m_Entries[i].tag_entry.data._longs);
2526 m_Entries[i].tag_entry.data._longs = NULL;
2527 }
2528 }
2529 break;
2530 case EXIF_RATIONAL:
2531 {
2532 if (m_Entries[i].tag_entry.count > 1 &&
2533 m_Entries[i].tag_entry.data._rats != NULL) {
2534 free(m_Entries[i].tag_entry.data._rats);
2535 m_Entries[i].tag_entry.data._rats = NULL;
2536 }
2537 }
2538 break;
2539 case EXIF_UNDEFINED:
2540 {
2541 if (m_Entries[i].tag_entry.data._undefined != NULL) {
2542 free(m_Entries[i].tag_entry.data._undefined);
2543 m_Entries[i].tag_entry.data._undefined = NULL;
2544 }
2545 }
2546 break;
2547 case EXIF_SLONG:
2548 {
2549 if (m_Entries[i].tag_entry.count > 1 &&
2550 m_Entries[i].tag_entry.data._slongs != NULL) {
2551 free(m_Entries[i].tag_entry.data._slongs);
2552 m_Entries[i].tag_entry.data._slongs = NULL;
2553 }
2554 }
2555 break;
2556 case EXIF_SRATIONAL:
2557 {
2558 if (m_Entries[i].tag_entry.count > 1 &&
2559 m_Entries[i].tag_entry.data._srats != NULL) {
2560 free(m_Entries[i].tag_entry.data._srats);
2561 m_Entries[i].tag_entry.data._srats = NULL;
2562 }
2563 }
2564 break;
2565 default:
2566 ALOGE("%s: Error, Unknown type",__func__);
2567 break;
2568 }
2569 }
2570 }
2571
2572 /*===========================================================================
2573 * FUNCTION : addEntry
2574 *
2575 * DESCRIPTION: function to add an entry to exif data
2576 *
2577 * PARAMETERS :
2578 * @tagid : exif tag ID
2579 * @type : data type
2580 * @count : number of data in uint of its type
2581 * @data : input data ptr
2582 *
2583 * RETURN : int32_t type of status
2584 * NO_ERROR -- success
2585 * none-zero failure code
2586 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)2587 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
2588 exif_tag_type_t type,
2589 uint32_t count,
2590 void *data)
2591 {
2592 int32_t rc = NO_ERROR;
2593 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
2594 ALOGE("%s: Number of entries exceeded limit", __func__);
2595 return NO_MEMORY;
2596 }
2597
2598 m_Entries[m_nNumEntries].tag_id = tagid;
2599 m_Entries[m_nNumEntries].tag_entry.type = type;
2600 m_Entries[m_nNumEntries].tag_entry.count = count;
2601 m_Entries[m_nNumEntries].tag_entry.copy = 1;
2602 switch (type) {
2603 case EXIF_BYTE:
2604 {
2605 if (count > 1) {
2606 uint8_t *values = (uint8_t *)malloc(count);
2607 if (values == NULL) {
2608 ALOGE("%s: No memory for byte array", __func__);
2609 rc = NO_MEMORY;
2610 } else {
2611 memcpy(values, data, count);
2612 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
2613 }
2614 } else {
2615 m_Entries[m_nNumEntries].tag_entry.data._byte =
2616 *(uint8_t *)data;
2617 }
2618 }
2619 break;
2620 case EXIF_ASCII:
2621 {
2622 char *str = NULL;
2623 str = (char *)malloc(count + 1);
2624 if (str == NULL) {
2625 ALOGE("%s: No memory for ascii string", __func__);
2626 rc = NO_MEMORY;
2627 } else {
2628 memset(str, 0, count + 1);
2629 memcpy(str, data, count);
2630 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
2631 }
2632 }
2633 break;
2634 case EXIF_SHORT:
2635 {
2636 if (count > 1) {
2637 uint16_t *values =
2638 (uint16_t *)malloc(count * sizeof(uint16_t));
2639 if (values == NULL) {
2640 ALOGE("%s: No memory for short array", __func__);
2641 rc = NO_MEMORY;
2642 } else {
2643 memcpy(values, data, count * sizeof(uint16_t));
2644 m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
2645 }
2646 } else {
2647 m_Entries[m_nNumEntries].tag_entry.data._short =
2648 *(uint16_t *)data;
2649 }
2650 }
2651 break;
2652 case EXIF_LONG:
2653 {
2654 if (count > 1) {
2655 uint32_t *values =
2656 (uint32_t *)malloc(count * sizeof(uint32_t));
2657 if (values == NULL) {
2658 ALOGE("%s: No memory for long array", __func__);
2659 rc = NO_MEMORY;
2660 } else {
2661 memcpy(values, data, count * sizeof(uint32_t));
2662 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
2663 }
2664 } else {
2665 m_Entries[m_nNumEntries].tag_entry.data._long =
2666 *(uint32_t *)data;
2667 }
2668 }
2669 break;
2670 case EXIF_RATIONAL:
2671 {
2672 if (count > 1) {
2673 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
2674 if (values == NULL) {
2675 ALOGE("%s: No memory for rational array", __func__);
2676 rc = NO_MEMORY;
2677 } else {
2678 memcpy(values, data, count * sizeof(rat_t));
2679 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
2680 }
2681 } else {
2682 m_Entries[m_nNumEntries].tag_entry.data._rat =
2683 *(rat_t *)data;
2684 }
2685 }
2686 break;
2687 case EXIF_UNDEFINED:
2688 {
2689 uint8_t *values = (uint8_t *)malloc(count);
2690 if (values == NULL) {
2691 ALOGE("%s: No memory for undefined array", __func__);
2692 rc = NO_MEMORY;
2693 } else {
2694 memcpy(values, data, count);
2695 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
2696 }
2697 }
2698 break;
2699 case EXIF_SLONG:
2700 {
2701 if (count > 1) {
2702 int32_t *values =
2703 (int32_t *)malloc(count * sizeof(int32_t));
2704 if (values == NULL) {
2705 ALOGE("%s: No memory for signed long array", __func__);
2706 rc = NO_MEMORY;
2707 } else {
2708 memcpy(values, data, count * sizeof(int32_t));
2709 m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
2710 }
2711 } else {
2712 m_Entries[m_nNumEntries].tag_entry.data._slong =
2713 *(int32_t *)data;
2714 }
2715 }
2716 break;
2717 case EXIF_SRATIONAL:
2718 {
2719 if (count > 1) {
2720 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
2721 if (values == NULL) {
2722 ALOGE("%s: No memory for sign rational array",__func__);
2723 rc = NO_MEMORY;
2724 } else {
2725 memcpy(values, data, count * sizeof(srat_t));
2726 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
2727 }
2728 } else {
2729 m_Entries[m_nNumEntries].tag_entry.data._srat =
2730 *(srat_t *)data;
2731 }
2732 }
2733 break;
2734 default:
2735 ALOGE("%s: Error, Unknown type",__func__);
2736 break;
2737 }
2738
2739 // Increase number of entries
2740 m_nNumEntries++;
2741 return rc;
2742 }
2743
2744 }; // namespace qcamera
2745