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