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