1 /* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 #define ATRACE_TAG ATRACE_TAG_CAMERA
30
31 #define LOG_TAG "QCamera3PostProc"
32 //#define LOG_NDEBUG 0
33
34 #include <stdlib.h>
35 #include <utils/Errors.h>
36 #include <utils/Trace.h>
37
38 #include "QCamera3PostProc.h"
39 #include "QCamera3HWI.h"
40 #include "QCamera3Channel.h"
41 #include "QCamera3Stream.h"
42
43 namespace qcamera {
44
45 /*===========================================================================
46 * FUNCTION : QCamera3PostProcessor
47 *
48 * DESCRIPTION: constructor of QCamera3PostProcessor.
49 *
50 * PARAMETERS :
51 * @cam_ctrl : ptr to HWI object
52 *
53 * RETURN : None
54 *==========================================================================*/
QCamera3PostProcessor(QCamera3PicChannel * ch_ctrl)55 QCamera3PostProcessor::QCamera3PostProcessor(QCamera3PicChannel* ch_ctrl)
56 : m_parent(ch_ctrl),
57 mJpegCB(NULL),
58 mJpegUserData(NULL),
59 mJpegClientHandle(0),
60 mJpegSessionId(0),
61 m_bThumbnailNeeded(TRUE),
62 m_pReprocChannel(NULL),
63 m_inputPPQ(releasePPInputData, this),
64 m_inputFWKPPQ(NULL, this),
65 m_ongoingPPQ(releaseOngoingPPData, this),
66 m_inputJpegQ(releaseJpegData, this),
67 m_ongoingJpegQ(releaseJpegData, this),
68 m_inputRawQ(releasePPInputData, this),
69 m_inputMetaQ(releaseMetadata, this),
70 m_jpegSettingsQ(NULL, this)
71 {
72 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
73 pthread_mutex_init(&mReprocJobLock, NULL);
74 }
75
76 /*===========================================================================
77 * FUNCTION : ~QCamera3PostProcessor
78 *
79 * DESCRIPTION: deconstructor of QCamera3PostProcessor.
80 *
81 * PARAMETERS : None
82 *
83 * RETURN : None
84 *==========================================================================*/
~QCamera3PostProcessor()85 QCamera3PostProcessor::~QCamera3PostProcessor()
86 {
87 pthread_mutex_destroy(&mReprocJobLock);
88 }
89
90 /*===========================================================================
91 * FUNCTION : init
92 *
93 * DESCRIPTION: initialization of postprocessor
94 *
95 * PARAMETERS :
96 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface
97 * @user_data : user data ptr for jpeg callback
98 *
99 * RETURN : int32_t type of status
100 * NO_ERROR -- success
101 * none-zero failure code
102 *==========================================================================*/
init(QCamera3Memory * mMemory,jpeg_encode_callback_t jpeg_cb,uint32_t postprocess_mask,void * user_data)103 int32_t QCamera3PostProcessor::init(QCamera3Memory* mMemory,
104 jpeg_encode_callback_t jpeg_cb,
105 uint32_t postprocess_mask,
106 void *user_data)
107 {
108 ATRACE_CALL();
109 mJpegCB = jpeg_cb;
110 mJpegUserData = user_data;
111 mm_dimension max_size;
112
113 //set max pic size
114 memset(&max_size, 0, sizeof(mm_dimension));
115 max_size.w = m_parent->m_max_pic_dim.width;
116 max_size.h = m_parent->m_max_pic_dim.height;
117
118 mJpegClientHandle = jpeg_open(&mJpegHandle,max_size);
119 mJpegMem = mMemory;
120 if(!mJpegClientHandle) {
121 ALOGE("%s : jpeg_open did not work", __func__);
122 return UNKNOWN_ERROR;
123 }
124 mPostProcMask = postprocess_mask;
125 m_dataProcTh.launch(dataProcessRoutine, this);
126
127 return NO_ERROR;
128 }
129
130 /*===========================================================================
131 * FUNCTION : deinit
132 *
133 * DESCRIPTION: de-initialization of postprocessor
134 *
135 * PARAMETERS : None
136 *
137 * RETURN : int32_t type of status
138 * NO_ERROR -- success
139 * none-zero failure code
140 *==========================================================================*/
deinit()141 int32_t QCamera3PostProcessor::deinit()
142 {
143 m_dataProcTh.exit();
144
145 if (m_pReprocChannel != NULL) {
146 m_pReprocChannel->stop();
147 delete m_pReprocChannel;
148 m_pReprocChannel = NULL;
149 }
150
151 if(mJpegClientHandle > 0) {
152 int rc = mJpegHandle.close(mJpegClientHandle);
153 CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
154 __func__, rc, mJpegClientHandle);
155 mJpegClientHandle = 0;
156 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
157 }
158
159 mJpegMem = NULL;
160
161 return NO_ERROR;
162 }
163
164 /*===========================================================================
165 * FUNCTION : start
166 *
167 * DESCRIPTION: start postprocessor. Data process thread and data notify thread
168 * will be launched.
169 *
170 * PARAMETERS :
171 * @pMemory : memory object representing buffers to store JPEG.
172 * @config : reprocess configuration
173 * @metadata : metadata for the reprocessing
174 *
175 * RETURN : int32_t type of status
176 * NO_ERROR -- success
177 * none-zero failure code
178 *
179 * NOTE : if any reprocess is needed, a reprocess channel/stream
180 * will be started.
181 *==========================================================================*/
start(const reprocess_config_t & config,metadata_buffer_t * metadata)182 int32_t QCamera3PostProcessor::start(const reprocess_config_t &config,
183 metadata_buffer_t *metadata)
184 {
185 int32_t rc = NO_ERROR;
186 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
187
188 if (hal_obj->needReprocess(mPostProcMask)) {
189 if (m_pReprocChannel != NULL) {
190 m_pReprocChannel->stop();
191 delete m_pReprocChannel;
192 m_pReprocChannel = NULL;
193 }
194
195 // if reprocess is needed, start reprocess channel
196 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
197 CDBG("%s: Setting input channel as pInputChannel", __func__);
198 m_pReprocChannel = hal_obj->addOfflineReprocChannel(config, m_parent, metadata);
199 if (m_pReprocChannel == NULL) {
200 ALOGE("%s: cannot add reprocess channel", __func__);
201 return UNKNOWN_ERROR;
202 }
203
204 rc = m_pReprocChannel->start();
205 if (rc != 0) {
206 ALOGE("%s: cannot start reprocess channel", __func__);
207 delete m_pReprocChannel;
208 m_pReprocChannel = NULL;
209 return rc;
210 }
211 }
212 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, FALSE, FALSE);
213
214 return rc;
215 }
216
217 /*===========================================================================
218 * FUNCTION : stop
219 *
220 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
221 *
222 * PARAMETERS : None
223 *
224 * RETURN : int32_t type of status
225 * NO_ERROR -- success
226 * none-zero failure code
227 *
228 * NOTE : reprocess channel will be stopped and deleted if there is any
229 *==========================================================================*/
stop()230 int32_t QCamera3PostProcessor::stop()
231 {
232 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
233
234 if (m_pReprocChannel != NULL) {
235 m_pReprocChannel->stop();
236 delete m_pReprocChannel;
237 m_pReprocChannel = NULL;
238 }
239
240 return NO_ERROR;
241 }
242
243 /*===========================================================================
244 * FUNCTION : getFWKJpegEncodeConfig
245 *
246 * DESCRIPTION: function to prepare encoding job information
247 *
248 * PARAMETERS :
249 * @encode_parm : param to be filled with encoding configuration
250 * @frame : framework input buffer
251 * @jpeg_settings : jpeg settings to be applied for encoding
252 *
253 * RETURN : int32_t type of status
254 * NO_ERROR -- success
255 * none-zero failure code
256 *==========================================================================*/
getFWKJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,qcamera_fwk_input_pp_data_t * frame,jpeg_settings_t * jpeg_settings)257 int32_t QCamera3PostProcessor::getFWKJpegEncodeConfig(
258 mm_jpeg_encode_params_t& encode_parm,
259 qcamera_fwk_input_pp_data_t *frame,
260 jpeg_settings_t *jpeg_settings)
261 {
262 CDBG("%s : E", __func__);
263 int32_t ret = NO_ERROR;
264
265 if ((NULL == frame) || (NULL == jpeg_settings)) {
266 return BAD_VALUE;
267 }
268
269 encode_parm.jpeg_cb = mJpegCB;
270 encode_parm.userdata = mJpegUserData;
271
272 if (jpeg_settings->thumbnail_size.width > 0 &&
273 jpeg_settings->thumbnail_size.height > 0)
274 m_bThumbnailNeeded = TRUE;
275 else
276 m_bThumbnailNeeded = FALSE;
277 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
278
279 // get color format
280 cam_format_t img_fmt = frame->reproc_config.stream_format;
281 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
282
283 // get jpeg quality
284 encode_parm.quality = jpeg_settings->jpeg_quality;
285 if (encode_parm.quality <= 0) {
286 encode_parm.quality = 85;
287 }
288
289 // get jpeg thumbnail quality
290 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
291
292 cam_frame_len_offset_t main_offset =
293 frame->reproc_config.input_stream_plane_info.plane_info;
294
295 encode_parm.num_src_bufs = 1;
296 encode_parm.src_main_buf[0].index = 0;
297 encode_parm.src_main_buf[0].buf_size = frame->input_buffer.frame_len;
298 encode_parm.src_main_buf[0].buf_vaddr = (uint8_t *) frame->input_buffer.buffer;
299 encode_parm.src_main_buf[0].fd = frame->input_buffer.fd;
300 encode_parm.src_main_buf[0].format = MM_JPEG_FMT_YUV;
301 encode_parm.src_main_buf[0].offset = main_offset;
302
303 //Pass input thumbnail buffer info to encoder.
304 //Note: Use main buffer to encode thumbnail
305 if (m_bThumbnailNeeded == TRUE) {
306 encode_parm.num_tmb_bufs = 1;
307 encode_parm.src_thumb_buf[0] = encode_parm.src_main_buf[0];
308 }
309
310 //Pass output jpeg buffer info to encoder.
311 //mJpegMem is allocated by framework.
312 encode_parm.num_dst_bufs = 1;
313 encode_parm.dest_buf[0].index = 0;
314 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
315 jpeg_settings->out_buf_index);
316 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
317 jpeg_settings->out_buf_index);
318 encode_parm.dest_buf[0].fd = mJpegMem->getFd(
319 jpeg_settings->out_buf_index);
320 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
321 encode_parm.dest_buf[0].offset = main_offset;
322
323 CDBG("%s : X", __func__);
324 return NO_ERROR;
325
326 on_error:
327 CDBG("%s : X with error %d", __func__, ret);
328 return ret;
329 }
330
331 /*===========================================================================
332 * FUNCTION : getJpegEncodeConfig
333 *
334 * DESCRIPTION: function to prepare encoding job information
335 *
336 * PARAMETERS :
337 * @encode_parm : param to be filled with encoding configuration
338 * #main_stream : stream object where the input buffer comes from
339 * @jpeg_settings : jpeg settings to be applied for encoding
340 *
341 * RETURN : int32_t type of status
342 * NO_ERROR -- success
343 * none-zero failure code
344 *==========================================================================*/
getJpegEncodeConfig(mm_jpeg_encode_params_t & encode_parm,QCamera3Stream * main_stream,jpeg_settings_t * jpeg_settings)345 int32_t QCamera3PostProcessor::getJpegEncodeConfig(
346 mm_jpeg_encode_params_t& encode_parm,
347 QCamera3Stream *main_stream,
348 jpeg_settings_t *jpeg_settings)
349 {
350 CDBG("%s : E", __func__);
351 int32_t ret = NO_ERROR;
352
353 encode_parm.jpeg_cb = mJpegCB;
354 encode_parm.userdata = mJpegUserData;
355
356 if (jpeg_settings->thumbnail_size.width > 0 &&
357 jpeg_settings->thumbnail_size.height > 0)
358 m_bThumbnailNeeded = TRUE;
359 else
360 m_bThumbnailNeeded = FALSE;
361 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
362
363 // get color format
364 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12; //default value
365 main_stream->getFormat(img_fmt);
366 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
367
368 //get rotation
369 encode_parm.jpeg_orientation = jpeg_settings->jpeg_orientation;
370
371 // get jpeg quality
372 encode_parm.quality = jpeg_settings->jpeg_quality;
373 if (encode_parm.quality <= 0) {
374 encode_parm.quality = 85;
375 }
376
377 // get jpeg thumbnail quality
378 encode_parm.thumb_quality = jpeg_settings->jpeg_thumb_quality;
379
380 cam_frame_len_offset_t main_offset;
381 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
382 main_stream->getFrameOffset(main_offset);
383
384 // src buf config
385 //Pass input main image buffer info to encoder.
386 QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
387 if (pStreamMem == NULL) {
388 ALOGE("%s: cannot get stream bufs from main stream", __func__);
389 ret = BAD_VALUE;
390 goto on_error;
391 }
392 encode_parm.num_src_bufs = pStreamMem->getCnt();
393 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
394 if (pStreamMem != NULL) {
395 encode_parm.src_main_buf[i].index = i;
396 encode_parm.src_main_buf[i].buf_size = pStreamMem->getSize(i);
397 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
398 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
399 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
400 encode_parm.src_main_buf[i].offset = main_offset;
401 }
402 }
403
404 //Pass input thumbnail buffer info to encoder.
405 //Note: Use main buffer to encode thumbnail
406 if (m_bThumbnailNeeded == TRUE) {
407 pStreamMem = main_stream->getStreamBufs();
408 if (pStreamMem == NULL) {
409 ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
410 ret = BAD_VALUE;
411 goto on_error;
412 }
413 cam_frame_len_offset_t thumb_offset;
414 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
415 main_stream->getFrameOffset(thumb_offset);
416 encode_parm.num_tmb_bufs = pStreamMem->getCnt();
417 for (int i = 0; i < pStreamMem->getCnt(); i++) {
418 if (pStreamMem != NULL) {
419 encode_parm.src_thumb_buf[i].index = i;
420 encode_parm.src_thumb_buf[i].buf_size = pStreamMem->getSize(i);
421 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)pStreamMem->getPtr(i);
422 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
423 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
424 encode_parm.src_thumb_buf[i].offset = thumb_offset;
425 }
426 }
427 }
428
429 //Pass output jpeg buffer info to encoder.
430 //mJpegMem is allocated by framework.
431 encode_parm.num_dst_bufs = 1;
432 encode_parm.dest_buf[0].index = 0;
433 encode_parm.dest_buf[0].buf_size = mJpegMem->getSize(
434 jpeg_settings->out_buf_index);
435 encode_parm.dest_buf[0].buf_vaddr = (uint8_t *)mJpegMem->getPtr(
436 jpeg_settings->out_buf_index);
437 encode_parm.dest_buf[0].fd = mJpegMem->getFd(
438 jpeg_settings->out_buf_index);
439 encode_parm.dest_buf[0].format = MM_JPEG_FMT_YUV;
440 encode_parm.dest_buf[0].offset = main_offset;
441
442 CDBG("%s : X", __func__);
443 return NO_ERROR;
444
445 on_error:
446 CDBG("%s : X with error %d", __func__, ret);
447 return ret;
448 }
449
450 /*===========================================================================
451 * FUNCTION : processData
452 *
453 * DESCRIPTION: enqueue data into dataProc thread
454 *
455 * PARAMETERS :
456 * @frame : process frame
457 *
458 * RETURN : int32_t type of status
459 * NO_ERROR -- success
460 * none-zero failure code
461 *
462 * NOTE : depends on if offline reprocess is needed, received frame will
463 * be sent to either input queue of postprocess or jpeg encoding
464 *==========================================================================*/
processData(mm_camera_super_buf_t * frame)465 int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
466 {
467 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
468 pthread_mutex_lock(&mReprocJobLock);
469 // enqueue to post proc input queue
470 m_inputPPQ.enqueue((void *)frame);
471 if (!(m_inputMetaQ.isEmpty())) {
472 CDBG("%s: meta queue is not empty, do next job", __func__);
473 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
474 }
475 pthread_mutex_unlock(&mReprocJobLock);
476
477 return NO_ERROR;
478 }
479
480 /*===========================================================================
481 * FUNCTION : processData
482 *
483 * DESCRIPTION: enqueue data into dataProc thread
484 *
485 * PARAMETERS :
486 * @frame : process frame
487 *
488 * RETURN : int32_t type of status
489 * NO_ERROR -- success
490 * none-zero failure code
491 *
492 * NOTE : depends on if offline reprocess is needed, received frame will
493 * be sent to either input queue of postprocess or jpeg encoding
494 *==========================================================================*/
processData(qcamera_fwk_input_pp_data_t * frame)495 int32_t QCamera3PostProcessor::processData(qcamera_fwk_input_pp_data_t *frame)
496 {
497 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
498 if (hal_obj->needReprocess(mPostProcMask)) {
499 pthread_mutex_lock(&mReprocJobLock);
500 // enqueu to post proc input queue
501 m_inputFWKPPQ.enqueue((void *)frame);
502 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
503 pthread_mutex_unlock(&mReprocJobLock);
504 } else {
505 jpeg_settings_t *jpeg_settings = (jpeg_settings_t *)m_jpegSettingsQ.dequeue();
506
507 if (jpeg_settings == NULL) {
508 ALOGE("%s: Cannot find jpeg settings", __func__);
509 return BAD_VALUE;
510 }
511
512 CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
513 qcamera_hal3_jpeg_data_t *jpeg_job =
514 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
515 if (jpeg_job == NULL) {
516 ALOGE("%s: No memory for jpeg job", __func__);
517 return NO_MEMORY;
518 }
519
520 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
521 jpeg_job->fwk_frame = frame;
522 jpeg_job->jpeg_settings = jpeg_settings;
523 jpeg_job->metadata =
524 (metadata_buffer_t *) frame->metadata_buffer.buffer;
525
526 // enqueu to jpeg input queue
527 m_inputJpegQ.enqueue((void *)jpeg_job);
528 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
529 }
530
531 return NO_ERROR;
532 }
533
534 /*===========================================================================
535 * FUNCTION : processPPMetadata
536 *
537 * DESCRIPTION: enqueue data into dataProc thread
538 *
539 * PARAMETERS :
540 * @frame : process metadata frame received from pic channel
541 *
542 * RETURN : int32_t type of status
543 * NO_ERROR -- success
544 * none-zero failure code
545 *
546 *==========================================================================*/
processPPMetadata(mm_camera_super_buf_t * reproc_meta)547 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
548 {
549 pthread_mutex_lock(&mReprocJobLock);
550 // enqueue to metadata input queue
551 m_inputMetaQ.enqueue((void *)reproc_meta);
552 if (!(m_inputPPQ.isEmpty())) {
553 CDBG("%s: pp queue is not empty, do next job", __func__);
554 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
555 } else {
556 CDBG("%s: pp queue is empty, not calling do next job", __func__);
557 }
558 pthread_mutex_unlock(&mReprocJobLock);
559 return NO_ERROR;
560 }
561
562 /*===========================================================================
563 * FUNCTION : processJpegSettingData
564 *
565 * DESCRIPTION: enqueue jpegSetting into dataProc thread
566 *
567 * PARAMETERS :
568 * @jpeg_settings : jpeg settings data received from pic channel
569 *
570 * RETURN : int32_t type of status
571 * NO_ERROR -- success
572 * none-zero failure code
573 *
574 *==========================================================================*/
processJpegSettingData(jpeg_settings_t * jpeg_settings)575 int32_t QCamera3PostProcessor::processJpegSettingData(
576 jpeg_settings_t *jpeg_settings)
577 {
578 if (!jpeg_settings) {
579 ALOGE("%s: invalid jpeg settings pointer", __func__);
580 return -EINVAL;
581 }
582 return m_jpegSettingsQ.enqueue((void *)jpeg_settings);
583 }
584
585 /*===========================================================================
586 * FUNCTION : processRawData
587 *
588 * DESCRIPTION: enqueue raw data into dataProc thread
589 *
590 * PARAMETERS :
591 * @frame : process frame received from mm-camera-interface
592 *
593 * RETURN : int32_t type of status
594 * NO_ERROR -- success
595 * none-zero failure code
596 *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)597 int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
598 {
599 // enqueu to raw input queue
600 m_inputRawQ.enqueue((void *)frame);
601 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
602 return NO_ERROR;
603 }
604
605 /*===========================================================================
606 * FUNCTION : processPPData
607 *
608 * DESCRIPTION: process received frame after reprocess.
609 *
610 * PARAMETERS :
611 * @frame : received frame from reprocess channel.
612 *
613 * RETURN : int32_t type of status
614 * NO_ERROR -- success
615 * none-zero failure code
616 *
617 * NOTE : The frame after reprocess need to send to jpeg encoding.
618 *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)619 int32_t QCamera3PostProcessor::processPPData(mm_camera_super_buf_t *frame)
620 {
621 qcamera_hal3_pp_data_t *job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
622
623 if (job == NULL || ((NULL == job->src_frame) && (NULL == job->fwk_src_frame))) {
624 ALOGE("%s: Cannot find reprocess job", __func__);
625 return BAD_VALUE;
626 }
627 if (job->jpeg_settings == NULL) {
628 ALOGE("%s: Cannot find jpeg settings", __func__);
629 return BAD_VALUE;
630 }
631
632 qcamera_hal3_jpeg_data_t *jpeg_job =
633 (qcamera_hal3_jpeg_data_t *)malloc(sizeof(qcamera_hal3_jpeg_data_t));
634 if (jpeg_job == NULL) {
635 ALOGE("%s: No memory for jpeg job", __func__);
636 return NO_MEMORY;
637 }
638
639 memset(jpeg_job, 0, sizeof(qcamera_hal3_jpeg_data_t));
640 jpeg_job->src_frame = frame;
641 if(frame != job->src_frame)
642 jpeg_job->src_reproc_frame = job->src_frame;
643 if (NULL == job->fwk_src_frame) {
644 jpeg_job->metadata = job->metadata;
645 } else {
646 jpeg_job->metadata =
647 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
648 jpeg_job->fwk_src_buffer = job->fwk_src_frame;
649 }
650 jpeg_job->src_metadata = job->src_metadata;
651 jpeg_job->jpeg_settings = job->jpeg_settings;
652
653 // free pp job buf
654 free(job);
655
656 // enqueu reprocessed frame to jpeg input queue
657 m_inputJpegQ.enqueue((void *)jpeg_job);
658
659 // wait up data proc thread
660 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
661
662 return NO_ERROR;
663 }
664
665 /*===========================================================================
666 * FUNCTION : findJpegJobByJobId
667 *
668 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
669 *
670 * PARAMETERS :
671 * @jobId : job Id of the job
672 *
673 * RETURN : ptr to a jpeg job struct. NULL if not found.
674 *
675 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg
676 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue
677 * will serve the purpose to find the jpeg job.
678 *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)679 qcamera_hal3_jpeg_data_t *QCamera3PostProcessor::findJpegJobByJobId(uint32_t jobId)
680 {
681 qcamera_hal3_jpeg_data_t * job = NULL;
682 if (jobId == 0) {
683 ALOGE("%s: not a valid jpeg jobId", __func__);
684 return NULL;
685 }
686
687 // currely only one jpeg job ongoing, so simply dequeue the head
688 job = (qcamera_hal3_jpeg_data_t *)m_ongoingJpegQ.dequeue();
689 return job;
690 }
691
692 /*===========================================================================
693 * FUNCTION : releasePPInputData
694 *
695 * DESCRIPTION: callback function to release post process input data node
696 *
697 * PARAMETERS :
698 * @data : ptr to post process input data
699 * @user_data : user data ptr (QCamera3Reprocessor)
700 *
701 * RETURN : None
702 *==========================================================================*/
releasePPInputData(void * data,void * user_data)703 void QCamera3PostProcessor::releasePPInputData(void *data, void *user_data)
704 {
705 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
706 if (NULL != pme) {
707 pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
708 }
709 }
710
711 /*===========================================================================
712 * FUNCTION : releaseMetaData
713 *
714 * DESCRIPTION: callback function to release metadata camera buffer
715 *
716 * PARAMETERS :
717 * @data : ptr to post process input data
718 * @user_data : user data ptr (QCamera3Reprocessor)
719 *
720 * RETURN : None
721 *==========================================================================*/
releaseMetadata(void * data,void * user_data)722 void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
723 {
724 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
725 if (NULL != pme) {
726 pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
727 }
728 }
729
730 /*===========================================================================
731 * FUNCTION : releaseJpegData
732 *
733 * DESCRIPTION: callback function to release jpeg job node
734 *
735 * PARAMETERS :
736 * @data : ptr to ongoing jpeg job data
737 * @user_data : user data ptr (QCamera3Reprocessor)
738 *
739 * RETURN : None
740 *==========================================================================*/
releaseJpegData(void * data,void * user_data)741 void QCamera3PostProcessor::releaseJpegData(void *data, void *user_data)
742 {
743 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
744 if (NULL != pme) {
745 pme->releaseJpegJobData((qcamera_hal3_jpeg_data_t *)data);
746 }
747 }
748
749 /*===========================================================================
750 * FUNCTION : releaseOngoingPPData
751 *
752 * DESCRIPTION: callback function to release ongoing postprocess job node
753 *
754 * PARAMETERS :
755 * @data : ptr to onging postprocess job
756 * @user_data : user data ptr (QCamera3Reprocessor)
757 *
758 * RETURN : None
759 *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)760 void QCamera3PostProcessor::releaseOngoingPPData(void *data, void *user_data)
761 {
762 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
763 if (NULL != pme) {
764 qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
765 if (NULL != pp_job->src_frame) {
766 pme->releaseSuperBuf(pp_job->src_frame);
767 free(pp_job->src_frame);
768 if (NULL != pp_job->src_metadata) {
769 pme->m_parent->metadataBufDone(pp_job->src_metadata);
770 free(pp_job->src_metadata);
771 }
772 pp_job->src_frame = NULL;
773 pp_job->metadata = NULL;
774 }
775
776 if (NULL != pp_job->fwk_src_frame) {
777 free(pp_job->fwk_src_frame);
778 pp_job->fwk_src_frame = NULL;
779 }
780 }
781 }
782
783 /*===========================================================================
784 * FUNCTION : releaseSuperBuf
785 *
786 * DESCRIPTION: function to release a superbuf frame by returning back to kernel
787 *
788 * PARAMETERS :
789 * @super_buf : ptr to the superbuf frame
790 *
791 * RETURN : None
792 *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)793 void QCamera3PostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
794 {
795 if (NULL != super_buf) {
796 if (m_parent != NULL) {
797 m_parent->bufDone(super_buf);
798 }
799 }
800 }
801
802 /*===========================================================================
803 * FUNCTION : releaseOfflineBuffers
804 *
805 * DESCRIPTION: function to release/unmap offline buffers if any
806 *
807 * PARAMETERS : None
808 *
809 * RETURN : int32_t type of status
810 * NO_ERROR -- success
811 * none-zero failure code
812 *==========================================================================*/
releaseOfflineBuffers()813 int32_t QCamera3PostProcessor::releaseOfflineBuffers()
814 {
815 int32_t rc = NO_ERROR;
816
817 if(NULL != m_pReprocChannel) {
818 rc = m_pReprocChannel->unmapOfflineBuffers(false);
819 }
820
821 return rc;
822 }
823
824 /*===========================================================================
825 * FUNCTION : releaseJpegJobData
826 *
827 * DESCRIPTION: function to release internal resources in jpeg job struct
828 *
829 * PARAMETERS :
830 * @job : ptr to jpeg job struct
831 *
832 * RETURN : None
833 *
834 * NOTE : original source frame need to be queued back to kernel for
835 * future use. Output buf of jpeg job need to be released since
836 * it's allocated for each job. Exif object need to be deleted.
837 *==========================================================================*/
releaseJpegJobData(qcamera_hal3_jpeg_data_t * job)838 void QCamera3PostProcessor::releaseJpegJobData(qcamera_hal3_jpeg_data_t *job)
839 {
840 ATRACE_CALL();
841 int32_t rc = NO_ERROR;
842 CDBG("%s: E", __func__);
843 if (NULL != job) {
844 if (NULL != job->src_reproc_frame) {
845 free(job->src_reproc_frame);
846 job->src_reproc_frame = NULL;
847 }
848
849 if (NULL != job->src_frame) {
850 if (NULL != m_pReprocChannel) {
851 rc = m_pReprocChannel->bufDone(job->src_frame);
852 if (NO_ERROR != rc)
853 ALOGE("%s: bufDone error: %d", __func__, rc);
854 }
855 free(job->src_frame);
856 job->src_frame = NULL;
857 }
858
859 if (NULL != job->fwk_src_buffer) {
860 free(job->fwk_src_buffer);
861 job->fwk_src_buffer = NULL;
862 } else if (NULL != job->src_metadata) {
863 m_parent->metadataBufDone(job->src_metadata);
864 free(job->src_metadata);
865 job->src_metadata = NULL;
866 }
867
868 if (NULL != job->fwk_frame) {
869 free(job->fwk_frame);
870 job->fwk_frame = NULL;
871 }
872
873 if (NULL != job->pJpegExifObj) {
874 delete job->pJpegExifObj;
875 job->pJpegExifObj = NULL;
876 }
877
878 if (NULL != job->jpeg_settings) {
879 free(job->jpeg_settings);
880 job->jpeg_settings = NULL;
881 }
882 }
883 /* Additional trigger to process any pending jobs in the input queue */
884 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
885 CDBG("%s: X", __func__);
886 }
887
888 /*===========================================================================
889 * FUNCTION : getColorfmtFromImgFmt
890 *
891 * DESCRIPTION: function to return jpeg color format based on its image format
892 *
893 * PARAMETERS :
894 * @img_fmt : image format
895 *
896 * RETURN : jpeg color format that can be understandable by omx lib
897 *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)898 mm_jpeg_color_format QCamera3PostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
899 {
900 switch (img_fmt) {
901 case CAM_FORMAT_YUV_420_NV21:
902 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
903 case CAM_FORMAT_YUV_420_NV21_ADRENO:
904 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
905 case CAM_FORMAT_YUV_420_NV12:
906 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
907 case CAM_FORMAT_YUV_420_YV12:
908 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
909 case CAM_FORMAT_YUV_422_NV61:
910 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
911 case CAM_FORMAT_YUV_422_NV16:
912 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
913 default:
914 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
915 }
916 }
917
918 /*===========================================================================
919 * FUNCTION : getJpegImgTypeFromImgFmt
920 *
921 * DESCRIPTION: function to return jpeg encode image type based on its image format
922 *
923 * PARAMETERS :
924 * @img_fmt : image format
925 *
926 * RETURN : return jpeg source image format (YUV or Bitstream)
927 *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)928 mm_jpeg_format_t QCamera3PostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
929 {
930 switch (img_fmt) {
931 case CAM_FORMAT_YUV_420_NV21:
932 case CAM_FORMAT_YUV_420_NV21_ADRENO:
933 case CAM_FORMAT_YUV_420_NV12:
934 case CAM_FORMAT_YUV_420_YV12:
935 case CAM_FORMAT_YUV_422_NV61:
936 case CAM_FORMAT_YUV_422_NV16:
937 return MM_JPEG_FMT_YUV;
938 default:
939 return MM_JPEG_FMT_YUV;
940 }
941 }
942
943 /*===========================================================================
944 * FUNCTION : encodeFWKData
945 *
946 * DESCRIPTION: function to prepare encoding job information and send to
947 * mm-jpeg-interface to do the encoding job
948 *
949 * PARAMETERS :
950 * @jpeg_job_data : ptr to a struct saving job related information
951 * @needNewSess : flag to indicate if a new jpeg encoding session need
952 * to be created. After creation, this flag will be toggled
953 *
954 * RETURN : int32_t type of status
955 * NO_ERROR -- success
956 * none-zero failure code
957 *==========================================================================*/
encodeFWKData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)958 int32_t QCamera3PostProcessor::encodeFWKData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
959 uint8_t &needNewSess)
960 {
961 CDBG("%s : E", __func__);
962 int32_t ret = NO_ERROR;
963 mm_jpeg_job_t jpg_job;
964 uint32_t jobId = 0;
965 qcamera_fwk_input_pp_data_t *recvd_frame = NULL;
966 metadata_buffer_t *metadata = NULL;
967 jpeg_settings_t *jpeg_settings = NULL;
968 QCamera3HardwareInterface* hal_obj = NULL;
969
970 if (NULL == jpeg_job_data) {
971 ALOGE("%s: Invalid jpeg job", __func__);
972 return BAD_VALUE;
973 }
974
975 recvd_frame = jpeg_job_data->fwk_frame;
976 if (NULL == recvd_frame) {
977 ALOGE("%s: Invalid input buffer", __func__);
978 return BAD_VALUE;
979 }
980
981 metadata = jpeg_job_data->metadata;
982 if (NULL == metadata) {
983 ALOGE("%s: Invalid metadata buffer", __func__);
984 return BAD_VALUE;
985 }
986
987 jpeg_settings = jpeg_job_data->jpeg_settings;
988 if (NULL == jpeg_settings) {
989 ALOGE("%s: Invalid jpeg settings buffer", __func__);
990 return BAD_VALUE;
991 }
992
993 if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
994 ALOGE("%s: Unsupported case both framework and camera source buffers are invalid!",
995 __func__);
996 return BAD_VALUE;
997 }
998
999 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1000
1001 if (mJpegClientHandle <= 0) {
1002 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1003 return UNKNOWN_ERROR;
1004 }
1005
1006 cam_dimension_t src_dim;
1007 memset(&src_dim, 0, sizeof(cam_dimension_t));
1008 src_dim.width = recvd_frame->reproc_config.input_stream_dim.width;
1009 src_dim.height = recvd_frame->reproc_config.input_stream_dim.height;
1010
1011 cam_dimension_t dst_dim;
1012 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1013 dst_dim.width = recvd_frame->reproc_config.output_stream_dim.width;
1014 dst_dim.height = recvd_frame->reproc_config.output_stream_dim.height;
1015
1016 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1017 if (needNewSess) {
1018 //creating a new session, so we must destroy the old one
1019 if ( 0 < mJpegSessionId ) {
1020 ret = mJpegHandle.destroy_session(mJpegSessionId);
1021 if (ret != NO_ERROR) {
1022 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1023 __func__, mJpegSessionId);
1024 return ret;
1025 }
1026 mJpegSessionId = 0;
1027 }
1028 // create jpeg encoding session
1029 mm_jpeg_encode_params_t encodeParam;
1030 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1031 encodeParam.main_dim.src_dim = src_dim;
1032 encodeParam.main_dim.dst_dim = dst_dim;
1033 encodeParam.thumb_dim.src_dim = src_dim;
1034 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1035
1036 getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
1037 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1038 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1039
1040 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1041 if (ret != NO_ERROR) {
1042 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1043 return ret;
1044 }
1045 needNewSess = FALSE;
1046 }
1047
1048 // Fill in new job
1049 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1050 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1051 jpg_job.encode_job.session_id = mJpegSessionId;
1052 jpg_job.encode_job.src_index = 0;
1053 jpg_job.encode_job.dst_index = 0;
1054
1055 cam_rect_t crop;
1056 memset(&crop, 0, sizeof(cam_rect_t));
1057 //TBD_later - Zoom event removed in stream
1058 //main_stream->getCropInfo(crop);
1059
1060 // main dim
1061 jpg_job.encode_job.main_dim.src_dim = src_dim;
1062 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1063 jpg_job.encode_job.main_dim.crop = crop;
1064
1065 // get exif data
1066 QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
1067 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1068 if (pJpegExifObj != NULL) {
1069 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1070 jpg_job.encode_job.exif_info.numOfEntries =
1071 pJpegExifObj->getNumOfEntries();
1072 }
1073
1074 // thumbnail dim
1075 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1076 if (m_bThumbnailNeeded == TRUE) {
1077 memset(&crop, 0, sizeof(cam_rect_t));
1078 jpg_job.encode_job.thumb_dim.dst_dim =
1079 jpeg_settings->thumbnail_size;
1080
1081 if (!hal_obj->needRotationReprocess()) {
1082 jpg_job.encode_job.rotation =
1083 jpeg_settings->jpeg_orientation;
1084 CDBG_HIGH("%s: jpeg rotation is set to %d", __func__,
1085 jpg_job.encode_job.rotation);
1086 } else if (jpeg_settings->jpeg_orientation == 90 ||
1087 jpeg_settings->jpeg_orientation == 270) {
1088 //swap the thumbnail destination width and height if it has
1089 //already been rotated
1090 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1091 jpg_job.encode_job.thumb_dim.dst_dim.width =
1092 jpg_job.encode_job.thumb_dim.dst_dim.height;
1093 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1094 }
1095 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1096 jpg_job.encode_job.thumb_dim.crop = crop;
1097 jpg_job.encode_job.thumb_index = 0;
1098 }
1099
1100 if (metadata != NULL) {
1101 //Fill in the metadata passed as parameter
1102 jpg_job.encode_job.p_metadata = metadata;
1103 } else {
1104 ALOGE("%s: Metadata is null", __func__);
1105 }
1106
1107 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1108
1109 //Start jpeg encoding
1110 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1111 if (ret == NO_ERROR) {
1112 // remember job info
1113 jpeg_job_data->jobId = jobId;
1114 }
1115
1116 CDBG("%s : X", __func__);
1117 return ret;
1118 }
1119
1120 /*===========================================================================
1121 * FUNCTION : encodeData
1122 *
1123 * DESCRIPTION: function to prepare encoding job information and send to
1124 * mm-jpeg-interface to do the encoding job
1125 *
1126 * PARAMETERS :
1127 * @jpeg_job_data : ptr to a struct saving job related information
1128 * @needNewSess : flag to indicate if a new jpeg encoding session need
1129 * to be created. After creation, this flag will be toggled
1130 *
1131 * RETURN : int32_t type of status
1132 * NO_ERROR -- success
1133 * none-zero failure code
1134 *==========================================================================*/
encodeData(qcamera_hal3_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1135 int32_t QCamera3PostProcessor::encodeData(qcamera_hal3_jpeg_data_t *jpeg_job_data,
1136 uint8_t &needNewSess)
1137 {
1138 ATRACE_CALL();
1139 CDBG("%s : E", __func__);
1140 int32_t ret = NO_ERROR;
1141 mm_jpeg_job_t jpg_job;
1142 uint32_t jobId = 0;
1143 QCamera3Stream *main_stream = NULL;
1144 mm_camera_buf_def_t *main_frame = NULL;
1145 QCamera3Channel *srcChannel = NULL;
1146 mm_camera_super_buf_t *recvd_frame = NULL;
1147 metadata_buffer_t *metadata = NULL;
1148 jpeg_settings_t *jpeg_settings = NULL;
1149 QCamera3HardwareInterface* hal_obj = NULL;
1150 bool needJpegRotation = false;
1151
1152 hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
1153 recvd_frame = jpeg_job_data->src_frame;
1154 metadata = jpeg_job_data->metadata;
1155 jpeg_settings = jpeg_job_data->jpeg_settings;
1156
1157 CDBG("%s: encoding bufIndex: %u", __func__,
1158 jpeg_job_data->src_frame->bufs[0]->buf_idx);
1159
1160 QCamera3Channel *pChannel = NULL;
1161 // first check picture channel
1162 if (m_parent != NULL &&
1163 m_parent->getMyHandle() == recvd_frame->ch_id) {
1164 pChannel = m_parent;
1165 }
1166 // check reprocess channel if not found
1167 if (pChannel == NULL) {
1168 if (m_pReprocChannel != NULL &&
1169 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1170 pChannel = m_pReprocChannel;
1171 }
1172 }
1173
1174 srcChannel = pChannel;
1175
1176 if (srcChannel == NULL) {
1177 ALOGE("%s: No corresponding channel (ch_id = %d) exist, return here",
1178 __func__, recvd_frame->ch_id);
1179 return BAD_VALUE;
1180 }
1181
1182 // find snapshot frame and thumnail frame
1183 //Note: In this version we will receive only snapshot frame.
1184 for (int i = 0; i < recvd_frame->num_bufs; i++) {
1185 QCamera3Stream *srcStream =
1186 srcChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1187 if (srcStream != NULL) {
1188 switch (srcStream->getMyType()) {
1189 case CAM_STREAM_TYPE_SNAPSHOT:
1190 case CAM_STREAM_TYPE_OFFLINE_PROC:
1191 main_stream = srcStream;
1192 main_frame = recvd_frame->bufs[i];
1193 break;
1194 default:
1195 break;
1196 }
1197 }
1198 }
1199
1200 if(NULL == main_frame){
1201 ALOGE("%s : Main frame is NULL", __func__);
1202 return BAD_VALUE;
1203 }
1204
1205 QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
1206 if (NULL == memObj) {
1207 ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
1208 return NO_MEMORY;
1209 }
1210
1211 // clean and invalidate cache ops through mem obj of the frame
1212 memObj->cleanInvalidateCache(main_frame->buf_idx);
1213
1214 if (mJpegClientHandle <= 0) {
1215 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1216 return UNKNOWN_ERROR;
1217 }
1218 cam_dimension_t src_dim;
1219 memset(&src_dim, 0, sizeof(cam_dimension_t));
1220 main_stream->getFrameDimension(src_dim);
1221
1222 cam_dimension_t dst_dim;
1223 memset(&dst_dim, 0, sizeof(cam_dimension_t));
1224 srcChannel->getStreamByIndex(0)->getFrameDimension(dst_dim);
1225
1226 needJpegRotation = hal_obj->needJpegRotation();
1227 CDBG_HIGH("%s: Need new session?:%d",__func__, needNewSess);
1228 if (needNewSess) {
1229 //creating a new session, so we must destroy the old one
1230 if ( 0 < mJpegSessionId ) {
1231 ret = mJpegHandle.destroy_session(mJpegSessionId);
1232 if (ret != NO_ERROR) {
1233 ALOGE("%s: Error destroying an old jpeg encoding session, id = %d",
1234 __func__, mJpegSessionId);
1235 return ret;
1236 }
1237 mJpegSessionId = 0;
1238 }
1239 // create jpeg encoding session
1240 mm_jpeg_encode_params_t encodeParam;
1241 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1242 getJpegEncodeConfig(encodeParam, main_stream, jpeg_settings);
1243 CDBG_HIGH("%s: #src bufs:%d # tmb bufs:%d #dst_bufs:%d", __func__,
1244 encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
1245 if (!needJpegRotation &&
1246 (jpeg_settings->jpeg_orientation == 90 ||
1247 jpeg_settings->jpeg_orientation == 270)) {
1248 //swap src width and height, stride and scanline due to rotation
1249 encodeParam.main_dim.src_dim.width = src_dim.height;
1250 encodeParam.main_dim.src_dim.height = src_dim.width;
1251 encodeParam.thumb_dim.src_dim.width = src_dim.height;
1252 encodeParam.thumb_dim.src_dim.height = src_dim.width;
1253
1254 int32_t temp = encodeParam.src_main_buf[0].offset.mp[0].stride;
1255 encodeParam.src_main_buf[0].offset.mp[0].stride =
1256 encodeParam.src_main_buf[0].offset.mp[0].scanline;
1257 encodeParam.src_main_buf[0].offset.mp[0].scanline = temp;
1258
1259 temp = encodeParam.src_thumb_buf[0].offset.mp[0].stride;
1260 encodeParam.src_thumb_buf[0].offset.mp[0].stride =
1261 encodeParam.src_thumb_buf[0].offset.mp[0].scanline;
1262 encodeParam.src_thumb_buf[0].offset.mp[0].scanline = temp;
1263 } else {
1264 encodeParam.main_dim.src_dim = src_dim;
1265 encodeParam.thumb_dim.src_dim = src_dim;
1266 }
1267 encodeParam.main_dim.dst_dim = dst_dim;
1268 encodeParam.thumb_dim.dst_dim = jpeg_settings->thumbnail_size;
1269 if (needJpegRotation) {
1270 encodeParam.rotation = jpeg_settings->jpeg_orientation;
1271 }
1272
1273
1274 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1275 if (ret != NO_ERROR) {
1276 ALOGE("%s: Error creating a new jpeg encoding session, ret = %d", __func__, ret);
1277 return ret;
1278 }
1279 needNewSess = FALSE;
1280 }
1281
1282 // Fill in new job
1283 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1284 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1285 jpg_job.encode_job.session_id = mJpegSessionId;
1286 jpg_job.encode_job.src_index = main_frame->buf_idx;
1287 jpg_job.encode_job.dst_index = 0;
1288
1289 if (needJpegRotation) {
1290 jpg_job.encode_job.rotation =
1291 jpeg_settings->jpeg_orientation;
1292 CDBG("%s: %d: jpeg rotation is set to %d", __func__, __LINE__,
1293 jpg_job.encode_job.rotation);
1294 }
1295
1296 cam_rect_t crop;
1297 memset(&crop, 0, sizeof(cam_rect_t));
1298 //TBD_later - Zoom event removed in stream
1299 //main_stream->getCropInfo(crop);
1300
1301 // main dim
1302 jpg_job.encode_job.main_dim.src_dim = src_dim;
1303 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1304 jpg_job.encode_job.main_dim.crop = crop;
1305
1306 // get exif data
1307 QCamera3Exif *pJpegExifObj = m_parent->getExifData(metadata, jpeg_settings);
1308 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1309 if (pJpegExifObj != NULL) {
1310 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1311 jpg_job.encode_job.exif_info.numOfEntries =
1312 pJpegExifObj->getNumOfEntries();
1313 }
1314
1315 // thumbnail dim
1316 CDBG_HIGH("%s: Thumbnail needed:%d",__func__, m_bThumbnailNeeded);
1317 if (m_bThumbnailNeeded == TRUE) {
1318 memset(&crop, 0, sizeof(cam_rect_t));
1319 jpg_job.encode_job.thumb_dim.dst_dim =
1320 jpeg_settings->thumbnail_size;
1321
1322 if (!needJpegRotation &&
1323 (jpeg_settings->jpeg_orientation == 90 ||
1324 jpeg_settings->jpeg_orientation == 270)) {
1325 //swap the thumbnail destination width and height if it has
1326 //already been rotated
1327 int temp = jpg_job.encode_job.thumb_dim.dst_dim.width;
1328 jpg_job.encode_job.thumb_dim.dst_dim.width =
1329 jpg_job.encode_job.thumb_dim.dst_dim.height;
1330 jpg_job.encode_job.thumb_dim.dst_dim.height = temp;
1331
1332 jpg_job.encode_job.thumb_dim.src_dim.width = src_dim.height;
1333 jpg_job.encode_job.thumb_dim.src_dim.height = src_dim.width;
1334 } else {
1335 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1336 }
1337 jpg_job.encode_job.thumb_dim.crop = crop;
1338 jpg_job.encode_job.thumb_index = main_frame->buf_idx;
1339 }
1340
1341 if (metadata != NULL) {
1342 //Fill in the metadata passed as parameter
1343 jpg_job.encode_job.p_metadata = metadata;
1344 } else {
1345 ALOGE("%s: Metadata is null", __func__);
1346 }
1347
1348 jpg_job.encode_job.hal_version = CAM_HAL_V3;
1349
1350 //Start jpeg encoding
1351 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1352 if (ret == NO_ERROR) {
1353 // remember job info
1354 jpeg_job_data->jobId = jobId;
1355 }
1356
1357 CDBG("%s : X", __func__);
1358 return ret;
1359 }
1360
1361 /*===========================================================================
1362 * FUNCTION : dataProcessRoutine
1363 *
1364 * DESCRIPTION: data process routine that handles input data either from input
1365 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
1366 * reprocess.
1367 *
1368 * PARAMETERS :
1369 * @data : user data ptr (QCamera3PostProcessor)
1370 *
1371 * RETURN : None
1372 *==========================================================================*/
dataProcessRoutine(void * data)1373 void *QCamera3PostProcessor::dataProcessRoutine(void *data)
1374 {
1375 int running = 1;
1376 int ret;
1377 uint8_t is_active = FALSE;
1378 uint8_t needNewSess = TRUE;
1379 mm_camera_super_buf_t *meta_buffer = NULL;
1380 CDBG("%s: E", __func__);
1381 QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
1382 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
1383 cmdThread->setName("cam_data_proc");
1384
1385 do {
1386 do {
1387 ret = cam_sem_wait(&cmdThread->cmd_sem);
1388 if (ret != 0 && errno != EINVAL) {
1389 ALOGE("%s: cam_sem_wait error (%s)",
1390 __func__, strerror(errno));
1391 return NULL;
1392 }
1393 } while (ret != 0);
1394
1395 // we got notified about new cmd avail in cmd queue
1396 camera_cmd_type_t cmd = cmdThread->getCmd();
1397 switch (cmd) {
1398 case CAMERA_CMD_TYPE_START_DATA_PROC:
1399 CDBG_HIGH("%s: start data proc", __func__);
1400 is_active = TRUE;
1401 needNewSess = TRUE;
1402
1403 pme->m_ongoingPPQ.init();
1404 pme->m_inputJpegQ.init();
1405 pme->m_inputPPQ.init();
1406 pme->m_inputFWKPPQ.init();
1407 pme->m_inputRawQ.init();
1408 pme->m_inputMetaQ.init();
1409
1410 break;
1411 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1412 {
1413 CDBG_HIGH("%s: stop data proc", __func__);
1414 is_active = FALSE;
1415
1416 // cancel all ongoing jpeg jobs
1417 qcamera_hal3_jpeg_data_t *jpeg_job =
1418 (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1419 while (jpeg_job != NULL) {
1420 pme->mJpegHandle.abort_job(jpeg_job->jobId);
1421
1422 pme->releaseJpegJobData(jpeg_job);
1423 free(jpeg_job);
1424
1425 jpeg_job = (qcamera_hal3_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
1426 }
1427
1428 // destroy jpeg encoding session
1429 if ( 0 < pme->mJpegSessionId ) {
1430 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
1431 pme->mJpegSessionId = 0;
1432 }
1433
1434 needNewSess = TRUE;
1435
1436 // flush ongoing postproc Queue
1437 pme->m_ongoingPPQ.flush();
1438
1439 // flush input jpeg Queue
1440 pme->m_inputJpegQ.flush();
1441
1442 // flush input Postproc Queue
1443 pme->m_inputPPQ.flush();
1444
1445 // flush framework input Postproc Queue
1446 pme->m_inputFWKPPQ.flush();
1447
1448 // flush input raw Queue
1449 pme->m_inputRawQ.flush();
1450
1451 pme->m_inputMetaQ.flush();
1452
1453 // signal cmd is completed
1454 cam_sem_post(&cmdThread->sync_sem);
1455 }
1456 break;
1457 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1458 {
1459 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
1460 /* needNewSess is set to TRUE as postproc is not re-STARTed
1461 * anymore for every captureRequest */
1462 needNewSess = TRUE;
1463 if (is_active == TRUE) {
1464 // check if there is any ongoing jpeg jobs
1465 if (pme->m_ongoingJpegQ.isEmpty()) {
1466 CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
1467 // no ongoing jpeg job, we are fine to send jpeg encoding job
1468 qcamera_hal3_jpeg_data_t *jpeg_job =
1469 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1470
1471 if (NULL != jpeg_job) {
1472 // add into ongoing jpeg job Q
1473 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
1474
1475 if (jpeg_job->fwk_frame) {
1476 ret = pme->encodeFWKData(jpeg_job, needNewSess);
1477 } else {
1478 ret = pme->encodeData(jpeg_job, needNewSess);
1479 }
1480 if (NO_ERROR != ret) {
1481 // dequeue the last one
1482 pme->m_ongoingJpegQ.dequeue(false);
1483
1484 pme->releaseJpegJobData(jpeg_job);
1485 free(jpeg_job);
1486 }
1487 }
1488 }
1489
1490 // check if there are any framework pp jobs
1491 if (!pme->m_inputFWKPPQ.isEmpty()) {
1492 qcamera_fwk_input_pp_data_t *fwk_frame =
1493 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1494 if (NULL != fwk_frame) {
1495 qcamera_hal3_pp_data_t *pp_job =
1496 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1497 jpeg_settings_t *jpeg_settings =
1498 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1499 if (pp_job != NULL) {
1500 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1501 pp_job->jpeg_settings = jpeg_settings;
1502 if (pme->m_pReprocChannel != NULL) {
1503 if (NO_ERROR != pme->m_pReprocChannel->extractCrop(fwk_frame)) {
1504 ALOGE("%s: Failed to extract output crop", __func__);
1505 }
1506 // add into ongoing PP job Q
1507 pp_job->fwk_src_frame = fwk_frame;
1508 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1509 ret = pme->m_pReprocChannel->doReprocessOffline(fwk_frame);
1510 if (NO_ERROR != ret) {
1511 // remove from ongoing PP job Q
1512 pme->m_ongoingPPQ.dequeue(false);
1513 }
1514 } else {
1515 ALOGE("%s: Reprocess channel is NULL", __func__);
1516 ret = -1;
1517 }
1518 } else {
1519 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1520 ret = -1;
1521 }
1522
1523 if (0 != ret) {
1524 // free pp_job
1525 if (pp_job != NULL) {
1526 free(pp_job);
1527 }
1528 // free frame
1529 if (fwk_frame != NULL) {
1530 free(fwk_frame);
1531 }
1532 }
1533 }
1534 }
1535
1536 CDBG_HIGH("%s: dequeuing pp frame", __func__);
1537 pthread_mutex_lock(&pme->mReprocJobLock);
1538 if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
1539 mm_camera_super_buf_t *pp_frame =
1540 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1541 meta_buffer =
1542 (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1543 jpeg_settings_t *jpeg_settings =
1544 (jpeg_settings_t *)pme->m_jpegSettingsQ.dequeue();
1545 pthread_mutex_unlock(&pme->mReprocJobLock);
1546 qcamera_hal3_pp_data_t *pp_job =
1547 (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
1548 if (pp_job != NULL) {
1549 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
1550 pp_job->src_frame = pp_frame;
1551 pp_job->src_metadata = meta_buffer;
1552 pp_job->metadata =
1553 (metadata_buffer_t *)meta_buffer->bufs[0]->buffer;
1554 pp_job->jpeg_settings = jpeg_settings;
1555 pme->m_ongoingPPQ.enqueue((void *)pp_job);
1556 if (pme->m_pReprocChannel != NULL) {
1557 qcamera_fwk_input_pp_data_t fwk_frame;
1558 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
1559 ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
1560 pp_frame, meta_buffer->bufs[0],
1561 pp_job->jpeg_settings,
1562 fwk_frame);
1563 if (NO_ERROR == ret) {
1564 // add into ongoing PP job Q
1565 ret = pme->m_pReprocChannel->doReprocessOffline(
1566 &fwk_frame);
1567 if (NO_ERROR != ret) {
1568 // remove from ongoing PP job Q
1569 pme->m_ongoingPPQ.dequeue(false);
1570 }
1571 }
1572 } else {
1573 CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
1574 __func__);
1575 ret = pme->processPPData(pp_frame);
1576 }
1577 } else {
1578 ALOGE("%s: no mem for qcamera_hal3_pp_data_t", __func__);
1579 ret = -1;
1580 }
1581
1582 if (0 != ret) {
1583 // free pp_job
1584 if (pp_job != NULL) {
1585 free(pp_job);
1586 }
1587 // free frame
1588 if (pp_frame != NULL) {
1589 pme->releaseSuperBuf(pp_frame);
1590 free(pp_frame);
1591 }
1592 //free metadata
1593 if (NULL != meta_buffer) {
1594 pme->m_parent->metadataBufDone(meta_buffer);
1595 free(meta_buffer);
1596 }
1597 }
1598 } else {
1599 pthread_mutex_unlock(&pme->mReprocJobLock);
1600 }
1601 } else {
1602 // not active, simply return buf and do no op
1603 qcamera_hal3_jpeg_data_t *jpeg_job =
1604 (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
1605 if (NULL != jpeg_job) {
1606 free(jpeg_job);
1607 }
1608 mm_camera_super_buf_t *super_buf;
1609 super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
1610 if (NULL != super_buf) {
1611 pme->releaseSuperBuf(super_buf);
1612 free(super_buf);
1613 }
1614 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
1615 if (NULL != super_buf) {
1616 pme->releaseSuperBuf(super_buf);
1617 free(super_buf);
1618 }
1619 mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
1620 if (metadata != NULL) {
1621 pme->m_parent->metadataBufDone(metadata);
1622 free(metadata);
1623 }
1624 qcamera_fwk_input_pp_data_t *fwk_frame =
1625 (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
1626 if (NULL != fwk_frame) {
1627 free(fwk_frame);
1628 }
1629 }
1630 }
1631 break;
1632 case CAMERA_CMD_TYPE_EXIT:
1633 running = 0;
1634 break;
1635 default:
1636 break;
1637 }
1638 } while (running);
1639 CDBG("%s: X", __func__);
1640 return NULL;
1641 }
1642
1643 /*===========================================================================
1644 * FUNCTION : QCamera3Exif
1645 *
1646 * DESCRIPTION: constructor of QCamera3Exif
1647 *
1648 * PARAMETERS : None
1649 *
1650 * RETURN : None
1651 *==========================================================================*/
QCamera3Exif()1652 QCamera3Exif::QCamera3Exif()
1653 : m_nNumEntries(0)
1654 {
1655 memset(m_Entries, 0, sizeof(m_Entries));
1656 }
1657
1658 /*===========================================================================
1659 * FUNCTION : ~QCamera3Exif
1660 *
1661 * DESCRIPTION: deconstructor of QCamera3Exif. Will release internal memory ptr.
1662 *
1663 * PARAMETERS : None
1664 *
1665 * RETURN : None
1666 *==========================================================================*/
~QCamera3Exif()1667 QCamera3Exif::~QCamera3Exif()
1668 {
1669 for (uint32_t i = 0; i < m_nNumEntries; i++) {
1670 switch (m_Entries[i].tag_entry.type) {
1671 case EXIF_BYTE:
1672 {
1673 if (m_Entries[i].tag_entry.count > 1 &&
1674 m_Entries[i].tag_entry.data._bytes != NULL) {
1675 free(m_Entries[i].tag_entry.data._bytes);
1676 m_Entries[i].tag_entry.data._bytes = NULL;
1677 }
1678 }
1679 break;
1680 case EXIF_ASCII:
1681 {
1682 if (m_Entries[i].tag_entry.data._ascii != NULL) {
1683 free(m_Entries[i].tag_entry.data._ascii);
1684 m_Entries[i].tag_entry.data._ascii = NULL;
1685 }
1686 }
1687 break;
1688 case EXIF_SHORT:
1689 {
1690 if (m_Entries[i].tag_entry.count > 1 &&
1691 m_Entries[i].tag_entry.data._shorts != NULL) {
1692 free(m_Entries[i].tag_entry.data._shorts);
1693 m_Entries[i].tag_entry.data._shorts = NULL;
1694 }
1695 }
1696 break;
1697 case EXIF_LONG:
1698 {
1699 if (m_Entries[i].tag_entry.count > 1 &&
1700 m_Entries[i].tag_entry.data._longs != NULL) {
1701 free(m_Entries[i].tag_entry.data._longs);
1702 m_Entries[i].tag_entry.data._longs = NULL;
1703 }
1704 }
1705 break;
1706 case EXIF_RATIONAL:
1707 {
1708 if (m_Entries[i].tag_entry.count > 1 &&
1709 m_Entries[i].tag_entry.data._rats != NULL) {
1710 free(m_Entries[i].tag_entry.data._rats);
1711 m_Entries[i].tag_entry.data._rats = NULL;
1712 }
1713 }
1714 break;
1715 case EXIF_UNDEFINED:
1716 {
1717 if (m_Entries[i].tag_entry.data._undefined != NULL) {
1718 free(m_Entries[i].tag_entry.data._undefined);
1719 m_Entries[i].tag_entry.data._undefined = NULL;
1720 }
1721 }
1722 break;
1723 case EXIF_SLONG:
1724 {
1725 if (m_Entries[i].tag_entry.count > 1 &&
1726 m_Entries[i].tag_entry.data._slongs != NULL) {
1727 free(m_Entries[i].tag_entry.data._slongs);
1728 m_Entries[i].tag_entry.data._slongs = NULL;
1729 }
1730 }
1731 break;
1732 case EXIF_SRATIONAL:
1733 {
1734 if (m_Entries[i].tag_entry.count > 1 &&
1735 m_Entries[i].tag_entry.data._srats != NULL) {
1736 free(m_Entries[i].tag_entry.data._srats);
1737 m_Entries[i].tag_entry.data._srats = NULL;
1738 }
1739 }
1740 break;
1741 default:
1742 ALOGE("%s: Error, Unknown type",__func__);
1743 break;
1744 }
1745 }
1746 }
1747
1748 /*===========================================================================
1749 * FUNCTION : addEntry
1750 *
1751 * DESCRIPTION: function to add an entry to exif data
1752 *
1753 * PARAMETERS :
1754 * @tagid : exif tag ID
1755 * @type : data type
1756 * @count : number of data in uint of its type
1757 * @data : input data ptr
1758 *
1759 * RETURN : int32_t type of status
1760 * NO_ERROR -- success
1761 * none-zero failure code
1762 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)1763 int32_t QCamera3Exif::addEntry(exif_tag_id_t tagid,
1764 exif_tag_type_t type,
1765 uint32_t count,
1766 void *data)
1767 {
1768 int32_t rc = NO_ERROR;
1769 if(m_nNumEntries >= MAX_HAL3_EXIF_TABLE_ENTRIES) {
1770 ALOGE("%s: Number of entries exceeded limit", __func__);
1771 return NO_MEMORY;
1772 }
1773
1774 m_Entries[m_nNumEntries].tag_id = tagid;
1775 m_Entries[m_nNumEntries].tag_entry.type = type;
1776 m_Entries[m_nNumEntries].tag_entry.count = count;
1777 m_Entries[m_nNumEntries].tag_entry.copy = 1;
1778 switch (type) {
1779 case EXIF_BYTE:
1780 {
1781 if (count > 1) {
1782 uint8_t *values = (uint8_t *)malloc(count);
1783 if (values == NULL) {
1784 ALOGE("%s: No memory for byte array", __func__);
1785 rc = NO_MEMORY;
1786 } else {
1787 memcpy(values, data, count);
1788 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
1789 }
1790 } else {
1791 m_Entries[m_nNumEntries].tag_entry.data._byte =
1792 *(uint8_t *)data;
1793 }
1794 }
1795 break;
1796 case EXIF_ASCII:
1797 {
1798 char *str = NULL;
1799 str = (char *)malloc(count + 1);
1800 if (str == NULL) {
1801 ALOGE("%s: No memory for ascii string", __func__);
1802 rc = NO_MEMORY;
1803 } else {
1804 memset(str, 0, count + 1);
1805 memcpy(str, data, count);
1806 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
1807 }
1808 }
1809 break;
1810 case EXIF_SHORT:
1811 {
1812 if (count > 1) {
1813 uint16_t *values =
1814 (uint16_t *)malloc(count * sizeof(uint16_t));
1815 if (values == NULL) {
1816 ALOGE("%s: No memory for short array", __func__);
1817 rc = NO_MEMORY;
1818 } else {
1819 memcpy(values, data, count * sizeof(uint16_t));
1820 m_Entries[m_nNumEntries].tag_entry.data._shorts =values;
1821 }
1822 } else {
1823 m_Entries[m_nNumEntries].tag_entry.data._short =
1824 *(uint16_t *)data;
1825 }
1826 }
1827 break;
1828 case EXIF_LONG:
1829 {
1830 if (count > 1) {
1831 uint32_t *values =
1832 (uint32_t *)malloc(count * sizeof(uint32_t));
1833 if (values == NULL) {
1834 ALOGE("%s: No memory for long array", __func__);
1835 rc = NO_MEMORY;
1836 } else {
1837 memcpy(values, data, count * sizeof(uint32_t));
1838 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
1839 }
1840 } else {
1841 m_Entries[m_nNumEntries].tag_entry.data._long =
1842 *(uint32_t *)data;
1843 }
1844 }
1845 break;
1846 case EXIF_RATIONAL:
1847 {
1848 if (count > 1) {
1849 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
1850 if (values == NULL) {
1851 ALOGE("%s: No memory for rational array", __func__);
1852 rc = NO_MEMORY;
1853 } else {
1854 memcpy(values, data, count * sizeof(rat_t));
1855 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
1856 }
1857 } else {
1858 m_Entries[m_nNumEntries].tag_entry.data._rat =
1859 *(rat_t *)data;
1860 }
1861 }
1862 break;
1863 case EXIF_UNDEFINED:
1864 {
1865 uint8_t *values = (uint8_t *)malloc(count);
1866 if (values == NULL) {
1867 ALOGE("%s: No memory for undefined array", __func__);
1868 rc = NO_MEMORY;
1869 } else {
1870 memcpy(values, data, count);
1871 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
1872 }
1873 }
1874 break;
1875 case EXIF_SLONG:
1876 {
1877 if (count > 1) {
1878 int32_t *values =
1879 (int32_t *)malloc(count * sizeof(int32_t));
1880 if (values == NULL) {
1881 ALOGE("%s: No memory for signed long array", __func__);
1882 rc = NO_MEMORY;
1883 } else {
1884 memcpy(values, data, count * sizeof(int32_t));
1885 m_Entries[m_nNumEntries].tag_entry.data._slongs =values;
1886 }
1887 } else {
1888 m_Entries[m_nNumEntries].tag_entry.data._slong =
1889 *(int32_t *)data;
1890 }
1891 }
1892 break;
1893 case EXIF_SRATIONAL:
1894 {
1895 if (count > 1) {
1896 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
1897 if (values == NULL) {
1898 ALOGE("%s: No memory for sign rational array",__func__);
1899 rc = NO_MEMORY;
1900 } else {
1901 memcpy(values, data, count * sizeof(srat_t));
1902 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
1903 }
1904 } else {
1905 m_Entries[m_nNumEntries].tag_entry.data._srat =
1906 *(srat_t *)data;
1907 }
1908 }
1909 break;
1910 default:
1911 ALOGE("%s: Error, Unknown type",__func__);
1912 break;
1913 }
1914
1915 // Increase number of entries
1916 m_nNumEntries++;
1917 return rc;
1918 }
1919
1920 }; // namespace qcamera
1921