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