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