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
30 #define LOG_TAG "QCameraPostProc"
31
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <utils/Errors.h>
35
36 #include "QCamera2HWI.h"
37 #include "QCameraPostProc.h"
38
39 namespace qcamera {
40
41 const char *QCameraPostProcessor::STORE_LOCATION = "/sdcard/img_%d.jpg";
42
43 #define FREE_JPEG_OUTPUT_BUFFER(ptr,cnt) \
44 int jpeg_bufs; \
45 for (jpeg_bufs = 0; jpeg_bufs < (int)cnt; jpeg_bufs++) { \
46 if (ptr[jpeg_bufs] != NULL) { \
47 free(ptr[jpeg_bufs]); \
48 ptr[jpeg_bufs] = NULL; \
49 } \
50 }
51
52 /*===========================================================================
53 * FUNCTION : QCameraPostProcessor
54 *
55 * DESCRIPTION: constructor of QCameraPostProcessor.
56 *
57 * PARAMETERS :
58 * @cam_ctrl : ptr to HWI object
59 *
60 * RETURN : None
61 *==========================================================================*/
QCameraPostProcessor(QCamera2HardwareInterface * cam_ctrl)62 QCameraPostProcessor::QCameraPostProcessor(QCamera2HardwareInterface *cam_ctrl)
63 : m_parent(cam_ctrl),
64 mJpegCB(NULL),
65 mJpegUserData(NULL),
66 mJpegClientHandle(0),
67 mJpegSessionId(0),
68 m_pJpegExifObj(NULL),
69 m_bThumbnailNeeded(TRUE),
70 m_pReprocChannel(NULL),
71 m_bInited(FALSE),
72 m_inputPPQ(releasePPInputData, this),
73 m_ongoingPPQ(releaseOngoingPPData, this),
74 m_inputJpegQ(releaseJpegData, this),
75 m_ongoingJpegQ(releaseJpegData, this),
76 m_inputRawQ(releaseRawData, this),
77 mSaveFrmCnt(0),
78 mUseSaveProc(false),
79 mUseJpegBurst(false),
80 mJpegMemOpt(true),
81 m_JpegOutputMemCount(0),
82 mNewJpegSessionNeeded(true)
83 {
84 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
85 memset(&m_pJpegOutputMem, 0, sizeof(m_pJpegOutputMem));
86 }
87
88 /*===========================================================================
89 * FUNCTION : ~QCameraPostProcessor
90 *
91 * DESCRIPTION: deconstructor of QCameraPostProcessor.
92 *
93 * PARAMETERS : None
94 *
95 * RETURN : None
96 *==========================================================================*/
~QCameraPostProcessor()97 QCameraPostProcessor::~QCameraPostProcessor()
98 {
99 FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem,m_JpegOutputMemCount);
100 if (m_pJpegExifObj != NULL) {
101 delete m_pJpegExifObj;
102 m_pJpegExifObj = NULL;
103 }
104 if (m_pReprocChannel != NULL) {
105 m_pReprocChannel->stop();
106 delete m_pReprocChannel;
107 m_pReprocChannel = NULL;
108 }
109 }
110
111 /*===========================================================================
112 * FUNCTION : init
113 *
114 * DESCRIPTION: initialization of postprocessor
115 *
116 * PARAMETERS :
117 * @jpeg_cb : callback to handle jpeg event from mm-camera-interface
118 * @user_data : user data ptr for jpeg callback
119 *
120 * RETURN : int32_t type of status
121 * NO_ERROR -- success
122 * none-zero failure code
123 *==========================================================================*/
init(jpeg_encode_callback_t jpeg_cb,void * user_data)124 int32_t QCameraPostProcessor::init(jpeg_encode_callback_t jpeg_cb, void *user_data)
125 {
126 mJpegCB = jpeg_cb;
127 mJpegUserData = user_data;
128 mm_dimension max_size;
129
130 //set max pic size
131 memset(&max_size, 0, sizeof(mm_dimension));
132 max_size.w = m_parent->m_max_pic_width;
133 max_size.h = m_parent->m_max_pic_height;
134
135 mJpegClientHandle = jpeg_open(&mJpegHandle, max_size);
136 if(!mJpegClientHandle) {
137 ALOGE("%s : jpeg_open did not work", __func__);
138 return UNKNOWN_ERROR;
139 }
140
141 m_dataProcTh.launch(dataProcessRoutine, this);
142 m_saveProcTh.launch(dataSaveRoutine, this);
143
144 m_bInited = TRUE;
145 return NO_ERROR;
146 }
147
148 /*===========================================================================
149 * FUNCTION : deinit
150 *
151 * DESCRIPTION: de-initialization of postprocessor
152 *
153 * PARAMETERS : None
154 *
155 * RETURN : int32_t type of status
156 * NO_ERROR -- success
157 * none-zero failure code
158 *==========================================================================*/
deinit()159 int32_t QCameraPostProcessor::deinit()
160 {
161 if (m_bInited == TRUE) {
162 m_dataProcTh.exit();
163 m_saveProcTh.exit();
164
165 if(mJpegClientHandle > 0) {
166 int rc = mJpegHandle.close(mJpegClientHandle);
167 CDBG_HIGH("%s: Jpeg closed, rc = %d, mJpegClientHandle = %x",
168 __func__, rc, mJpegClientHandle);
169 mJpegClientHandle = 0;
170 memset(&mJpegHandle, 0, sizeof(mJpegHandle));
171 }
172 m_bInited = FALSE;
173 }
174 return NO_ERROR;
175 }
176
177 /*===========================================================================
178 * FUNCTION : start
179 *
180 * DESCRIPTION: start postprocessor. Data process thread and data notify thread
181 * will be launched.
182 *
183 * PARAMETERS :
184 * @pSrcChannel : source channel obj ptr that possibly needs reprocess
185 *
186 * RETURN : int32_t type of status
187 * NO_ERROR -- success
188 * none-zero failure code
189 *
190 * NOTE : if any reprocess is needed, a reprocess channel/stream
191 * will be started.
192 *==========================================================================*/
start(QCameraChannel * pSrcChannel)193 int32_t QCameraPostProcessor::start(QCameraChannel *pSrcChannel)
194 {
195 char prop[PROPERTY_VALUE_MAX];
196 int32_t rc = NO_ERROR;
197 if (m_bInited == FALSE) {
198 ALOGE("%s: postproc not initialized yet", __func__);
199 return UNKNOWN_ERROR;
200 }
201
202 if (m_parent->needReprocess()) {
203 if (m_pReprocChannel != NULL) {
204 delete m_pReprocChannel;
205 m_pReprocChannel = NULL;
206 }
207 // if reprocess is needed, start reprocess channel
208 m_pReprocChannel = m_parent->addReprocChannel(pSrcChannel);
209 if (m_pReprocChannel == NULL) {
210 ALOGE("%s: cannot add reprocess channel", __func__);
211 return UNKNOWN_ERROR;
212 }
213
214 rc = m_pReprocChannel->start();
215 if (rc != 0) {
216 ALOGE("%s: cannot start reprocess channel", __func__);
217 delete m_pReprocChannel;
218 m_pReprocChannel = NULL;
219 return rc;
220 }
221 }
222
223 property_get("persist.camera.longshot.save", prop, "0");
224 mUseSaveProc = atoi(prop) > 0 ? true : false;
225
226 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC, TRUE, FALSE);
227 m_parent->m_cbNotifier.startSnapshots();
228
229 // Create Jpeg session
230 if ( !m_parent->mParameters.getRecordingHintValue() &&
231 !m_parent->isLongshotEnabled() &&
232 !m_parent->isZSLMode()) {
233
234 QCameraChannel *pChannel = NULL;
235 pChannel = m_parent->needReprocess() ? m_pReprocChannel : pSrcChannel;
236 QCameraStream *pSnapshotStream = NULL;
237 QCameraStream *pThumbStream = NULL;
238
239 for (int i = 0; i < pChannel->getNumOfStreams(); ++i) {
240 QCameraStream *pStream = pChannel->getStreamByIndex(i);
241
242 if ( NULL == pStream ) {
243 break;
244 }
245
246 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
247 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
248 pSnapshotStream = pStream;
249 }
250
251 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
252 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
253 pThumbStream = pStream;
254 }
255 }
256
257 // If thumbnail is not part of the reprocess channel, then
258 // try to get it from the source channel
259 if ((NULL == pThumbStream) && (pChannel == m_pReprocChannel)) {
260 for (int i = 0; i < pSrcChannel->getNumOfStreams(); ++i) {
261 QCameraStream *pStream = pSrcChannel->getStreamByIndex(i);
262
263 if ( NULL == pStream ) {
264 break;
265 }
266
267 if (pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
268 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
269 pThumbStream = pStream;
270 }
271 }
272 }
273
274 if (m_parent->mParameters.generateThumbFromMain()) {
275 pThumbStream = NULL;
276 }
277
278 if ( NULL != pSnapshotStream ) {
279 mm_jpeg_encode_params_t encodeParam;
280 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
281 getJpegEncodingConfig(encodeParam, pSnapshotStream, pThumbStream);
282 CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
283
284 rc = mJpegHandle.create_session(mJpegClientHandle,
285 &encodeParam,
286 &mJpegSessionId);
287 if (rc != NO_ERROR) {
288 ALOGE("%s: error creating a new jpeg encoding session", __func__);
289 return rc;
290 }
291 mNewJpegSessionNeeded = false;
292 }
293 }
294
295 return rc;
296 }
297
298 /*===========================================================================
299 * FUNCTION : stop
300 *
301 * DESCRIPTION: stop postprocessor. Data process and notify thread will be stopped.
302 *
303 * PARAMETERS : None
304 *
305 * RETURN : int32_t type of status
306 * NO_ERROR -- success
307 * none-zero failure code
308 *
309 * NOTE : reprocess channel will be stopped and deleted if there is any
310 *==========================================================================*/
stop()311 int32_t QCameraPostProcessor::stop()
312 {
313 if (m_bInited == TRUE) {
314 m_parent->m_cbNotifier.stopSnapshots();
315 // dataProc Thread need to process "stop" as sync call because abort jpeg job should be a sync call
316 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC, TRUE, TRUE);
317 }
318
319 return NO_ERROR;
320 }
321
322 /*===========================================================================
323 * FUNCTION : getJpegEncodingConfig
324 *
325 * DESCRIPTION: function to prepare encoding job information
326 *
327 * PARAMETERS :
328 * @encode_parm : param to be filled with encoding configuration
329 *
330 * RETURN : int32_t type of status
331 * NO_ERROR -- success
332 * none-zero failure code
333 *==========================================================================*/
getJpegEncodingConfig(mm_jpeg_encode_params_t & encode_parm,QCameraStream * main_stream,QCameraStream * thumb_stream)334 int32_t QCameraPostProcessor::getJpegEncodingConfig(mm_jpeg_encode_params_t& encode_parm,
335 QCameraStream *main_stream,
336 QCameraStream *thumb_stream)
337 {
338 CDBG("%s : E", __func__);
339 int32_t ret = NO_ERROR;
340 uint32_t out_size;
341
342 char prop[PROPERTY_VALUE_MAX];
343 property_get("persist.camera.jpeg_burst", prop, "0");
344 mUseJpegBurst = (atoi(prop) > 0) && !mUseSaveProc;
345 encode_parm.burst_mode = mUseJpegBurst;
346
347 cam_rect_t crop;
348 memset(&crop, 0, sizeof(cam_rect_t));
349 main_stream->getCropInfo(crop);
350
351 cam_dimension_t src_dim, dst_dim;
352 memset(&src_dim, 0, sizeof(cam_dimension_t));
353 memset(&dst_dim, 0, sizeof(cam_dimension_t));
354 main_stream->getFrameDimension(src_dim);
355
356 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
357 if (hdr_output_crop && crop.height) {
358 dst_dim.height = crop.height;
359 } else {
360 dst_dim.height = src_dim.height;
361 }
362 if (hdr_output_crop && crop.width) {
363 dst_dim.width = crop.width;
364 } else {
365 dst_dim.width = src_dim.width;
366 }
367
368 // set rotation only when no online rotation or offline pp rotation is done before
369 if (!m_parent->needRotationReprocess()) {
370 encode_parm.rotation = m_parent->getJpegRotation();
371 }
372
373 encode_parm.main_dim.src_dim = src_dim;
374 encode_parm.main_dim.dst_dim = dst_dim;
375
376 encode_parm.jpeg_cb = mJpegCB;
377 encode_parm.userdata = mJpegUserData;
378
379 m_bThumbnailNeeded = TRUE; // need encode thumbnail by default
380 cam_dimension_t thumbnailSize;
381 memset(&thumbnailSize, 0, sizeof(cam_dimension_t));
382 m_parent->getThumbnailSize(thumbnailSize);
383 if (thumbnailSize.width == 0 || thumbnailSize.height == 0) {
384 // (0,0) means no thumbnail
385 m_bThumbnailNeeded = FALSE;
386 }
387 encode_parm.encode_thumbnail = m_bThumbnailNeeded;
388
389 // get color format
390 cam_format_t img_fmt = CAM_FORMAT_YUV_420_NV12;
391 main_stream->getFormat(img_fmt);
392 encode_parm.color_format = getColorfmtFromImgFmt(img_fmt);
393
394 // get jpeg quality
395 encode_parm.quality = m_parent->getJpegQuality();
396 if (encode_parm.quality <= 0) {
397 encode_parm.quality = 85;
398 }
399 cam_frame_len_offset_t main_offset;
400 memset(&main_offset, 0, sizeof(cam_frame_len_offset_t));
401 main_stream->getFrameOffset(main_offset);
402
403 // src buf config
404 QCameraMemory *pStreamMem = main_stream->getStreamBufs();
405 if (pStreamMem == NULL) {
406 ALOGE("%s: cannot get stream bufs from main stream", __func__);
407 ret = BAD_VALUE;
408 goto on_error;
409 }
410 encode_parm.num_src_bufs = pStreamMem->getCnt();
411 for (uint32_t i = 0; i < encode_parm.num_src_bufs; i++) {
412 camera_memory_t *stream_mem = pStreamMem->getMemory(i, false);
413 if (stream_mem != NULL) {
414 encode_parm.src_main_buf[i].index = i;
415 encode_parm.src_main_buf[i].buf_size = stream_mem->size;
416 encode_parm.src_main_buf[i].buf_vaddr = (uint8_t *)stream_mem->data;
417 encode_parm.src_main_buf[i].fd = pStreamMem->getFd(i);
418 encode_parm.src_main_buf[i].format = MM_JPEG_FMT_YUV;
419 encode_parm.src_main_buf[i].offset = main_offset;
420 }
421 }
422
423 if (m_bThumbnailNeeded == TRUE) {
424 bool need_thumb_rotate = true;
425 int jpeg_rotation = m_parent->getJpegRotation();
426 m_parent->getThumbnailSize(encode_parm.thumb_dim.dst_dim);
427
428 if (thumb_stream == NULL) {
429 thumb_stream = main_stream;
430 need_thumb_rotate = false;
431 }
432 pStreamMem = thumb_stream->getStreamBufs();
433 if (pStreamMem == NULL) {
434 ALOGE("%s: cannot get stream bufs from thumb stream", __func__);
435 ret = BAD_VALUE;
436 goto on_error;
437 }
438 cam_frame_len_offset_t thumb_offset;
439 memset(&thumb_offset, 0, sizeof(cam_frame_len_offset_t));
440 thumb_stream->getFrameOffset(thumb_offset);
441 encode_parm.num_tmb_bufs = pStreamMem->getCnt();
442 for (int i = 0; i < pStreamMem->getCnt(); i++) {
443 camera_memory_t *stream_mem = pStreamMem->getMemory(i, false);
444 if (stream_mem != NULL) {
445 encode_parm.src_thumb_buf[i].index = i;
446 encode_parm.src_thumb_buf[i].buf_size = stream_mem->size;
447 encode_parm.src_thumb_buf[i].buf_vaddr = (uint8_t *)stream_mem->data;
448 encode_parm.src_thumb_buf[i].fd = pStreamMem->getFd(i);
449 encode_parm.src_thumb_buf[i].format = MM_JPEG_FMT_YUV;
450 encode_parm.src_thumb_buf[i].offset = thumb_offset;
451 }
452 }
453 cam_format_t img_fmt_thumb = CAM_FORMAT_YUV_420_NV12;
454 thumb_stream->getFormat(img_fmt_thumb);
455 encode_parm.thumb_color_format = getColorfmtFromImgFmt(img_fmt_thumb);
456
457 // crop is the same if frame is the same
458 if (thumb_stream != main_stream) {
459 memset(&crop, 0, sizeof(cam_rect_t));
460 thumb_stream->getCropInfo(crop);
461 }
462
463 memset(&src_dim, 0, sizeof(cam_dimension_t));
464 thumb_stream->getFrameDimension(src_dim);
465 encode_parm.thumb_dim.src_dim = src_dim;
466
467 if (!m_parent->needRotationReprocess() || need_thumb_rotate) {
468 encode_parm.thumb_rotation = jpeg_rotation;
469 } else if ((90 == jpeg_rotation) || (270 == jpeg_rotation)) {
470 // swap thumbnail dimensions
471 cam_dimension_t tmp_dim = encode_parm.thumb_dim.dst_dim;
472 encode_parm.thumb_dim.dst_dim.width = tmp_dim.height;
473 encode_parm.thumb_dim.dst_dim.height = tmp_dim.width;
474 }
475 encode_parm.thumb_dim.crop = crop;
476 }
477
478 encode_parm.num_dst_bufs = 1;
479 if (mUseJpegBurst) {
480 encode_parm.num_dst_bufs = MAX_JPEG_BURST;
481 }
482 encode_parm.get_memory = NULL;
483 out_size = main_offset.frame_len;
484 if (mJpegMemOpt) {
485 encode_parm.get_memory = getJpegMemory;
486 out_size = sizeof(omx_jpeg_ouput_buf_t);
487 encode_parm.num_dst_bufs = encode_parm.num_src_bufs;
488 }
489 m_JpegOutputMemCount = encode_parm.num_dst_bufs;
490 for (int i = 0; i < (int)m_JpegOutputMemCount; i++) {
491 if (m_pJpegOutputMem[i] != NULL)
492 free(m_pJpegOutputMem[i]);
493 omx_jpeg_ouput_buf_t omx_out_buf;
494 omx_out_buf.handle = this;
495 // allocate output buf for jpeg encoding
496 m_pJpegOutputMem[i] = malloc(out_size);
497
498 if (NULL == m_pJpegOutputMem[i]) {
499 ret = NO_MEMORY;
500 ALOGE("%s : initHeapMem for jpeg, ret = NO_MEMORY", __func__);
501 goto on_error;
502 }
503
504 if (mJpegMemOpt) {
505 memcpy(m_pJpegOutputMem[i], &omx_out_buf, sizeof(omx_out_buf));
506 }
507
508
509 encode_parm.dest_buf[i].index = i;
510 encode_parm.dest_buf[i].buf_size = main_offset.frame_len;
511 encode_parm.dest_buf[i].buf_vaddr = (uint8_t *)m_pJpegOutputMem[i];
512 encode_parm.dest_buf[i].fd = 0;
513 encode_parm.dest_buf[i].format = MM_JPEG_FMT_YUV;
514 encode_parm.dest_buf[i].offset = main_offset;
515 }
516
517
518 CDBG("%s : X", __func__);
519 return NO_ERROR;
520
521 on_error:
522 FREE_JPEG_OUTPUT_BUFFER(m_pJpegOutputMem, m_JpegOutputMemCount);
523
524 CDBG("%s : X with error %d", __func__, ret);
525 return ret;
526 }
527
528 /*===========================================================================
529 * FUNCTION : sendEvtNotify
530 *
531 * DESCRIPTION: send event notify through notify callback registered by upper layer
532 *
533 * PARAMETERS :
534 * @msg_type: msg type of notify
535 * @ext1 : extension
536 * @ext2 : extension
537 *
538 * RETURN : int32_t type of status
539 * NO_ERROR -- success
540 * none-zero failure code
541 *==========================================================================*/
sendEvtNotify(int32_t msg_type,int32_t ext1,int32_t ext2)542 int32_t QCameraPostProcessor::sendEvtNotify(int32_t msg_type,
543 int32_t ext1,
544 int32_t ext2)
545 {
546 return m_parent->sendEvtNotify(msg_type, ext1, ext2);
547 }
548
549 /*===========================================================================
550 * FUNCTION : sendDataNotify
551 *
552 * DESCRIPTION: enqueue data into dataNotify thread
553 *
554 * PARAMETERS :
555 * @msg_type: data callback msg type
556 * @data : ptr to data memory struct
557 * @index : index to data buffer
558 * @metadata: ptr to meta data buffer if there is any
559 * @release_data : ptr to struct indicating if data need to be released
560 * after notify
561 *
562 * RETURN : int32_t type of status
563 * NO_ERROR -- success
564 * none-zero failure code
565 *==========================================================================*/
sendDataNotify(int32_t msg_type,camera_memory_t * data,uint8_t index,camera_frame_metadata_t * metadata,qcamera_release_data_t * release_data)566 int32_t QCameraPostProcessor::sendDataNotify(int32_t msg_type,
567 camera_memory_t *data,
568 uint8_t index,
569 camera_frame_metadata_t *metadata,
570 qcamera_release_data_t *release_data)
571 {
572 qcamera_data_argm_t *data_cb = (qcamera_data_argm_t *)malloc(sizeof(qcamera_data_argm_t));
573 if (NULL == data_cb) {
574 ALOGE("%s: no mem for acamera_data_argm_t", __func__);
575 return NO_MEMORY;
576 }
577 memset(data_cb, 0, sizeof(qcamera_data_argm_t));
578 data_cb->msg_type = msg_type;
579 data_cb->data = data;
580 data_cb->index = index;
581 data_cb->metadata = metadata;
582 if (release_data != NULL) {
583 data_cb->release_data = *release_data;
584 }
585
586 qcamera_callback_argm_t cbArg;
587 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
588 cbArg.cb_type = QCAMERA_DATA_SNAPSHOT_CALLBACK;
589 cbArg.msg_type = msg_type;
590 cbArg.data = data;
591 cbArg.metadata = metadata;
592 cbArg.user_data = data_cb;
593 cbArg.cookie = this;
594 cbArg.release_cb = releaseNotifyData;
595 int rc = m_parent->m_cbNotifier.notifyCallback(cbArg);
596 if ( NO_ERROR != rc ) {
597 ALOGE("%s: Error enqueuing jpeg data into notify queue", __func__);
598 releaseNotifyData(data_cb, this, UNKNOWN_ERROR);
599 return UNKNOWN_ERROR;
600 }
601
602 return rc;
603 }
604
605 /*===========================================================================
606 * FUNCTION : processData
607 *
608 * DESCRIPTION: enqueue data into dataProc thread
609 *
610 * PARAMETERS :
611 * @frame : process frame received from mm-camera-interface
612 *
613 * RETURN : int32_t type of status
614 * NO_ERROR -- success
615 * none-zero failure code
616 *
617 * NOTE : depends on if offline reprocess is needed, received frame will
618 * be sent to either input queue of postprocess or jpeg encoding
619 *==========================================================================*/
processData(mm_camera_super_buf_t * frame)620 int32_t QCameraPostProcessor::processData(mm_camera_super_buf_t *frame)
621 {
622 if (m_bInited == FALSE) {
623 ALOGE("%s: postproc not initialized yet", __func__);
624 return UNKNOWN_ERROR;
625 }
626
627 if (m_parent->needReprocess()) {
628 if ((!m_parent->isLongshotEnabled() &&
629 !m_parent->m_stateMachine.isNonZSLCaptureRunning()) ||
630 (m_parent->isLongshotEnabled() &&
631 m_parent->isCaptureShutterEnabled())) {
632 //play shutter sound
633 m_parent->playShutter();
634 }
635
636 CDBG_HIGH("%s: need reprocess", __func__);
637 // enqueu to post proc input queue
638 m_inputPPQ.enqueue((void *)frame);
639 } else if (m_parent->mParameters.isNV16PictureFormat() ||
640 m_parent->mParameters.isNV21PictureFormat()) {
641 //check if raw frame information is needed.
642 if(m_parent->mParameters.isYUVFrameInfoNeeded())
643 setYUVFrameInfo(frame);
644
645 processRawData(frame);
646 } else {
647 //play shutter sound
648 if(!m_parent->m_stateMachine.isNonZSLCaptureRunning() &&
649 !m_parent->mLongshotEnabled)
650 m_parent->playShutter();
651
652 CDBG_HIGH("%s: no need offline reprocess, sending to jpeg encoding", __func__);
653 qcamera_jpeg_data_t *jpeg_job =
654 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
655 if (jpeg_job == NULL) {
656 ALOGE("%s: No memory for jpeg job", __func__);
657 return NO_MEMORY;
658 }
659
660 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
661 jpeg_job->src_frame = frame;
662
663 // find meta data frame
664 mm_camera_buf_def_t *meta_frame = NULL;
665 for (int i = 0; i < frame->num_bufs; i++) {
666 // look through input superbuf
667 if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
668 meta_frame = frame->bufs[i];
669 break;
670 }
671 }
672
673 if (meta_frame != NULL) {
674 // fill in meta data frame ptr
675 jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
676 }
677
678 // enqueu to jpeg input queue
679 m_inputJpegQ.enqueue((void *)jpeg_job);
680 }
681 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
682
683 return NO_ERROR;
684 }
685
686 /*===========================================================================
687 * FUNCTION : processRawData
688 *
689 * DESCRIPTION: enqueue raw data into dataProc thread
690 *
691 * PARAMETERS :
692 * @frame : process frame received from mm-camera-interface
693 *
694 * RETURN : int32_t type of status
695 * NO_ERROR -- success
696 * none-zero failure code
697 *==========================================================================*/
processRawData(mm_camera_super_buf_t * frame)698 int32_t QCameraPostProcessor::processRawData(mm_camera_super_buf_t *frame)
699 {
700 if (m_bInited == FALSE) {
701 ALOGE("%s: postproc not initialized yet", __func__);
702 return UNKNOWN_ERROR;
703 }
704
705 // enqueu to raw input queue
706 m_inputRawQ.enqueue((void *)frame);
707 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
708 return NO_ERROR;
709 }
710
711 /*===========================================================================
712 * FUNCTION : processJpegEvt
713 *
714 * DESCRIPTION: process jpeg event from mm-jpeg-interface.
715 *
716 * PARAMETERS :
717 * @evt : payload of jpeg event, including information about jpeg encoding
718 * status, jpeg size and so on.
719 *
720 * RETURN : int32_t type of status
721 * NO_ERROR -- success
722 * none-zero failure code
723 *
724 * NOTE : This event will also trigger DataProc thread to move to next job
725 * processing (i.e., send a new jpeg encoding job to mm-jpeg-interface
726 * if there is any pending job in jpeg input queue)
727 *==========================================================================*/
processJpegEvt(qcamera_jpeg_evt_payload_t * evt)728 int32_t QCameraPostProcessor::processJpegEvt(qcamera_jpeg_evt_payload_t *evt)
729 {
730 if (m_bInited == FALSE) {
731 ALOGE("%s: postproc not initialized yet", __func__);
732 return UNKNOWN_ERROR;
733 }
734
735 int32_t rc = NO_ERROR;
736 camera_memory_t *jpeg_mem = NULL;
737 omx_jpeg_ouput_buf_t *jpeg_out = NULL;
738
739 if (mUseSaveProc && m_parent->isLongshotEnabled()) {
740 qcamera_jpeg_evt_payload_t *saveData = ( qcamera_jpeg_evt_payload_t * ) malloc(sizeof(qcamera_jpeg_evt_payload_t));
741 if ( NULL == saveData ) {
742 ALOGE("%s: Can not allocate save data message!", __func__);
743 return NO_MEMORY;
744 }
745 *saveData = *evt;
746 m_inputSaveQ.enqueue((void *) saveData);
747 m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
748 } else {
749 // Release jpeg job data
750 m_ongoingJpegQ.flushNodes(matchJobId, (void*)&evt->jobId);
751
752 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, evt->jobId);
753
754 if (m_parent->mDataCb == NULL ||
755 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 ) {
756 CDBG_HIGH("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled",
757 __func__);
758 rc = NO_ERROR;
759 goto end;
760 }
761
762 if(evt->status == JPEG_JOB_STATUS_ERROR) {
763 ALOGE("%s: Error event handled from jpeg, status = %d",
764 __func__, evt->status);
765 rc = FAILED_TRANSACTION;
766 goto end;
767 }
768
769 m_parent->dumpJpegToFile(evt->out_data.buf_vaddr,
770 evt->out_data.buf_filled_len,
771 evt->jobId);
772 CDBG_HIGH("%s: Dump jpeg_size=%d", __func__, evt->out_data.buf_filled_len);
773
774 /* check if the all the captures are done */
775 if (m_parent->mParameters.isUbiRefocus() &&
776 (m_parent->getOutputImageCount() <
777 m_parent->mParameters.UfOutputCount())) {
778 jpeg_out = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
779 jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
780 if (NULL != jpeg_mem) {
781 jpeg_mem->release(jpeg_mem);
782 jpeg_mem = NULL;
783 }
784 goto end;
785 }
786
787 if (!mJpegMemOpt) {
788 // alloc jpeg memory to pass to upper layer
789 jpeg_mem = m_parent->mGetMemory(-1, evt->out_data.buf_filled_len,
790 1, m_parent->mCallbackCookie);
791 if (NULL == jpeg_mem) {
792 rc = NO_MEMORY;
793 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
794 goto end;
795 }
796 memcpy(jpeg_mem->data, evt->out_data.buf_vaddr, evt->out_data.buf_filled_len);
797 } else {
798 jpeg_out = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
799 jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
800 }
801
802 CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
803 qcamera_release_data_t release_data;
804 memset(&release_data, 0, sizeof(qcamera_release_data_t));
805 release_data.data = jpeg_mem;
806 CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
807 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
808 jpeg_mem,
809 0,
810 NULL,
811 &release_data);
812
813 end:
814 if (rc != NO_ERROR) {
815 // send error msg to upper layer
816 sendEvtNotify(CAMERA_MSG_ERROR,
817 UNKNOWN_ERROR,
818 0);
819
820 if (NULL != jpeg_mem) {
821 jpeg_mem->release(jpeg_mem);
822 jpeg_mem = NULL;
823 }
824 }
825 }
826
827 // wait up data proc thread to do next job,
828 // if previous request is blocked due to ongoing jpeg job
829 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
830
831 return rc;
832 }
833
834 /*===========================================================================
835 * FUNCTION : processPPData
836 *
837 * DESCRIPTION: process received frame after reprocess.
838 *
839 * PARAMETERS :
840 * @frame : received frame from reprocess channel.
841 *
842 * RETURN : int32_t type of status
843 * NO_ERROR -- success
844 * none-zero failure code
845 *
846 * NOTE : The frame after reprocess need to send to jpeg encoding.
847 *==========================================================================*/
processPPData(mm_camera_super_buf_t * frame)848 int32_t QCameraPostProcessor::processPPData(mm_camera_super_buf_t *frame)
849 {
850 bool needSuperBufMatch = m_parent->mParameters.generateThumbFromMain();
851 if (m_bInited == FALSE) {
852 ALOGE("%s: postproc not initialized yet", __func__);
853 return UNKNOWN_ERROR;
854 }
855
856 qcamera_pp_data_t *job = (qcamera_pp_data_t *)m_ongoingPPQ.dequeue();
857
858 if (!needSuperBufMatch && (job == NULL || job->src_frame == NULL) ) {
859 ALOGE("%s: Cannot find reprocess job", __func__);
860 return BAD_VALUE;
861 }
862
863 if (!needSuperBufMatch && (m_parent->mParameters.isNV16PictureFormat() ||
864 m_parent->mParameters.isNV21PictureFormat())) {
865 releaseSuperBuf(job->src_frame);
866 free(job->src_frame);
867 free(job);
868
869 if(m_parent->mParameters.isYUVFrameInfoNeeded())
870 setYUVFrameInfo(frame);
871 return processRawData(frame);
872 }
873
874 if (m_parent->isLongshotEnabled() &&
875 !m_parent->isCaptureShutterEnabled()) {
876 // play shutter sound for longshot
877 // after reprocess is done
878 // TODO: Move this after CAC done event
879 m_parent->playShutter();
880 }
881
882 qcamera_jpeg_data_t *jpeg_job =
883 (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
884 if (jpeg_job == NULL) {
885 ALOGE("%s: No memory for jpeg job", __func__);
886 return NO_MEMORY;
887 }
888
889 memset(jpeg_job, 0, sizeof(qcamera_jpeg_data_t));
890 jpeg_job->src_frame = frame;
891 jpeg_job->src_reproc_frame = job ? job->src_frame : NULL;
892 jpeg_job->src_reproc_bufs = job ? job->src_reproc_bufs : NULL;
893 jpeg_job->reproc_frame_release = job ? job->reproc_frame_release : false;
894
895 // find meta data frame
896 mm_camera_buf_def_t *meta_frame = NULL;
897 for (int i = 0; job && (i < job->src_frame->num_bufs); i++) {
898 // look through input superbuf
899 if (job->src_frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
900 meta_frame = job->src_frame->bufs[i];
901 break;
902 }
903 }
904
905 if (meta_frame == NULL) {
906 // look through reprocess superbuf
907 for (int i = 0; i < frame->num_bufs; i++) {
908 if (frame->bufs[i]->stream_type == CAM_STREAM_TYPE_METADATA) {
909 meta_frame = frame->bufs[i];
910 break;
911 }
912 }
913 }
914
915 if (meta_frame != NULL) {
916 // fill in meta data frame ptr
917 jpeg_job->metadata = (metadata_buffer_t *)meta_frame->buffer;
918 }
919
920 // free pp job buf
921 if (job) {
922 free(job);
923 }
924
925 // enqueu reprocessed frame to jpeg input queue
926 m_inputJpegQ.enqueue((void *)jpeg_job);
927
928 ALOGD("%s: %d] ", __func__, __LINE__);
929 // wait up data proc thread
930 m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
931
932 return NO_ERROR;
933 }
934
935 /*===========================================================================
936 * FUNCTION : findJpegJobByJobId
937 *
938 * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
939 *
940 * PARAMETERS :
941 * @jobId : job Id of the job
942 *
943 * RETURN : ptr to a jpeg job struct. NULL if not found.
944 *
945 * NOTE : Currently only one job is sending to mm-jpeg-interface for jpeg
946 * encoding. Therefore simply dequeue from the ongoing Jpeg Queue
947 * will serve the purpose to find the jpeg job.
948 *==========================================================================*/
findJpegJobByJobId(uint32_t jobId)949 qcamera_jpeg_data_t *QCameraPostProcessor::findJpegJobByJobId(uint32_t jobId)
950 {
951 qcamera_jpeg_data_t * job = NULL;
952 if (jobId == 0) {
953 ALOGE("%s: not a valid jpeg jobId", __func__);
954 return NULL;
955 }
956
957 // currely only one jpeg job ongoing, so simply dequeue the head
958 job = (qcamera_jpeg_data_t *)m_ongoingJpegQ.dequeue();
959 return job;
960 }
961
962 /*===========================================================================
963 * FUNCTION : releasePPInputData
964 *
965 * DESCRIPTION: callback function to release post process input data node
966 *
967 * PARAMETERS :
968 * @data : ptr to post process input data
969 * @user_data : user data ptr (QCameraReprocessor)
970 *
971 * RETURN : None
972 *==========================================================================*/
releasePPInputData(void * data,void * user_data)973 void QCameraPostProcessor::releasePPInputData(void *data, void *user_data)
974 {
975 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
976 if (NULL != pme) {
977 pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
978 }
979 }
980
981 /*===========================================================================
982 * FUNCTION : releaseJpegData
983 *
984 * DESCRIPTION: callback function to release jpeg job node
985 *
986 * PARAMETERS :
987 * @data : ptr to ongoing jpeg job data
988 * @user_data : user data ptr (QCameraReprocessor)
989 *
990 * RETURN : None
991 *==========================================================================*/
releaseJpegData(void * data,void * user_data)992 void QCameraPostProcessor::releaseJpegData(void *data, void *user_data)
993 {
994 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
995 if (NULL != pme) {
996 pme->releaseJpegJobData((qcamera_jpeg_data_t *)data);
997 CDBG_HIGH("%s : Rleased job ID %u", __func__,
998 ((qcamera_jpeg_data_t *)data)->jobId);
999 }
1000 }
1001
1002 /*===========================================================================
1003 * FUNCTION : releaseOngoingPPData
1004 *
1005 * DESCRIPTION: callback function to release ongoing postprocess job node
1006 *
1007 * PARAMETERS :
1008 * @data : ptr to onging postprocess job
1009 * @user_data : user data ptr (QCameraReprocessor)
1010 *
1011 * RETURN : None
1012 *==========================================================================*/
releaseOngoingPPData(void * data,void * user_data)1013 void QCameraPostProcessor::releaseOngoingPPData(void *data, void *user_data)
1014 {
1015 QCameraPostProcessor *pme = (QCameraPostProcessor *)user_data;
1016 if (NULL != pme) {
1017 qcamera_pp_data_t *pp_job = (qcamera_pp_data_t *)data;
1018 if (NULL != pp_job->src_frame) {
1019 if (!pp_job->reproc_frame_release) {
1020 pme->releaseSuperBuf(pp_job->src_frame);
1021 }
1022 free(pp_job->src_frame);
1023 pp_job->src_frame = NULL;
1024 }
1025 }
1026 }
1027
1028 /*===========================================================================
1029 * FUNCTION : releaseNotifyData
1030 *
1031 * DESCRIPTION: function to release internal resources in notify data struct
1032 *
1033 * PARAMETERS :
1034 * @user_data : ptr user data
1035 * @cookie : callback cookie
1036 * @cb_status : callback status
1037 *
1038 * RETURN : None
1039 *
1040 * NOTE : deallocate jpeg heap memory if it's not NULL
1041 *==========================================================================*/
releaseNotifyData(void * user_data,void * cookie,int32_t cb_status)1042 void QCameraPostProcessor::releaseNotifyData(void *user_data,
1043 void *cookie,
1044 int32_t cb_status)
1045 {
1046 qcamera_data_argm_t *app_cb = ( qcamera_data_argm_t * ) user_data;
1047 QCameraPostProcessor *postProc = ( QCameraPostProcessor * ) cookie;
1048 if ( ( NULL != app_cb ) && ( NULL != postProc ) ) {
1049
1050 if ( postProc->mUseSaveProc &&
1051 app_cb->release_data.unlinkFile &&
1052 ( NO_ERROR != cb_status ) ) {
1053
1054 String8 unlinkPath((const char *) app_cb->release_data.data->data,
1055 app_cb->release_data.data->size);
1056 int rc = unlink(unlinkPath.string());
1057 CDBG_HIGH("%s : Unlinking stored file rc = %d",
1058 __func__,
1059 rc);
1060 }
1061
1062 if (app_cb && NULL != app_cb->release_data.data) {
1063 app_cb->release_data.data->release(app_cb->release_data.data);
1064 app_cb->release_data.data = NULL;
1065 }
1066 if (app_cb && NULL != app_cb->release_data.frame) {
1067 postProc->releaseSuperBuf(app_cb->release_data.frame);
1068 free(app_cb->release_data.frame);
1069 app_cb->release_data.frame = NULL;
1070 }
1071 if (app_cb && NULL != app_cb->release_data.streamBufs) {
1072 app_cb->release_data.streamBufs->deallocate();
1073 delete app_cb->release_data.streamBufs;
1074 app_cb->release_data.streamBufs = NULL;
1075 }
1076 free(app_cb);
1077 }
1078 }
1079
1080 /*===========================================================================
1081 * FUNCTION : releaseSuperBuf
1082 *
1083 * DESCRIPTION: function to release a superbuf frame by returning back to kernel
1084 *
1085 * PARAMETERS :
1086 * @super_buf : ptr to the superbuf frame
1087 *
1088 * RETURN : None
1089 *==========================================================================*/
releaseSuperBuf(mm_camera_super_buf_t * super_buf)1090 void QCameraPostProcessor::releaseSuperBuf(mm_camera_super_buf_t *super_buf)
1091 {
1092 QCameraChannel *pChannel = NULL;
1093
1094 if (NULL != super_buf) {
1095 pChannel = m_parent->getChannelByHandle(super_buf->ch_id);
1096
1097 if ( NULL == pChannel ) {
1098 if (m_pReprocChannel != NULL &&
1099 m_pReprocChannel->getMyHandle() == super_buf->ch_id) {
1100 pChannel = m_pReprocChannel;
1101 }
1102 }
1103
1104 if (pChannel != NULL) {
1105 pChannel->bufDone(super_buf);
1106 } else {
1107 ALOGE(" %s : Channel id %d not found!!",
1108 __func__,
1109 super_buf->ch_id);
1110 }
1111 }
1112 }
1113
1114 /*===========================================================================
1115 * FUNCTION : releaseJpegJobData
1116 *
1117 * DESCRIPTION: function to release internal resources in jpeg job struct
1118 *
1119 * PARAMETERS :
1120 * @job : ptr to jpeg job struct
1121 *
1122 * RETURN : None
1123 *
1124 * NOTE : original source frame need to be queued back to kernel for
1125 * future use. Output buf of jpeg job need to be released since
1126 * it's allocated for each job. Exif object need to be deleted.
1127 *==========================================================================*/
releaseJpegJobData(qcamera_jpeg_data_t * job)1128 void QCameraPostProcessor::releaseJpegJobData(qcamera_jpeg_data_t *job)
1129 {
1130 CDBG("%s: E", __func__);
1131 if (NULL != job) {
1132 if (NULL != job->src_reproc_frame) {
1133 if (!job->reproc_frame_release) {
1134 releaseSuperBuf(job->src_reproc_frame);
1135 }
1136 free(job->src_reproc_frame);
1137 job->src_reproc_frame = NULL;
1138 }
1139
1140 if (NULL != job->src_frame) {
1141 releaseSuperBuf(job->src_frame);
1142 free(job->src_frame);
1143 job->src_frame = NULL;
1144 }
1145
1146 if (NULL != job->pJpegExifObj) {
1147 delete job->pJpegExifObj;
1148 job->pJpegExifObj = NULL;
1149 }
1150
1151 if (NULL != job->src_reproc_bufs) {
1152 delete [] job->src_reproc_bufs;
1153 }
1154
1155 }
1156 CDBG("%s: X", __func__);
1157 }
1158
1159 /*===========================================================================
1160 * FUNCTION : releaseSaveJobData
1161 *
1162 * DESCRIPTION: function to release internal resources in store jobs
1163 *
1164 * PARAMETERS :
1165 * @job : ptr to save job struct
1166 *
1167 * RETURN : None
1168 *
1169 *==========================================================================*/
releaseSaveJobData(void * data,void * user_data)1170 void QCameraPostProcessor::releaseSaveJobData(void *data, void *user_data)
1171 {
1172 CDBG("%s: E", __func__);
1173
1174 QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
1175 if (NULL == pme) {
1176 ALOGE("%s: Invalid postproc handle", __func__);
1177 return;
1178 }
1179
1180 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) data;
1181 if (job_data == NULL) {
1182 ALOGE("%s: Invalid jpeg event data", __func__);
1183 return;
1184 }
1185
1186 // find job by jobId
1187 qcamera_jpeg_data_t *job = pme->findJpegJobByJobId(job_data->jobId);
1188
1189 if (NULL != job) {
1190 pme->releaseJpegJobData(job);
1191 free(job);
1192 } else {
1193 ALOGE("%s : Invalid jpeg job", __func__);
1194 }
1195
1196 CDBG("%s: X", __func__);
1197 }
1198
1199 /*===========================================================================
1200 * FUNCTION : releaseRawData
1201 *
1202 * DESCRIPTION: function to release internal resources in store jobs
1203 *
1204 * PARAMETERS :
1205 * @job : ptr to save job struct
1206 *
1207 * RETURN : None
1208 *
1209 *==========================================================================*/
releaseRawData(void * data,void * user_data)1210 void QCameraPostProcessor::releaseRawData(void *data, void *user_data)
1211 {
1212 CDBG("%s: E", __func__);
1213
1214 QCameraPostProcessor *pme = (QCameraPostProcessor *) user_data;
1215 if (NULL == pme) {
1216 ALOGE("%s: Invalid postproc handle", __func__);
1217 return;
1218 }
1219 mm_camera_super_buf_t *super_buf = (mm_camera_super_buf_t *) data;
1220 pme->releaseSuperBuf(super_buf);
1221
1222 CDBG("%s: X", __func__);
1223 }
1224
1225
1226 /*===========================================================================
1227 * FUNCTION : getColorfmtFromImgFmt
1228 *
1229 * DESCRIPTION: function to return jpeg color format based on its image format
1230 *
1231 * PARAMETERS :
1232 * @img_fmt : image format
1233 *
1234 * RETURN : jpeg color format that can be understandable by omx lib
1235 *==========================================================================*/
getColorfmtFromImgFmt(cam_format_t img_fmt)1236 mm_jpeg_color_format QCameraPostProcessor::getColorfmtFromImgFmt(cam_format_t img_fmt)
1237 {
1238 switch (img_fmt) {
1239 case CAM_FORMAT_YUV_420_NV21:
1240 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1241 case CAM_FORMAT_YUV_420_NV21_ADRENO:
1242 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1243 case CAM_FORMAT_YUV_420_NV12:
1244 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1245 case CAM_FORMAT_YUV_420_YV12:
1246 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2;
1247 case CAM_FORMAT_YUV_422_NV61:
1248 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1;
1249 case CAM_FORMAT_YUV_422_NV16:
1250 return MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1;
1251 default:
1252 return MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
1253 }
1254 }
1255
1256 /*===========================================================================
1257 * FUNCTION : getJpegImgTypeFromImgFmt
1258 *
1259 * DESCRIPTION: function to return jpeg encode image type based on its image format
1260 *
1261 * PARAMETERS :
1262 * @img_fmt : image format
1263 *
1264 * RETURN : return jpeg source image format (YUV or Bitstream)
1265 *==========================================================================*/
getJpegImgTypeFromImgFmt(cam_format_t img_fmt)1266 mm_jpeg_format_t QCameraPostProcessor::getJpegImgTypeFromImgFmt(cam_format_t img_fmt)
1267 {
1268 switch (img_fmt) {
1269 case CAM_FORMAT_YUV_420_NV21:
1270 case CAM_FORMAT_YUV_420_NV21_ADRENO:
1271 case CAM_FORMAT_YUV_420_NV12:
1272 case CAM_FORMAT_YUV_420_YV12:
1273 case CAM_FORMAT_YUV_422_NV61:
1274 case CAM_FORMAT_YUV_422_NV16:
1275 return MM_JPEG_FMT_YUV;
1276 default:
1277 return MM_JPEG_FMT_YUV;
1278 }
1279 }
1280
1281 /*===========================================================================
1282 * FUNCTION : queryStreams
1283 *
1284 * DESCRIPTION: utility method for retrieving main, thumbnail and reprocess
1285 * streams and frame from bundled super buffer
1286 *
1287 * PARAMETERS :
1288 * @main : ptr to main stream if present
1289 * @thumb : ptr to thumbnail stream if present
1290 * @reproc : ptr to reprocess stream if present
1291 * @main_image : ptr to main image if present
1292 * @thumb_image: ptr to thumbnail image if present
1293 * @frame : bundled super buffer
1294 * @reproc_frame : bundled source frame buffer
1295 *
1296 * RETURN : int32_t type of status
1297 * NO_ERROR -- success
1298 * none-zero failure code
1299 *==========================================================================*/
queryStreams(QCameraStream ** main,QCameraStream ** thumb,QCameraStream ** reproc,mm_camera_buf_def_t ** main_image,mm_camera_buf_def_t ** thumb_image,mm_camera_super_buf_t * frame,mm_camera_super_buf_t * reproc_frame)1300 int32_t QCameraPostProcessor::queryStreams(QCameraStream **main,
1301 QCameraStream **thumb,
1302 QCameraStream **reproc,
1303 mm_camera_buf_def_t **main_image,
1304 mm_camera_buf_def_t **thumb_image,
1305 mm_camera_super_buf_t *frame,
1306 mm_camera_super_buf_t *reproc_frame)
1307 {
1308 if (NULL == frame) {
1309 return NO_INIT;
1310 }
1311
1312 QCameraChannel *pChannel = m_parent->getChannelByHandle(frame->ch_id);
1313 // check reprocess channel if not found
1314 if (pChannel == NULL) {
1315 if (m_pReprocChannel != NULL &&
1316 m_pReprocChannel->getMyHandle() == frame->ch_id) {
1317 pChannel = m_pReprocChannel;
1318 }
1319 }
1320 if (pChannel == NULL) {
1321 ALOGD("%s: No corresponding channel (ch_id = %d) exist, return here",
1322 __func__, frame->ch_id);
1323 return BAD_VALUE;
1324 }
1325
1326 // Use snapshot stream to create thumbnail if snapshot and preview
1327 // flip settings doesn't match in ZSL mode.
1328 bool thumb_stream_needed = !m_parent->isZSLMode() ||
1329 (m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_SNAPSHOT) ==
1330 m_parent->mParameters.getFlipMode(CAM_STREAM_TYPE_PREVIEW));
1331
1332 *main = *thumb = *reproc = NULL;
1333 *main_image = *thumb_image = NULL;
1334 // find snapshot frame and thumnail frame
1335 for (int i = 0; i < frame->num_bufs; i++) {
1336 QCameraStream *pStream =
1337 pChannel->getStreamByHandle(frame->bufs[i]->stream_id);
1338 if (pStream != NULL) {
1339 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
1340 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
1341 *main= pStream;
1342 *main_image = frame->bufs[i];
1343 } else if (thumb_stream_needed &&
1344 (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1345 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW) ||
1346 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1347 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_POSTVIEW))) {
1348 *thumb = pStream;
1349 *thumb_image = frame->bufs[i];
1350 }
1351 if (pStream->isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC) ) {
1352 *reproc = pStream;
1353 }
1354 }
1355 }
1356
1357 if (thumb_stream_needed && *thumb_image == NULL && reproc_frame != NULL) {
1358 QCameraChannel *pSrcReprocChannel = NULL;
1359 pSrcReprocChannel = m_parent->getChannelByHandle(reproc_frame->ch_id);
1360 if (pSrcReprocChannel != NULL) {
1361 // find thumbnail frame
1362 for (int i = 0; i < reproc_frame->num_bufs; i++) {
1363 QCameraStream *pStream =
1364 pSrcReprocChannel->getStreamByHandle(
1365 reproc_frame->bufs[i]->stream_id);
1366 if (pStream != NULL) {
1367 if (pStream->isTypeOf(CAM_STREAM_TYPE_PREVIEW) ||
1368 pStream->isTypeOf(CAM_STREAM_TYPE_POSTVIEW)) {
1369 *thumb = pStream;
1370 *thumb_image = reproc_frame->bufs[i];
1371 }
1372 }
1373 }
1374 }
1375 }
1376
1377 if (m_parent->mParameters.generateThumbFromMain()) {
1378 *thumb = NULL;
1379 *thumb_image = NULL;
1380 }
1381
1382 return NO_ERROR;
1383 }
1384
1385 /*===========================================================================
1386 * FUNCTION : syncStreamParams
1387 *
1388 * DESCRIPTION: Query the runtime parameters of all streams included
1389 * in the main and reprocessed frames
1390 *
1391 * PARAMETERS :
1392 * @frame : Main image super buffer
1393 * @reproc_frame : Image supper buffer that got processed
1394 *
1395 * RETURN : int32_t type of status
1396 * NO_ERROR -- success
1397 * none-zero failure code
1398 *==========================================================================*/
syncStreamParams(mm_camera_super_buf_t * frame,mm_camera_super_buf_t * reproc_frame)1399 int32_t QCameraPostProcessor::syncStreamParams(mm_camera_super_buf_t *frame,
1400 mm_camera_super_buf_t *reproc_frame)
1401 {
1402 QCameraStream *reproc_stream = NULL;
1403 QCameraStream *main_stream = NULL;
1404 QCameraStream *thumb_stream = NULL;
1405 mm_camera_buf_def_t *main_frame = NULL;
1406 mm_camera_buf_def_t *thumb_frame = NULL;
1407 int32_t ret = NO_ERROR;
1408
1409 ret = queryStreams(&main_stream,
1410 &thumb_stream,
1411 &reproc_stream,
1412 &main_frame,
1413 &thumb_frame,
1414 frame,
1415 reproc_frame);
1416 if (NO_ERROR != ret) {
1417 ALOGE("%s : Camera streams query from input frames failed %d",
1418 __func__,
1419 ret);
1420 return ret;
1421 }
1422
1423 if (NULL != main_stream) {
1424 ret = main_stream->syncRuntimeParams();
1425 if (NO_ERROR != ret) {
1426 ALOGE("%s : Syncing of main stream runtime parameters failed %d",
1427 __func__,
1428 ret);
1429 return ret;
1430 }
1431 }
1432
1433 if (NULL != thumb_stream) {
1434 ret = thumb_stream->syncRuntimeParams();
1435 if (NO_ERROR != ret) {
1436 ALOGE("%s : Syncing of thumb stream runtime parameters failed %d",
1437 __func__,
1438 ret);
1439 return ret;
1440 }
1441 }
1442
1443 if ((NULL != reproc_stream) && (reproc_stream != main_stream)) {
1444 ret = reproc_stream->syncRuntimeParams();
1445 if (NO_ERROR != ret) {
1446 ALOGE("%s : Syncing of reproc stream runtime parameters failed %d",
1447 __func__,
1448 ret);
1449 return ret;
1450 }
1451 }
1452
1453 return ret;
1454 }
1455
1456 /*===========================================================================
1457 * FUNCTION : encodeData
1458 *
1459 * DESCRIPTION: function to prepare encoding job information and send to
1460 * mm-jpeg-interface to do the encoding job
1461 *
1462 * PARAMETERS :
1463 * @jpeg_job_data : ptr to a struct saving job related information
1464 * @needNewSess : flag to indicate if a new jpeg encoding session need
1465 * to be created. After creation, this flag will be toggled
1466 *
1467 * RETURN : int32_t type of status
1468 * NO_ERROR -- success
1469 * none-zero failure code
1470 *==========================================================================*/
encodeData(qcamera_jpeg_data_t * jpeg_job_data,uint8_t & needNewSess)1471 int32_t QCameraPostProcessor::encodeData(qcamera_jpeg_data_t *jpeg_job_data,
1472 uint8_t &needNewSess)
1473 {
1474 CDBG("%s : E", __func__);
1475 int32_t ret = NO_ERROR;
1476 mm_jpeg_job_t jpg_job;
1477 uint32_t jobId = 0;
1478 QCameraStream *reproc_stream = NULL;
1479 QCameraStream *main_stream = NULL;
1480 mm_camera_buf_def_t *main_frame = NULL;
1481 QCameraStream *thumb_stream = NULL;
1482 mm_camera_buf_def_t *thumb_frame = NULL;
1483 mm_camera_super_buf_t *recvd_frame = jpeg_job_data->src_frame;
1484 cam_rect_t crop;
1485 cam_stream_parm_buffer_t param;
1486 cam_stream_img_prop_t imgProp;
1487
1488 // find channel
1489 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
1490 // check reprocess channel if not found
1491 if (pChannel == NULL) {
1492 if (m_pReprocChannel != NULL &&
1493 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1494 pChannel = m_pReprocChannel;
1495 }
1496 }
1497
1498 if (pChannel == NULL) {
1499 ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
1500 __func__, __LINE__, recvd_frame->ch_id);
1501 return BAD_VALUE;
1502 }
1503
1504 const int jpeg_rotation = m_parent->getJpegRotation();
1505
1506 ret = queryStreams(&main_stream,
1507 &thumb_stream,
1508 &reproc_stream,
1509 &main_frame,
1510 &thumb_frame,
1511 recvd_frame,
1512 jpeg_job_data->src_reproc_frame);
1513 if (NO_ERROR != ret) {
1514 return ret;
1515 }
1516
1517 if(NULL == main_frame){
1518 ALOGE("%s : Main frame is NULL", __func__);
1519 return BAD_VALUE;
1520 }
1521
1522 if(NULL == thumb_frame){
1523 CDBG("%s : Thumbnail frame does not exist", __func__);
1524 }
1525
1526 QCameraMemory *memObj = (QCameraMemory *)main_frame->mem_info;
1527 if (NULL == memObj) {
1528 ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
1529 return NO_MEMORY;
1530 }
1531
1532 // dump snapshot frame if enabled
1533 m_parent->dumpFrameToFile(main_stream, main_frame, QCAMERA_DUMP_FRM_SNAPSHOT);
1534
1535 // send upperlayer callback for raw image
1536 camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false);
1537 if (NULL != m_parent->mDataCb &&
1538 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
1539 qcamera_callback_argm_t cbArg;
1540 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1541 cbArg.cb_type = QCAMERA_DATA_CALLBACK;
1542 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
1543 cbArg.data = mem;
1544 cbArg.index = 1;
1545 m_parent->m_cbNotifier.notifyCallback(cbArg);
1546 }
1547 if (NULL != m_parent->mNotifyCb &&
1548 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
1549 qcamera_callback_argm_t cbArg;
1550 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1551 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
1552 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
1553 cbArg.ext1 = 0;
1554 cbArg.ext2 = 0;
1555 m_parent->m_cbNotifier.notifyCallback(cbArg);
1556 }
1557
1558 if (thumb_frame != NULL) {
1559 // dump thumbnail frame if enabled
1560 m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL);
1561 }
1562
1563 if (mJpegClientHandle <= 0) {
1564 ALOGE("%s: Error: bug here, mJpegClientHandle is 0", __func__);
1565 return UNKNOWN_ERROR;
1566 }
1567
1568 if (needNewSess) {
1569 // create jpeg encoding session
1570 mm_jpeg_encode_params_t encodeParam;
1571 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
1572 getJpegEncodingConfig(encodeParam, main_stream, thumb_stream);
1573 CDBG_HIGH("[KPI Perf] %s : call jpeg create_session", __func__);
1574 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
1575 if (ret != NO_ERROR) {
1576 ALOGE("%s: error creating a new jpeg encoding session", __func__);
1577 return ret;
1578 }
1579 needNewSess = FALSE;
1580 }
1581 // Fill in new job
1582 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
1583 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
1584 jpg_job.encode_job.session_id = mJpegSessionId;
1585 jpg_job.encode_job.src_index = main_frame->buf_idx;
1586 jpg_job.encode_job.dst_index = 0;
1587
1588 if (mJpegMemOpt) {
1589 jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index;
1590 } else if (mUseJpegBurst) {
1591 jpg_job.encode_job.dst_index = -1;
1592 }
1593
1594 cam_dimension_t src_dim;
1595 memset(&src_dim, 0, sizeof(cam_dimension_t));
1596 main_stream->getFrameDimension(src_dim);
1597
1598 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
1599 bool img_feature_enabled =
1600 m_parent->mParameters.isUbiFocusEnabled() ||
1601 m_parent->mParameters.isChromaFlashEnabled() ||
1602 m_parent->mParameters.isOptiZoomEnabled();
1603
1604 CDBG_HIGH("%s:%d] Crop needed %d", __func__, __LINE__, img_feature_enabled);
1605 crop.left = 0;
1606 crop.top = 0;
1607 crop.height = src_dim.height;
1608 crop.width = src_dim.width;
1609
1610 param = main_stream->getOutputCrop();
1611 for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
1612 if (param.outputCrop.crop_info[i].stream_id
1613 == main_stream->getMyServerID()) {
1614 crop = param.outputCrop.crop_info[i].crop;
1615 main_stream->setCropInfo(crop);
1616 }
1617 }
1618 if (img_feature_enabled) {
1619 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
1620
1621 param = main_stream->getImgProp();
1622 imgProp = param.imgProp;
1623 main_stream->setCropInfo(imgProp.crop);
1624 crop = imgProp.crop;
1625 thumb_stream = NULL; /* use thumbnail from main image */
1626 if (imgProp.is_raw_image) {
1627 camera_memory_t *mem = memObj->getMemory(
1628 main_frame->buf_idx, false);
1629 ALOGE("%s:%d] Process raw image %p %d", __func__, __LINE__,
1630 mem, imgProp.size);
1631 /* dump image */
1632 if (mem && mem->data) {
1633 CAM_DUMP_TO_FILE("/data/local/ubifocus", "DepthMapImage",
1634 -1, "y",
1635 (uint8_t *)mem->data,
1636 imgProp.size);
1637 }
1638 return NO_ERROR;
1639 }
1640 }
1641
1642 cam_dimension_t dst_dim;
1643
1644 if (hdr_output_crop && crop.height) {
1645 dst_dim.height = crop.height;
1646 } else {
1647 dst_dim.height = src_dim.height;
1648 }
1649 if (hdr_output_crop && crop.width) {
1650 dst_dim.width = crop.width;
1651 } else {
1652 dst_dim.width = src_dim.width;
1653 }
1654
1655 // main dim
1656 jpg_job.encode_job.main_dim.src_dim = src_dim;
1657 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
1658 jpg_job.encode_job.main_dim.crop = crop;
1659
1660 // get exif data
1661 QCameraExif *pJpegExifObj = m_parent->getExifData();
1662 jpeg_job_data->pJpegExifObj = pJpegExifObj;
1663 if (pJpegExifObj != NULL) {
1664 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
1665 jpg_job.encode_job.exif_info.numOfEntries =
1666 pJpegExifObj->getNumOfEntries();
1667 }
1668
1669 // set rotation only when no online rotation or offline pp rotation is done before
1670 if (!m_parent->needRotationReprocess()) {
1671 jpg_job.encode_job.rotation = jpeg_rotation;
1672 }
1673 CDBG_HIGH("%s: jpeg rotation is set to %d", __func__, jpg_job.encode_job.rotation);
1674
1675 // thumbnail dim
1676 if (m_bThumbnailNeeded == TRUE) {
1677 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim);
1678
1679 if (thumb_stream == NULL) {
1680 // need jpeg thumbnail, but no postview/preview stream exists
1681 // we use the main stream/frame to encode thumbnail
1682 thumb_stream = main_stream;
1683 thumb_frame = main_frame;
1684 if (m_parent->needRotationReprocess() &&
1685 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) {
1686 // swap thumbnail dimensions
1687 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim;
1688 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height;
1689 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width;
1690 }
1691 }
1692
1693 memset(&src_dim, 0, sizeof(cam_dimension_t));
1694 thumb_stream->getFrameDimension(src_dim);
1695 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
1696
1697 // crop is the same if frame is the same
1698 if (thumb_frame != main_frame) {
1699 crop.left = 0;
1700 crop.top = 0;
1701 crop.height = src_dim.height;
1702 crop.width = src_dim.width;
1703
1704 param = thumb_stream->getOutputCrop();
1705 for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
1706 if (param.outputCrop.crop_info[i].stream_id
1707 == thumb_stream->getMyServerID()) {
1708 crop = param.outputCrop.crop_info[i].crop;
1709 thumb_stream->setCropInfo(crop);
1710 }
1711 }
1712 }
1713
1714 jpg_job.encode_job.thumb_dim.crop = crop;
1715 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
1716 CDBG_HIGH("%s, thumbnail src w/h (%dx%d), dst w/h (%dx%d)", __func__,
1717 jpg_job.encode_job.thumb_dim.src_dim.width,
1718 jpg_job.encode_job.thumb_dim.src_dim.height,
1719 jpg_job.encode_job.thumb_dim.dst_dim.width,
1720 jpg_job.encode_job.thumb_dim.dst_dim.height);
1721 }
1722
1723 if (jpeg_job_data->metadata != NULL) {
1724 // fill in meta data frame ptr
1725 jpg_job.encode_job.p_metadata = jpeg_job_data->metadata;
1726 }
1727
1728 jpg_job.encode_job.hal_version = CAM_HAL_V1;
1729 jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
1730
1731 /* Init the QTable */
1732 for (int i = 0; i < QTABLE_MAX; i++) {
1733 jpg_job.encode_job.qtable_set[i] = 0;
1734 }
1735
1736 CDBG_HIGH("[KPI Perf] %s : PROFILE_JPEG_JOB_START", __func__);
1737 ret = mJpegHandle.start_job(&jpg_job, &jobId);
1738 if (ret == NO_ERROR) {
1739 // remember job info
1740 jpeg_job_data->jobId = jobId;
1741 }
1742
1743 return ret;
1744 }
1745
1746 /*===========================================================================
1747 * FUNCTION : processRawImageImpl
1748 *
1749 * DESCRIPTION: function to send raw image to upper layer
1750 *
1751 * PARAMETERS :
1752 * @recvd_frame : frame to be encoded
1753 *
1754 * RETURN : int32_t type of status
1755 * NO_ERROR -- success
1756 * none-zero failure code
1757 *==========================================================================*/
processRawImageImpl(mm_camera_super_buf_t * recvd_frame)1758 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame)
1759 {
1760 int32_t rc = NO_ERROR;
1761
1762 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
1763 QCameraStream *pStream = NULL;
1764 mm_camera_buf_def_t *frame = NULL;
1765 // check reprocess channel if not found
1766 if (pChannel == NULL) {
1767 if (m_pReprocChannel != NULL &&
1768 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
1769 pChannel = m_pReprocChannel;
1770 }
1771 }
1772 if (pChannel == NULL) {
1773 ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
1774 __func__, __LINE__, recvd_frame->ch_id);
1775 return BAD_VALUE;
1776 }
1777
1778 // find snapshot frame
1779 for (int i = 0; i < recvd_frame->num_bufs; i++) {
1780 QCameraStream *pCurStream =
1781 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
1782 if (pCurStream != NULL) {
1783 if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
1784 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) ||
1785 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
1786 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) {
1787 pStream = pCurStream;
1788 frame = recvd_frame->bufs[i];
1789 break;
1790 }
1791 }
1792 }
1793
1794 if ( NULL == frame ) {
1795 ALOGE("%s: No valid raw buffer", __func__);
1796 return BAD_VALUE;
1797 }
1798
1799 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info;
1800 bool zslChannelUsed = m_parent->isZSLMode() &&
1801 ( pChannel != m_pReprocChannel );
1802 camera_memory_t *raw_mem = NULL;
1803
1804 if (rawMemObj != NULL) {
1805 if (zslChannelUsed) {
1806 raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
1807 } else {
1808 raw_mem = m_parent->mGetMemory(-1,
1809 frame->frame_len,
1810 1,
1811 m_parent->mCallbackCookie);
1812 if (NULL == raw_mem) {
1813 ALOGE("%s : Not enough memory for RAW cb ", __func__);
1814 return NO_MEMORY;
1815 }
1816 memcpy(raw_mem->data, frame->buffer, frame->frame_len);
1817 }
1818 }
1819
1820 if (NULL != rawMemObj && NULL != raw_mem) {
1821 // dump frame into file
1822 if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT ||
1823 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
1824 // for YUV422 NV16 case
1825 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT);
1826 } else {
1827 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW);
1828 }
1829
1830 // send data callback / notify for RAW_IMAGE
1831 if (NULL != m_parent->mDataCb &&
1832 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
1833 qcamera_callback_argm_t cbArg;
1834 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1835 cbArg.cb_type = QCAMERA_DATA_CALLBACK;
1836 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
1837 cbArg.data = raw_mem;
1838 cbArg.index = 0;
1839 m_parent->m_cbNotifier.notifyCallback(cbArg);
1840 }
1841 if (NULL != m_parent->mNotifyCb &&
1842 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
1843 qcamera_callback_argm_t cbArg;
1844 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
1845 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
1846 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
1847 cbArg.ext1 = 0;
1848 cbArg.ext2 = 0;
1849 m_parent->m_cbNotifier.notifyCallback(cbArg);
1850 }
1851
1852 if ((m_parent->mDataCb != NULL) &&
1853 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
1854 qcamera_release_data_t release_data;
1855 memset(&release_data, 0, sizeof(qcamera_release_data_t));
1856 if ( zslChannelUsed ) {
1857 release_data.frame = recvd_frame;
1858 } else {
1859 release_data.data = raw_mem;
1860 }
1861 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
1862 raw_mem,
1863 0,
1864 NULL,
1865 &release_data);
1866 } else {
1867 raw_mem->release(raw_mem);
1868 }
1869 } else {
1870 ALOGE("%s: Cannot get raw mem", __func__);
1871 rc = UNKNOWN_ERROR;
1872 }
1873
1874 return rc;
1875 }
1876
1877 /*===========================================================================
1878 * FUNCTION : dataSaveRoutine
1879 *
1880 * DESCRIPTION: data saving routine
1881 *
1882 * PARAMETERS :
1883 * @data : user data ptr (QCameraPostProcessor)
1884 *
1885 * RETURN : None
1886 *==========================================================================*/
dataSaveRoutine(void * data)1887 void *QCameraPostProcessor::dataSaveRoutine(void *data)
1888 {
1889 int running = 1;
1890 int ret;
1891 uint8_t is_active = FALSE;
1892 QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
1893 QCameraCmdThread *cmdThread = &pme->m_saveProcTh;
1894 char saveName[PROPERTY_VALUE_MAX];
1895
1896 CDBG_HIGH("%s: E", __func__);
1897 do {
1898 do {
1899 ret = cam_sem_wait(&cmdThread->cmd_sem);
1900 if (ret != 0 && errno != EINVAL) {
1901 ALOGE("%s: cam_sem_wait error (%s)",
1902 __func__, strerror(errno));
1903 return NULL;
1904 }
1905 } while (ret != 0);
1906
1907 // we got notified about new cmd avail in cmd queue
1908 camera_cmd_type_t cmd = cmdThread->getCmd();
1909 switch (cmd) {
1910 case CAMERA_CMD_TYPE_START_DATA_PROC:
1911 CDBG_HIGH("%s: start data proc", __func__);
1912 is_active = TRUE;
1913 pme->m_inputSaveQ.init();
1914 break;
1915 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
1916 {
1917 CDBG_HIGH("%s: stop data proc", __func__);
1918 is_active = FALSE;
1919
1920 // flush input save Queue
1921 pme->m_inputSaveQ.flush();
1922
1923 // signal cmd is completed
1924 cam_sem_post(&cmdThread->sync_sem);
1925 }
1926 break;
1927 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1928 {
1929 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
1930
1931 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue();
1932 if (job_data == NULL) {
1933 ALOGE("%s: Invalid jpeg event data", __func__);
1934 continue;
1935 }
1936
1937 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId);
1938
1939 CDBG_HIGH("[KPI Perf] %s : jpeg job %d", __func__, job_data->jobId);
1940
1941 if (is_active == TRUE) {
1942 memset(saveName, '\0', sizeof(saveName));
1943 snprintf(saveName,
1944 sizeof(saveName),
1945 QCameraPostProcessor::STORE_LOCATION,
1946 pme->mSaveFrmCnt);
1947
1948 int file_fd = open(saveName, O_RDWR | O_CREAT, 0655);
1949 if (file_fd > 0) {
1950 size_t written_len = write(file_fd,
1951 job_data->out_data.buf_vaddr,
1952 job_data->out_data.buf_filled_len);
1953 if ( job_data->out_data.buf_filled_len != written_len ) {
1954 ALOGE("%s: Failed save complete data %d bytes written instead of %d bytes!",
1955 __func__,
1956 written_len,
1957 job_data->out_data.buf_filled_len);
1958 } else {
1959 CDBG_HIGH("%s: written number of bytes %d\n", __func__, written_len);
1960 }
1961
1962 close(file_fd);
1963 } else {
1964 ALOGE("%s: fail t open file for saving", __func__);
1965 }
1966 pme->mSaveFrmCnt++;
1967
1968 camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1,
1969 strlen(saveName),
1970 1,
1971 pme->m_parent->mCallbackCookie);
1972 if (NULL == jpeg_mem) {
1973 ret = NO_MEMORY;
1974 ALOGE("%s : getMemory for jpeg, ret = NO_MEMORY", __func__);
1975 goto end;
1976 }
1977 memcpy(jpeg_mem->data, saveName, strlen(saveName));
1978
1979 CDBG_HIGH("%s : Calling upperlayer callback to store JPEG image", __func__);
1980 qcamera_release_data_t release_data;
1981 memset(&release_data, 0, sizeof(qcamera_release_data_t));
1982 release_data.data = jpeg_mem;
1983 release_data.unlinkFile = true;
1984 CDBG_HIGH("[KPI Perf] %s: PROFILE_JPEG_CB ",__func__);
1985 ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
1986 jpeg_mem,
1987 0,
1988 NULL,
1989 &release_data);
1990 }
1991
1992 end:
1993 free(job_data);
1994 }
1995 break;
1996 case CAMERA_CMD_TYPE_EXIT:
1997 CDBG_HIGH("%s : save thread exit", __func__);
1998 running = 0;
1999 break;
2000 default:
2001 break;
2002 }
2003 } while (running);
2004 CDBG_HIGH("%s: X", __func__);
2005 return NULL;
2006 }
2007
2008 /*===========================================================================
2009 * FUNCTION : dataProcessRoutine
2010 *
2011 * DESCRIPTION: data process routine that handles input data either from input
2012 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
2013 * reprocess.
2014 *
2015 * PARAMETERS :
2016 * @data : user data ptr (QCameraPostProcessor)
2017 *
2018 * RETURN : None
2019 *==========================================================================*/
dataProcessRoutine(void * data)2020 void *QCameraPostProcessor::dataProcessRoutine(void *data)
2021 {
2022 int running = 1;
2023 int ret;
2024 uint8_t is_active = FALSE;
2025 QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
2026 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
2027
2028 CDBG_HIGH("%s: E", __func__);
2029 do {
2030 do {
2031 ret = cam_sem_wait(&cmdThread->cmd_sem);
2032 if (ret != 0 && errno != EINVAL) {
2033 ALOGE("%s: cam_sem_wait error (%s)",
2034 __func__, strerror(errno));
2035 return NULL;
2036 }
2037 } while (ret != 0);
2038
2039 // we got notified about new cmd avail in cmd queue
2040 camera_cmd_type_t cmd = cmdThread->getCmd();
2041 switch (cmd) {
2042 case CAMERA_CMD_TYPE_START_DATA_PROC:
2043 CDBG_HIGH("%s: start data proc", __func__);
2044 is_active = TRUE;
2045
2046 pme->m_ongoingPPQ.init();
2047 pme->m_inputJpegQ.init();
2048 pme->m_inputPPQ.init();
2049 pme->m_inputRawQ.init();
2050
2051 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC,
2052 FALSE,
2053 FALSE);
2054
2055 // signal cmd is completed
2056 cam_sem_post(&cmdThread->sync_sem);
2057
2058 break;
2059 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
2060 {
2061 CDBG_HIGH("%s: stop data proc", __func__);
2062 is_active = FALSE;
2063
2064 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC,
2065 TRUE,
2066 TRUE);
2067 // cancel all ongoing jpeg jobs
2068 qcamera_jpeg_data_t *jpeg_job =
2069 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2070 while (jpeg_job != NULL) {
2071 pme->mJpegHandle.abort_job(jpeg_job->jobId);
2072
2073 pme->releaseJpegJobData(jpeg_job);
2074 free(jpeg_job);
2075
2076 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2077 }
2078
2079 // destroy jpeg encoding session
2080 if ( 0 < pme->mJpegSessionId ) {
2081 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
2082 pme->mJpegSessionId = 0;
2083 }
2084
2085 // free jpeg out buf and exif obj
2086 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem,
2087 pme->m_JpegOutputMemCount);
2088
2089 if (pme->m_pJpegExifObj != NULL) {
2090 delete pme->m_pJpegExifObj;
2091 pme->m_pJpegExifObj = NULL;
2092 }
2093
2094 // stop reproc channel if exists
2095 if (pme->m_pReprocChannel != NULL) {
2096 pme->m_pReprocChannel->stop();
2097 delete pme->m_pReprocChannel;
2098 pme->m_pReprocChannel = NULL;
2099 }
2100
2101 // flush ongoing postproc Queue
2102 pme->m_ongoingPPQ.flush();
2103
2104 // flush input jpeg Queue
2105 pme->m_inputJpegQ.flush();
2106
2107 // flush input Postproc Queue
2108 pme->m_inputPPQ.flush();
2109
2110 // flush input raw Queue
2111 pme->m_inputRawQ.flush();
2112
2113 // signal cmd is completed
2114 cam_sem_post(&cmdThread->sync_sem);
2115
2116 pme->mNewJpegSessionNeeded = true;
2117 }
2118 break;
2119 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
2120 {
2121 CDBG_HIGH("%s: Do next job, active is %d", __func__, is_active);
2122 if (is_active == TRUE) {
2123 qcamera_jpeg_data_t *jpeg_job =
2124 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2125
2126 if (NULL != jpeg_job) {
2127 // To avoid any race conditions,
2128 // sync any stream specific parameters here.
2129 pme->syncStreamParams(jpeg_job->src_frame, NULL);
2130
2131 // add into ongoing jpeg job Q
2132 pme->m_ongoingJpegQ.enqueue((void *)jpeg_job);
2133 ret = pme->encodeData(jpeg_job,
2134 pme->mNewJpegSessionNeeded);
2135 if (NO_ERROR != ret) {
2136 // dequeue the last one
2137 pme->m_ongoingJpegQ.dequeue(false);
2138 pme->releaseJpegJobData(jpeg_job);
2139 free(jpeg_job);
2140 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2141 }
2142 }
2143
2144
2145 // process raw data if any
2146 mm_camera_super_buf_t *super_buf =
2147 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
2148
2149 if (NULL != super_buf) {
2150 //play shutter sound
2151 pme->m_parent->playShutter();
2152 ret = pme->processRawImageImpl(super_buf);
2153 if (NO_ERROR != ret) {
2154 pme->releaseSuperBuf(super_buf);
2155 free(super_buf);
2156 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2157 }
2158 }
2159
2160 mm_camera_super_buf_t *pp_frame =
2161 (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
2162 if (NULL != pp_frame) {
2163 qcamera_pp_data_t *pp_job =
2164 (qcamera_pp_data_t *)malloc(sizeof(qcamera_pp_data_t));
2165 if (pp_job != NULL) {
2166 pme->syncStreamParams(pp_frame, NULL);
2167 memset(pp_job, 0, sizeof(qcamera_pp_data_t));
2168 if (pme->m_pReprocChannel != NULL) {
2169 // add into ongoing PP job Q
2170 pp_job->src_frame = pp_frame;
2171 ret = pme->reprocess(pp_job);
2172 if (NO_ERROR == ret) {
2173 pme->stopCapture();
2174 }
2175 } else {
2176 ALOGE("%s: Reprocess channel is NULL", __func__);
2177 ret = -1;
2178 }
2179 } else {
2180 ALOGE("%s: no mem for qcamera_pp_data_t", __func__);
2181 ret = -1;
2182 }
2183
2184 if (0 != ret) {
2185 // free pp_job
2186 if (pp_job != NULL) {
2187 free(pp_job);
2188 }
2189 // free frame
2190 if (pp_frame != NULL) {
2191 pme->releaseSuperBuf(pp_frame);
2192 free(pp_frame);
2193 }
2194 // send error notify
2195 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2196 }
2197 }
2198 } else {
2199 // not active, simply return buf and do no op
2200 qcamera_jpeg_data_t *jpeg_data =
2201 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2202 if (NULL != jpeg_data) {
2203 pme->releaseJpegJobData(jpeg_data);
2204 free(jpeg_data);
2205 }
2206 mm_camera_super_buf_t *super_buf =
2207 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
2208 if (NULL != super_buf) {
2209 pme->releaseSuperBuf(super_buf);
2210 free(super_buf);
2211 }
2212 super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
2213 if (NULL != super_buf) {
2214 pme->releaseSuperBuf(super_buf);
2215 free(super_buf);
2216 }
2217 }
2218 }
2219 break;
2220 case CAMERA_CMD_TYPE_EXIT:
2221 running = 0;
2222 break;
2223 default:
2224 break;
2225 }
2226 } while (running);
2227 CDBG_HIGH("%s: X", __func__);
2228 return NULL;
2229 }
2230
2231 /*===========================================================================
2232 * FUNCTION : reprocess
2233 *
2234 * DESCRIPTION: Trigger reprocessing
2235 *
2236 * PARAMETERS :
2237 * @pp_job : Postproc job
2238 *
2239 * RETURN : int32_t type of status
2240 * NO_ERROR -- success
2241 * none-zero failure code
2242 *==========================================================================*/
reprocess(qcamera_pp_data_t * pp_job)2243 int32_t QCameraPostProcessor::reprocess(qcamera_pp_data_t *pp_job)
2244 {
2245 int rc = NO_ERROR;
2246
2247 if (NULL == pp_job) {
2248 return BAD_VALUE;
2249 }
2250
2251 if (m_parent->isRegularCapture()) {
2252 if ((NULL != pp_job->src_frame) &&
2253 (0 < pp_job->src_frame->num_bufs)) {
2254 mm_camera_buf_def_t *bufs = NULL;
2255 uint8_t num_bufs = -1;
2256 num_bufs = pp_job->src_frame->num_bufs;
2257 bufs = new mm_camera_buf_def_t[num_bufs];
2258 if (NULL == bufs) {
2259 ALOGE("%s:Unable to allocate cached buffers",
2260 __func__);
2261 return NO_MEMORY;
2262 }
2263
2264 for (int i = 0; i < num_bufs; i++) {
2265 bufs[i] = *pp_job->src_frame->bufs[i];
2266 pp_job->src_frame->bufs[i] = &bufs[i];
2267 }
2268 pp_job->src_reproc_bufs = bufs;
2269 }
2270
2271 // Don't release source frame after encoding
2272 // at this point the source channel will not exist.
2273 pp_job->reproc_frame_release = true;
2274 m_ongoingPPQ.enqueue((void *)pp_job);
2275 rc = m_pReprocChannel->doReprocessOffline(pp_job->src_frame);
2276 } else {
2277 m_ongoingPPQ.enqueue((void *)pp_job);
2278 rc = m_pReprocChannel->doReprocess(pp_job->src_frame);
2279 }
2280
2281 if (NO_ERROR != rc) {
2282 // remove from ongoing PP job Q
2283 m_ongoingPPQ.dequeue(false);
2284 }
2285
2286 return rc;
2287 }
2288
2289 /*===========================================================================
2290 * FUNCTION : stopCapture
2291 *
2292 * DESCRIPTION: Trigger image capture stop
2293 *
2294 * PARAMETERS :
2295 * None
2296 *
2297 * RETURN : int32_t type of status
2298 * NO_ERROR -- success
2299 * none-zero failure code
2300 *==========================================================================*/
stopCapture()2301 int32_t QCameraPostProcessor::stopCapture()
2302 {
2303 int rc = NO_ERROR;
2304
2305 if (m_parent->isRegularCapture()) {
2306 rc = m_parent->processAPI(
2307 QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL,
2308 NULL);
2309 }
2310
2311 return rc;
2312 }
2313
2314 /*===========================================================================
2315 * FUNCTION : getJpegPaddingReq
2316 *
2317 * DESCRIPTION: function to add an entry to exif data
2318 *
2319 * PARAMETERS :
2320 * @padding_info : jpeg specific padding requirement
2321 *
2322 * RETURN : int32_t type of status
2323 * NO_ERROR -- success
2324 * none-zero failure code
2325 *==========================================================================*/
getJpegPaddingReq(cam_padding_info_t & padding_info)2326 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info)
2327 {
2328 // TODO: hardcode for now, needs to query from mm-jpeg-interface
2329 padding_info.width_padding = CAM_PAD_NONE;
2330 padding_info.height_padding = CAM_PAD_TO_16;
2331 padding_info.plane_padding = CAM_PAD_TO_WORD;
2332 return NO_ERROR;
2333 }
2334
2335 /*===========================================================================
2336 * FUNCTION : setYUVFrameInfo
2337 *
2338 * DESCRIPTION: set Raw YUV frame data info for up-layer
2339 *
2340 * PARAMETERS :
2341 * @frame : process frame received from mm-camera-interface
2342 *
2343 * RETURN : int32_t type of status
2344 * NO_ERROR -- success
2345 * none-zero failure code
2346 *
2347 * NOTE : currently we return frame len, y offset, cbcr offset and frame format
2348 *==========================================================================*/
setYUVFrameInfo(mm_camera_super_buf_t * recvd_frame)2349 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame)
2350 {
2351 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
2352 // check reprocess channel if not found
2353 if (pChannel == NULL) {
2354 if (m_pReprocChannel != NULL &&
2355 m_pReprocChannel->getMyHandle() == recvd_frame->ch_id) {
2356 pChannel = m_pReprocChannel;
2357 }
2358 }
2359
2360 if (pChannel == NULL) {
2361 ALOGE("%s:%d] No corresponding channel (ch_id = %d) exist, return here",
2362 __func__, __LINE__, recvd_frame->ch_id);
2363 return BAD_VALUE;
2364 }
2365
2366 // find snapshot frame
2367 for (int i = 0; i < recvd_frame->num_bufs; i++) {
2368 QCameraStream *pStream =
2369 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
2370 if (pStream != NULL) {
2371 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
2372 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
2373 //get the main frame, use stream info
2374 cam_frame_len_offset_t frame_offset;
2375 cam_dimension_t frame_dim;
2376 cam_format_t frame_fmt;
2377 const char *fmt_string;
2378 pStream->getFrameDimension(frame_dim);
2379 pStream->getFrameOffset(frame_offset);
2380 pStream->getFormat(frame_fmt);
2381 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt);
2382
2383 int cbcr_offset = frame_offset.mp[0].len - frame_dim.width * frame_dim.height;
2384 m_parent->mParameters.set("snapshot-framelen", frame_offset.frame_len);
2385 m_parent->mParameters.set("snapshot-yoff", frame_offset.mp[0].offset);
2386 m_parent->mParameters.set("snapshot-cbcroff", cbcr_offset);
2387 if(fmt_string != NULL){
2388 m_parent->mParameters.set("snapshot-format", fmt_string);
2389 }else{
2390 m_parent->mParameters.set("snapshot-format", "");
2391 }
2392
2393 CDBG_HIGH("%s: frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s", __func__,
2394 frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string);
2395 return NO_ERROR;
2396 }
2397 }
2398 }
2399
2400 return BAD_VALUE;
2401 }
2402
matchJobId(void * data,void *,void * match_data)2403 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data)
2404 {
2405 qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data;
2406 uint32_t job_id = *((uint32_t *) match_data);
2407 return job->jobId == job_id;
2408 }
2409
2410 /*===========================================================================
2411 * FUNCTION : getJpegMemory
2412 *
2413 * DESCRIPTION: buffer allocation function
2414 * to pass to jpeg interface
2415 *
2416 * PARAMETERS :
2417 * @out_buf : buffer descriptor struct
2418 *
2419 * RETURN : int32_t type of status
2420 * NO_ERROR -- success
2421 * none-zero failure code
2422 *==========================================================================*/
getJpegMemory(omx_jpeg_ouput_buf_t * out_buf)2423 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf)
2424 {
2425 CDBG_HIGH("%s: Allocating jpeg out buffer of size: %d", __func__, out_buf->size);
2426 QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle;
2427 camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(-1, out_buf->size,
2428 1, procInst->m_parent->mCallbackCookie);
2429 out_buf->mem_hdl = cam_mem;
2430 out_buf->vaddr = cam_mem->data;
2431
2432 return 0;
2433 }
2434
2435 /*===========================================================================
2436 * FUNCTION : QCameraExif
2437 *
2438 * DESCRIPTION: constructor of QCameraExif
2439 *
2440 * PARAMETERS : None
2441 *
2442 * RETURN : None
2443 *==========================================================================*/
QCameraExif()2444 QCameraExif::QCameraExif()
2445 : m_nNumEntries(0)
2446 {
2447 memset(m_Entries, 0, sizeof(m_Entries));
2448 }
2449
2450 /*===========================================================================
2451 * FUNCTION : ~QCameraExif
2452 *
2453 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr.
2454 *
2455 * PARAMETERS : None
2456 *
2457 * RETURN : None
2458 *==========================================================================*/
~QCameraExif()2459 QCameraExif::~QCameraExif()
2460 {
2461 for (uint32_t i = 0; i < m_nNumEntries; i++) {
2462 switch (m_Entries[i].tag_entry.type) {
2463 case EXIF_BYTE:
2464 {
2465 if (m_Entries[i].tag_entry.count > 1 &&
2466 m_Entries[i].tag_entry.data._bytes != NULL) {
2467 free(m_Entries[i].tag_entry.data._bytes);
2468 m_Entries[i].tag_entry.data._bytes = NULL;
2469 }
2470 }
2471 break;
2472 case EXIF_ASCII:
2473 {
2474 if (m_Entries[i].tag_entry.data._ascii != NULL) {
2475 free(m_Entries[i].tag_entry.data._ascii);
2476 m_Entries[i].tag_entry.data._ascii = NULL;
2477 }
2478 }
2479 break;
2480 case EXIF_SHORT:
2481 {
2482 if (m_Entries[i].tag_entry.count > 1 &&
2483 m_Entries[i].tag_entry.data._shorts != NULL) {
2484 free(m_Entries[i].tag_entry.data._shorts);
2485 m_Entries[i].tag_entry.data._shorts = NULL;
2486 }
2487 }
2488 break;
2489 case EXIF_LONG:
2490 {
2491 if (m_Entries[i].tag_entry.count > 1 &&
2492 m_Entries[i].tag_entry.data._longs != NULL) {
2493 free(m_Entries[i].tag_entry.data._longs);
2494 m_Entries[i].tag_entry.data._longs = NULL;
2495 }
2496 }
2497 break;
2498 case EXIF_RATIONAL:
2499 {
2500 if (m_Entries[i].tag_entry.count > 1 &&
2501 m_Entries[i].tag_entry.data._rats != NULL) {
2502 free(m_Entries[i].tag_entry.data._rats);
2503 m_Entries[i].tag_entry.data._rats = NULL;
2504 }
2505 }
2506 break;
2507 case EXIF_UNDEFINED:
2508 {
2509 if (m_Entries[i].tag_entry.data._undefined != NULL) {
2510 free(m_Entries[i].tag_entry.data._undefined);
2511 m_Entries[i].tag_entry.data._undefined = NULL;
2512 }
2513 }
2514 break;
2515 case EXIF_SLONG:
2516 {
2517 if (m_Entries[i].tag_entry.count > 1 &&
2518 m_Entries[i].tag_entry.data._slongs != NULL) {
2519 free(m_Entries[i].tag_entry.data._slongs);
2520 m_Entries[i].tag_entry.data._slongs = NULL;
2521 }
2522 }
2523 break;
2524 case EXIF_SRATIONAL:
2525 {
2526 if (m_Entries[i].tag_entry.count > 1 &&
2527 m_Entries[i].tag_entry.data._srats != NULL) {
2528 free(m_Entries[i].tag_entry.data._srats);
2529 m_Entries[i].tag_entry.data._srats = NULL;
2530 }
2531 }
2532 break;
2533 }
2534 }
2535 }
2536
2537 /*===========================================================================
2538 * FUNCTION : addEntry
2539 *
2540 * DESCRIPTION: function to add an entry to exif data
2541 *
2542 * PARAMETERS :
2543 * @tagid : exif tag ID
2544 * @type : data type
2545 * @count : number of data in uint of its type
2546 * @data : input data ptr
2547 *
2548 * RETURN : int32_t type of status
2549 * NO_ERROR -- success
2550 * none-zero failure code
2551 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)2552 int32_t QCameraExif::addEntry(exif_tag_id_t tagid,
2553 exif_tag_type_t type,
2554 uint32_t count,
2555 void *data)
2556 {
2557 int32_t rc = NO_ERROR;
2558 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
2559 ALOGE("%s: Number of entries exceeded limit", __func__);
2560 return NO_MEMORY;
2561 }
2562
2563 m_Entries[m_nNumEntries].tag_id = tagid;
2564 m_Entries[m_nNumEntries].tag_entry.type = type;
2565 m_Entries[m_nNumEntries].tag_entry.count = count;
2566 m_Entries[m_nNumEntries].tag_entry.copy = 1;
2567 switch (type) {
2568 case EXIF_BYTE:
2569 {
2570 if (count > 1) {
2571 uint8_t *values = (uint8_t *)malloc(count);
2572 if (values == NULL) {
2573 ALOGE("%s: No memory for byte array", __func__);
2574 rc = NO_MEMORY;
2575 } else {
2576 memcpy(values, data, count);
2577 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
2578 }
2579 } else {
2580 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data;
2581 }
2582 }
2583 break;
2584 case EXIF_ASCII:
2585 {
2586 char *str = NULL;
2587 str = (char *)malloc(count + 1);
2588 if (str == NULL) {
2589 ALOGE("%s: No memory for ascii string", __func__);
2590 rc = NO_MEMORY;
2591 } else {
2592 memset(str, 0, count + 1);
2593 memcpy(str, data, count);
2594 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
2595 }
2596 }
2597 break;
2598 case EXIF_SHORT:
2599 {
2600 if (count > 1) {
2601 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t));
2602 if (values == NULL) {
2603 ALOGE("%s: No memory for short array", __func__);
2604 rc = NO_MEMORY;
2605 } else {
2606 memcpy(values, data, count * sizeof(uint16_t));
2607 m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
2608 }
2609 } else {
2610 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data;
2611 }
2612 }
2613 break;
2614 case EXIF_LONG:
2615 {
2616 if (count > 1) {
2617 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t));
2618 if (values == NULL) {
2619 ALOGE("%s: No memory for long array", __func__);
2620 rc = NO_MEMORY;
2621 } else {
2622 memcpy(values, data, count * sizeof(uint32_t));
2623 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
2624 }
2625 } else {
2626 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data;
2627 }
2628 }
2629 break;
2630 case EXIF_RATIONAL:
2631 {
2632 if (count > 1) {
2633 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
2634 if (values == NULL) {
2635 ALOGE("%s: No memory for rational array", __func__);
2636 rc = NO_MEMORY;
2637 } else {
2638 memcpy(values, data, count * sizeof(rat_t));
2639 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
2640 }
2641 } else {
2642 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data;
2643 }
2644 }
2645 break;
2646 case EXIF_UNDEFINED:
2647 {
2648 uint8_t *values = (uint8_t *)malloc(count);
2649 if (values == NULL) {
2650 ALOGE("%s: No memory for undefined array", __func__);
2651 rc = NO_MEMORY;
2652 } else {
2653 memcpy(values, data, count);
2654 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
2655 }
2656 }
2657 break;
2658 case EXIF_SLONG:
2659 {
2660 if (count > 1) {
2661 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t));
2662 if (values == NULL) {
2663 ALOGE("%s: No memory for signed long array", __func__);
2664 rc = NO_MEMORY;
2665 } else {
2666 memcpy(values, data, count * sizeof(int32_t));
2667 m_Entries[m_nNumEntries].tag_entry.data._slongs = values;
2668 }
2669 } else {
2670 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data;
2671 }
2672 }
2673 break;
2674 case EXIF_SRATIONAL:
2675 {
2676 if (count > 1) {
2677 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
2678 if (values == NULL) {
2679 ALOGE("%s: No memory for signed rational array", __func__);
2680 rc = NO_MEMORY;
2681 } else {
2682 memcpy(values, data, count * sizeof(srat_t));
2683 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
2684 }
2685 } else {
2686 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data;
2687 }
2688 }
2689 break;
2690 }
2691
2692 // Increase number of entries
2693 m_nNumEntries++;
2694 return rc;
2695 }
2696
2697 }; // namespace qcamera
2698