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