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 // Data callback, set read/write flags
2157 main_frame->cache_flags |= CPU_HAS_READ;
2158 m_parent->m_cbNotifier.notifyCallback(cbArg);
2159 }
2160 if (NULL != m_parent->mNotifyCb &&
2161 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
2162 qcamera_callback_argm_t cbArg;
2163 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
2164 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
2165 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
2166 cbArg.ext1 = 0;
2167 cbArg.ext2 = 0;
2168 m_parent->m_cbNotifier.notifyCallback(cbArg);
2169 }
2170
2171 if (mJpegClientHandle <= 0) {
2172 LOGE("Error: bug here, mJpegClientHandle is 0");
2173 return UNKNOWN_ERROR;
2174 }
2175
2176 if (needNewSess) {
2177 // create jpeg encoding session
2178 mm_jpeg_encode_params_t encodeParam;
2179 memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
2180 ret = getJpegEncodingConfig(encodeParam, main_stream, thumb_stream);
2181 if (ret != NO_ERROR) {
2182 LOGE("error getting encoding config");
2183 return ret;
2184 }
2185 LOGH("[KPI Perf] : call jpeg create_session");
2186 ret = mJpegHandle.create_session(mJpegClientHandle, &encodeParam, &mJpegSessionId);
2187 if (ret != NO_ERROR) {
2188 LOGE("error creating a new jpeg encoding session");
2189 return ret;
2190 }
2191 needNewSess = FALSE;
2192 }
2193 // Fill in new job
2194 memset(&jpg_job, 0, sizeof(mm_jpeg_job_t));
2195 jpg_job.job_type = JPEG_JOB_TYPE_ENCODE;
2196 jpg_job.encode_job.session_id = mJpegSessionId;
2197 jpg_job.encode_job.src_index = (int32_t)main_frame->buf_idx;
2198 jpg_job.encode_job.dst_index = 0;
2199
2200 if (mJpegMemOpt) {
2201 jpg_job.encode_job.dst_index = jpg_job.encode_job.src_index;
2202 } else if (mUseJpegBurst) {
2203 jpg_job.encode_job.dst_index = -1;
2204 }
2205
2206 // use src to reproc frame as work buffer; if src buf is not available
2207 // jpeg interface will allocate work buffer
2208 if (jpeg_job_data->src_reproc_frame != NULL) {
2209 int32_t ret = NO_ERROR;
2210 QCameraStream *main_stream = NULL;
2211 mm_camera_buf_def_t *main_frame = NULL;
2212 QCameraStream *thumb_stream = NULL;
2213 mm_camera_buf_def_t *thumb_frame = NULL;
2214 QCameraStream *reproc_stream = NULL;
2215 mm_camera_buf_def_t *workBuf = NULL;
2216 // Call queryStreams to fetch source of reproc frame
2217 ret = queryStreams(&main_stream,
2218 &thumb_stream,
2219 &reproc_stream,
2220 &main_frame,
2221 &thumb_frame,
2222 jpeg_job_data->src_reproc_frame,
2223 NULL);
2224
2225 if ((NO_ERROR == ret) && ((workBuf = main_frame) != NULL)
2226 && !m_parent->isLowPowerMode()) {
2227 camera_memory_t *camWorkMem = NULL;
2228 int workBufIndex = workBuf->buf_idx;
2229 QCameraMemory *workMem = (QCameraMemory *)workBuf->mem_info;
2230 if (workMem != NULL) {
2231 camWorkMem = workMem->getMemory(workBufIndex, false);
2232 }
2233 if (camWorkMem != NULL && workMem != NULL) {
2234 jpg_job.encode_job.work_buf.buf_size = camWorkMem->size;
2235 jpg_job.encode_job.work_buf.buf_vaddr = (uint8_t *)camWorkMem->data;
2236 jpg_job.encode_job.work_buf.fd = workMem->getFd(workBufIndex);
2237 workMem->invalidateCache(workBufIndex);
2238 }
2239 }
2240 }
2241
2242 cam_dimension_t src_dim;
2243 memset(&src_dim, 0, sizeof(cam_dimension_t));
2244 main_stream->getFrameDimension(src_dim);
2245
2246 bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
2247 bool img_feature_enabled =
2248 m_parent->mParameters.isUbiFocusEnabled() ||
2249 m_parent->mParameters.isUbiRefocus() ||
2250 m_parent->mParameters.isChromaFlashEnabled() ||
2251 m_parent->mParameters.isOptiZoomEnabled() ||
2252 m_parent->mParameters.isStillMoreEnabled();
2253
2254 LOGH("Crop needed %d", img_feature_enabled);
2255 crop.left = 0;
2256 crop.top = 0;
2257 crop.height = src_dim.height;
2258 crop.width = src_dim.width;
2259
2260 param = main_stream->getOutputCrop();
2261 for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
2262 if (param.outputCrop.crop_info[i].stream_id
2263 == main_stream->getMyServerID()) {
2264 crop = param.outputCrop.crop_info[i].crop;
2265 main_stream->setCropInfo(crop);
2266 }
2267 }
2268 if (img_feature_enabled) {
2269 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
2270
2271 param = main_stream->getImgProp();
2272 imgProp = param.imgProp;
2273 main_stream->setCropInfo(imgProp.crop);
2274 crop = imgProp.crop;
2275 thumb_stream = NULL; /* use thumbnail from main image */
2276
2277 if ((reproc_stream != NULL) && (m_DataMem == NULL) &&
2278 m_parent->mParameters.isUbiRefocus()) {
2279
2280 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf();
2281 cam_misc_buf_t* refocusResult =
2282 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0));
2283 uint32_t resultSize = refocusResult->header_size +
2284 refocusResult->width * refocusResult->height;
2285 camera_memory_t *dataMem = m_parent->mGetMemory(-1, resultSize,
2286 1, m_parent->mCallbackCookie);
2287
2288 LOGH("Refocus result header %u dims %dx%d",
2289 resultSize, refocusResult->width, refocusResult->height);
2290
2291 if (dataMem && dataMem->data) {
2292 memcpy(dataMem->data, refocusResult->data, resultSize);
2293 //save mem pointer for depth map
2294 m_DataMem = dataMem;
2295 }
2296 }
2297 } else if ((reproc_stream != NULL) && (m_parent->mParameters.isTruePortraitEnabled())) {
2298
2299 QCameraHeapMemory* miscBufHandler = reproc_stream->getMiscBuf();
2300 cam_misc_buf_t* tpResult =
2301 reinterpret_cast<cam_misc_buf_t *>(miscBufHandler->getPtr(0));
2302 uint32_t tpMetaSize = tpResult->header_size + tpResult->width * tpResult->height;
2303
2304 LOGH("True portrait result header %d% dims dx%d",
2305 tpMetaSize, tpResult->width, tpResult->height);
2306
2307 CAM_DUMP_TO_FILE(QCAMERA_DUMP_FRM_LOCATION"tp", "bm", -1, "y",
2308 &tpResult->data, tpMetaSize);
2309 }
2310
2311 cam_dimension_t dst_dim;
2312
2313 if (hdr_output_crop && crop.height) {
2314 dst_dim.height = crop.height;
2315 } else {
2316 dst_dim.height = src_dim.height;
2317 }
2318 if (hdr_output_crop && crop.width) {
2319 dst_dim.width = crop.width;
2320 } else {
2321 dst_dim.width = src_dim.width;
2322 }
2323
2324 // main dim
2325 jpg_job.encode_job.main_dim.src_dim = src_dim;
2326 jpg_job.encode_job.main_dim.dst_dim = dst_dim;
2327 jpg_job.encode_job.main_dim.crop = crop;
2328
2329 // get 3a sw version info
2330 cam_q3a_version_t sw_version =
2331 m_parent->getCamHalCapabilities()->q3a_version;
2332
2333 // get exif data
2334 QCameraExif *pJpegExifObj = m_parent->getExifData();
2335 jpeg_job_data->pJpegExifObj = pJpegExifObj;
2336 if (pJpegExifObj != NULL) {
2337 jpg_job.encode_job.exif_info.exif_data = pJpegExifObj->getEntries();
2338 jpg_job.encode_job.exif_info.numOfEntries =
2339 pJpegExifObj->getNumOfEntries();
2340 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[0] =
2341 sw_version.major_version;
2342 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[1] =
2343 sw_version.minor_version;
2344 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[2] =
2345 sw_version.patch_version;
2346 jpg_job.encode_job.exif_info.debug_data.sw_3a_version[3] =
2347 sw_version.new_feature_des;
2348 }
2349
2350 // set rotation only when no online rotation or offline pp rotation is done before
2351 if (!m_parent->needRotationReprocess()) {
2352 jpg_job.encode_job.rotation = jpeg_rotation;
2353 }
2354 LOGH("jpeg rotation is set to %d", jpg_job.encode_job.rotation);
2355
2356 // thumbnail dim
2357 if (m_bThumbnailNeeded == TRUE) {
2358 m_parent->getThumbnailSize(jpg_job.encode_job.thumb_dim.dst_dim);
2359
2360 if (thumb_stream == NULL) {
2361 // need jpeg thumbnail, but no postview/preview stream exists
2362 // we use the main stream/frame to encode thumbnail
2363 thumb_stream = main_stream;
2364 thumb_frame = main_frame;
2365 }
2366 if (m_parent->needRotationReprocess() &&
2367 ((90 == jpeg_rotation) || (270 == jpeg_rotation))) {
2368 // swap thumbnail dimensions
2369 cam_dimension_t tmp_dim = jpg_job.encode_job.thumb_dim.dst_dim;
2370 jpg_job.encode_job.thumb_dim.dst_dim.width = tmp_dim.height;
2371 jpg_job.encode_job.thumb_dim.dst_dim.height = tmp_dim.width;
2372 }
2373
2374 memset(&src_dim, 0, sizeof(cam_dimension_t));
2375 thumb_stream->getFrameDimension(src_dim);
2376 jpg_job.encode_job.thumb_dim.src_dim = src_dim;
2377
2378 // crop is the same if frame is the same
2379 if (thumb_frame != main_frame) {
2380 crop.left = 0;
2381 crop.top = 0;
2382 crop.height = src_dim.height;
2383 crop.width = src_dim.width;
2384
2385 param = thumb_stream->getOutputCrop();
2386 for (int i = 0; i < param.outputCrop.num_of_streams; i++) {
2387 if (param.outputCrop.crop_info[i].stream_id
2388 == thumb_stream->getMyServerID()) {
2389 crop = param.outputCrop.crop_info[i].crop;
2390 thumb_stream->setCropInfo(crop);
2391 }
2392 }
2393 }
2394
2395
2396 jpg_job.encode_job.thumb_dim.crop = crop;
2397 if (thumb_frame != NULL) {
2398 jpg_job.encode_job.thumb_index = thumb_frame->buf_idx;
2399 }
2400 LOGI("Thumbnail idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
2401 jpg_job.encode_job.thumb_index,
2402 jpg_job.encode_job.thumb_dim.src_dim.width,
2403 jpg_job.encode_job.thumb_dim.src_dim.height,
2404 jpg_job.encode_job.thumb_dim.dst_dim.width,
2405 jpg_job.encode_job.thumb_dim.dst_dim.height);
2406 }
2407
2408 LOGI("Main image idx = %d src w/h (%dx%d), dst w/h (%dx%d)",
2409 jpg_job.encode_job.src_index,
2410 jpg_job.encode_job.main_dim.src_dim.width,
2411 jpg_job.encode_job.main_dim.src_dim.height,
2412 jpg_job.encode_job.main_dim.dst_dim.width,
2413 jpg_job.encode_job.main_dim.dst_dim.height);
2414
2415 if (thumb_frame != NULL) {
2416 // dump thumbnail frame if enabled
2417 m_parent->dumpFrameToFile(thumb_stream, thumb_frame, QCAMERA_DUMP_FRM_THUMBNAIL);
2418 }
2419
2420 if (jpeg_job_data->metadata != NULL) {
2421 // fill in meta data frame ptr
2422 jpg_job.encode_job.p_metadata = jpeg_job_data->metadata;
2423 }
2424
2425 jpg_job.encode_job.hal_version = CAM_HAL_V1;
2426 m_parent->mExifParams.sensor_params.sens_type = m_parent->getSensorType();
2427 jpg_job.encode_job.cam_exif_params = m_parent->mExifParams;
2428 jpg_job.encode_job.cam_exif_params.debug_params =
2429 (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
2430 if (!jpg_job.encode_job.cam_exif_params.debug_params) {
2431 LOGE("Out of Memory. Allocation failed for 3A debug exif params");
2432 return NO_MEMORY;
2433 }
2434
2435 jpg_job.encode_job.mobicat_mask = m_parent->mParameters.getMobicatMask();
2436
2437
2438 if (NULL != jpg_job.encode_job.p_metadata && (jpg_job.encode_job.mobicat_mask > 0)) {
2439
2440 if (m_parent->mExifParams.debug_params) {
2441 memcpy(jpg_job.encode_job.cam_exif_params.debug_params,
2442 m_parent->mExifParams.debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
2443
2444 /* Save a copy of mobicat params */
2445 jpg_job.encode_job.p_metadata->is_mobicat_aec_params_valid =
2446 jpg_job.encode_job.cam_exif_params.cam_3a_params_valid;
2447
2448 if (jpg_job.encode_job.cam_exif_params.cam_3a_params_valid) {
2449 jpg_job.encode_job.p_metadata->mobicat_aec_params =
2450 jpg_job.encode_job.cam_exif_params.cam_3a_params;
2451 }
2452
2453 /* Save a copy of 3A debug params */
2454 jpg_job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
2455 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
2456 jpg_job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
2457 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
2458 jpg_job.encode_job.p_metadata->is_statsdebug_af_params_valid =
2459 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
2460 jpg_job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
2461 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
2462 jpg_job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
2463 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
2464 jpg_job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
2465 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
2466 jpg_job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
2467 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
2468 jpg_job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
2469 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
2470
2471 if (jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
2472 jpg_job.encode_job.p_metadata->statsdebug_ae_data =
2473 jpg_job.encode_job.cam_exif_params.debug_params->ae_debug_params;
2474 }
2475 if (jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
2476 jpg_job.encode_job.p_metadata->statsdebug_awb_data =
2477 jpg_job.encode_job.cam_exif_params.debug_params->awb_debug_params;
2478 }
2479 if (jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
2480 jpg_job.encode_job.p_metadata->statsdebug_af_data =
2481 jpg_job.encode_job.cam_exif_params.debug_params->af_debug_params;
2482 }
2483 if (jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
2484 jpg_job.encode_job.p_metadata->statsdebug_asd_data =
2485 jpg_job.encode_job.cam_exif_params.debug_params->asd_debug_params;
2486 }
2487 if (jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
2488 jpg_job.encode_job.p_metadata->statsdebug_stats_buffer_data =
2489 jpg_job.encode_job.cam_exif_params.debug_params->stats_debug_params;
2490 }
2491 if (jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
2492 jpg_job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
2493 jpg_job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
2494 }
2495 if (jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
2496 jpg_job.encode_job.p_metadata->statsdebug_bhist_data =
2497 jpg_job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
2498 }
2499 if (jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
2500 jpg_job.encode_job.p_metadata->statsdebug_3a_tuning_data =
2501 jpg_job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
2502 }
2503 }
2504
2505 }
2506
2507 /* Init the QTable */
2508 for (int i = 0; i < QTABLE_MAX; i++) {
2509 jpg_job.encode_job.qtable_set[i] = 0;
2510 }
2511
2512 const cam_sync_related_sensors_event_info_t* related_cam_info =
2513 m_parent->getRelatedCamSyncInfo();
2514 if (related_cam_info->sync_control == CAM_SYNC_RELATED_SENSORS_ON &&
2515 m_parent->getMpoComposition()) {
2516 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_MPO;
2517 if (related_cam_info->type == CAM_TYPE_MAIN ) {
2518 jpg_job.encode_job.multi_image_info.is_primary = TRUE;
2519 LOGD("Encoding MPO Primary JPEG");
2520 } else {
2521 jpg_job.encode_job.multi_image_info.is_primary = FALSE;
2522 LOGD("Encoding MPO Aux JPEG");
2523 }
2524 jpg_job.encode_job.multi_image_info.num_of_images = 2;
2525 } else {
2526 LOGD("Encoding Single JPEG");
2527 jpg_job.encode_job.multi_image_info.type = MM_JPEG_TYPE_JPEG;
2528 jpg_job.encode_job.multi_image_info.is_primary = FALSE;
2529 jpg_job.encode_job.multi_image_info.num_of_images = 1;
2530 }
2531 //Do Cache ops before sending to encode
2532 if (main_frame != NULL) {
2533 main_stream->handleCacheOps(main_frame);
2534 }
2535 if (thumb_frame != NULL) {
2536 thumb_stream->handleCacheOps(thumb_frame);
2537 }
2538
2539 LOGI("[KPI Perf] : PROFILE_JPEG_JOB_START");
2540 ret = mJpegHandle.start_job(&jpg_job, &jobId);
2541 if (jpg_job.encode_job.cam_exif_params.debug_params) {
2542 free(jpg_job.encode_job.cam_exif_params.debug_params);
2543 }
2544 if (ret == NO_ERROR) {
2545 // remember job info
2546 jpeg_job_data->jobId = jobId;
2547 }
2548
2549 return ret;
2550 }
2551
2552 /*===========================================================================
2553 * FUNCTION : processRawImageImpl
2554 *
2555 * DESCRIPTION: function to send raw image to upper layer
2556 *
2557 * PARAMETERS :
2558 * @recvd_frame : frame to be encoded
2559 *
2560 * RETURN : int32_t type of status
2561 * NO_ERROR -- success
2562 * none-zero failure code
2563 *==========================================================================*/
processRawImageImpl(mm_camera_super_buf_t * recvd_frame)2564 int32_t QCameraPostProcessor::processRawImageImpl(mm_camera_super_buf_t *recvd_frame)
2565 {
2566 int32_t rc = NO_ERROR;
2567
2568 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
2569 QCameraStream *pStream = NULL;
2570 mm_camera_buf_def_t *frame = NULL;
2571 // check reprocess channel if not found
2572 if (pChannel == NULL) {
2573 for (int8_t i = 0; i < mPPChannelCount; i++) {
2574 if ((mPPChannels[i] != NULL) &&
2575 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) {
2576 pChannel = mPPChannels[i];
2577 break;
2578 }
2579 }
2580 }
2581 if (pChannel == NULL) {
2582 LOGE("No corresponding channel (ch_id = %d) exist, return here",
2583 recvd_frame->ch_id);
2584 return BAD_VALUE;
2585 }
2586
2587 // find snapshot frame
2588 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
2589 QCameraStream *pCurStream =
2590 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
2591 if (pCurStream != NULL) {
2592 if (pCurStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
2593 pCurStream->isTypeOf(CAM_STREAM_TYPE_RAW) ||
2594 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
2595 pCurStream->isOrignalTypeOf(CAM_STREAM_TYPE_RAW)) {
2596 pStream = pCurStream;
2597 frame = recvd_frame->bufs[i];
2598 break;
2599 }
2600 }
2601 }
2602
2603 if ( NULL == frame ) {
2604 LOGE("No valid raw buffer");
2605 return BAD_VALUE;
2606 }
2607
2608 QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info;
2609 bool zslChannelUsed = m_parent->isZSLMode() &&
2610 ( pChannel != mPPChannels[0] );
2611 camera_memory_t *raw_mem = NULL;
2612
2613 if (rawMemObj != NULL) {
2614 if (zslChannelUsed) {
2615 raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
2616 } else {
2617 raw_mem = m_parent->mGetMemory(-1,
2618 frame->frame_len,
2619 1,
2620 m_parent->mCallbackCookie);
2621 if (NULL == raw_mem) {
2622 LOGE("Not enough memory for RAW cb ");
2623 return NO_MEMORY;
2624 }
2625 memcpy(raw_mem->data, frame->buffer, frame->frame_len);
2626 }
2627 }
2628
2629 if (NULL != rawMemObj && NULL != raw_mem) {
2630 // dump frame into file
2631 if (frame->stream_type == CAM_STREAM_TYPE_SNAPSHOT ||
2632 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
2633 // for YUV422 NV16 case
2634 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_SNAPSHOT);
2635 } else {
2636 //Received RAW snapshot taken notification
2637 m_parent->dumpFrameToFile(pStream, frame, QCAMERA_DUMP_FRM_RAW);
2638
2639 if(true == m_parent->m_bIntRawEvtPending) {
2640 //Sending RAW snapshot taken notification to HAL
2641 memset(&m_dst_dim, 0, sizeof(m_dst_dim));
2642 pStream->getFrameDimension(m_dst_dim);
2643 pthread_mutex_lock(&m_parent->m_int_lock);
2644 pthread_cond_signal(&m_parent->m_int_cond);
2645 pthread_mutex_unlock(&m_parent->m_int_lock);
2646 raw_mem->release(raw_mem);
2647 return rc;
2648 }
2649 }
2650
2651 // send data callback / notify for RAW_IMAGE
2652 if (NULL != m_parent->mDataCb &&
2653 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
2654 qcamera_callback_argm_t cbArg;
2655 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
2656 cbArg.cb_type = QCAMERA_DATA_CALLBACK;
2657 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
2658 cbArg.data = raw_mem;
2659 cbArg.index = 0;
2660 frame->cache_flags |= CPU_HAS_READ;
2661 m_parent->m_cbNotifier.notifyCallback(cbArg);
2662 }
2663 if (NULL != m_parent->mNotifyCb &&
2664 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
2665 qcamera_callback_argm_t cbArg;
2666 memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
2667 cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
2668 cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
2669 cbArg.ext1 = 0;
2670 cbArg.ext2 = 0;
2671 frame->cache_flags |= CPU_HAS_READ;
2672 m_parent->m_cbNotifier.notifyCallback(cbArg);
2673 }
2674
2675 if ((m_parent->mDataCb != NULL) &&
2676 m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
2677 qcamera_release_data_t release_data;
2678 memset(&release_data, 0, sizeof(qcamera_release_data_t));
2679 if ( zslChannelUsed ) {
2680 release_data.frame = recvd_frame;
2681 } else {
2682 release_data.data = raw_mem;
2683 }
2684 rc = sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
2685 raw_mem,
2686 0,
2687 NULL,
2688 &release_data);
2689 } else {
2690 raw_mem->release(raw_mem);
2691 }
2692 } else {
2693 LOGE("Cannot get raw mem");
2694 rc = UNKNOWN_ERROR;
2695 }
2696
2697 return rc;
2698 }
2699
2700 /*===========================================================================
2701 * FUNCTION : dataSaveRoutine
2702 *
2703 * DESCRIPTION: data saving routine
2704 *
2705 * PARAMETERS :
2706 * @data : user data ptr (QCameraPostProcessor)
2707 *
2708 * RETURN : None
2709 *==========================================================================*/
dataSaveRoutine(void * data)2710 void *QCameraPostProcessor::dataSaveRoutine(void *data)
2711 {
2712 int running = 1;
2713 int ret;
2714 uint8_t is_active = FALSE;
2715 QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
2716 QCameraCmdThread *cmdThread = &pme->m_saveProcTh;
2717 cmdThread->setName("CAM_JpegSave");
2718 char saveName[PROPERTY_VALUE_MAX];
2719
2720 LOGH("E");
2721 do {
2722 do {
2723 ret = cam_sem_wait(&cmdThread->cmd_sem);
2724 if (ret != 0 && errno != EINVAL) {
2725 LOGE("cam_sem_wait error (%s)",
2726 strerror(errno));
2727 return NULL;
2728 }
2729 } while (ret != 0);
2730
2731 // we got notified about new cmd avail in cmd queue
2732 camera_cmd_type_t cmd = cmdThread->getCmd();
2733 switch (cmd) {
2734 case CAMERA_CMD_TYPE_START_DATA_PROC:
2735 LOGH("start data proc");
2736 is_active = TRUE;
2737 pme->m_inputSaveQ.init();
2738 break;
2739 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
2740 {
2741 LOGH("stop data proc");
2742 is_active = FALSE;
2743
2744 // flush input save Queue
2745 pme->m_inputSaveQ.flush();
2746
2747 // signal cmd is completed
2748 cam_sem_post(&cmdThread->sync_sem);
2749 }
2750 break;
2751 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
2752 {
2753 LOGH("Do next job, active is %d", is_active);
2754
2755 qcamera_jpeg_evt_payload_t *job_data = (qcamera_jpeg_evt_payload_t *) pme->m_inputSaveQ.dequeue();
2756 if (job_data == NULL) {
2757 LOGE("Invalid jpeg event data");
2758 continue;
2759 }
2760 //qcamera_jpeg_data_t *jpeg_job =
2761 // (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue(false);
2762 //uint32_t frame_idx = jpeg_job->src_frame->bufs[0]->frame_idx;
2763 uint32_t frame_idx = 75;
2764
2765 pme->m_ongoingJpegQ.flushNodes(matchJobId, (void*)&job_data->jobId);
2766
2767 LOGH("[KPI Perf] : jpeg job %d", job_data->jobId);
2768
2769 if (is_active == TRUE) {
2770 memset(saveName, '\0', sizeof(saveName));
2771 snprintf(saveName,
2772 sizeof(saveName),
2773 QCameraPostProcessor::STORE_LOCATION,
2774 pme->mSaveFrmCnt);
2775
2776 int file_fd = open(saveName, O_RDWR | O_CREAT, 0655);
2777 if (file_fd >= 0) {
2778 ssize_t written_len = write(file_fd, job_data->out_data.buf_vaddr,
2779 job_data->out_data.buf_filled_len);
2780 if ((ssize_t)job_data->out_data.buf_filled_len != written_len) {
2781 LOGE("Failed save complete data %d bytes "
2782 "written instead of %d bytes!",
2783 written_len,
2784 job_data->out_data.buf_filled_len);
2785 } else {
2786 LOGH("written number of bytes %d\n",
2787 written_len);
2788 }
2789
2790 close(file_fd);
2791 } else {
2792 LOGE("fail t open file for saving");
2793 }
2794 pme->mSaveFrmCnt++;
2795
2796 camera_memory_t* jpeg_mem = pme->m_parent->mGetMemory(-1,
2797 strlen(saveName),
2798 1,
2799 pme->m_parent->mCallbackCookie);
2800 if (NULL == jpeg_mem) {
2801 ret = NO_MEMORY;
2802 LOGE("getMemory for jpeg, ret = NO_MEMORY");
2803 goto end;
2804 }
2805 memcpy(jpeg_mem->data, saveName, strlen(saveName));
2806
2807 LOGH("Calling upperlayer callback to store JPEG image");
2808 qcamera_release_data_t release_data;
2809 memset(&release_data, 0, sizeof(qcamera_release_data_t));
2810 release_data.data = jpeg_mem;
2811 release_data.unlinkFile = true;
2812 LOGI("[KPI Perf]: PROFILE_JPEG_CB ");
2813 ret = pme->sendDataNotify(CAMERA_MSG_COMPRESSED_IMAGE,
2814 jpeg_mem,
2815 0,
2816 NULL,
2817 &release_data,
2818 frame_idx);
2819 }
2820
2821 end:
2822 free(job_data);
2823 }
2824 break;
2825 case CAMERA_CMD_TYPE_EXIT:
2826 LOGH("save thread exit");
2827 running = 0;
2828 break;
2829 default:
2830 break;
2831 }
2832 } while (running);
2833 LOGH("X");
2834 return NULL;
2835 }
2836
2837 /*===========================================================================
2838 * FUNCTION : dataProcessRoutine
2839 *
2840 * DESCRIPTION: data process routine that handles input data either from input
2841 * Jpeg Queue to do jpeg encoding, or from input PP Queue to do
2842 * reprocess.
2843 *
2844 * PARAMETERS :
2845 * @data : user data ptr (QCameraPostProcessor)
2846 *
2847 * RETURN : None
2848 *==========================================================================*/
dataProcessRoutine(void * data)2849 void *QCameraPostProcessor::dataProcessRoutine(void *data)
2850 {
2851 int running = 1;
2852 int ret;
2853 uint8_t is_active = FALSE;
2854 QCameraPostProcessor *pme = (QCameraPostProcessor *)data;
2855 QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
2856 cmdThread->setName("CAM_DataProc");
2857
2858 LOGH("E");
2859 do {
2860 do {
2861 ret = cam_sem_wait(&cmdThread->cmd_sem);
2862 if (ret != 0 && errno != EINVAL) {
2863 LOGE("cam_sem_wait error (%s)",
2864 strerror(errno));
2865 return NULL;
2866 }
2867 } while (ret != 0);
2868
2869 // we got notified about new cmd avail in cmd queue
2870 camera_cmd_type_t cmd = cmdThread->getCmd();
2871 switch (cmd) {
2872 case CAMERA_CMD_TYPE_START_DATA_PROC:
2873 LOGH("start data proc");
2874 is_active = TRUE;
2875
2876 pme->m_ongoingPPQ.init();
2877 pme->m_inputJpegQ.init();
2878 pme->m_inputPPQ.init();
2879 pme->m_inputRawQ.init();
2880
2881 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_START_DATA_PROC,
2882 FALSE,
2883 FALSE);
2884
2885 // signal cmd is completed
2886 cam_sem_post(&cmdThread->sync_sem);
2887
2888 break;
2889 case CAMERA_CMD_TYPE_STOP_DATA_PROC:
2890 {
2891 LOGH("stop data proc");
2892 is_active = FALSE;
2893
2894 pme->m_saveProcTh.sendCmd(CAMERA_CMD_TYPE_STOP_DATA_PROC,
2895 TRUE,
2896 TRUE);
2897 // cancel all ongoing jpeg jobs
2898 qcamera_jpeg_data_t *jpeg_job =
2899 (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2900 while (jpeg_job != NULL) {
2901 pme->mJpegHandle.abort_job(jpeg_job->jobId);
2902
2903 pme->releaseJpegJobData(jpeg_job);
2904 free(jpeg_job);
2905
2906 jpeg_job = (qcamera_jpeg_data_t *)pme->m_ongoingJpegQ.dequeue();
2907 }
2908
2909 // destroy jpeg encoding session
2910 if ( 0 < pme->mJpegSessionId ) {
2911 pme->mJpegHandle.destroy_session(pme->mJpegSessionId);
2912 pme->mJpegSessionId = 0;
2913 }
2914
2915 // free jpeg out buf and exif obj
2916 FREE_JPEG_OUTPUT_BUFFER(pme->m_pJpegOutputMem,
2917 pme->m_JpegOutputMemCount);
2918
2919 if (pme->m_pJpegExifObj != NULL) {
2920 delete pme->m_pJpegExifObj;
2921 pme->m_pJpegExifObj = NULL;
2922 }
2923
2924 // flush ongoing postproc Queue
2925 pme->m_ongoingPPQ.flush();
2926
2927 // flush input jpeg Queue
2928 pme->m_inputJpegQ.flush();
2929
2930 // flush input Postproc Queue
2931 pme->m_inputPPQ.flush();
2932
2933 // flush input raw Queue
2934 pme->m_inputRawQ.flush();
2935
2936 // signal cmd is completed
2937 cam_sem_post(&cmdThread->sync_sem);
2938
2939 pme->mNewJpegSessionNeeded = true;
2940 }
2941 break;
2942 case CAMERA_CMD_TYPE_DO_NEXT_JOB:
2943 {
2944 LOGH("Do next job, active is %d", is_active);
2945 if (is_active == TRUE) {
2946 qcamera_jpeg_data_t *jpeg_job =
2947 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
2948
2949 if (NULL != jpeg_job) {
2950 // To avoid any race conditions,
2951 // sync any stream specific parameters here.
2952 if (pme->m_parent->mParameters.isAdvCamFeaturesEnabled()) {
2953 // Sync stream params, only if advanced features configured
2954 // Reduces the latency for normal snapshot.
2955 pme->syncStreamParams(jpeg_job->src_frame, NULL);
2956 }
2957
2958 // add into ongoing jpeg job Q
2959 if (pme->m_ongoingJpegQ.enqueue((void *)jpeg_job)) {
2960 ret = pme->encodeData(jpeg_job,
2961 pme->mNewJpegSessionNeeded);
2962 if (NO_ERROR != ret) {
2963 // dequeue the last one
2964 pme->m_ongoingJpegQ.dequeue(false);
2965 pme->releaseJpegJobData(jpeg_job);
2966 free(jpeg_job);
2967 jpeg_job = NULL;
2968 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2969 }
2970 } else {
2971 LOGW("m_ongoingJpegQ is not active!!!");
2972 pme->releaseJpegJobData(jpeg_job);
2973 free(jpeg_job);
2974 jpeg_job = NULL;
2975 }
2976 }
2977
2978
2979 // process raw data if any
2980 mm_camera_super_buf_t *super_buf =
2981 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
2982
2983 if (NULL != super_buf) {
2984 //play shutter sound
2985 pme->m_parent->playShutter();
2986 ret = pme->processRawImageImpl(super_buf);
2987 if (NO_ERROR != ret) {
2988 pme->releaseSuperBuf(super_buf);
2989 free(super_buf);
2990 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2991 }
2992 }
2993
2994 ret = pme->doReprocess();
2995 if (NO_ERROR != ret) {
2996 pme->sendEvtNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
2997 } else {
2998 ret = pme->stopCapture();
2999 }
3000
3001 } else {
3002 // not active, simply return buf and do no op
3003 qcamera_jpeg_data_t *jpeg_data =
3004 (qcamera_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
3005 if (NULL != jpeg_data) {
3006 pme->releaseJpegJobData(jpeg_data);
3007 free(jpeg_data);
3008 }
3009 mm_camera_super_buf_t *super_buf =
3010 (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
3011 if (NULL != super_buf) {
3012 pme->releaseSuperBuf(super_buf);
3013 free(super_buf);
3014 }
3015
3016 // flush input Postproc Queue
3017 pme->m_inputPPQ.flush();
3018 }
3019 }
3020 break;
3021 case CAMERA_CMD_TYPE_EXIT:
3022 running = 0;
3023 break;
3024 default:
3025 break;
3026 }
3027 } while (running);
3028 LOGH("X");
3029 return NULL;
3030 }
3031
3032 /*===========================================================================
3033 * FUNCTION : doReprocess
3034 *
3035 * DESCRIPTION: Trigger channel reprocessing
3036 *
3037 * PARAMETERS :None
3038 *
3039 * RETURN : int32_t type of status
3040 * NO_ERROR -- success
3041 * none-zero failure code
3042 *==========================================================================*/
doReprocess()3043 int32_t QCameraPostProcessor::doReprocess()
3044 {
3045 int32_t ret = NO_ERROR;
3046 QCameraChannel *m_pSrcChannel = NULL;
3047 QCameraStream *pMetaStream = NULL;
3048 uint8_t meta_buf_index = 0;
3049 mm_camera_buf_def_t *meta_buf = NULL;
3050 mm_camera_super_buf_t *ppInputFrame = NULL;
3051
3052 qcamera_pp_data_t *ppreq_job = (qcamera_pp_data_t *)m_inputPPQ.peek();
3053 if ((ppreq_job == NULL) || (ppreq_job->src_frame == NULL)) {
3054 return ret;
3055 }
3056
3057 if (!validatePostProcess(ppreq_job->src_frame)) {
3058 return ret;
3059 }
3060
3061 ppreq_job = (qcamera_pp_data_t *)m_inputPPQ.dequeue();
3062 if (ppreq_job == NULL || ppreq_job->src_frame == NULL ||
3063 ppreq_job->src_reproc_frame == NULL) {
3064 return ret;
3065 }
3066
3067 mm_camera_super_buf_t *src_frame = ppreq_job->src_frame;
3068 mm_camera_super_buf_t *src_reproc_frame = ppreq_job->src_reproc_frame;
3069 int8_t mCurReprocCount = ppreq_job->reprocCount;
3070 int8_t mCurChannelIdx = ppreq_job->ppChannelIndex;
3071
3072 LOGD("frame = %p src_frame = %p mCurReprocCount = %d mCurChannelIdx = %d",
3073 src_frame,src_reproc_frame,mCurReprocCount, mCurChannelIdx);
3074
3075 if ((m_parent->mParameters.getManualCaptureMode() >=
3076 CAM_MANUAL_CAPTURE_TYPE_3) && (mCurChannelIdx == 0)) {
3077 ppInputFrame = src_reproc_frame;
3078 } else {
3079 ppInputFrame = src_frame;
3080 }
3081
3082 if (mPPChannelCount >= CAM_PP_CHANNEL_MAX) {
3083 LOGE("invalid channel count");
3084 return UNKNOWN_ERROR;
3085 }
3086
3087 // find meta data stream and index of meta data frame in the superbuf
3088 for (int8_t j = 0; j < mPPChannelCount; j++) {
3089 /*First search in src buffer for any offline metadata */
3090 for (uint32_t i = 0; i < src_frame->num_bufs; i++) {
3091 QCameraStream *pStream = mPPChannels[j]->getStreamByHandle(
3092 src_frame->bufs[i]->stream_id);
3093 if (pStream != NULL && pStream->isOrignalTypeOf(CAM_STREAM_TYPE_METADATA)) {
3094 meta_buf_index = (uint8_t) src_frame->bufs[i]->buf_idx;
3095 pMetaStream = pStream;
3096 meta_buf = src_frame->bufs[i];
3097 break;
3098 }
3099 }
3100
3101 if ((pMetaStream != NULL) && (meta_buf != NULL)) {
3102 LOGD("Found Offline stream metadata = %d",
3103 (int)meta_buf_index);
3104 break;
3105 }
3106 }
3107
3108 if ((pMetaStream == NULL) && (meta_buf == NULL)) {
3109 for (int8_t j = 0; j < mPPChannelCount; j++) {
3110 m_pSrcChannel = mPPChannels[j]->getSrcChannel();
3111 if (m_pSrcChannel == NULL)
3112 continue;
3113 for (uint32_t i = 0; i < src_reproc_frame->num_bufs; i++) {
3114 QCameraStream *pStream =
3115 m_pSrcChannel->getStreamByHandle(
3116 src_reproc_frame->bufs[i]->stream_id);
3117 if (pStream != NULL && pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
3118 meta_buf_index = (uint8_t) src_reproc_frame->bufs[i]->buf_idx;
3119 pMetaStream = pStream;
3120 meta_buf = src_reproc_frame->bufs[i];
3121 break;
3122 }
3123 }
3124 if ((pMetaStream != NULL) && (meta_buf != NULL)) {
3125 LOGD("Found Meta data info for reprocessing index = %d",
3126 (int)meta_buf_index);
3127 break;
3128 }
3129 }
3130 }
3131
3132 if (m_parent->mParameters.isAdvCamFeaturesEnabled()) {
3133 // No need to sync stream params, if none of the advanced features configured
3134 // Reduces the latency for normal snapshot.
3135 syncStreamParams(src_frame, src_reproc_frame);
3136 }
3137 if (mPPChannels[mCurChannelIdx] != NULL) {
3138 // add into ongoing PP job Q
3139 ppreq_job->reprocCount = (int8_t) (mCurReprocCount + 1);
3140
3141 if ((m_parent->isRegularCapture()) || (ppreq_job->offline_buffer)) {
3142 m_bufCountPPQ++;
3143 if (m_ongoingPPQ.enqueue((void *)ppreq_job)) {
3144 pthread_mutex_lock(&m_reprocess_lock);
3145 ret = mPPChannels[mCurChannelIdx]->doReprocessOffline(ppInputFrame,
3146 meta_buf, m_parent->mParameters);
3147 if (ret != NO_ERROR) {
3148 pthread_mutex_unlock(&m_reprocess_lock);
3149 goto end;
3150 }
3151
3152 if ((ppreq_job->offline_buffer) &&
3153 (ppreq_job->offline_reproc_buf)) {
3154 mPPChannels[mCurChannelIdx]->doReprocessOffline(
3155 ppreq_job->offline_reproc_buf, meta_buf);
3156 }
3157 pthread_mutex_unlock(&m_reprocess_lock);
3158 } else {
3159 LOGW("m_ongoingPPQ is not active!!!");
3160 ret = UNKNOWN_ERROR;
3161 goto end;
3162 }
3163 } else {
3164 m_bufCountPPQ++;
3165 if (!m_ongoingPPQ.enqueue((void *)ppreq_job)) {
3166 LOGW("m_ongoingJpegQ is not active!!!");
3167 ret = UNKNOWN_ERROR;
3168 goto end;
3169 }
3170
3171 int32_t numRequiredPPQBufsForSingleOutput = (int32_t)
3172 m_parent->mParameters.getNumberInBufsForSingleShot();
3173
3174 if (m_bufCountPPQ % numRequiredPPQBufsForSingleOutput == 0) {
3175 int32_t extra_pp_job_count =
3176 m_parent->mParameters.getNumberOutBufsForSingleShot() -
3177 m_parent->mParameters.getNumberInBufsForSingleShot();
3178
3179 for (int32_t i = 0; i < extra_pp_job_count; i++) {
3180 qcamera_pp_data_t *extra_pp_job =
3181 (qcamera_pp_data_t *)calloc(1, sizeof(qcamera_pp_data_t));
3182 if (!extra_pp_job) {
3183 LOGE("no mem for qcamera_pp_data_t");
3184 ret = NO_MEMORY;
3185 break;
3186 }
3187 extra_pp_job->reprocCount = ppreq_job->reprocCount;
3188 if (!m_ongoingPPQ.enqueue((void *)extra_pp_job)) {
3189 LOGW("m_ongoingJpegQ is not active!!!");
3190 releaseOngoingPPData(extra_pp_job, this);
3191 free(extra_pp_job);
3192 extra_pp_job = NULL;
3193 goto end;
3194 }
3195 }
3196 }
3197
3198 ret = mPPChannels[mCurChannelIdx]->doReprocess(ppInputFrame,
3199 m_parent->mParameters, pMetaStream, meta_buf_index);
3200 }
3201 } else {
3202 LOGE("Reprocess channel is NULL");
3203 ret = UNKNOWN_ERROR;
3204 }
3205
3206 end:
3207 if (ret != NO_ERROR) {
3208 releaseOngoingPPData(ppreq_job, this);
3209 if (ppreq_job != NULL) {
3210 free(ppreq_job);
3211 ppreq_job = NULL;
3212 }
3213 }
3214 return ret;
3215 }
3216
3217 /*===========================================================================
3218 * FUNCTION : getReprocChannel
3219 *
3220 * DESCRIPTION: Returns reprocessing channel handle
3221 *
3222 * PARAMETERS : index for reprocessing array
3223 *
3224 * RETURN : QCameraReprocessChannel * type of pointer
3225 NULL if no reprocessing channel
3226 *==========================================================================*/
getReprocChannel(uint8_t index)3227 QCameraReprocessChannel * QCameraPostProcessor::getReprocChannel(uint8_t index)
3228 {
3229 if (index >= mPPChannelCount) {
3230 LOGE("Invalid index value");
3231 return NULL;
3232 }
3233 return mPPChannels[index];
3234 }
3235
3236 /*===========================================================================
3237 * FUNCTION : stopCapture
3238 *
3239 * DESCRIPTION: Trigger image capture stop
3240 *
3241 * PARAMETERS :
3242 * None
3243 *
3244 * RETURN : int32_t type of status
3245 * NO_ERROR -- success
3246 * none-zero failure code
3247 *==========================================================================*/
stopCapture()3248 int32_t QCameraPostProcessor::stopCapture()
3249 {
3250 int rc = NO_ERROR;
3251
3252 if (m_parent->isRegularCapture()) {
3253 rc = m_parent->processAPI(
3254 QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL,
3255 NULL);
3256 }
3257
3258 return rc;
3259 }
3260
3261 /*===========================================================================
3262 * FUNCTION : getJpegPaddingReq
3263 *
3264 * DESCRIPTION: function to add an entry to exif data
3265 *
3266 * PARAMETERS :
3267 * @padding_info : jpeg specific padding requirement
3268 *
3269 * RETURN : int32_t type of status
3270 * NO_ERROR -- success
3271 * none-zero failure code
3272 *==========================================================================*/
getJpegPaddingReq(cam_padding_info_t & padding_info)3273 int32_t QCameraPostProcessor::getJpegPaddingReq(cam_padding_info_t &padding_info)
3274 {
3275 // TODO: hardcode for now, needs to query from mm-jpeg-interface
3276 padding_info.width_padding = CAM_PAD_NONE;
3277 padding_info.height_padding = CAM_PAD_TO_16;
3278 padding_info.plane_padding = CAM_PAD_TO_WORD;
3279 padding_info.offset_info.offset_x = 0;
3280 padding_info.offset_info.offset_y = 0;
3281 return NO_ERROR;
3282 }
3283
3284 /*===========================================================================
3285 * FUNCTION : setYUVFrameInfo
3286 *
3287 * DESCRIPTION: set Raw YUV frame data info for up-layer
3288 *
3289 * PARAMETERS :
3290 * @frame : process frame received from mm-camera-interface
3291 *
3292 * RETURN : int32_t type of status
3293 * NO_ERROR -- success
3294 * none-zero failure code
3295 *
3296 * NOTE : currently we return frame len, y offset, cbcr offset and frame format
3297 *==========================================================================*/
setYUVFrameInfo(mm_camera_super_buf_t * recvd_frame)3298 int32_t QCameraPostProcessor::setYUVFrameInfo(mm_camera_super_buf_t *recvd_frame)
3299 {
3300 QCameraChannel *pChannel = m_parent->getChannelByHandle(recvd_frame->ch_id);
3301 // check reprocess channel if not found
3302 if (pChannel == NULL) {
3303 for (int8_t i = 0; i < mPPChannelCount; i++) {
3304 if ((mPPChannels[i] != NULL) &&
3305 (mPPChannels[i]->getMyHandle() == recvd_frame->ch_id)) {
3306 pChannel = mPPChannels[i];
3307 break;
3308 }
3309 }
3310 }
3311
3312 if (pChannel == NULL) {
3313 LOGE("No corresponding channel (ch_id = %d) exist, return here",
3314 recvd_frame->ch_id);
3315 return BAD_VALUE;
3316 }
3317
3318 // find snapshot frame
3319 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
3320 QCameraStream *pStream =
3321 pChannel->getStreamByHandle(recvd_frame->bufs[i]->stream_id);
3322 if (pStream != NULL) {
3323 if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
3324 pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) {
3325 //get the main frame, use stream info
3326 cam_frame_len_offset_t frame_offset;
3327 cam_dimension_t frame_dim;
3328 cam_format_t frame_fmt;
3329 const char *fmt_string;
3330 pStream->getFrameDimension(frame_dim);
3331 pStream->getFrameOffset(frame_offset);
3332 pStream->getFormat(frame_fmt);
3333 fmt_string = m_parent->mParameters.getFrameFmtString(frame_fmt);
3334
3335 int cbcr_offset = (int32_t)frame_offset.mp[0].len -
3336 frame_dim.width * frame_dim.height;
3337
3338 LOGH("frame width=%d, height=%d, yoff=%d, cbcroff=%d, fmt_string=%s",
3339 frame_dim.width, frame_dim.height, frame_offset.mp[0].offset, cbcr_offset, fmt_string);
3340 return NO_ERROR;
3341 }
3342 }
3343 }
3344
3345 return BAD_VALUE;
3346 }
3347
matchJobId(void * data,void *,void * match_data)3348 bool QCameraPostProcessor::matchJobId(void *data, void *, void *match_data)
3349 {
3350 qcamera_jpeg_data_t * job = (qcamera_jpeg_data_t *) data;
3351 uint32_t job_id = *((uint32_t *) match_data);
3352 return job->jobId == job_id;
3353 }
3354
3355 /*===========================================================================
3356 * FUNCTION : getJpegMemory
3357 *
3358 * DESCRIPTION: buffer allocation function
3359 * to pass to jpeg interface
3360 *
3361 * PARAMETERS :
3362 * @out_buf : buffer descriptor struct
3363 *
3364 * RETURN : int32_t type of status
3365 * NO_ERROR -- success
3366 * none-zero failure code
3367 *==========================================================================*/
getJpegMemory(omx_jpeg_ouput_buf_t * out_buf)3368 int QCameraPostProcessor::getJpegMemory(omx_jpeg_ouput_buf_t *out_buf)
3369 {
3370 LOGH("Allocating jpeg out buffer of size: %d", out_buf->size);
3371 QCameraPostProcessor *procInst = (QCameraPostProcessor *) out_buf->handle;
3372 camera_memory_t *cam_mem = procInst->m_parent->mGetMemory(out_buf->fd, out_buf->size, 1U,
3373 procInst->m_parent->mCallbackCookie);
3374 out_buf->mem_hdl = cam_mem;
3375 out_buf->vaddr = cam_mem->data;
3376
3377 return 0;
3378 }
3379
3380 /*===========================================================================
3381 * FUNCTION : releaseJpegMemory
3382 *
3383 * DESCRIPTION: release jpeg memory function
3384 * to pass to jpeg interface, in case of abort
3385 *
3386 * PARAMETERS :
3387 * @out_buf : buffer descriptor struct
3388 *
3389 * RETURN : int32_t type of status
3390 * NO_ERROR -- success
3391 * none-zero failure code
3392 *==========================================================================*/
releaseJpegMemory(omx_jpeg_ouput_buf_t * out_buf)3393 int QCameraPostProcessor::releaseJpegMemory(omx_jpeg_ouput_buf_t *out_buf)
3394 {
3395 if (out_buf && out_buf->mem_hdl) {
3396 LOGD("releasing jpeg out buffer of size: %d", out_buf->size);
3397 camera_memory_t *cam_mem = (camera_memory_t*)out_buf->mem_hdl;
3398 cam_mem->release(cam_mem);
3399 out_buf->mem_hdl = NULL;
3400 out_buf->vaddr = NULL;
3401 return NO_ERROR;
3402 }
3403 return -1;
3404 }
3405
3406 /*===========================================================================
3407 * FUNCTION : QCameraExif
3408 *
3409 * DESCRIPTION: constructor of QCameraExif
3410 *
3411 * PARAMETERS : None
3412 *
3413 * RETURN : None
3414 *==========================================================================*/
QCameraExif()3415 QCameraExif::QCameraExif()
3416 : m_nNumEntries(0)
3417 {
3418 memset(m_Entries, 0, sizeof(m_Entries));
3419 }
3420
3421 /*===========================================================================
3422 * FUNCTION : ~QCameraExif
3423 *
3424 * DESCRIPTION: deconstructor of QCameraExif. Will release internal memory ptr.
3425 *
3426 * PARAMETERS : None
3427 *
3428 * RETURN : None
3429 *==========================================================================*/
~QCameraExif()3430 QCameraExif::~QCameraExif()
3431 {
3432 for (uint32_t i = 0; i < m_nNumEntries; i++) {
3433 switch (m_Entries[i].tag_entry.type) {
3434 case EXIF_BYTE:
3435 {
3436 if (m_Entries[i].tag_entry.count > 1 &&
3437 m_Entries[i].tag_entry.data._bytes != NULL) {
3438 free(m_Entries[i].tag_entry.data._bytes);
3439 m_Entries[i].tag_entry.data._bytes = NULL;
3440 }
3441 }
3442 break;
3443 case EXIF_ASCII:
3444 {
3445 if (m_Entries[i].tag_entry.data._ascii != NULL) {
3446 free(m_Entries[i].tag_entry.data._ascii);
3447 m_Entries[i].tag_entry.data._ascii = NULL;
3448 }
3449 }
3450 break;
3451 case EXIF_SHORT:
3452 {
3453 if (m_Entries[i].tag_entry.count > 1 &&
3454 m_Entries[i].tag_entry.data._shorts != NULL) {
3455 free(m_Entries[i].tag_entry.data._shorts);
3456 m_Entries[i].tag_entry.data._shorts = NULL;
3457 }
3458 }
3459 break;
3460 case EXIF_LONG:
3461 {
3462 if (m_Entries[i].tag_entry.count > 1 &&
3463 m_Entries[i].tag_entry.data._longs != NULL) {
3464 free(m_Entries[i].tag_entry.data._longs);
3465 m_Entries[i].tag_entry.data._longs = NULL;
3466 }
3467 }
3468 break;
3469 case EXIF_RATIONAL:
3470 {
3471 if (m_Entries[i].tag_entry.count > 1 &&
3472 m_Entries[i].tag_entry.data._rats != NULL) {
3473 free(m_Entries[i].tag_entry.data._rats);
3474 m_Entries[i].tag_entry.data._rats = NULL;
3475 }
3476 }
3477 break;
3478 case EXIF_UNDEFINED:
3479 {
3480 if (m_Entries[i].tag_entry.data._undefined != NULL) {
3481 free(m_Entries[i].tag_entry.data._undefined);
3482 m_Entries[i].tag_entry.data._undefined = NULL;
3483 }
3484 }
3485 break;
3486 case EXIF_SLONG:
3487 {
3488 if (m_Entries[i].tag_entry.count > 1 &&
3489 m_Entries[i].tag_entry.data._slongs != NULL) {
3490 free(m_Entries[i].tag_entry.data._slongs);
3491 m_Entries[i].tag_entry.data._slongs = NULL;
3492 }
3493 }
3494 break;
3495 case EXIF_SRATIONAL:
3496 {
3497 if (m_Entries[i].tag_entry.count > 1 &&
3498 m_Entries[i].tag_entry.data._srats != NULL) {
3499 free(m_Entries[i].tag_entry.data._srats);
3500 m_Entries[i].tag_entry.data._srats = NULL;
3501 }
3502 }
3503 break;
3504 }
3505 }
3506 }
3507
3508 /*===========================================================================
3509 * FUNCTION : addEntry
3510 *
3511 * DESCRIPTION: function to add an entry to exif data
3512 *
3513 * PARAMETERS :
3514 * @tagid : exif tag ID
3515 * @type : data type
3516 * @count : number of data in uint of its type
3517 * @data : input data ptr
3518 *
3519 * RETURN : int32_t type of status
3520 * NO_ERROR -- success
3521 * none-zero failure code
3522 *==========================================================================*/
addEntry(exif_tag_id_t tagid,exif_tag_type_t type,uint32_t count,void * data)3523 int32_t QCameraExif::addEntry(exif_tag_id_t tagid,
3524 exif_tag_type_t type,
3525 uint32_t count,
3526 void *data)
3527 {
3528 int32_t rc = NO_ERROR;
3529 if(m_nNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
3530 LOGE("Number of entries exceeded limit");
3531 return NO_MEMORY;
3532 }
3533
3534 m_Entries[m_nNumEntries].tag_id = tagid;
3535 m_Entries[m_nNumEntries].tag_entry.type = type;
3536 m_Entries[m_nNumEntries].tag_entry.count = count;
3537 m_Entries[m_nNumEntries].tag_entry.copy = 1;
3538 switch (type) {
3539 case EXIF_BYTE:
3540 {
3541 if (count > 1) {
3542 uint8_t *values = (uint8_t *)malloc(count);
3543 if (values == NULL) {
3544 LOGE("No memory for byte array");
3545 rc = NO_MEMORY;
3546 } else {
3547 memcpy(values, data, count);
3548 m_Entries[m_nNumEntries].tag_entry.data._bytes = values;
3549 }
3550 } else {
3551 m_Entries[m_nNumEntries].tag_entry.data._byte = *(uint8_t *)data;
3552 }
3553 }
3554 break;
3555 case EXIF_ASCII:
3556 {
3557 char *str = NULL;
3558 str = (char *)malloc(count + 1);
3559 if (str == NULL) {
3560 LOGE("No memory for ascii string");
3561 rc = NO_MEMORY;
3562 } else {
3563 memset(str, 0, count + 1);
3564 memcpy(str, data, count);
3565 m_Entries[m_nNumEntries].tag_entry.data._ascii = str;
3566 }
3567 }
3568 break;
3569 case EXIF_SHORT:
3570 {
3571 uint16_t *exif_data = (uint16_t *)data;
3572 if (count > 1) {
3573 uint16_t *values = (uint16_t *)malloc(count * sizeof(uint16_t));
3574 if (values == NULL) {
3575 LOGE("No memory for short array");
3576 rc = NO_MEMORY;
3577 } else {
3578 memcpy(values, exif_data, count * sizeof(uint16_t));
3579 m_Entries[m_nNumEntries].tag_entry.data._shorts = values;
3580 }
3581 } else {
3582 m_Entries[m_nNumEntries].tag_entry.data._short = *(uint16_t *)data;
3583 }
3584 }
3585 break;
3586 case EXIF_LONG:
3587 {
3588 uint32_t *exif_data = (uint32_t *)data;
3589 if (count > 1) {
3590 uint32_t *values = (uint32_t *)malloc(count * sizeof(uint32_t));
3591 if (values == NULL) {
3592 LOGE("No memory for long array");
3593 rc = NO_MEMORY;
3594 } else {
3595 memcpy(values, exif_data, count * sizeof(uint32_t));
3596 m_Entries[m_nNumEntries].tag_entry.data._longs = values;
3597 }
3598 } else {
3599 m_Entries[m_nNumEntries].tag_entry.data._long = *(uint32_t *)data;
3600 }
3601 }
3602 break;
3603 case EXIF_RATIONAL:
3604 {
3605 rat_t *exif_data = (rat_t *)data;
3606 if (count > 1) {
3607 rat_t *values = (rat_t *)malloc(count * sizeof(rat_t));
3608 if (values == NULL) {
3609 LOGE("No memory for rational array");
3610 rc = NO_MEMORY;
3611 } else {
3612 memcpy(values, exif_data, count * sizeof(rat_t));
3613 m_Entries[m_nNumEntries].tag_entry.data._rats = values;
3614 }
3615 } else {
3616 m_Entries[m_nNumEntries].tag_entry.data._rat = *(rat_t *)data;
3617 }
3618 }
3619 break;
3620 case EXIF_UNDEFINED:
3621 {
3622 uint8_t *values = (uint8_t *)malloc(count);
3623 if (values == NULL) {
3624 LOGE("No memory for undefined array");
3625 rc = NO_MEMORY;
3626 } else {
3627 memcpy(values, data, count);
3628 m_Entries[m_nNumEntries].tag_entry.data._undefined = values;
3629 }
3630 }
3631 break;
3632 case EXIF_SLONG:
3633 {
3634 uint32_t *exif_data = (uint32_t *)data;
3635 if (count > 1) {
3636 int32_t *values = (int32_t *)malloc(count * sizeof(int32_t));
3637 if (values == NULL) {
3638 LOGE("No memory for signed long array");
3639 rc = NO_MEMORY;
3640 } else {
3641 memcpy(values, exif_data, count * sizeof(int32_t));
3642 m_Entries[m_nNumEntries].tag_entry.data._slongs = values;
3643 }
3644 } else {
3645 m_Entries[m_nNumEntries].tag_entry.data._slong = *(int32_t *)data;
3646 }
3647 }
3648 break;
3649 case EXIF_SRATIONAL:
3650 {
3651 srat_t *exif_data = (srat_t *)data;
3652 if (count > 1) {
3653 srat_t *values = (srat_t *)malloc(count * sizeof(srat_t));
3654 if (values == NULL) {
3655 LOGE("No memory for signed rational array");
3656 rc = NO_MEMORY;
3657 } else {
3658 memcpy(values, exif_data, count * sizeof(srat_t));
3659 m_Entries[m_nNumEntries].tag_entry.data._srats = values;
3660 }
3661 } else {
3662 m_Entries[m_nNumEntries].tag_entry.data._srat = *(srat_t *)data;
3663 }
3664 }
3665 break;
3666 }
3667
3668 // Increase number of entries
3669 m_nNumEntries++;
3670 return rc;
3671 }
3672
3673 }; // namespace qcamera
3674