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