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.src_dim = src_dim;
1189 encodeParam.main_dim.dst_dim = dst_dim;
1190 encodeParam.thumb_dim.src_dim = src_dim;
1191 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1192
1193 if (needJpegExifRotation) {
1194 encodeParam.thumb_rotation = (uint32_t)jpeg_settings->jpeg_orientation;
1195 }
1196
1197 getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1198 LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1199 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1200
1201 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1202 if (ret != NO_ERROR) {
1203 LOGE("Error creating a new jpeg encoding session, ret = %d", ret);
1204 return ret;
1205 }
1206 needNewSess = FALSE;
1207 }
1208
1209 // Fill in new job
1210 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1211 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1212 jpg_job.encode_job.session_id = mJpegSessionId;
1213 jpg_job.encode_job.src_index = 0;
1214 jpg_job.encode_job.dst_index = 0;
1215
1216 cam_rect_t crop;
1217 memset(&crop, 0, sizeof(cam_rect_t));
1218 //TBD_later - Zoom event removed in stream
1219 //main_stream->getCropInfo(crop);
1220
1221 // Set main dim job parameters and handle rotation
1222 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1223 jpeg_settings->jpeg_orientation == 270)) {
1224
1225 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1226 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1227
1228 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1229 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1230
1231 jpg_job.encode_job.main_dim.crop.width = crop.height;
1232 jpg_job.encode_job.main_dim.crop.height = crop.width;
1233 jpg_job.encode_job.main_dim.crop.left = crop.top;
1234 jpg_job.encode_job.main_dim.crop.top = crop.left;
1235 } else {
1236 jpg_job.encode_job.main_dim.src_dim = src_dim;
1237 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1238 jpg_job.encode_job.main_dim.crop = crop;
1239 }
1240
1241 QCamera3HardwareInterface* obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1242 // get 3a sw version info
1243 cam_q3a_version_t sw_version;
1244 memset(&sw_version, 0, sizeof(sw_version));
1245 if (obj)
1246 obj->get3AVersion(sw_version);
1247
1248 // get exif data
1249 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings);
1250 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1251 if (pJpegExifObj != NULL) {
1252 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1253 jpg_job.encode_job.exif_info.numOfEntries =
1254 pJpegExifObj->getNumOfEntries();
1255 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1256 sw_version.major_version;
1257 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1258 sw_version.minor_version;
1259 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1260 sw_version.patch_version;
1261 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1262 sw_version.new_feature_des;
1263 }
1264
1265 // thumbnail dim
1266 LOGH("Thumbnail needed:%d", m_bThumbnailNeeded);
1267 if (m_bThumbnailNeeded == TRUE) {
1268 memset(&crop, 0, sizeof(cam_rect_t));
1269 jpg_job.encode_job.thumb_dim.dst_dim =
1270 jpeg_settings->thumbnail_size;
1271
1272 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1273 jpeg_settings->jpeg_orientation == 270)) {
1274 //swap the thumbnail destination width and height if it has
1275 //already been rotated
1276 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1277 jpg_job.encode_job.thumb_dim.dst_dim.width =
1278 jpg_job.encode_job.thumb_dim.dst_dim.height;
1279 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1280 }
1281 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1282 jpg_job.encode_job.thumb_dim.crop = crop;
1283 jpg_job.encode_job.thumb_index = 0;
1284 }
1285
1286 if (metadata != NULL) {
1287 //Fill in the metadata passed as parameter
1288 jpg_job.encode_job.p_metadata = metadata;
1289 } else {
1290 LOGW("Metadata is null");
1291 }
1292
1293 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1294
1295 //Start jpeg encoding
1296 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1297 if (ret == NO_ERROR) {
1298 // remember job info
1299 jpeg_job_data->jobId = jobId;
1300 }
1301
1302 LOGD("X");
1303 return ret;
1304 }
1305
1306 /*===========================================================================
1307 * FUNCTION : encodeData
1308 *
1309 * DESCRIPTION: function to prepare encoding job information and send to
1310 * mm-jpeg-interface to do the encoding job
1311 *
1312 * PARAMETERS :
1313 * @jpeg_job_data : ptr to a struct saving job related information
1314 * @needNewSess : flag to indicate if a new jpeg encoding session need
1315 * to be created. After creation, this flag will be toggled
1316 *
1317 * RETURN : int32_t type of status
1318 * NO_ERROR -- success
1319 * none-zero failure code
1320 *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1321 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1322 uint8_t &needNewSess)
1323 {
1324 ATRACE_CALL();
1325 LOGD("E");
1326 int32_t ret = NO_ERROR;
1327 mm_jpeg_job_t jpg_job;
1328 uint32_t jobId = 0;
1329 QCamera3Stream *main_stream = NULL;
1330 mm_camera_buf_def_t *main_frame = NULL;
1331 QCamera3Channel *srcChannel = NULL;
1332 mm_camera_super_buf_t *recvd_frame = NULL;
1333 metadata_buffer_t *metadata = NULL;
1334 jpeg_settings_t *jpeg_settings = NULL;
1335 QCamera3HardwareInterface* hal_obj = NULL;
1336 mm_jpeg_debug_exif_params_t *exif_debug_params = NULL;
1337 if (m_parent != NULL) {
1338 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1339 } else {
1340 LOGE("m_parent is NULL, Error");
1341 return BAD_VALUE;
1342 }
1343 bool needJpegExifRotation = false;
1344
1345 recvd_frame = jpeg_job_data->src_frame;
1346 metadata = jpeg_job_data->metadata;
1347 jpeg_settings = jpeg_job_data->jpeg_settings;
1348
1349 LOGD("encoding bufIndex: %u",
1350 jpeg_job_data->src_frame->bufs[0]->buf_idx);
1351
1352 QCamera3Channel *pChannel = NULL;
1353 // first check picture channel
1354 if (m_parent->getMyHandle() == recvd_frame->ch_id) {
1355 pChannel = m_parent;
1356 }
1357 // check reprocess channel if not found
1358 if (pChannel == NULL) {
1359 if (m_pReprocChannel != NULL &&
1360 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1361 pChannel = m_pReprocChannel;
1362 }
1363 }
1364
1365 srcChannel = pChannel;
1366
1367 if (srcChannel == NULL) {
1368 LOGE("No corresponding channel (ch_id = %d) exist, return here",
1369 recvd_frame->ch_id);
1370 return BAD_VALUE;
1371 }
1372
1373 // find snapshot frame and thumnail frame
1374 //Note: In this version we will receive only snapshot frame.
1375 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
1376 QCamera3Stream *srcStream =
1377 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1378 if (srcStream != NULL) {
1379 switch (srcStream->getMyType()) {
1380 case CAM_STREAM_TYPE_SNAPSHOT:
1381 case CAM_STREAM_TYPE_OFFLINE_PROC:
1382 main_stream = srcStream;
1383 main_frame = recvd_frame->bufs[i];
1384 break;
1385 default:
1386 break;
1387 }
1388 }
1389 }
1390
1391 if(NULL == main_frame){
1392 LOGE("Main frame is NULL");
1393 return BAD_VALUE;
1394 }
1395
1396 QCamera3StreamMem *memObj = (QCamera3StreamMem *)main_frame->mem_info;
1397 if (NULL == memObj) {
1398 LOGE("Memeory Obj of main frame is NULL");
1399 return NO_MEMORY;
1400 }
1401
1402 // clean and invalidate cache ops through mem obj of the frame
1403 memObj->cleanInvalidateCache(main_frame->buf_idx);
1404
1405 if (mJpegClientHandle <= 0) {
1406 LOGE("Error: bug here, mJpegClientHandle is 0");
1407 return UNKNOWN_ERROR;
1408 }
1409 cam_dimension_t src_dim;
1410 memset(&src_dim, 0, sizeof(cam_dimension_t));
1411 main_stream->getFrameDimension(src_dim);
1412
1413 cam_dimension_t dst_dim;
1414 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1415 if (NO_ERROR != m_parent->getStreamSize(dst_dim)) {
1416 LOGE("Failed to get size of the JPEG stream");
1417 return UNKNOWN_ERROR;
1418 }
1419
1420 needJpegExifRotation = hal_obj->needJpegExifRotation();
1421 LOGH("Need new session?:%d", needNewSess);
1422 if (needNewSess) {
1423 //creating a new session, so we must destroy the old one
1424 if ( 0 < mJpegSessionId ) {
1425 ret = mJpegHandle.destroy_session(mJpegSessionId);
1426 if (ret != NO_ERROR) {
1427 LOGE("Error destroying an old jpeg encoding session, id = %d",
1428 mJpegSessionId);
1429 return ret;
1430 }
1431 mJpegSessionId = 0;
1432 }
1433 // create jpeg encoding session
1434 mm_jpeg_encode_params_t encodeParam;
1435 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1436 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1437 LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
1438 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1439 if (!needJpegExifRotation &&
1440 (jpeg_settings->jpeg_orientation == 90 ||
1441 jpeg_settings->jpeg_orientation == 270)) {
1442 //swap src width and height, stride and scanline due to rotation
1443 encodeParam.main_dim.src_dim.width = src_dim.height;
1444 encodeParam.main_dim.src_dim.height = src_dim.width;
1445 encodeParam.thumb_dim.src_dim.width = src_dim.height;
1446 encodeParam.thumb_dim.src_dim.height = src_dim.width;
1447
1448 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1449 encodeParam.src_main_buf[0].offset.mp[0].stride =
1450 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1451 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1452
1453 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1454 encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1455 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1456 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1457 } else {
1458 encodeParam.main_dim.src_dim = src_dim;
1459 encodeParam.thumb_dim.src_dim = src_dim;
1460 }
1461 encodeParam.main_dim.dst_dim = dst_dim;
1462 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1463
1464 if (needJpegExifRotation) {
1465 encodeParam.thumb_rotation = (uint32_t)jpeg_settings->jpeg_orientation;
1466 }
1467
1468 LOGI("Src Buffer cnt = %d, res = %dX%d len = %d rot = %d "
1469 "src_dim = %dX%d dst_dim = %dX%d",
1470 encodeParam.num_src_bufs,
1471 encodeParam.src_main_buf[0].offset.mp[0].stride,
1472 encodeParam.src_main_buf[0].offset.mp[0].scanline,
1473 encodeParam.src_main_buf[0].offset.frame_len,
1474 encodeParam.rotation,
1475 src_dim.width, src_dim.height,
1476 dst_dim.width, dst_dim.height);
1477 LOGI("Src THUMB buf_cnt = %d, res = %dX%d len = %d rot = %d "
1478 "src_dim = %dX%d, dst_dim = %dX%d",
1479 encodeParam.num_tmb_bufs,
1480 encodeParam.src_thumb_buf[0].offset.mp[0].stride,
1481 encodeParam.src_thumb_buf[0].offset.mp[0].scanline,
1482 encodeParam.src_thumb_buf[0].offset.frame_len,
1483 encodeParam.thumb_rotation,
1484 encodeParam.thumb_dim.src_dim.width,
1485 encodeParam.thumb_dim.src_dim.height,
1486 encodeParam.thumb_dim.dst_dim.width,
1487 encodeParam.thumb_dim.dst_dim.height);
1488 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1489 if (ret != NO_ERROR) {
1490 LOGE("Error creating a new jpeg encoding session, ret = %d", ret);
1491 return ret;
1492 }
1493 needNewSess = FALSE;
1494 }
1495
1496 // Fill in new job
1497 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1498 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1499 jpg_job.encode_job.session_id = mJpegSessionId;
1500 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
1501 jpg_job.encode_job.dst_index = 0;
1502
1503 cam_rect_t crop;
1504 memset(&crop, 0, sizeof(cam_rect_t));
1505 //TBD_later - Zoom event removed in stream
1506 //main_stream->getCropInfo(crop);
1507
1508 // Set main dim job parameters and handle rotation
1509 if (!needJpegExifRotation && (jpeg_settings->jpeg_orientation == 90 ||
1510 jpeg_settings->jpeg_orientation == 270)) {
1511
1512 jpg_job.encode_job.main_dim.src_dim.width = src_dim.height;
1513 jpg_job.encode_job.main_dim.src_dim.height = src_dim.width;
1514
1515 jpg_job.encode_job.main_dim.dst_dim.width = dst_dim.height;
1516 jpg_job.encode_job.main_dim.dst_dim.height = dst_dim.width;
1517
1518 jpg_job.encode_job.main_dim.crop.width = crop.height;
1519 jpg_job.encode_job.main_dim.crop.height = crop.width;
1520 jpg_job.encode_job.main_dim.crop.left = crop.top;
1521 jpg_job.encode_job.main_dim.crop.top = crop.left;
1522 } else {
1523 jpg_job.encode_job.main_dim.src_dim = src_dim;
1524 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1525 jpg_job.encode_job.main_dim.crop = crop;
1526 }
1527
1528 QCamera3HardwareInterface* obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1529 // get 3a sw version info
1530 cam_q3a_version_t sw_version;
1531 memset(&sw_version, 0, sizeof(sw_version));
1532
1533 if (obj)
1534 obj->get3AVersion(sw_version);
1535
1536 // get exif data
1537 QCamera3Exif *pJpegExifObj = getExifData(metadata, jpeg_settings);
1538 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1539 if (pJpegExifObj != NULL) {
1540 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1541 jpg_job.encode_job.exif_info.numOfEntries =
1542 pJpegExifObj->getNumOfEntries();
1543 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
1544 sw_version.major_version;
1545 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
1546 sw_version.minor_version;
1547 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
1548 sw_version.patch_version;
1549 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
1550 sw_version.new_feature_des;
1551 }
1552
1553 // thumbnail dim
1554 LOGH("Thumbnail needed:%d", m_bThumbnailNeeded);
1555 if (m_bThumbnailNeeded == TRUE) {
1556 memset(&crop, 0, sizeof(cam_rect_t));
1557 jpg_job.encode_job.thumb_dim.dst_dim =
1558 jpeg_settings->thumbnail_size;
1559
1560 if (!needJpegExifRotation &&
1561 (jpeg_settings->jpeg_orientation == 90 ||
1562 jpeg_settings->jpeg_orientation == 270)) {
1563 //swap the thumbnail destination width and height if it has
1564 //already been rotated
1565 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1566 jpg_job.encode_job.thumb_dim.dst_dim.width =
1567 jpg_job.encode_job.thumb_dim.dst_dim.height;
1568 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1569
1570 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1571 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1572 } else {
1573 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1574 }
1575 jpg_job.encode_job.thumb_dim.crop = crop;
1576 jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1577 LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
1578 jpg_job.encode_job.thumb_index,
1579 jpg_job.encode_job.thumb_dim.src_dim.width,
1580 jpg_job.encode_job.thumb_dim.src_dim.height,
1581 jpg_job.encode_job.thumb_dim.dst_dim.width,
1582 jpg_job.encode_job.thumb_dim.dst_dim.height);
1583 }
1584 LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
1585 jpg_job.encode_job.src_index,
1586 jpg_job.encode_job.main_dim.src_dim.width,
1587 jpg_job.encode_job.main_dim.src_dim.height,
1588 jpg_job.encode_job.main_dim.dst_dim.width,
1589 jpg_job.encode_job.main_dim.dst_dim.height);
1590
1591 jpg_job.encode_job.cam_exif_params = hal_obj->get3AExifParams();
1592 exif_debug_params = jpg_job.encode_job.cam_exif_params.debug_params;
1593
1594 // Allocate for a local copy of debug parameters
1595 jpg_job.encode_job.cam_exif_params.debug_params =
1596 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
1597 if (!jpg_job.encode_job.cam_exif_params.debug_params) {
1598 LOGE("Out of Memory. Allocation failed for 3A debug exif params");
1599 return NO_MEMORY;
1600 }
1601
1602 jpg_job.encode_job.mobicat_mask = hal_obj->getMobicatMask();
1603
1604 if (metadata != NULL) {
1605 //Fill in the metadata passed as parameter
1606 jpg_job.encode_job.p_metadata = metadata;
1607
1608 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
1609 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
1610
1611 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
1612 jpg_job.encode_job.p_metadata->mobicat_aec_params =
1613 jpg_job.encode_job.cam_exif_params.cam_3a_params;
1614 }
1615
1616 if (exif_debug_params) {
1617 // Copy debug parameters locally.
1618 memcpy(jpg_job.encode_job.cam_exif_params.debug_params,
1619 exif_debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
1620 /* Save a copy of 3A debug params */
1621 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
1622 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
1623 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
1624 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
1625 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
1626 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
1627 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
1628 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
1629 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
1630 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
1631 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
1632 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
1633 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
1634 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
1635 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
1636 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
1637
1638 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
1639 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
1640 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params;
1641 }
1642 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
1643 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
1644 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params;
1645 }
1646 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
1647 jpg_job.encode_job.p_metadata->statsdebug_af_data =
1648 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params;
1649 }
1650 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
1651 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
1652 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params;
1653 }
1654 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
1655 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
1656 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params;
1657 }
1658 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
1659 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
1660 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
1661 }
1662 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
1663 jpg_job.encode_job.p_metadata->statsdebug_bhist_data =
1664 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
1665 }
1666 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
1667 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data =
1668 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
1669 }
1670 }
1671 } else {
1672 LOGW("Metadata is null");
1673 }
1674
1675 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1676
1677 //Start jpeg encoding
1678 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1679 if (jpg_job.encode_job.cam_exif_params.debug_params) {
1680 free(jpg_job.encode_job.cam_exif_params.debug_params);
1681 }
1682 if (ret == NO_ERROR) {
1683 // remember job info
1684 jpeg_job_data->jobId = jobId;
1685 }
1686
1687 LOGD("X");
1688 return ret;
1689 }
1690
1691 /*===========================================================================
1692 * FUNCTION : dataProcessRoutine
1693 *
1694 * DESCRIPTION: data process routine that handles input data either from input
1695 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1696 * reprocess.
1697 *
1698 * PARAMETERS :
1699 * @data : user data ptr (QCamera3PostProcessor)
1700 *
1701 * RETURN : None
1702 *==========================================================================*/
dataProcessRoutine(void * data)1703 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1704 {
1705 int running = 1;
1706 int ret;
1707 uint8_t is_active = FALSE;
1708 uint8_t needNewSess = TRUE;
1709 mm_camera_super_buf_t *meta_buffer = NULL;
1710 LOGD("E");
1711 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1712 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1713 cmdThread->setName("cam_data_proc");
1714
1715 do {
1716 do {
1717 ret = cam_sem_wait(&cmdThread->cmd_sem);
1718 if (ret != 0 && errno != EINVAL) {
1719 LOGE("cam_sem_wait error (%s)",
1720 strerror(errno));
1721 return NULL;
1722 }
1723 } while (ret != 0);
1724
1725 // we got notified about new cmd avail in cmd queue
1726 camera_cmd_type_t cmd = cmdThread->getCmd();
1727 switch (cmd) {
1728 case CAMERA_CMD_TYPE_START_DATA_PROC:
1729 LOGH("start data proc");
1730 is_active = TRUE;
1731 needNewSess = TRUE;
1732
1733 pme->m_ongoingPPQ.init();
1734 pme->m_inputJpegQ.init();
1735 pme->m_inputPPQ.init();
1736 pme->m_inputFWKPPQ.init();
1737 pme->m_inputMetaQ.init();
1738 cam_sem_post(&cmdThread->sync_sem);
1739
1740 break;
1741 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1742 {
1743 LOGH("stop data proc");
1744 is_active = FALSE;
1745
1746 // cancel all ongoing jpeg jobs
1747 qcamera_hal3_jpeg_data_t *jpeg_job =
1748 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1749 while (jpeg_job != NULL) {
1750 pme->mJpegHandle.abort_job(jpeg_job->jobId);
1751
1752 pme->releaseJpegJobData(jpeg_job);
1753 free(jpeg_job);
1754
1755 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1756 }
1757
1758 // destroy jpeg encoding session
1759 if ( 0 < pme->mJpegSessionId ) {
1760 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
1761 pme->mJpegSessionId = 0;
1762 }
1763
1764 needNewSess = TRUE;
1765
1766 // flush ongoing postproc Queue
1767 pme->m_ongoingPPQ.flush();
1768
1769 // flush input jpeg Queue
1770 pme->m_inputJpegQ.flush();
1771
1772 // flush input Postproc Queue
1773 pme->m_inputPPQ.flush();
1774
1775 // flush framework input Postproc Queue
1776 pme->m_inputFWKPPQ.flush();
1777
1778 pme->m_inputMetaQ.flush();
1779
1780 // signal cmd is completed
1781 cam_sem_post(&cmdThread->sync_sem);
1782 }
1783 break;
1784 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1785 {
1786 LOGH("Do next job, active is %d", is_active);
1787 /* needNewSess is set to TRUE as postproc is not re-STARTed
1788 * anymore for every captureRequest */
1789 needNewSess = TRUE;
1790 if (is_active == TRUE) {
1791 // check if there is any ongoing jpeg jobs
1792 if (pme->m_ongoingJpegQ.isEmpty()) {
1793 LOGD("ongoing jpeg queue is empty so doing the jpeg job");
1794 // no ongoing jpeg job, we are fine to send jpeg encoding job
1795 qcamera_hal3_jpeg_data_t *jpeg_job =
1796 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1797
1798 if (NULL != jpeg_job) {
1799 // add into ongoing jpeg job Q
1800 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
1801
1802 if (jpeg_job->fwk_frame) {
1803 ret = pme->encodeFWKData(jpeg_job, needNewSess);
1804 } else {
1805 ret = pme->encodeData(jpeg_job, needNewSess);
1806 }
1807 if (NO_ERROR != ret) {
1808 // dequeue the last one
1809 pme->m_ongoingJpegQ.dequeue(false);
1810
1811 pme->releaseJpegJobData(jpeg_job);
1812 free(jpeg_job);
1813 }
1814 }
1815 }
1816
1817 // check if there are any framework pp jobs
1818 if (!pme->m_inputFWKPPQ.isEmpty()) {
1819 qcamera_fwk_input_pp_data_t *fwk_frame =
1820 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1821 if (NULL != fwk_frame) {
1822 qcamera_hal3_pp_data_t *pp_job =
1823 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1824 jpeg_settings_t *jpeg_settings =
1825 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1826 if (pp_job != NULL) {
1827 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1828 pp_job->jpeg_settings = jpeg_settings;
1829 if (pme->m_pReprocChannel != NULL) {
1830 if (NO_ERROR != pme->m_pReprocChannel->overrideFwkMetadata(fwk_frame)) {
1831 LOGE("Failed to extract output crop");
1832 }
1833 // add into ongoing PP job Q
1834 pp_job->fwk_src_frame = fwk_frame;
1835 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1836 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame, true);
1837 if (NO_ERROR != ret) {
1838 // remove from ongoing PP job Q
1839 pme->m_ongoingPPQ.dequeue(false);
1840 }
1841 } else {
1842 LOGE("Reprocess channel is NULL");
1843 ret = -1;
1844 }
1845 } else {
1846 LOGE("no mem for qcamera_hal3_pp_data_t");
1847 ret = -1;
1848 }
1849
1850 if (0 != ret) {
1851 // free pp_job
1852 if (pp_job != NULL) {
1853 free(pp_job);
1854 }
1855 // free frame
1856 if (fwk_frame != NULL) {
1857 free(fwk_frame);
1858 }
1859 }
1860 }
1861 }
1862
1863 LOGH("dequeuing pp frame");
1864 pthread_mutex_lock(&pme->mReprocJobLock);
1865 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
1866 qcamera_hal3_pp_buffer_t *pp_buffer =
1867 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
1868 meta_buffer =
1869 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1870 jpeg_settings_t *jpeg_settings =
1871 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1872 pthread_mutex_unlock(&pme->mReprocJobLock);
1873 qcamera_hal3_pp_data_t *pp_job =
1874 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1875 if (pp_job == NULL) {
1876 LOGE("no mem for qcamera_hal3_pp_data_t");
1877 ret = -1;
1878 } else if (meta_buffer == NULL) {
1879 LOGE("failed to dequeue from m_inputMetaQ");
1880 ret = -1;
1881 } else if (pp_buffer == NULL) {
1882 LOGE("failed to dequeue from m_inputPPQ");
1883 ret = -1;
1884 } else if (pp_buffer != NULL){
1885 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1886 pp_job->src_frame = pp_buffer->input;
1887 pp_job->src_metadata = meta_buffer;
1888 if (meta_buffer->bufs[0] != NULL) {
1889 pp_job->metadata = (metadata_buffer_t *)
1890 meta_buffer->bufs[0]->buffer;
1891 }
1892 pp_job->jpeg_settings = jpeg_settings;
1893 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1894 if (pme->m_pReprocChannel != NULL) {
1895 mm_camera_buf_def_t *meta_buffer_arg = NULL;
1896 meta_buffer_arg = meta_buffer->bufs[0];
1897 qcamera_fwk_input_pp_data_t fwk_frame;
1898 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
1899 fwk_frame.frameNumber = pp_buffer->frameNumber;
1900 ret = pme->m_pReprocChannel->overrideMetadata(
1901 pp_buffer, meta_buffer_arg,
1902 pp_job->jpeg_settings,
1903 fwk_frame);
1904 if (NO_ERROR == ret) {
1905 // add into ongoing PP job Q
1906 ret = pme->m_pReprocChannel->doReprocessOffline(
1907 &fwk_frame, true);
1908 if (NO_ERROR != ret) {
1909 // remove from ongoing PP job Q
1910 pme->m_ongoingPPQ.dequeue(false);
1911 }
1912 }
1913 } else {
1914 LOGE("No reprocess. Calling processPPData directly");
1915 ret = pme->processPPData(pp_buffer->input);
1916 }
1917 }
1918
1919 if (0 != ret) {
1920 // free pp_job
1921 if (pp_job != NULL) {
1922 free(pp_job);
1923 }
1924 // free frame
1925 if (pp_buffer != NULL) {
1926 if (pp_buffer->input) {
1927 pme->releaseSuperBuf(pp_buffer->input);
1928 free(pp_buffer->input);
1929 }
1930 free(pp_buffer);
1931 }
1932 //free metadata
1933 if (NULL != meta_buffer) {
1934 pme->m_parent->metadataBufDone(meta_buffer);
1935 free(meta_buffer);
1936 }
1937 } else {
1938 if (pp_buffer != NULL) {
1939 free(pp_buffer);
1940 }
1941 }
1942 } else {
1943 pthread_mutex_unlock(&pme->mReprocJobLock);
1944 }
1945 } else {
1946 // not active, simply return buf and do no op
1947 qcamera_hal3_jpeg_data_t *jpeg_job =
1948 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1949 if (NULL != jpeg_job) {
1950 free(jpeg_job);
1951 }
1952
1953 qcamera_hal3_pp_buffer_t* pp_buf =
1954 (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
1955 if (NULL != pp_buf) {
1956 if (pp_buf->input) {
1957 pme->releaseSuperBuf(pp_buf->input);
1958 free(pp_buf->input);
1959 pp_buf->input = NULL;
1960 }
1961 free(pp_buf);
1962 }
1963 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1964 if (metadata != NULL) {
1965 pme->m_parent->metadataBufDone(metadata);
1966 free(metadata);
1967 }
1968 qcamera_fwk_input_pp_data_t *fwk_frame =
1969 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1970 if (NULL != fwk_frame) {
1971 free(fwk_frame);
1972 }
1973 }
1974 }
1975 break;
1976 case CAMERA_CMD_TYPE_EXIT:
1977 running = 0;
1978 break;
1979 default:
1980 break;
1981 }
1982 } while (running);
1983 LOGD("X");
1984 return NULL;
1985 }
1986
1987 /* EXIF related helper methods */
1988
1989 /*===========================================================================
1990 * FUNCTION : getRational
1991 *
1992 * DESCRIPTION: compose rational struct
1993 *
1994 * PARAMETERS :
1995 * @rat : ptr to struct to store rational info
1996 * @num :num of the rational
1997 * @denom : denom of the rational
1998 *
1999 * RETURN : int32_t type of status
2000 * NO_ERROR -- success
2001 * none-zero failure code
2002 *==========================================================================*/
getRational(rat_t * rat,int num,int denom)2003 int32_t getRational(rat_t *rat, int num, int denom)
2004 {
2005 if ((0 > num) || (0 >= denom)) {
2006 LOGE("Negative values");
2007 return BAD_VALUE;
2008 }
2009 if (NULL == rat) {
2010 LOGE("NULL rat input");
2011 return BAD_VALUE;
2012 }
2013 rat->num = (uint32_t)num;
2014 rat->denom = (uint32_t)denom;
2015 return NO_ERROR;
2016 }
2017
2018 /*===========================================================================
2019 * FUNCTION : parseGPSCoordinate
2020 *
2021 * DESCRIPTION: parse GPS coordinate string
2022 *
2023 * PARAMETERS :
2024 * @coord_str : [input] coordinate string
2025 * @coord : [output] ptr to struct to store coordinate
2026 *
2027 * RETURN : int32_t type of status
2028 * NO_ERROR -- success
2029 * none-zero failure code
2030 *==========================================================================*/
parseGPSCoordinate(const char * coord_str,rat_t * coord)2031 int parseGPSCoordinate(const char *coord_str, rat_t* coord)
2032 {
2033 if(coord == NULL) {
2034 LOGE("error, invalid argument coord == NULL");
2035 return BAD_VALUE;
2036 }
2037 double degF = atof(coord_str);
2038 if (degF < 0) {
2039 degF = -degF;
2040 }
2041 double minF = (degF - (int) degF) * 60;
2042 double secF = (minF - (int) minF) * 60;
2043
2044 getRational(&coord[0], (int)degF, 1);
2045 getRational(&coord[1], (int)minF, 1);
2046 getRational(&coord[2], (int)(secF * 10000), 10000);
2047 return NO_ERROR;
2048 }
2049
2050 /*===========================================================================
2051 * FUNCTION : getExifDateTime
2052 *
2053 * DESCRIPTION: query exif date time
2054 *
2055 * PARAMETERS :
2056 * @dateTime : string to store exif date time
2057 * @subsecTime : string to store exif subsec time
2058 *
2059 * RETURN : int32_t type of status
2060 * NO_ERROR -- success
2061 * none-zero failure code
2062 *==========================================================================*/
getExifDateTime(String8 & dateTime,String8 & subsecTime)2063 int32_t getExifDateTime(String8 &dateTime, String8 &subsecTime)
2064 {
2065 int32_t ret = NO_ERROR;
2066
2067 //get time and date from system
2068 struct timeval tv;
2069 struct tm timeinfo_data;
2070
2071 int res = gettimeofday(&tv, NULL);
2072 if (0 == res) {
2073 struct tm *timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2074 if (NULL != timeinfo) {
2075 //Write datetime according to EXIF Spec
2076 //"YYYY:MM:DD HH:MM:SS" (20 chars including \0)
2077 dateTime = String8::format("%04d:%02d:%02d %02d:%02d:%02d",
2078 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2079 timeinfo->tm_mday, timeinfo->tm_hour,
2080 timeinfo->tm_min, timeinfo->tm_sec);
2081 //Write subsec according to EXIF Sepc
2082 subsecTime = String8::format("%06ld", tv.tv_usec);
2083 } else {
2084 LOGE("localtime_r() error");
2085 ret = UNKNOWN_ERROR;
2086 }
2087 } else if (-1 == res) {
2088 LOGE("gettimeofday() error: %s", strerror(errno));
2089 ret = UNKNOWN_ERROR;
2090 } else {
2091 LOGE("gettimeofday() unexpected return code: %d", res);
2092 ret = UNKNOWN_ERROR;
2093 }
2094
2095 return ret;
2096 }
2097
2098 /*===========================================================================
2099 * FUNCTION : getExifFocalLength
2100 *
2101 * DESCRIPTION: get exif focal length
2102 *
2103 * PARAMETERS :
2104 * @focalLength : ptr to rational struct to store focal length
2105 * @value : focal length value
2106 *
2107 * RETURN : int32_t type of status
2108 * NO_ERROR -- success
2109 * none-zero failure code
2110 *==========================================================================*/
getExifFocalLength(rat_t * focalLength,float value)2111 int32_t getExifFocalLength(rat_t *focalLength, float value)
2112 {
2113 int focalLengthValue =
2114 (int)(value * FOCAL_LENGTH_DECIMAL_PRECISION);
2115 return getRational(focalLength, focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
2116 }
2117
2118 /*===========================================================================
2119 * FUNCTION : getExifExpTimeInfo
2120 *
2121 * DESCRIPTION: get exif exposure time information
2122 *
2123 * PARAMETERS :
2124 * @expoTimeInfo : rational exposure time value
2125 * @value : exposure time value
2126 * RETURN : nt32_t type of status
2127 * NO_ERROR -- success
2128 * none-zero failure code
2129 *==========================================================================*/
getExifExpTimeInfo(rat_t * expoTimeInfo,int64_t value)2130 int32_t getExifExpTimeInfo(rat_t *expoTimeInfo, int64_t value)
2131 {
2132
2133 int64_t cal_exposureTime;
2134 if (value != 0)
2135 cal_exposureTime = value;
2136 else
2137 cal_exposureTime = 60;
2138
2139 return getRational(expoTimeInfo, 1, (int)cal_exposureTime);
2140 }
2141
2142 /*===========================================================================
2143 * FUNCTION : getExifGpsProcessingMethod
2144 *
2145 * DESCRIPTION: get GPS processing method
2146 *
2147 * PARAMETERS :
2148 * @gpsProcessingMethod : string to store GPS process method
2149 * @count : length of the string
2150 * @value : the value of the processing method
2151 *
2152 * RETURN : int32_t type of status
2153 * NO_ERROR -- success
2154 * none-zero failure code
2155 *==========================================================================*/
getExifGpsProcessingMethod(char * gpsProcessingMethod,uint32_t & count,char * value)2156 int32_t getExifGpsProcessingMethod(char *gpsProcessingMethod,
2157 uint32_t &count, char* value)
2158 {
2159 if(value != NULL) {
2160 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
2161 count = EXIF_ASCII_PREFIX_SIZE;
2162 strlcpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE,
2163 value,
2164 GPS_PROCESSING_METHOD_SIZE);
2165 count += (uint32_t)strlen(value);
2166 gpsProcessingMethod[count++] = '\0'; // increase 1 for the last NULL char
2167 return NO_ERROR;
2168 } else {
2169 return BAD_VALUE;
2170 }
2171 }
2172
2173 /*===========================================================================
2174 * FUNCTION : getExifLatitude
2175 *
2176 * DESCRIPTION: get exif latitude
2177 *
2178 * PARAMETERS :
2179 * @latitude : ptr to rational struct to store latitude info
2180 * @latRef : character to indicate latitude reference
2181 * @value : value of the latitude
2182 *
2183 * RETURN : int32_t type of status
2184 * NO_ERROR -- success
2185 * none-zero failure code
2186 *==========================================================================*/
getExifLatitude(rat_t * latitude,char * latRef,double value)2187 int32_t getExifLatitude(rat_t *latitude, char *latRef, double value)
2188 {
2189 char str[30];
2190 snprintf(str, sizeof(str), "%f", value);
2191 if(str[0] != '\0') {
2192 parseGPSCoordinate(str, latitude);
2193
2194 //set Latitude Ref
2195 float latitudeValue = strtof(str, 0);
2196 if(latitudeValue < 0.0f) {
2197 latRef[0] = 'S';
2198 } else {
2199 latRef[0] = 'N';
2200 }
2201 latRef[1] = '\0';
2202 return NO_ERROR;
2203 }else{
2204 return BAD_VALUE;
2205 }
2206 }
2207
2208 /*===========================================================================
2209 * FUNCTION : getExifLongitude
2210 *
2211 * DESCRIPTION: get exif longitude
2212 *
2213 * PARAMETERS :
2214 * @longitude : ptr to rational struct to store longitude info
2215 * @lonRef : character to indicate longitude reference
2216 * @value : value of the longitude
2217 *
2218 * RETURN : int32_t type of status
2219 * NO_ERROR -- success
2220 * none-zero failure code
2221 *==========================================================================*/
getExifLongitude(rat_t * longitude,char * lonRef,double value)2222 int32_t getExifLongitude(rat_t *longitude, char *lonRef, double value)
2223 {
2224 char str[30];
2225 snprintf(str, sizeof(str), "%f", value);
2226 if(str[0] != '\0') {
2227 parseGPSCoordinate(str, longitude);
2228
2229 //set Longitude Ref
2230 float longitudeValue = strtof(str, 0);
2231 if(longitudeValue < 0.0f) {
2232 lonRef[0] = 'W';
2233 } else {
2234 lonRef[0] = 'E';
2235 }
2236 lonRef[1] = '\0';
2237 return NO_ERROR;
2238 }else{
2239 return BAD_VALUE;
2240 }
2241 }
2242
2243 /*===========================================================================
2244 * FUNCTION : getExifAltitude
2245 *
2246 * DESCRIPTION: get exif altitude
2247 *
2248 * PARAMETERS :
2249 * @altitude : ptr to rational struct to store altitude info
2250 * @altRef : character to indicate altitude reference
2251 * @argValue : altitude value
2252 *
2253 * RETURN : int32_t type of status
2254 * NO_ERROR -- success
2255 * none-zero failure code
2256 *==========================================================================*/
getExifAltitude(rat_t * altitude,char * altRef,double argValue)2257 int32_t getExifAltitude(rat_t *altitude, char *altRef, double argValue)
2258 {
2259 char str[30];
2260 snprintf(str, sizeof(str), "%f", argValue);
2261 if (str[0] != '\0') {
2262 double value = atof(str);
2263 *altRef = 0;
2264 if(value < 0){
2265 *altRef = 1;
2266 value = -value;
2267 }
2268 return getRational(altitude, (int)(value * 1000), 1000);
2269 } else {
2270 return BAD_VALUE;
2271 }
2272 }
2273
2274 /*===========================================================================
2275 * FUNCTION : getExifGpsDateTimeStamp
2276 *
2277 * DESCRIPTION: get exif GPS date time stamp
2278 *
2279 * PARAMETERS :
2280 * @gpsDateStamp : GPS date time stamp string
2281 * @bufLen : length of the string
2282 * @gpsTimeStamp : ptr to rational struct to store time stamp info
2283 * @value : timestamp value
2284 *
2285 * RETURN : int32_t type of status
2286 * NO_ERROR -- success
2287 * none-zero failure code
2288 *==========================================================================*/
getExifGpsDateTimeStamp(char * gpsDateStamp,uint32_t bufLen,rat_t * gpsTimeStamp,int64_t value)2289 int32_t getExifGpsDateTimeStamp(char *gpsDateStamp, uint32_t bufLen,
2290 rat_t *gpsTimeStamp, int64_t value)
2291 {
2292 char str[30];
2293 snprintf(str, sizeof(str), "%lld", (long long int)value);
2294 if(str[0] != '\0') {
2295 time_t unixTime = (time_t)atol(str);
2296 struct tm *UTCTimestamp = gmtime(&unixTime);
2297 if (UTCTimestamp != NULL && gpsDateStamp != NULL
2298 && gpsTimeStamp != NULL) {
2299 strftime(gpsDateStamp, bufLen, "%Y:%m:%d", UTCTimestamp);
2300
2301 getRational(&gpsTimeStamp[0], UTCTimestamp->tm_hour, 1);
2302 getRational(&gpsTimeStamp[1], UTCTimestamp->tm_min, 1);
2303 getRational(&gpsTimeStamp[2], UTCTimestamp->tm_sec, 1);
2304 return NO_ERROR;
2305 } else {
2306 LOGE("Could not get the timestamp");
2307 return BAD_VALUE;
2308 }
2309 } else {
2310 return BAD_VALUE;
2311 }
2312 }
2313
2314 /*===========================================================================
2315 * FUNCTION : getExifExposureValue
2316 *
2317 * DESCRIPTION: get exif GPS date time stamp
2318 *
2319 * PARAMETERS :
2320 * @exposure_val : rational exposure value
2321 * @exposure_comp : exposure compensation
2322 * @step : exposure step
2323 *
2324 * RETURN : int32_t type of status
2325 * NO_ERROR -- success
2326 * none-zero failure code
2327 *==========================================================================*/
getExifExposureValue(srat_t * exposure_val,int32_t exposure_comp,cam_rational_type_t step)2328 int32_t getExifExposureValue(srat_t* exposure_val, int32_t exposure_comp,
2329 cam_rational_type_t step)
2330 {
2331 exposure_val->num = exposure_comp * step.numerator;
2332 exposure_val->denom = step.denominator;
2333 return 0;
2334 }
2335
2336 /*===========================================================================
2337 * FUNCTION : getExifData
2338 *
2339 * DESCRIPTION: get exif data to be passed into jpeg encoding
2340 *
2341 * PARAMETERS :
2342 * @metadata : metadata of the encoding request
2343 * @jpeg_settings : jpeg_settings for encoding
2344 *
2345 * RETURN : exif data from user setting and GPS
2346 *==========================================================================*/
getExifData(metadata_buffer_t * metadata,jpeg_settings_t * jpeg_settings)2347 QCamera3Exif *QCamera3PostProcessor::getExifData(metadata_buffer_t *metadata,
2348 jpeg_settings_t *jpeg_settings)
2349 {
2350 QCamera3Exif *exif = new QCamera3Exif();
2351 if (exif == NULL) {
2352 LOGE("No memory for QCamera3Exif");
2353 return NULL;
2354 }
2355 QCamera3HardwareInterface* hal_obj = NULL;
2356 if (m_parent != NULL) {
2357 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
2358 } else {
2359 LOGE("m_parent is NULL, Error");
2360 return NULL;
2361 }
2362
2363 int32_t rc = NO_ERROR;
2364 uint32_t count = 0;
2365
2366 // add exif entries
2367 String8 dateTime;
2368 String8 subsecTime;
2369 rc = getExifDateTime(dateTime, subsecTime);
2370 if (rc == NO_ERROR) {
2371 exif->addEntry(EXIFTAGID_DATE_TIME, EXIF_ASCII,
2372 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2373 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
2374 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2375 exif->addEntry(EXIFTAGID_EXIF_DATE_TIME_DIGITIZED, EXIF_ASCII,
2376 (uint32_t)(dateTime.length() + 1), (void *)dateTime.string());
2377 exif->addEntry(EXIFTAGID_SUBSEC_TIME, EXIF_ASCII,
2378 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2379 exif->addEntry(EXIFTAGID_SUBSEC_TIME_ORIGINAL, EXIF_ASCII,
2380 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2381 exif->addEntry(EXIFTAGID_SUBSEC_TIME_DIGITIZED, EXIF_ASCII,
2382 (uint32_t)(subsecTime.length() + 1), (void *)subsecTime.string());
2383 } else {
2384 LOGW("getExifDateTime failed");
2385 }
2386
2387
2388 if (metadata != NULL) {
2389 IF_META_AVAILABLE(float, focal_length, CAM_INTF_META_LENS_FOCAL_LENGTH, metadata) {
2390 rat_t focalLength;
2391 rc = getExifFocalLength(&focalLength, *focal_length);
2392 if (rc == NO_ERROR) {
2393 exif->addEntry(EXIFTAGID_FOCAL_LENGTH,
2394 EXIF_RATIONAL,
2395 1,
2396 (void *)&(focalLength));
2397 } else {
2398 LOGW("getExifFocalLength failed");
2399 }
2400 }
2401
2402 IF_META_AVAILABLE(int32_t, isoSpeed, CAM_INTF_META_SENSOR_SENSITIVITY, metadata) {
2403 int16_t fwk_isoSpeed = (int16_t) *isoSpeed;
2404 exif->addEntry(EXIFTAGID_ISO_SPEED_RATING, EXIF_SHORT, 1, (void *) &(fwk_isoSpeed));
2405 }
2406
2407
2408 IF_META_AVAILABLE(int64_t, sensor_exposure_time,
2409 CAM_INTF_META_SENSOR_EXPOSURE_TIME, metadata) {
2410 rat_t sensorExpTime;
2411 rc = getExifExpTimeInfo(&sensorExpTime, *sensor_exposure_time);
2412 if (rc == NO_ERROR){
2413 exif->addEntry(EXIFTAGID_EXPOSURE_TIME,
2414 EXIF_RATIONAL,
2415 1,
2416 (void *)&(sensorExpTime));
2417 } else {
2418 LOGW("getExifExpTimeInfo failed");
2419 }
2420 }
2421
2422 char* jpeg_gps_processing_method = jpeg_settings->gps_processing_method;
2423 if (strlen(jpeg_gps_processing_method) > 0) {
2424 char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE +
2425 GPS_PROCESSING_METHOD_SIZE];
2426 count = 0;
2427 rc = getExifGpsProcessingMethod(gpsProcessingMethod,
2428 count,
2429 jpeg_gps_processing_method);
2430 if(rc == NO_ERROR) {
2431 exif->addEntry(EXIFTAGID_GPS_PROCESSINGMETHOD,
2432 EXIF_ASCII,
2433 count,
2434 (void *)gpsProcessingMethod);
2435 } else {
2436 LOGW("getExifGpsProcessingMethod failed");
2437 }
2438 }
2439
2440 if (jpeg_settings->gps_coordinates_valid) {
2441
2442 //latitude
2443 rat_t latitude[3];
2444 char latRef[2];
2445 rc = getExifLatitude(latitude, latRef,
2446 jpeg_settings->gps_coordinates[0]);
2447 if(rc == NO_ERROR) {
2448 exif->addEntry(EXIFTAGID_GPS_LATITUDE,
2449 EXIF_RATIONAL,
2450 3,
2451 (void *)latitude);
2452 exif->addEntry(EXIFTAGID_GPS_LATITUDE_REF,
2453 EXIF_ASCII,
2454 2,
2455 (void *)latRef);
2456 } else {
2457 LOGW("getExifLatitude failed");
2458 }
2459
2460 //longitude
2461 rat_t longitude[3];
2462 char lonRef[2];
2463 rc = getExifLongitude(longitude, lonRef,
2464 jpeg_settings->gps_coordinates[1]);
2465 if(rc == NO_ERROR) {
2466 exif->addEntry(EXIFTAGID_GPS_LONGITUDE,
2467 EXIF_RATIONAL,
2468 3,
2469 (void *)longitude);
2470
2471 exif->addEntry(EXIFTAGID_GPS_LONGITUDE_REF,
2472 EXIF_ASCII,
2473 2,
2474 (void *)lonRef);
2475 } else {
2476 LOGW("getExifLongitude failed");
2477 }
2478
2479 //altitude
2480 rat_t altitude;
2481 char altRef;
2482 rc = getExifAltitude(&altitude, &altRef,
2483 jpeg_settings->gps_coordinates[2]);
2484 if(rc == NO_ERROR) {
2485 exif->addEntry(EXIFTAGID_GPS_ALTITUDE,
2486 EXIF_RATIONAL,
2487 1,
2488 (void *)&(altitude));
2489
2490 exif->addEntry(EXIFTAGID_GPS_ALTITUDE_REF,
2491 EXIF_BYTE,
2492 1,
2493 (void *)&altRef);
2494 } else {
2495 LOGW("getExifAltitude failed");
2496 }
2497 }
2498
2499 if (jpeg_settings->gps_timestamp_valid) {
2500
2501 char gpsDateStamp[20];
2502 rat_t gpsTimeStamp[3];
2503 rc = getExifGpsDateTimeStamp(gpsDateStamp, 20, gpsTimeStamp,
2504 jpeg_settings->gps_timestamp);
2505 if(rc == NO_ERROR) {
2506 exif->addEntry(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
2507 (uint32_t)(strlen(gpsDateStamp) + 1),
2508 (void *)gpsDateStamp);
2509
2510 exif->addEntry(EXIFTAGID_GPS_TIMESTAMP,
2511 EXIF_RATIONAL,
2512 3,
2513 (void *)gpsTimeStamp);
2514 } else {
2515 LOGW("getExifGpsDataTimeStamp failed");
2516 }
2517 }
2518
2519 IF_META_AVAILABLE(int32_t, exposure_comp, CAM_INTF_PARM_EXPOSURE_COMPENSATION, metadata) {
2520 IF_META_AVAILABLE(cam_rational_type_t, comp_step, CAM_INTF_PARM_EV_STEP, metadata) {
2521 srat_t exposure_val;
2522 rc = getExifExposureValue(&exposure_val, *exposure_comp, *comp_step);
2523 if(rc == NO_ERROR) {
2524 exif->addEntry(EXIFTAGID_EXPOSURE_BIAS_VALUE,
2525 EXIF_SRATIONAL,
2526 1,
2527 (void *)(&exposure_val));
2528 } else {
2529 LOGW("getExifExposureValue failed ");
2530 }
2531 }
2532 }
2533 } else {
2534 LOGW("no metadata provided ");
2535 }
2536
2537 #ifdef ENABLE_MODEL_INFO_EXIF
2538
2539 char value[PROPERTY_VALUE_MAX];
2540 if (property_get("ro.product.manufacturer", value, "QCOM-AA") > 0) {
2541 exif->addEntry(EXIFTAGID_MAKE, EXIF_ASCII,
2542 (uint32_t)(strlen(value) + 1), (void *)value);
2543 } else {
2544 LOGW("getExifMaker failed");
2545 }
2546
2547 if (property_get("ro.product.model", value, "QCAM-AA") > 0) {
2548 exif->addEntry(EXIFTAGID_MODEL, EXIF_ASCII,
2549 (uint32_t)(strlen(value) + 1), (void *)value);
2550 } else {
2551 LOGW("getExifModel failed");
2552 }
2553
2554 if (property_get("ro.build.description", value, "QCAM-AA") > 0) {
2555 exif->addEntry(EXIFTAGID_SOFTWARE, EXIF_ASCII,
2556 (uint32_t)(strlen(value) + 1), (void *)value);
2557 } else {
2558 LOGW("getExifSoftware failed");
2559 }
2560
2561 #endif
2562
2563 if (jpeg_settings->image_desc_valid) {
2564 if (exif->addEntry(EXIFTAGID_IMAGE_DESCRIPTION, EXIF_ASCII,
2565 strlen(jpeg_settings->image_desc)+1,
2566 (void *)jpeg_settings->image_desc)) {
2567 LOGW("Adding IMAGE_DESCRIPTION tag failed");
2568 }
2569 }
2570
2571 if( hal_obj->needJpegExifRotation()) {
2572 int16_t orientation;
2573 switch (jpeg_settings->jpeg_orientation) {
2574 case 0:
2575 orientation = 1;
2576 break;
2577 case 90:
2578 orientation = 6;
2579 break;
2580 case 180:
2581 orientation = 3;
2582 break;
2583 case 270:
2584 orientation = 8;
2585 break;
2586 default:
2587 orientation = 1;
2588 break;
2589 }
2590 exif->addEntry(EXIFTAGID_ORIENTATION,
2591 EXIF_SHORT,
2592 1,
2593 (void *)&orientation);
2594 exif->addEntry(EXIFTAGID_TN_ORIENTATION,
2595 EXIF_SHORT,
2596 1,
2597 (void *)&orientation);
2598
2599 }
2600
2601 return exif;
2602 }
2603
2604 /*===========================================================================
2605 * FUNCTION : QCamera3Exif
2606 *
2607 * DESCRIPTION: constructor of QCamera3Exif
2608 *
2609 * PARAMETERS : None
2610 *
2611 * RETURN : None
2612 *==========================================================================*/
QCamera3Exif()2613 QCamera3Exif::QCamera3Exif()
2614 : m_nNumEntries(0)
2615 {
2616 memset(m_Entries, 0, sizeof(m_Entries));
2617 }
2618
2619 /*===========================================================================
2620 * FUNCTION : ~QCamera3Exif
2621 *
2622 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
2623 *
2624 * PARAMETERS : None
2625 *
2626 * RETURN : None
2627 *==========================================================================*/
~QCamera3Exif()2628 QCamera3Exif::~QCamera3Exif()
2629 {
2630 for (uint32_t i = 0; i < m_nNumEntries; i++) {
2631 switch (m_Entries[i].tag_entry.type) {
2632 case EXIF_BYTE:
2633 {
2634 if (m_Entries[i].tag_entry.count > 1 &&
2635 m_Entries[i].tag_entry.data._bytes != NULL) {
2636 free(m_Entries[i].tag_entry.data._bytes);
2637 m_Entries[i].tag_entry.data._bytes = NULL;
2638 }
2639 }
2640 break;
2641 case EXIF_ASCII:
2642 {
2643 if (m_Entries[i].tag_entry.data._ascii != NULL) {
2644 free(m_Entries[i].tag_entry.data._ascii);
2645 m_Entries[i].tag_entry.data._ascii = NULL;
2646 }
2647 }
2648 break;
2649 case EXIF_SHORT:
2650 {
2651 if (m_Entries[i].tag_entry.count > 1 &&
2652 m_Entries[i].tag_entry.data._shorts != NULL) {
2653 free(m_Entries[i].tag_entry.data._shorts);
2654 m_Entries[i].tag_entry.data._shorts = NULL;
2655 }
2656 }
2657 break;
2658 case EXIF_LONG:
2659 {
2660 if (m_Entries[i].tag_entry.count > 1 &&
2661 m_Entries[i].tag_entry.data._longs != NULL) {
2662 free(m_Entries[i].tag_entry.data._longs);
2663 m_Entries[i].tag_entry.data._longs = NULL;
2664 }
2665 }
2666 break;
2667 case EXIF_RATIONAL:
2668 {
2669 if (m_Entries[i].tag_entry.count > 1 &&
2670 m_Entries[i].tag_entry.data._rats != NULL) {
2671 free(m_Entries[i].tag_entry.data._rats);
2672 m_Entries[i].tag_entry.data._rats = NULL;
2673 }
2674 }
2675 break;
2676 case EXIF_UNDEFINED:
2677 {
2678 if (m_Entries[i].tag_entry.data._undefined != NULL) {
2679 free(m_Entries[i].tag_entry.data._undefined);
2680 m_Entries[i].tag_entry.data._undefined = NULL;
2681 }
2682 }
2683 break;
2684 case EXIF_SLONG:
2685 {
2686 if (m_Entries[i].tag_entry.count > 1 &&
2687 m_Entries[i].tag_entry.data._slongs != NULL) {
2688 free(m_Entries[i].tag_entry.data._slongs);
2689 m_Entries[i].tag_entry.data._slongs = NULL;
2690 }
2691 }
2692 break;
2693 case EXIF_SRATIONAL:
2694 {
2695 if (m_Entries[i].tag_entry.count > 1 &&
2696 m_Entries[i].tag_entry.data._srats != NULL) {
2697 free(m_Entries[i].tag_entry.data._srats);
2698 m_Entries[i].tag_entry.data._srats = NULL;
2699 }
2700 }
2701 break;
2702 default:
2703 LOGW("Error, Unknown type");
2704 break;
2705 }
2706 }
2707 }
2708
2709 /*===========================================================================
2710 * FUNCTION : addEntry
2711 *
2712 * DESCRIPTION: function to add an entry to exif data
2713 *
2714 * PARAMETERS :
2715 * @tagid : exif tag ID
2716 * @type : data type
2717 * @count : number of data in uint of its type
2718 * @data : input data ptr
2719 *
2720 * RETURN : int32_t type of status
2721 * NO_ERROR -- success
2722 * none-zero failure code
2723 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)2724 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
2725 exif_tag_type_t type,
2726 uint32_t count,
2727 void *data)
2728 {
2729 int32_t rc = NO_ERROR;
2730 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
2731 LOGE("Number of entries exceeded limit");
2732 return NO_MEMORY;
2733 }
2734
2735 m_Entries[m_nNumEntries].tag_id = tagid;
2736 m_Entries[m_nNumEntries].tag_entry.type = type;
2737 m_Entries[m_nNumEntries].tag_entry.count = count;
2738 m_Entries[m_nNumEntries].tag_entry.copy = 1;
2739 switch (type) {
2740 case EXIF_BYTE:
2741 {
2742 if (count > 1) {
2743 uint8_t *values = (uint8_t *)malloc(count);
2744 if (values == NULL) {
2745 LOGE("No memory for byte array");
2746 rc = NO_MEMORY;
2747 } else {
2748 memcpy(values, data, count);
2749 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
2750 }
2751 } else {
2752 m_Entries[m_nNumEntries].tag_entry.data._byte =
2753 *(uint8_t *)data;
2754 }
2755 }
2756 break;
2757 case EXIF_ASCII:
2758 {
2759 char *str = NULL;
2760 str = (char *)malloc(count + 1);
2761 if (str == NULL) {
2762 LOGE("No memory for ascii string");
2763 rc = NO_MEMORY;
2764 } else {
2765 memset(str, 0, count + 1);
2766 memcpy(str, data, count);
2767 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
2768 }
2769 }
2770 break;
2771 case EXIF_SHORT:
2772 {
2773 uint16_t *exif_data = (uint16_t *)data;
2774 if (count > 1) {
2775 uint16_t *values =
2776 (uint16_t *)malloc(count * sizeof(uint16_t));
2777 if (values == NULL) {
2778 LOGE("No memory for short array");
2779 rc = NO_MEMORY;
2780 } else {
2781 memcpy(values, exif_data, count * sizeof(uint16_t));
2782 m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
2783 }
2784 } else {
2785 m_Entries[m_nNumEntries].tag_entry.data._short =
2786 *(uint16_t *)data;
2787 }
2788 }
2789 break;
2790 case EXIF_LONG:
2791 {
2792 uint32_t *exif_data = (uint32_t *)data;
2793 if (count > 1) {
2794 uint32_t *values =
2795 (uint32_t *)malloc(count * sizeof(uint32_t));
2796 if (values == NULL) {
2797 LOGE("No memory for long array");
2798 rc = NO_MEMORY;
2799 } else {
2800 memcpy(values, exif_data, count * sizeof(uint32_t));
2801 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
2802 }
2803 } else {
2804 m_Entries[m_nNumEntries].tag_entry.data._long =
2805 *(uint32_t *)data;
2806 }
2807 }
2808 break;
2809 case EXIF_RATIONAL:
2810 {
2811 rat_t *exif_data = (rat_t *)data;
2812 if (count > 1) {
2813 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
2814 if (values == NULL) {
2815 LOGE("No memory for rational array");
2816 rc = NO_MEMORY;
2817 } else {
2818 memcpy(values, exif_data, count * sizeof(rat_t));
2819 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
2820 }
2821 } else {
2822 m_Entries[m_nNumEntries].tag_entry.data._rat =
2823 *(rat_t *)data;
2824 }
2825 }
2826 break;
2827 case EXIF_UNDEFINED:
2828 {
2829 uint8_t *values = (uint8_t *)malloc(count);
2830 if (values == NULL) {
2831 LOGE("No memory for undefined array");
2832 rc = NO_MEMORY;
2833 } else {
2834 memcpy(values, data, count);
2835 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
2836 }
2837 }
2838 break;
2839 case EXIF_SLONG:
2840 {
2841 int32_t *exif_data = (int32_t *)data;
2842 if (count > 1) {
2843 int32_t *values =
2844 (int32_t *)malloc(count * sizeof(int32_t));
2845 if (values == NULL) {
2846 LOGE("No memory for signed long array");
2847 rc = NO_MEMORY;
2848 } else {
2849 memcpy(values, exif_data, count * sizeof(int32_t));
2850 m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
2851 }
2852 } else {
2853 m_Entries[m_nNumEntries].tag_entry.data._slong =
2854 *(int32_t *)data;
2855 }
2856 }
2857 break;
2858 case EXIF_SRATIONAL:
2859 {
2860 srat_t *exif_data = (srat_t *)data;
2861 if (count > 1) {
2862 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
2863 if (values == NULL) {
2864 LOGE("No memory for sign rational array");
2865 rc = NO_MEMORY;
2866 } else {
2867 memcpy(values, exif_data, count * sizeof(srat_t));
2868 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
2869 }
2870 } else {
2871 m_Entries[m_nNumEntries].tag_entry.data._srat =
2872 *(srat_t *)data;
2873 }
2874 }
2875 break;
2876 default:
2877 LOGE("Error, Unknown type");
2878 break;
2879 }
2880
2881 // Increase number of entries
2882 m_nNumEntries++;
2883 return rc;
2884 }
2885
2886 }; // namespace qcamera
2887