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