1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 
30 #define LOG_TAG "QCamera3Channel"
31 
32 // To remove
33 #include <cutils/properties.h>
34 
35 // System dependencies
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include "gralloc.h"
40 
41 // Camera dependencies
42 #include "QCamera3Channel.h"
43 #include "QCamera3HWI.h"
44 #include "QCameraTrace.h"
45 
46 extern "C" {
47 #include "mm_camera_dbg.h"
48 }
49 
50 using namespace android;
51 
52 namespace qcamera {
53 #define IS_BUFFER_ERROR(x) (((x) & V4L2_BUF_FLAG_ERROR) == V4L2_BUF_FLAG_ERROR)
54 
55 /*===========================================================================
56  * FUNCTION   : QCamera3Channel
57  *
58  * DESCRIPTION: constrcutor of QCamera3Channel
59  *
60  * PARAMETERS :
61  *   @cam_handle : camera handle
62  *   @cam_ops    : ptr to camera ops table
63  *
64  * RETURN     : none
65  *==========================================================================*/
QCamera3Channel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,void * userData,uint32_t numBuffers)66 QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
67                                uint32_t channel_handle,
68                                mm_camera_ops_t *cam_ops,
69                                channel_cb_routine cb_routine,
70                                cam_padding_info_t *paddingInfo,
71                                uint32_t postprocess_mask,
72                                void *userData, uint32_t numBuffers)
73 {
74     m_camHandle = cam_handle;
75     m_handle = channel_handle;
76     m_camOps = cam_ops;
77     m_bIsActive = false;
78 
79     m_numStreams = 0;
80     memset(mStreams, 0, sizeof(mStreams));
81     mUserData = userData;
82 
83     mStreamInfoBuf = NULL;
84     mChannelCB = cb_routine;
85     mPaddingInfo = *paddingInfo;
86     mPaddingInfo.offset_info.offset_x = 0;
87     mPaddingInfo.offset_info.offset_y = 0;
88 
89     mPostProcMask = postprocess_mask;
90 
91     mIsType = IS_TYPE_NONE;
92     mNumBuffers = numBuffers;
93     mPerFrameMapUnmapEnable = true;
94     dumpFrmCnt = 0;
95 }
96 
97 /*===========================================================================
98  * FUNCTION   : ~QCamera3Channel
99  *
100  * DESCRIPTION: destructor of QCamera3Channel
101  *
102  * PARAMETERS : none
103  *
104  * RETURN     : none
105  *==========================================================================*/
~QCamera3Channel()106 QCamera3Channel::~QCamera3Channel()
107 {
108 }
109 
110 /*===========================================================================
111  * FUNCTION   : destroy
112  *
113  * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
114  *              this destructor will call pure virtual functions.  stop will eventuall call
115  *              QCamera3Stream::putBufs.  The putBufs function will
116  *              call QCamera3Channel::putStreamBufs which is pure virtual
117  *
118  * PARAMETERS : none
119  *
120  * RETURN     : none
121  *==========================================================================*/
destroy()122 void QCamera3Channel::destroy()
123 {
124     if (m_bIsActive)
125         stop();
126 
127     for (uint32_t i = 0; i < m_numStreams; i++) {
128         if (mStreams[i] != NULL) {
129             delete mStreams[i];
130             mStreams[i] = 0;
131         }
132     }
133     m_numStreams = 0;
134 }
135 
136 /*===========================================================================
137  * FUNCTION   : addStream
138  *
139  * DESCRIPTION: add a stream into channel
140  *
141  * PARAMETERS :
142  *   @streamType     : stream type
143  *   @streamFormat   : stream format
144  *   @streamDim      : stream dimension
145  *   @streamRotation : rotation of the stream
146  *   @minStreamBufNum : minimal buffer count for particular stream type
147  *   @postprocessMask : post-proccess feature mask
148  *   @isType         : type of image stabilization required on the stream
149  *
150  * RETURN     : int32_t type of status
151  *              NO_ERROR  -- success
152  *              none-zero failure code
153  *==========================================================================*/
addStream(cam_stream_type_t streamType,cam_format_t streamFormat,cam_dimension_t streamDim,cam_rotation_t streamRotation,uint8_t minStreamBufNum,uint32_t postprocessMask,cam_is_type_t isType,uint32_t batchSize)154 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
155                                   cam_format_t streamFormat,
156                                   cam_dimension_t streamDim,
157                                   cam_rotation_t streamRotation,
158                                   uint8_t minStreamBufNum,
159                                   uint32_t postprocessMask,
160                                   cam_is_type_t isType,
161                                   uint32_t batchSize)
162 {
163     int32_t rc = NO_ERROR;
164 
165     if (m_numStreams >= 1) {
166         LOGE("Only one stream per channel supported in v3 Hal");
167         return BAD_VALUE;
168     }
169 
170     if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
171         LOGE("stream number (%d) exceeds max limit (%d)",
172                m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
173         return BAD_VALUE;
174     }
175     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
176                                                m_handle,
177                                                m_camOps,
178                                                &mPaddingInfo,
179                                                this);
180     if (pStream == NULL) {
181         LOGE("No mem for Stream");
182         return NO_MEMORY;
183     }
184     LOGD("batch size is %d", batchSize);
185 
186     rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
187             NULL, minStreamBufNum, postprocessMask, isType, batchSize,
188             streamCbRoutine, this);
189     if (rc == 0) {
190         mStreams[m_numStreams] = pStream;
191         m_numStreams++;
192     } else {
193         delete pStream;
194     }
195     return rc;
196 }
197 
198 /*===========================================================================
199  * FUNCTION   : start
200  *
201  * DESCRIPTION: start channel, which will start all streams belong to this channel
202  *
203  * PARAMETERS :
204  *
205  * RETURN     : int32_t type of status
206  *              NO_ERROR  -- success
207  *              none-zero failure code
208  *==========================================================================*/
start()209 int32_t QCamera3Channel::start()
210 {
211     ATRACE_CALL();
212     int32_t rc = NO_ERROR;
213 
214     if (m_numStreams > 1) {
215         LOGW("bundle not supported");
216     } else if (m_numStreams == 0) {
217         return NO_INIT;
218     }
219 
220     if(m_bIsActive) {
221         LOGW("Attempt to start active channel");
222         return rc;
223     }
224 
225     for (uint32_t i = 0; i < m_numStreams; i++) {
226         if (mStreams[i] != NULL) {
227             mStreams[i]->start();
228         }
229     }
230 
231     m_bIsActive = true;
232 
233     return rc;
234 }
235 
236 /*===========================================================================
237  * FUNCTION   : stop
238  *
239  * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
240  *
241  * PARAMETERS : none
242  *
243  * RETURN     : int32_t type of status
244  *              NO_ERROR  -- success
245  *              none-zero failure code
246  *==========================================================================*/
stop()247 int32_t QCamera3Channel::stop()
248 {
249     ATRACE_CALL();
250     int32_t rc = NO_ERROR;
251     if(!m_bIsActive) {
252         LOGE("Attempt to stop inactive channel");
253         return rc;
254     }
255 
256     for (uint32_t i = 0; i < m_numStreams; i++) {
257         if (mStreams[i] != NULL) {
258             mStreams[i]->stop();
259         }
260     }
261 
262     m_bIsActive = false;
263     return rc;
264 }
265 
266 /*===========================================================================
267  * FUNCTION   : setBatchSize
268  *
269  * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
270  *              for the base class
271  *
272  * PARAMETERS :
273  *   @batchSize  : Number of image buffers in a batch
274  *
275  * RETURN     : int32_t type of status
276  *              NO_ERROR  -- success always
277  *              none-zero failure code
278  *==========================================================================*/
setBatchSize(uint32_t batchSize)279 int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
280 {
281     LOGD("Dummy method. batchSize: %d unused ", batchSize);
282     return NO_ERROR;
283 }
284 
285 /*===========================================================================
286  * FUNCTION   : queueBatchBuf
287  *
288  * DESCRIPTION: This is a dummy implementation for the base class
289  *
290  * PARAMETERS :
291  *
292  * RETURN     : int32_t type of status
293  *              NO_ERROR  -- success always
294  *              none-zero failure code
295  *==========================================================================*/
queueBatchBuf()296 int32_t QCamera3Channel::queueBatchBuf()
297 {
298     LOGD("Dummy method. Unused ");
299     return NO_ERROR;
300 }
301 
302 /*===========================================================================
303  * FUNCTION   : setPerFrameMapUnmap
304  *
305  * DESCRIPTION: Sets internal enable flag
306  *
307  * PARAMETERS :
308  *  @enable : Bool value for the enable flag
309  *
310  * RETURN     : int32_t type of status
311  *              NO_ERROR  -- success always
312  *              none-zero failure code
313  *==========================================================================*/
setPerFrameMapUnmap(bool enable)314 int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
315 {
316     mPerFrameMapUnmapEnable = enable;
317     return NO_ERROR;
318 }
319 
320 /*===========================================================================
321  * FUNCTION   : flush
322  *
323  * DESCRIPTION: flush a channel
324  *
325  * PARAMETERS : none
326  *
327  * RETURN     : int32_t type of status
328  *              NO_ERROR  -- success
329  *              none-zero failure code
330  *==========================================================================*/
flush()331 int32_t QCamera3Channel::flush()
332 {
333     ATRACE_CALL();
334     return NO_ERROR;
335 }
336 
337 /*===========================================================================
338  * FUNCTION   : bufDone
339  *
340  * DESCRIPTION: return a stream buf back to kernel
341  *
342  * PARAMETERS :
343  *   @recvd_frame  : stream buf frame to be returned
344  *
345  * RETURN     : int32_t type of status
346  *              NO_ERROR  -- success
347  *              none-zero failure code
348  *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)349 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
350 {
351     int32_t rc = NO_ERROR;
352     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
353          if (recvd_frame->bufs[i] != NULL) {
354              for (uint32_t j = 0; j < m_numStreams; j++) {
355                  if (mStreams[j] != NULL &&
356                      mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
357                      rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
358                      break; // break loop j
359                  }
360              }
361          }
362     }
363 
364     return rc;
365 }
366 
setBundleInfo(const cam_bundle_config_t & bundleInfo)367 int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
368 {
369     int32_t rc = NO_ERROR;
370     cam_stream_parm_buffer_t param;
371     memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
372     param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
373     param.bundleInfo = bundleInfo;
374     rc = mStreams[0]->setParameter(param);
375     if (rc != NO_ERROR) {
376         LOGE("stream setParameter for set bundle failed");
377     }
378 
379     return rc;
380 }
381 
382 /*===========================================================================
383  * FUNCTION   : getStreamTypeMask
384  *
385  * DESCRIPTION: Get bit mask of all stream types in this channel
386  *
387  * PARAMETERS : None
388  *
389  * RETURN     : Bit mask of all stream types in this channel
390  *==========================================================================*/
getStreamTypeMask()391 uint32_t QCamera3Channel::getStreamTypeMask()
392 {
393     uint32_t mask = 0;
394     for (uint32_t i = 0; i < m_numStreams; i++) {
395        mask |= (1U << mStreams[i]->getMyType());
396     }
397     return mask;
398 }
399 
400 /*===========================================================================
401  * FUNCTION   : getStreamID
402  *
403  * DESCRIPTION: Get StreamID of requested stream type
404  *
405  * PARAMETERS : streamMask
406  *
407  * RETURN     : Stream ID
408  *==========================================================================*/
getStreamID(uint32_t streamMask)409 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
410 {
411     uint32_t streamID = 0;
412     for (uint32_t i = 0; i < m_numStreams; i++) {
413         if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
414             streamID = mStreams[i]->getMyServerID();
415             break;
416         }
417     }
418     return streamID;
419 }
420 
421 /*===========================================================================
422  * FUNCTION   : getStreamByHandle
423  *
424  * DESCRIPTION: return stream object by stream handle
425  *
426  * PARAMETERS :
427  *   @streamHandle : stream handle
428  *
429  * RETURN     : stream object. NULL if not found
430  *==========================================================================*/
getStreamByHandle(uint32_t streamHandle)431 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
432 {
433     for (uint32_t i = 0; i < m_numStreams; i++) {
434         if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
435             return mStreams[i];
436         }
437     }
438     return NULL;
439 }
440 
441 /*===========================================================================
442  * FUNCTION   : getStreamByIndex
443  *
444  * DESCRIPTION: return stream object by index
445  *
446  * PARAMETERS :
447  *   @streamHandle : stream handle
448  *
449  * RETURN     : stream object. NULL if not found
450  *==========================================================================*/
getStreamByIndex(uint32_t index)451 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
452 {
453     if (index < m_numStreams) {
454         return mStreams[index];
455     }
456     return NULL;
457 }
458 
459 /*===========================================================================
460  * FUNCTION   : streamCbRoutine
461  *
462  * DESCRIPTION: callback routine for stream
463  *
464  * PARAMETERS :
465  *   @streamHandle : stream handle
466  *
467  * RETURN     : stream object. NULL if not found
468  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream,void * userdata)469 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
470                 QCamera3Stream *stream, void *userdata)
471 {
472     QCamera3Channel *channel = (QCamera3Channel *)userdata;
473     if (channel == NULL) {
474         LOGE("invalid channel pointer");
475         return;
476     }
477     channel->streamCbRoutine(super_frame, stream);
478 }
479 
480 /*===========================================================================
481  * FUNCTION   : dumpYUV
482  *
483  * DESCRIPTION: function to dump the YUV data from ISP/pproc
484  *
485  * PARAMETERS :
486  *   @frame   : frame to be dumped
487  *   @dim     : dimension of the stream
488  *   @offset  : offset of the data
489  *   @name    : 1 if it is ISP output/pproc input, 2 if it is pproc output
490  *
491  * RETURN  :
492  *==========================================================================*/
dumpYUV(mm_camera_buf_def_t * frame,cam_dimension_t dim,cam_frame_len_offset_t offset,uint8_t dump_type)493 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
494         cam_frame_len_offset_t offset, uint8_t dump_type)
495 {
496     char buf[FILENAME_MAX];
497     memset(buf, 0, sizeof(buf));
498     static int counter = 0;
499     char prop[PROPERTY_VALUE_MAX];
500     property_get("persist.camera.dumpimg", prop, "0");
501     mYUVDump = (uint8_t) atoi(prop);
502     if (mYUVDump & dump_type) {
503         frm_num = ((mYUVDump & 0xffff0000) >> 16);
504         if (frm_num == 0) {
505             frm_num = 10;
506         }
507         if (frm_num > 256) {
508             frm_num = 256;
509         }
510         skip_mode = ((mYUVDump & 0x0000ff00) >> 8);
511         if (skip_mode == 0) {
512             skip_mode = 1;
513         }
514         if (mDumpSkipCnt == 0) {
515             mDumpSkipCnt = 1;
516         }
517         if (mDumpSkipCnt % skip_mode == 0) {
518             if (dumpFrmCnt <= frm_num) {
519                 /* Note that the image dimension will be the unrotated stream dimension.
520                 * If you feel that the image would have been rotated during reprocess
521                 * then swap the dimensions while opening the file
522                 * */
523                 switch (dump_type) {
524                     case QCAMERA_DUMP_FRM_PREVIEW:
525                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
526                             counter, frame->frame_idx, dim.width, dim.height);
527                     break;
528                     case QCAMERA_DUMP_FRM_VIDEO:
529                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
530                             counter, frame->frame_idx, dim.width, dim.height);
531                     break;
532                     case QCAMERA_DUMP_FRM_SNAPSHOT:
533                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
534                             counter, frame->frame_idx, dim.width, dim.height);
535                     break;
536                     case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
537                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
538                             counter, frame->frame_idx, dim.width, dim.height);
539                     break;
540                     case QCAMERA_DUMP_FRM_CALLBACK:
541                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
542                             counter, frame->frame_idx, dim.width, dim.height);
543                     break;
544                     default :
545                         LOGE("dumping not enabled for stream type %d",dump_type);
546                     break;
547                 }
548                 counter++;
549                 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
550                 ssize_t written_len = 0;
551                 if (file_fd >= 0) {
552                     void *data = NULL;
553                     fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
554                     for (uint32_t i = 0; i < offset.num_planes; i++) {
555                         uint32_t index = offset.mp[i].offset;
556                         if (i > 0) {
557                             index += offset.mp[i-1].len;
558                         }
559                         for (int j = 0; j < offset.mp[i].height; j++) {
560                             data = (void *)((uint8_t *)frame->buffer + index);
561                             written_len += write(file_fd, data,
562                                     (size_t)offset.mp[i].width);
563                             index += (uint32_t)offset.mp[i].stride;
564                         }
565                     }
566                     LOGH("written number of bytes %ld\n", written_len);
567                     dumpFrmCnt++;
568                     close(file_fd);
569                 } else {
570                     LOGE("failed to open file to dump image");
571                 }
572             }
573         } else {
574             mDumpSkipCnt++;
575         }
576     }
577 }
578 
579 /*===========================================================================
580  * FUNCTION   : isUBWCEnabled
581  *
582  * DESCRIPTION: Function to get UBWC hardware support.
583  *
584  * PARAMETERS : None
585  *
586  * RETURN     : TRUE -- UBWC format supported
587  *              FALSE -- UBWC is not supported.
588  *==========================================================================*/
isUBWCEnabled()589 bool QCamera3Channel::isUBWCEnabled()
590 {
591 #ifdef UBWC_PRESENT
592     char value[PROPERTY_VALUE_MAX];
593     int prop_value = 0;
594     memset(value, 0, sizeof(value));
595     property_get("debug.gralloc.gfx_ubwc_disable", value, "0");
596     prop_value = atoi(value);
597     if (prop_value) {
598         return FALSE;
599     }
600 
601     //Disable UBWC if Eztune is enabled
602     //EzTune process CPP output frame and cannot understand UBWC.
603     memset(value, 0, sizeof(value));
604     property_get("persist.camera.eztune.enable", value, "0");
605     prop_value = atoi(value);
606     if (prop_value) {
607         return FALSE;
608     }
609     return TRUE;
610 #else
611     return FALSE;
612 #endif
613 }
614 
615 /*===========================================================================
616  * FUNCTION   : getStreamDefaultFormat
617  *
618  * DESCRIPTION: return default buffer format for the stream
619  *
620  * PARAMETERS : type : Stream type
621  *
622  ** RETURN    : format for stream type
623  *
624  *==========================================================================*/
getStreamDefaultFormat(cam_stream_type_t type)625 cam_format_t QCamera3Channel::getStreamDefaultFormat(cam_stream_type_t type)
626 {
627     cam_format_t streamFormat;
628 
629     switch (type) {
630     case CAM_STREAM_TYPE_PREVIEW:
631         if (isUBWCEnabled()) {
632             char prop[PROPERTY_VALUE_MAX];
633             int pFormat;
634             memset(prop, 0, sizeof(prop));
635             property_get("persist.camera.preview.ubwc", prop, "1");
636             pFormat = atoi(prop);
637             if (pFormat == 1) {
638                 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
639             } else {
640                 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
641             }
642         } else {
643             streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
644         }
645         break;
646     case CAM_STREAM_TYPE_VIDEO:
647         if (isUBWCEnabled()) {
648             char prop[PROPERTY_VALUE_MAX];
649             int pFormat;
650             memset(prop, 0, sizeof(prop));
651             property_get("persist.camera.video.ubwc", prop, "1");
652             pFormat = atoi(prop);
653             if (pFormat == 1) {
654                 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
655             } else {
656                 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
657             }
658         } else {
659 #if VENUS_PRESENT
660         streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
661 #else
662         streamFormat = CAM_FORMAT_YUV_420_NV12;
663 #endif
664         }
665         break;
666     case CAM_STREAM_TYPE_SNAPSHOT:
667         streamFormat = CAM_FORMAT_YUV_420_NV21;
668         break;
669     case CAM_STREAM_TYPE_CALLBACK:
670         streamFormat = CAM_FORMAT_YUV_420_NV21;
671         break;
672     case CAM_STREAM_TYPE_RAW:
673         streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
674         break;
675     default:
676         streamFormat = CAM_FORMAT_YUV_420_NV21;
677         break;
678     }
679     return streamFormat;
680 }
681 
682 
683 /* QCamera3ProcessingChannel methods */
684 
685 /*===========================================================================
686  * FUNCTION   : QCamera3ProcessingChannel
687  *
688  * DESCRIPTION: constructor of QCamera3ProcessingChannel
689  *
690  * PARAMETERS :
691  *   @cam_handle : camera handle
692  *   @cam_ops    : ptr to camera ops table
693  *   @cb_routine : callback routine to frame aggregator
694  *   @paddingInfo: stream padding info
695  *   @userData   : HWI handle
696  *   @stream     : camera3_stream_t structure
697  *   @stream_type: Channel stream type
698  *   @postprocess_mask: the postprocess mask for streams of this channel
699  *   @metadataChannel: handle to the metadataChannel
700  *   @numBuffers : number of max dequeued buffers
701  * RETURN     : none
702  *==========================================================================*/
QCamera3ProcessingChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,uint32_t postprocess_mask,QCamera3Channel * metadataChannel,uint32_t numBuffers)703 QCamera3ProcessingChannel::QCamera3ProcessingChannel(uint32_t cam_handle,
704         uint32_t channel_handle,
705         mm_camera_ops_t *cam_ops,
706         channel_cb_routine cb_routine,
707         cam_padding_info_t *paddingInfo,
708         void *userData,
709         camera3_stream_t *stream,
710         cam_stream_type_t stream_type,
711         uint32_t postprocess_mask,
712         QCamera3Channel *metadataChannel,
713         uint32_t numBuffers) :
714             QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine,
715                     paddingInfo, postprocess_mask, userData, numBuffers),
716             m_postprocessor(this),
717             mFrameCount(0),
718             mLastFrameCount(0),
719             mLastFpsTime(0),
720             mMemory(numBuffers),
721             mCamera3Stream(stream),
722             mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
723             mStreamType(stream_type),
724             mPostProcStarted(false),
725             mInputBufferConfig(false),
726             m_pMetaChannel(metadataChannel),
727             mMetaFrame(NULL),
728             mOfflineMemory(0),
729             mOfflineMetaMemory(numBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1),
730                     false)
731 {
732     char prop[PROPERTY_VALUE_MAX];
733     property_get("persist.debug.sf.showfps", prop, "0");
734     mDebugFPS = (uint8_t) atoi(prop);
735 
736     int32_t rc = m_postprocessor.init(&mMemory, mPostProcMask);
737     if (rc != 0) {
738         LOGE("Init Postprocessor failed");
739     }
740 }
741 
742 /*===========================================================================
743  * FUNCTION   : ~QCamera3ProcessingChannel
744  *
745  * DESCRIPTION: destructor of QCamera3ProcessingChannel
746  *
747  * PARAMETERS : none
748  *
749  * RETURN     : none
750  *==========================================================================*/
~QCamera3ProcessingChannel()751 QCamera3ProcessingChannel::~QCamera3ProcessingChannel()
752 {
753     destroy();
754 
755     int32_t rc = m_postprocessor.deinit();
756     if (rc != 0) {
757         LOGE("De-init Postprocessor failed");
758     }
759 
760     if (0 < mOfflineMetaMemory.getCnt()) {
761         mOfflineMetaMemory.deallocate();
762     }
763     if (0 < mOfflineMemory.getCnt()) {
764         mOfflineMemory.unregisterBuffers();
765     }
766 
767 }
768 
769 /*===========================================================================
770  * FUNCTION   : streamCbRoutine
771  *
772  * DESCRIPTION:
773  *
774  * PARAMETERS :
775  * @super_frame : the super frame with filled buffer
776  * @stream      : stream on which the buffer was requested and filled
777  *
778  * RETURN     : none
779  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)780 void QCamera3ProcessingChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
781         QCamera3Stream *stream)
782 {
783      ATRACE_CALL();
784     //FIXME Q Buf back in case of error?
785     uint8_t frameIndex;
786     buffer_handle_t *resultBuffer;
787     int32_t resultFrameNumber;
788     camera3_stream_buffer_t result;
789     cam_dimension_t dim;
790     cam_frame_len_offset_t offset;
791 
792     memset(&dim, 0, sizeof(dim));
793     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
794     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
795         LOGE("Error with the stream callback");
796         return;
797     }
798 
799     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
800     if(frameIndex >= mNumBufs) {
801          LOGE("Error, Invalid index for buffer");
802          stream->bufDone(frameIndex);
803          return;
804     }
805 
806     if (mDebugFPS) {
807         showDebugFPS(stream->getMyType());
808     }
809     stream->getFrameDimension(dim);
810     stream->getFrameOffset(offset);
811     if (stream->getMyType() == CAM_STREAM_TYPE_PREVIEW) {
812         dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_PREVIEW);
813     } else if (stream->getMyType() == CAM_STREAM_TYPE_VIDEO) {
814         dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_VIDEO);
815     } else if (stream->getMyType() == CAM_STREAM_TYPE_CALLBACK) {
816         dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_CALLBACK);
817     }
818     ////Use below data to issue framework callback
819     resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
820     resultFrameNumber = mMemory.getFrameNumber(frameIndex);
821 
822     result.stream = mCamera3Stream;
823     result.buffer = resultBuffer;
824     if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
825         result.status = CAMERA3_BUFFER_STATUS_ERROR;
826         LOGW("CAMERA3_BUFFER_STATUS_ERROR for stream_type: %d",
827                 mStreams[0]->getMyType());
828     } else {
829         result.status = CAMERA3_BUFFER_STATUS_OK;
830     }
831     result.acquire_fence = -1;
832     result.release_fence = -1;
833     if(mPerFrameMapUnmapEnable) {
834         int32_t rc = stream->bufRelease(frameIndex);
835         if (NO_ERROR != rc) {
836             LOGE("Error %d releasing stream buffer %d",
837                      rc, frameIndex);
838         }
839 
840         rc = mMemory.unregisterBuffer(frameIndex);
841         if (NO_ERROR != rc) {
842             LOGE("Error %d unregistering stream buffer %d",
843                      rc, frameIndex);
844         }
845     }
846 
847     if (0 <= resultFrameNumber) {
848         if (mChannelCB) {
849             mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, false, mUserData);
850         }
851     } else {
852         LOGE("Bad frame number");
853     }
854     free(super_frame);
855     return;
856 }
857 
858 /*===========================================================================
859  * FUNCTION   : putStreamBufs
860  *
861  * DESCRIPTION: release the buffers allocated to the stream
862  *
863  * PARAMETERS : NONE
864  *
865  * RETURN     : NONE
866  *==========================================================================*/
putStreamBufs()867 void QCamera3YUVChannel::putStreamBufs()
868 {
869     QCamera3ProcessingChannel::putStreamBufs();
870 
871     // Free allocated heap buffer.
872     mMemory.deallocate();
873     // Clear free heap buffer list.
874     mFreeHeapBufferList.clear();
875     // Clear offlinePpInfoList
876     mOfflinePpInfoList.clear();
877 }
878 
879 /*===========================================================================
880  * FUNCTION   : request
881  *
882  * DESCRIPTION: handle the request - either with an input buffer or a direct
883  *              output request
884  *
885  * PARAMETERS :
886  * @buffer          : pointer to the output buffer
887  * @frameNumber     : frame number of the request
888  * @pInputBuffer    : pointer to input buffer if an input request
889  * @metadata        : parameters associated with the request
890  *
891  * RETURN     : 0 on a success start of capture
892  *              -EINVAL on invalid input
893  *              -ENODEV on serious error
894  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata)895 int32_t QCamera3ProcessingChannel::request(buffer_handle_t *buffer,
896         uint32_t frameNumber,
897         camera3_stream_buffer_t* pInputBuffer,
898         metadata_buffer_t* metadata)
899 {
900     int32_t rc = NO_ERROR;
901     int index;
902 
903     if (NULL == buffer || NULL == metadata) {
904         LOGE("Invalid buffer/metadata in channel request");
905         return BAD_VALUE;
906     }
907 
908     if (pInputBuffer) {
909         //need to send to reprocessing
910         LOGD("Got a request with input buffer, output streamType = %d", mStreamType);
911         reprocess_config_t reproc_cfg;
912         cam_dimension_t dim;
913         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
914         memset(&dim, 0, sizeof(dim));
915         setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
916         startPostProc(reproc_cfg);
917 
918         qcamera_fwk_input_pp_data_t *src_frame = NULL;
919         src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
920                 sizeof(qcamera_fwk_input_pp_data_t));
921         if (src_frame == NULL) {
922             LOGE("No memory for src frame");
923             return NO_MEMORY;
924         }
925         rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata, buffer, frameNumber);
926         if (NO_ERROR != rc) {
927             LOGE("Error %d while setting framework input PP data", rc);
928             free(src_frame);
929             return rc;
930         }
931         LOGH("Post-process started");
932         m_postprocessor.processData(src_frame);
933     } else {
934         //need to fill output buffer with new data and return
935         if(!m_bIsActive) {
936             rc = registerBuffer(buffer, mIsType);
937             if (NO_ERROR != rc) {
938                 LOGE("On-the-fly buffer registration failed %d",
939                          rc);
940                 return rc;
941             }
942 
943             rc = start();
944             if (NO_ERROR != rc)
945                 return rc;
946         } else {
947             LOGD("Request on an existing stream");
948         }
949 
950         index = mMemory.getMatchBufIndex((void*)buffer);
951         if(index < 0) {
952             rc = registerBuffer(buffer, mIsType);
953             if (NO_ERROR != rc) {
954                 LOGE("On-the-fly buffer registration failed %d",
955                          rc);
956                 return rc;
957             }
958 
959             index = mMemory.getMatchBufIndex((void*)buffer);
960             if (index < 0) {
961                 LOGE("Could not find object among registered buffers");
962                 return DEAD_OBJECT;
963             }
964         }
965         rc = mStreams[0]->bufDone(index);
966         if(rc != NO_ERROR) {
967             LOGE("Failed to Q new buffer to stream");
968             return rc;
969         }
970         rc = mMemory.markFrameNumber(index, frameNumber);
971     }
972     return rc;
973 }
974 
975 /*===========================================================================
976  * FUNCTION   : initialize
977  *
978  * DESCRIPTION:
979  *
980  * PARAMETERS : isType : type of image stabilization on the buffer
981  *
982  * RETURN     : int32_t type of status
983  *              NO_ERROR  -- success
984  *              none-zero failure code
985  *==========================================================================*/
initialize(__unused cam_is_type_t isType)986 int32_t QCamera3ProcessingChannel::initialize(__unused cam_is_type_t isType)
987 {
988     int32_t rc = NO_ERROR;
989     rc = mOfflineMetaMemory.allocateAll(sizeof(metadata_buffer_t));
990     if (rc == NO_ERROR) {
991         Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
992         mFreeOfflineMetaBuffersList.clear();
993         for (uint32_t i = 0; i < mNumBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1);
994                 i++) {
995             mFreeOfflineMetaBuffersList.push_back(i);
996         }
997     } else {
998         LOGE("Could not allocate offline meta buffers for input reprocess");
999     }
1000     return rc;
1001 }
1002 
1003 /*===========================================================================
1004  * FUNCTION   : registerBuffer
1005  *
1006  * DESCRIPTION: register streaming buffer to the channel object
1007  *
1008  * PARAMETERS :
1009  *   @buffer     : buffer to be registered
1010  *   @isType     : image stabilization type on the stream
1011  *
1012  * RETURN     : int32_t type of status
1013  *              NO_ERROR  -- success
1014  *              none-zero failure code
1015  *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)1016 int32_t QCamera3ProcessingChannel::registerBuffer(buffer_handle_t *buffer,
1017         cam_is_type_t isType)
1018 {
1019     ATRACE_CALL();
1020     int rc = 0;
1021     mIsType = isType;
1022     cam_stream_type_t streamType;
1023 
1024     if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
1025         LOGE("Trying to register more buffers than initially requested");
1026         return BAD_VALUE;
1027     }
1028 
1029     if (0 == m_numStreams) {
1030         rc = initialize(mIsType);
1031         if (rc != NO_ERROR) {
1032             LOGE("Couldn't initialize camera stream %d", rc);
1033             return rc;
1034         }
1035     }
1036 
1037     streamType = mStreams[0]->getMyType();
1038     rc = mMemory.registerBuffer(buffer, streamType);
1039     if (ALREADY_EXISTS == rc) {
1040         return NO_ERROR;
1041     } else if (NO_ERROR != rc) {
1042         LOGE("Buffer %p couldn't be registered %d", buffer, rc);
1043         return rc;
1044     }
1045 
1046     return rc;
1047 }
1048 
1049 /*===========================================================================
1050  * FUNCTION   : setFwkInputPPData
1051  *
1052  * DESCRIPTION: fill out the framework src frame information for reprocessing
1053  *
1054  * PARAMETERS :
1055  *   @src_frame         : input pp data to be filled out
1056  *   @pInputBuffer      : input buffer for reprocessing
1057  *   @reproc_cfg        : pointer to the reprocess config
1058  *   @metadata          : pointer to the metadata buffer
1059  *   @output_buffer     : output buffer for reprocessing; could be NULL if not
1060  *                        framework allocated
1061  *   @frameNumber       : frame number of the request
1062  *
1063  * RETURN     : int32_t type of status
1064  *              NO_ERROR  -- success
1065  *              none-zero failure code
1066  *==========================================================================*/
setFwkInputPPData(qcamera_fwk_input_pp_data_t * src_frame,camera3_stream_buffer_t * pInputBuffer,reprocess_config_t * reproc_cfg,metadata_buffer_t * metadata,buffer_handle_t * output_buffer,uint32_t frameNumber)1067 int32_t QCamera3ProcessingChannel::setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
1068         camera3_stream_buffer_t *pInputBuffer, reprocess_config_t *reproc_cfg,
1069         metadata_buffer_t *metadata, buffer_handle_t *output_buffer,
1070         uint32_t frameNumber)
1071 {
1072     int32_t rc = NO_ERROR;
1073     int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1074     if(input_index < 0) {
1075         rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType);
1076         if (NO_ERROR != rc) {
1077             LOGE("On-the-fly input buffer registration failed %d",
1078                      rc);
1079             return rc;
1080         }
1081         input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1082         if (input_index < 0) {
1083             LOGE("Could not find object among registered buffers");
1084             return DEAD_OBJECT;
1085         }
1086     }
1087     mOfflineMemory.markFrameNumber(input_index, frameNumber);
1088 
1089     src_frame->src_frame = *pInputBuffer;
1090     rc = mOfflineMemory.getBufDef(reproc_cfg->input_stream_plane_info.plane_info,
1091             src_frame->input_buffer, input_index);
1092     if (rc != 0) {
1093         return rc;
1094     }
1095     dumpYUV(&src_frame->input_buffer, reproc_cfg->input_stream_dim,
1096             reproc_cfg->input_stream_plane_info.plane_info, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
1097     cam_dimension_t dim = {sizeof(metadata_buffer_t), 1};
1098     cam_stream_buf_plane_info_t meta_planes;
1099     rc = mm_stream_calc_offset_metadata(&dim, &mPaddingInfo, &meta_planes);
1100     if (rc != 0) {
1101         LOGE("Metadata stream plane info calculation failed!");
1102         return rc;
1103     }
1104     uint32_t metaBufIdx;
1105     {
1106         Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1107         if (mFreeOfflineMetaBuffersList.empty()) {
1108             LOGE("mFreeOfflineMetaBuffersList is null. Fatal");
1109             return BAD_VALUE;
1110         }
1111 
1112         metaBufIdx = *(mFreeOfflineMetaBuffersList.begin());
1113         mFreeOfflineMetaBuffersList.erase(mFreeOfflineMetaBuffersList.begin());
1114         LOGD("erasing %d, mFreeOfflineMetaBuffersList.size %d", metaBufIdx,
1115                 mFreeOfflineMetaBuffersList.size());
1116     }
1117 
1118     mOfflineMetaMemory.markFrameNumber(metaBufIdx, frameNumber);
1119 
1120     mm_camera_buf_def_t meta_buf;
1121     cam_frame_len_offset_t offset = meta_planes.plane_info;
1122     rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, metaBufIdx);
1123     if (NO_ERROR != rc) {
1124         return rc;
1125     }
1126     memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t));
1127     src_frame->metadata_buffer = meta_buf;
1128     src_frame->reproc_config = *reproc_cfg;
1129     src_frame->output_buffer = output_buffer;
1130     src_frame->frameNumber = frameNumber;
1131     return rc;
1132 }
1133 
1134 /*===========================================================================
1135  * FUNCTION   : checkStreamCbErrors
1136  *
1137  * DESCRIPTION: check the stream callback for errors
1138  *
1139  * PARAMETERS :
1140  *   @super_frame : the super frame with filled buffer
1141  *   @stream      : stream on which the buffer was requested and filled
1142  *
1143  * RETURN     : int32_t type of status
1144  *              NO_ERROR  -- success
1145  *              none-zero failure code
1146  *==========================================================================*/
checkStreamCbErrors(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)1147 int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
1148         QCamera3Stream *stream)
1149 {
1150     if (NULL == stream) {
1151         LOGE("Invalid stream");
1152         return BAD_VALUE;
1153     }
1154 
1155     if(NULL == super_frame) {
1156          LOGE("Invalid Super buffer");
1157          return BAD_VALUE;
1158     }
1159 
1160     if(super_frame->num_bufs != 1) {
1161          LOGE("Multiple streams are not supported");
1162          return BAD_VALUE;
1163     }
1164     if(NULL == super_frame->bufs[0]) {
1165          LOGE("Error, Super buffer frame does not contain valid buffer");
1166          return BAD_VALUE;
1167     }
1168     return NO_ERROR;
1169 }
1170 
1171 /*===========================================================================
1172  * FUNCTION   : getStreamSize
1173  *
1174  * DESCRIPTION: get the size from the camera3_stream_t for the channel
1175  *
1176  * PARAMETERS :
1177  *   @dim     : Return the size of the stream
1178  *
1179  * RETURN     : int32_t type of status
1180  *              NO_ERROR  -- success
1181  *              none-zero failure code
1182  *==========================================================================*/
getStreamSize(cam_dimension_t & dim)1183 int32_t QCamera3ProcessingChannel::getStreamSize(cam_dimension_t &dim)
1184 {
1185     if (mCamera3Stream) {
1186         dim.width = mCamera3Stream->width;
1187         dim.height = mCamera3Stream->height;
1188         return NO_ERROR;
1189     } else {
1190         return BAD_VALUE;
1191     }
1192 }
1193 
1194 /*===========================================================================
1195  * FUNCTION   : getStreamBufs
1196  *
1197  * DESCRIPTION: get the buffers allocated to the stream
1198  *
1199  * PARAMETERS :
1200  * @len       : buffer length
1201  *
1202  * RETURN     : int32_t type of status
1203  *              NO_ERROR  -- success
1204  *              none-zero failure code
1205  *==========================================================================*/
getStreamBufs(uint32_t)1206 QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
1207 {
1208     KPI_ATRACE_CALL();
1209     return &mMemory;
1210 }
1211 
1212 /*===========================================================================
1213  * FUNCTION   : putStreamBufs
1214  *
1215  * DESCRIPTION: release the buffers allocated to the stream
1216  *
1217  * PARAMETERS : NONE
1218  *
1219  * RETURN     : NONE
1220  *==========================================================================*/
putStreamBufs()1221 void QCamera3ProcessingChannel::putStreamBufs()
1222 {
1223     mMemory.unregisterBuffers();
1224 
1225     /* Reclaim all the offline metabuffers and push them to free list */
1226     {
1227         Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1228         mFreeOfflineMetaBuffersList.clear();
1229         for (uint32_t i = 0; i < mOfflineMetaMemory.getCnt(); i++) {
1230             mFreeOfflineMetaBuffersList.push_back(i);
1231         }
1232     }
1233 }
1234 
1235 
1236 /*===========================================================================
1237  * FUNCTION   : stop
1238  *
1239  * DESCRIPTION: stop processing channel, which will stop all streams within,
1240  *              including the reprocessing channel in postprocessor.
1241  *
1242  * PARAMETERS : none
1243  *
1244  * RETURN     : int32_t type of status
1245  *              NO_ERROR  -- success
1246  *              none-zero failure code
1247  *==========================================================================*/
stop()1248 int32_t QCamera3ProcessingChannel::stop()
1249 {
1250     int32_t rc = NO_ERROR;
1251     if(!m_bIsActive) {
1252         LOGE("Attempt to stop inactive channel");
1253         return rc;
1254     }
1255 
1256     m_postprocessor.stop();
1257     mPostProcStarted = false;
1258     rc |= QCamera3Channel::stop();
1259     return rc;
1260 }
1261 
1262 /*===========================================================================
1263  * FUNCTION   : startPostProc
1264  *
1265  * DESCRIPTION: figure out if the postprocessor needs to be restarted and if yes
1266  *              start it
1267  *
1268  * PARAMETERS :
1269  * @inputBufExists : whether there is an input buffer for post processing
1270  * @config         : reprocessing configuration
1271  * @metadata       : metadata associated with the reprocessing request
1272  *
1273  * RETURN     : NONE
1274  *==========================================================================*/
startPostProc(const reprocess_config_t & config)1275 void QCamera3ProcessingChannel::startPostProc(const reprocess_config_t &config)
1276 {
1277     if(!mPostProcStarted) {
1278         m_postprocessor.start(config);
1279         mPostProcStarted = true;
1280     }
1281 }
1282 
1283 /*===========================================================================
1284  * FUNCTION   : queueReprocMetadata
1285  *
1286  * DESCRIPTION: queue the reprocess metadata to the postprocessor
1287  *
1288  * PARAMETERS : metadata : the metadata corresponding to the pp frame
1289  *
1290  * RETURN     : int32_t type of status
1291  *              NO_ERROR  -- success
1292  *              none-zero failure code
1293  *==========================================================================*/
queueReprocMetadata(mm_camera_super_buf_t * metadata)1294 int32_t QCamera3ProcessingChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
1295 {
1296     return m_postprocessor.processPPMetadata(metadata);
1297 }
1298 
1299 /*===========================================================================
1300  * FUNCTION : metadataBufDone
1301  *
1302  * DESCRIPTION: Buffer done method for a metadata buffer
1303  *
1304  * PARAMETERS :
1305  * @recvd_frame : received metadata frame
1306  *
1307  * RETURN     : int32_t type of status
1308  *              NO_ERROR  -- success
1309  *              none-zero failure code
1310  *==========================================================================*/
metadataBufDone(mm_camera_super_buf_t * recvd_frame)1311 int32_t QCamera3ProcessingChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
1312 {
1313     int32_t rc = NO_ERROR;;
1314     if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
1315         LOGE("Metadata channel or metadata buffer invalid");
1316         return BAD_VALUE;
1317     }
1318 
1319     rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
1320 
1321     return rc;
1322 }
1323 
1324 /*===========================================================================
1325  * FUNCTION : translateStreamTypeAndFormat
1326  *
1327  * DESCRIPTION: translates the framework stream format into HAL stream type
1328  *              and format
1329  *
1330  * PARAMETERS :
1331  * @streamType   : translated stream type
1332  * @streamFormat : translated stream format
1333  * @stream       : fwk stream
1334  *
1335  * RETURN     : int32_t type of status
1336  *              NO_ERROR  -- success
1337  *              none-zero failure code
1338  *==========================================================================*/
translateStreamTypeAndFormat(camera3_stream_t * stream,cam_stream_type_t & streamType,cam_format_t & streamFormat)1339 int32_t QCamera3ProcessingChannel::translateStreamTypeAndFormat(camera3_stream_t *stream,
1340         cam_stream_type_t &streamType, cam_format_t &streamFormat)
1341 {
1342     switch (stream->format) {
1343         case HAL_PIXEL_FORMAT_YCbCr_420_888:
1344             if(stream->stream_type == CAMERA3_STREAM_INPUT){
1345                 streamType = CAM_STREAM_TYPE_SNAPSHOT;
1346                 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT);
1347             } else {
1348                 streamType = CAM_STREAM_TYPE_CALLBACK;
1349                 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK);
1350             }
1351             break;
1352         case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1353             if (stream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
1354                 streamType = CAM_STREAM_TYPE_VIDEO;
1355                 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO);
1356             } else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
1357                     stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
1358                     IS_USAGE_ZSL(stream->usage)){
1359                 streamType = CAM_STREAM_TYPE_SNAPSHOT;
1360                 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT);
1361             } else {
1362                 streamType = CAM_STREAM_TYPE_PREVIEW;
1363                 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW);
1364             }
1365             break;
1366         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1367         case HAL_PIXEL_FORMAT_RAW16:
1368         case HAL_PIXEL_FORMAT_RAW10:
1369             streamType = CAM_STREAM_TYPE_RAW;
1370             streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
1371             break;
1372         default:
1373             return -EINVAL;
1374     }
1375     LOGD("fwk_format = %d, streamType = %d, streamFormat = %d",
1376             stream->format, streamType, streamFormat);
1377     return NO_ERROR;
1378 }
1379 
1380 /*===========================================================================
1381  * FUNCTION : setReprocConfig
1382  *
1383  * DESCRIPTION: sets the reprocessing parameters for the input buffer
1384  *
1385  * PARAMETERS :
1386  * @reproc_cfg : the configuration to be set
1387  * @pInputBuffer : pointer to the input buffer
1388  * @metadata : pointer to the reprocessing metadata buffer
1389  * @streamFormat : format of the input stream
1390  *
1391  * RETURN     : int32_t type of status
1392  *              NO_ERROR  -- success
1393  *              none-zero failure code
1394  *==========================================================================*/
setReprocConfig(reprocess_config_t & reproc_cfg,camera3_stream_buffer_t * pInputBuffer,__unused metadata_buffer_t * metadata,cam_format_t streamFormat,cam_dimension_t dim)1395 int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
1396         camera3_stream_buffer_t *pInputBuffer,
1397         __unused metadata_buffer_t *metadata,
1398         cam_format_t streamFormat, cam_dimension_t dim)
1399 {
1400     int32_t rc = 0;
1401     reproc_cfg.padding = &mPaddingInfo;
1402     //to ensure a big enough buffer size set the height and width
1403     //padding to max(height padding, width padding)
1404     if (reproc_cfg.padding->height_padding > reproc_cfg.padding->width_padding) {
1405        reproc_cfg.padding->width_padding = reproc_cfg.padding->height_padding;
1406     } else {
1407        reproc_cfg.padding->height_padding = reproc_cfg.padding->width_padding;
1408     }
1409     if (NULL != pInputBuffer) {
1410         reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
1411         reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
1412     } else {
1413         reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
1414         reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
1415     }
1416     reproc_cfg.src_channel = this;
1417     reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
1418     reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
1419     reproc_cfg.reprocess_type = getReprocessType();
1420 
1421     //offset calculation
1422     if (NULL != pInputBuffer) {
1423         rc = translateStreamTypeAndFormat(pInputBuffer->stream,
1424                 reproc_cfg.stream_type, reproc_cfg.stream_format);
1425         if (rc != NO_ERROR) {
1426             LOGE("Stream format %d is not supported",
1427                     pInputBuffer->stream->format);
1428             return rc;
1429         }
1430     } else {
1431         reproc_cfg.stream_type = mStreamType;
1432         reproc_cfg.stream_format = streamFormat;
1433     }
1434 
1435     switch (reproc_cfg.stream_type) {
1436         case CAM_STREAM_TYPE_PREVIEW:
1437             if (getStreamByIndex(0) == NULL) {
1438                 LOGE("Could not find stream");
1439                 rc = -1;
1440                 break;
1441             }
1442             rc = mm_stream_calc_offset_preview(
1443                     getStreamByIndex(0)->getStreamInfo(),
1444                     &reproc_cfg.input_stream_dim,
1445                     reproc_cfg.padding,
1446                     &reproc_cfg.input_stream_plane_info);
1447             break;
1448         case CAM_STREAM_TYPE_VIDEO:
1449             rc = mm_stream_calc_offset_video(reproc_cfg.stream_format,
1450                     &reproc_cfg.input_stream_dim,
1451                     &reproc_cfg.input_stream_plane_info);
1452             break;
1453         case CAM_STREAM_TYPE_RAW:
1454             rc = mm_stream_calc_offset_raw(reproc_cfg.stream_format,
1455                     &reproc_cfg.input_stream_dim,
1456                     reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1457             break;
1458         case CAM_STREAM_TYPE_SNAPSHOT:
1459         case CAM_STREAM_TYPE_CALLBACK:
1460         default:
1461             rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
1462                     reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1463             break;
1464     }
1465     if (rc != 0) {
1466         LOGE("Stream %d plane info calculation failed!", mStreamType);
1467         return rc;
1468     }
1469     return rc;
1470 }
1471 
1472 /*===========================================================================
1473  * FUNCTION   : reprocessCbRoutine
1474  *
1475  * DESCRIPTION: callback function for the reprocessed frame. This frame now
1476  *              should be returned to the framework
1477  *
1478  * PARAMETERS :
1479  * @resultBuffer      : buffer containing the reprocessed data
1480  * @resultFrameNumber : frame number on which the buffer was requested
1481  *
1482  * RETURN     : NONE
1483  *
1484  *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)1485 void QCamera3ProcessingChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
1486         uint32_t resultFrameNumber)
1487 {
1488     ATRACE_CALL();
1489     int rc = NO_ERROR;
1490 
1491     rc = releaseOfflineMemory(resultFrameNumber);
1492     if (NO_ERROR != rc) {
1493         LOGE("Error releasing offline memory %d", rc);
1494     }
1495     /* Since reprocessing is done, send the callback to release the input buffer */
1496     if (mChannelCB) {
1497         mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
1498     }
1499     issueChannelCb(resultBuffer, resultFrameNumber);
1500 
1501     return;
1502 }
1503 
1504 /*===========================================================================
1505  * FUNCTION   : issueChannelCb
1506  *
1507  * DESCRIPTION: function to set the result and issue channel callback
1508  *
1509  * PARAMETERS :
1510  * @resultBuffer      : buffer containing the data
1511  * @resultFrameNumber : frame number on which the buffer was requested
1512  *
1513  * RETURN     : NONE
1514  *
1515  *
1516  *==========================================================================*/
issueChannelCb(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)1517 void QCamera3ProcessingChannel::issueChannelCb(buffer_handle_t *resultBuffer,
1518         uint32_t resultFrameNumber)
1519 {
1520     camera3_stream_buffer_t result;
1521     //Use below data to issue framework callback
1522     result.stream = mCamera3Stream;
1523     result.buffer = resultBuffer;
1524     result.status = CAMERA3_BUFFER_STATUS_OK;
1525     result.acquire_fence = -1;
1526     result.release_fence = -1;
1527 
1528     if (mChannelCB) {
1529         mChannelCB(NULL, &result, resultFrameNumber, false, mUserData);
1530     }
1531 }
1532 
1533 /*===========================================================================
1534  * FUNCTION   : showDebugFPS
1535  *
1536  * DESCRIPTION: Function to log the fps for preview, video, callback and raw
1537  *              streams
1538  *
1539  * PARAMETERS : Stream type
1540  *
1541  * RETURN  : None
1542  *==========================================================================*/
showDebugFPS(int32_t streamType)1543 void QCamera3ProcessingChannel::showDebugFPS(int32_t streamType)
1544 {
1545     double fps = 0;
1546     mFrameCount++;
1547     nsecs_t now = systemTime();
1548     nsecs_t diff = now - mLastFpsTime;
1549     if (diff > ms2ns(250)) {
1550         fps = (((double)(mFrameCount - mLastFrameCount)) *
1551                 (double)(s2ns(1))) / (double)diff;
1552         switch(streamType) {
1553             case CAM_STREAM_TYPE_PREVIEW:
1554                 LOGH("PROFILE_PREVIEW_FRAMES_PER_SECOND : %.4f",
1555                          fps);
1556                 break;
1557             case CAM_STREAM_TYPE_VIDEO:
1558                 LOGH("PROFILE_VIDEO_FRAMES_PER_SECOND : %.4f",
1559                          fps);
1560                 break;
1561             case CAM_STREAM_TYPE_CALLBACK:
1562                 LOGH("PROFILE_CALLBACK_FRAMES_PER_SECOND : %.4f",
1563                          fps);
1564                 break;
1565             case CAM_STREAM_TYPE_RAW:
1566                 LOGH("PROFILE_RAW_FRAMES_PER_SECOND : %.4f",
1567                          fps);
1568                 break;
1569             default:
1570                 LOGH("logging not supported for the stream");
1571                 break;
1572         }
1573         mLastFpsTime = now;
1574         mLastFrameCount = mFrameCount;
1575     }
1576 }
1577 
1578 /*===========================================================================
1579  * FUNCTION   : releaseOfflineMemory
1580  *
1581  * DESCRIPTION: function to clean up the offline memory used for input reprocess
1582  *
1583  * PARAMETERS :
1584  * @resultFrameNumber : frame number on which the buffer was requested
1585  *
1586  * RETURN     : int32_t type of status
1587  *              NO_ERROR  -- success
1588  *              non-zero failure code
1589  *
1590  *
1591  *==========================================================================*/
releaseOfflineMemory(uint32_t resultFrameNumber)1592 int32_t QCamera3ProcessingChannel::releaseOfflineMemory(uint32_t resultFrameNumber)
1593 {
1594     int32_t rc = NO_ERROR;
1595     int32_t inputBufIndex =
1596             mOfflineMemory.getGrallocBufferIndex(resultFrameNumber);
1597     if (0 <= inputBufIndex) {
1598         rc = mOfflineMemory.unregisterBuffer(inputBufIndex);
1599     } else {
1600         LOGW("Could not find offline input buffer, resultFrameNumber %d",
1601                  resultFrameNumber);
1602     }
1603     if (rc != NO_ERROR) {
1604         LOGE("Failed to unregister offline input buffer");
1605     }
1606 
1607     int32_t metaBufIndex =
1608             mOfflineMetaMemory.getHeapBufferIndex(resultFrameNumber);
1609     if (0 <= metaBufIndex) {
1610         Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1611         mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
1612     } else {
1613         LOGW("Could not find offline meta buffer, resultFrameNumber %d",
1614                 resultFrameNumber);
1615     }
1616 
1617     return rc;
1618 }
1619 
1620 /* Regular Channel methods */
1621 /*===========================================================================
1622  * FUNCTION   : QCamera3RegularChannel
1623  *
1624  * DESCRIPTION: constructor of QCamera3RegularChannel
1625  *
1626  * PARAMETERS :
1627  *   @cam_handle : camera handle
1628  *   @cam_ops    : ptr to camera ops table
1629  *   @cb_routine : callback routine to frame aggregator
1630  *   @stream     : camera3_stream_t structure
1631  *   @stream_type: Channel stream type
1632  *   @postprocess_mask: feature mask for postprocessing
1633  *   @metadataChannel : metadata channel for the session
1634  *   @numBuffers : number of max dequeued buffers
1635  *
1636  * RETURN     : none
1637  *==========================================================================*/
QCamera3RegularChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,uint32_t postprocess_mask,QCamera3Channel * metadataChannel,uint32_t numBuffers)1638 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
1639         uint32_t channel_handle,
1640         mm_camera_ops_t *cam_ops,
1641         channel_cb_routine cb_routine,
1642         cam_padding_info_t *paddingInfo,
1643         void *userData,
1644         camera3_stream_t *stream,
1645         cam_stream_type_t stream_type,
1646         uint32_t postprocess_mask,
1647         QCamera3Channel *metadataChannel,
1648         uint32_t numBuffers) :
1649             QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
1650                     cb_routine, paddingInfo, userData, stream, stream_type,
1651                     postprocess_mask, metadataChannel, numBuffers),
1652             mBatchSize(0),
1653             mRotation(ROTATE_0)
1654 {
1655 }
1656 
1657 /*===========================================================================
1658  * FUNCTION   : ~QCamera3RegularChannel
1659  *
1660  * DESCRIPTION: destructor of QCamera3RegularChannel
1661  *
1662  * PARAMETERS : none
1663  *
1664  * RETURN     : none
1665  *==========================================================================*/
~QCamera3RegularChannel()1666 QCamera3RegularChannel::~QCamera3RegularChannel()
1667 {
1668     destroy();
1669 }
1670 
1671 /*===========================================================================
1672  * FUNCTION   : initialize
1673  *
1674  * DESCRIPTION: Initialize and add camera channel & stream
1675  *
1676  * PARAMETERS :
1677  *    @isType : type of image stabilization required on this stream
1678  *
1679  * RETURN     : int32_t type of status
1680  *              NO_ERROR  -- success
1681  *              none-zero failure code
1682  *==========================================================================*/
1683 
initialize(cam_is_type_t isType)1684 int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType)
1685 {
1686     ATRACE_CALL();
1687     int32_t rc = NO_ERROR;
1688 
1689     cam_dimension_t streamDim;
1690 
1691     if (NULL == mCamera3Stream) {
1692         LOGE("Camera stream uninitialized");
1693         return NO_INIT;
1694     }
1695 
1696     if (1 <= m_numStreams) {
1697         // Only one stream per channel supported in v3 Hal
1698         return NO_ERROR;
1699     }
1700 
1701     mIsType  = isType;
1702 
1703     rc = translateStreamTypeAndFormat(mCamera3Stream, mStreamType,
1704             mStreamFormat);
1705     if (rc != NO_ERROR) {
1706         return -EINVAL;
1707     }
1708 
1709 
1710     if ((mStreamType == CAM_STREAM_TYPE_VIDEO) ||
1711             (mStreamType == CAM_STREAM_TYPE_PREVIEW)) {
1712         if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) &&
1713                 ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) {
1714             LOGE("attempting rotation %d when rotation is disabled",
1715                     mCamera3Stream->rotation);
1716             return -EINVAL;
1717         }
1718 
1719         switch (mCamera3Stream->rotation) {
1720             case CAMERA3_STREAM_ROTATION_0:
1721                 mRotation = ROTATE_0;
1722                 break;
1723             case CAMERA3_STREAM_ROTATION_90: {
1724                 mRotation = ROTATE_90;
1725                 break;
1726             }
1727             case CAMERA3_STREAM_ROTATION_180:
1728                 mRotation = ROTATE_180;
1729                 break;
1730             case CAMERA3_STREAM_ROTATION_270: {
1731                 mRotation = ROTATE_270;
1732                 break;
1733             }
1734             default:
1735                 LOGE("Unknown rotation: %d",
1736                          mCamera3Stream->rotation);
1737             return -EINVAL;
1738         }
1739     } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) {
1740         LOGE("Rotation %d is not supported by stream type %d",
1741                 mCamera3Stream->rotation,
1742                 mStreamType);
1743         return -EINVAL;
1744     }
1745 
1746     streamDim.width = mCamera3Stream->width;
1747     streamDim.height = mCamera3Stream->height;
1748 
1749     LOGD("batch size is %d", mBatchSize);
1750     rc = QCamera3Channel::addStream(mStreamType,
1751             mStreamFormat,
1752             streamDim,
1753             mRotation,
1754             mNumBufs,
1755             mPostProcMask,
1756             mIsType,
1757             mBatchSize);
1758 
1759     return rc;
1760 }
1761 
1762 /*===========================================================================
1763  * FUNCTION   : setBatchSize
1764  *
1765  * DESCRIPTION: Set batch size for the channel.
1766  *
1767  * PARAMETERS :
1768  *   @batchSize  : Number of image buffers in a batch
1769  *
1770  * RETURN     : int32_t type of status
1771  *              NO_ERROR  -- success always
1772  *              none-zero failure code
1773  *==========================================================================*/
setBatchSize(uint32_t batchSize)1774 int32_t QCamera3RegularChannel::setBatchSize(uint32_t batchSize)
1775 {
1776     int32_t rc = NO_ERROR;
1777 
1778     mBatchSize = batchSize;
1779     LOGD("Batch size set: %d", mBatchSize);
1780     return rc;
1781 }
1782 
1783 /*===========================================================================
1784  * FUNCTION   : getStreamTypeMask
1785  *
1786  * DESCRIPTION: Get bit mask of all stream types in this channel.
1787  *              If stream is not initialized, then generate mask based on
1788  *              local streamType
1789  *
1790  * PARAMETERS : None
1791  *
1792  * RETURN     : Bit mask of all stream types in this channel
1793  *==========================================================================*/
getStreamTypeMask()1794 uint32_t QCamera3RegularChannel::getStreamTypeMask()
1795 {
1796     if (mStreams[0]) {
1797         return QCamera3Channel::getStreamTypeMask();
1798     } else {
1799         return (1U << mStreamType);
1800     }
1801 }
1802 
1803 /*===========================================================================
1804  * FUNCTION   : queueBatchBuf
1805  *
1806  * DESCRIPTION: queue batch container to downstream
1807  *
1808  * PARAMETERS :
1809  *
1810  * RETURN     : int32_t type of status
1811  *              NO_ERROR  -- success always
1812  *              none-zero failure code
1813  *==========================================================================*/
queueBatchBuf()1814 int32_t QCamera3RegularChannel::queueBatchBuf()
1815 {
1816     int32_t rc = NO_ERROR;
1817 
1818     if (mStreams[0]) {
1819         rc = mStreams[0]->queueBatchBuf();
1820     }
1821     if (rc != NO_ERROR) {
1822         LOGE("stream->queueBatchContainer failed");
1823     }
1824     return rc;
1825 }
1826 
1827 /*===========================================================================
1828  * FUNCTION   : request
1829  *
1830  * DESCRIPTION: process a request from camera service. Stream on if ncessary.
1831  *
1832  * PARAMETERS :
1833  *   @buffer  : buffer to be filled for this request
1834  *
1835  * RETURN     : 0 on a success start of capture
1836  *              -EINVAL on invalid input
1837  *              -ENODEV on serious error
1838  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber)1839 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
1840 {
1841     ATRACE_CALL();
1842     //FIX ME: Return buffer back in case of failures below.
1843 
1844     int32_t rc = NO_ERROR;
1845     int index;
1846 
1847     if (NULL == buffer) {
1848         LOGE("Invalid buffer in channel request");
1849         return BAD_VALUE;
1850     }
1851 
1852     if(!m_bIsActive) {
1853         rc = registerBuffer(buffer, mIsType);
1854         if (NO_ERROR != rc) {
1855             LOGE("On-the-fly buffer registration failed %d",
1856                      rc);
1857             return rc;
1858         }
1859 
1860         rc = start();
1861         if (NO_ERROR != rc) {
1862             return rc;
1863         }
1864     } else {
1865         LOGD("Request on an existing stream");
1866     }
1867 
1868     index = mMemory.getMatchBufIndex((void*)buffer);
1869     if(index < 0) {
1870         rc = registerBuffer(buffer, mIsType);
1871         if (NO_ERROR != rc) {
1872             LOGE("On-the-fly buffer registration failed %d",
1873                      rc);
1874             return rc;
1875         }
1876 
1877         index = mMemory.getMatchBufIndex((void*)buffer);
1878         if (index < 0) {
1879             LOGE("Could not find object among registered buffers");
1880             return DEAD_OBJECT;
1881         }
1882     }
1883 
1884     rc = mStreams[0]->bufDone((uint32_t)index);
1885     if(rc != NO_ERROR) {
1886         LOGE("Failed to Q new buffer to stream");
1887         return rc;
1888     }
1889 
1890     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
1891     return rc;
1892 }
1893 
1894 /*===========================================================================
1895  * FUNCTION   : getReprocessType
1896  *
1897  * DESCRIPTION: get the type of reprocess output supported by this channel
1898  *
1899  * PARAMETERS : NONE
1900  *
1901  * RETURN     : reprocess_type_t : type of reprocess
1902  *==========================================================================*/
getReprocessType()1903 reprocess_type_t QCamera3RegularChannel::getReprocessType()
1904 {
1905     return REPROCESS_TYPE_PRIVATE;
1906 }
1907 
1908 
QCamera3MetadataChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,void * userData,uint32_t numBuffers)1909 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
1910                     uint32_t channel_handle,
1911                     mm_camera_ops_t *cam_ops,
1912                     channel_cb_routine cb_routine,
1913                     cam_padding_info_t *paddingInfo,
1914                     uint32_t postprocess_mask,
1915                     void *userData, uint32_t numBuffers) :
1916                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
1917                                 cb_routine, paddingInfo, postprocess_mask,
1918                                 userData, numBuffers),
1919                         mMemory(NULL)
1920 {
1921 }
1922 
~QCamera3MetadataChannel()1923 QCamera3MetadataChannel::~QCamera3MetadataChannel()
1924 {
1925     destroy();
1926 
1927     if (mMemory) {
1928         mMemory->deallocate();
1929         delete mMemory;
1930         mMemory = NULL;
1931     }
1932 }
1933 
initialize(cam_is_type_t isType)1934 int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType)
1935 {
1936     ATRACE_CALL();
1937     int32_t rc;
1938     cam_dimension_t streamDim;
1939 
1940     if (mMemory || m_numStreams > 0) {
1941         LOGE("metadata channel already initialized");
1942         return -EINVAL;
1943     }
1944 
1945     streamDim.width = (int32_t)sizeof(metadata_buffer_t),
1946     streamDim.height = 1;
1947 
1948     mIsType = isType;
1949     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
1950             streamDim, ROTATE_0, (uint8_t)mNumBuffers, mPostProcMask, mIsType);
1951     if (rc < 0) {
1952         LOGE("addStream failed");
1953     }
1954     return rc;
1955 }
1956 
request(buffer_handle_t *,uint32_t)1957 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
1958                                                 uint32_t /*frameNumber*/)
1959 {
1960     if (!m_bIsActive) {
1961         return start();
1962     }
1963     else
1964         return 0;
1965 }
1966 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)1967 void QCamera3MetadataChannel::streamCbRoutine(
1968                         mm_camera_super_buf_t *super_frame,
1969                         QCamera3Stream * /*stream*/)
1970 {
1971     ATRACE_NAME("metadata_stream_cb_routine");
1972     uint32_t requestNumber = 0;
1973     if (super_frame == NULL || super_frame->num_bufs != 1) {
1974         LOGE("super_frame is not valid");
1975         return;
1976     }
1977     if (mChannelCB) {
1978         mChannelCB(super_frame, NULL, requestNumber, false, mUserData);
1979     }
1980 }
1981 
getStreamBufs(uint32_t len)1982 QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
1983 {
1984     int rc;
1985     if (len < sizeof(metadata_buffer_t)) {
1986         LOGE("Metadata buffer size less than structure %d vs %d",
1987                 len,
1988                 sizeof(metadata_buffer_t));
1989         return NULL;
1990     }
1991     mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
1992     if (!mMemory) {
1993         LOGE("unable to create metadata memory");
1994         return NULL;
1995     }
1996     rc = mMemory->allocateAll(len);
1997     if (rc < 0) {
1998         LOGE("unable to allocate metadata memory");
1999         delete mMemory;
2000         mMemory = NULL;
2001         return NULL;
2002     }
2003     clear_metadata_buffer((metadata_buffer_t*)mMemory->getPtr(0));
2004     return mMemory;
2005 }
2006 
putStreamBufs()2007 void QCamera3MetadataChannel::putStreamBufs()
2008 {
2009     mMemory->deallocate();
2010     delete mMemory;
2011     mMemory = NULL;
2012 }
2013 /*************************************************************************************/
2014 // RAW Channel related functions
QCamera3RawChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,uint32_t postprocess_mask,QCamera3Channel * metadataChannel,bool raw_16,uint32_t numBuffers)2015 QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
2016                     uint32_t channel_handle,
2017                     mm_camera_ops_t *cam_ops,
2018                     channel_cb_routine cb_routine,
2019                     cam_padding_info_t *paddingInfo,
2020                     void *userData,
2021                     camera3_stream_t *stream,
2022                     uint32_t postprocess_mask,
2023                     QCamera3Channel *metadataChannel,
2024                     bool raw_16, uint32_t numBuffers) :
2025                         QCamera3RegularChannel(cam_handle, channel_handle, cam_ops,
2026                                 cb_routine, paddingInfo, userData, stream,
2027                                 CAM_STREAM_TYPE_RAW, postprocess_mask,
2028                                 metadataChannel, numBuffers),
2029                         mIsRaw16(raw_16)
2030 {
2031     char prop[PROPERTY_VALUE_MAX];
2032     property_get("persist.camera.raw.debug.dump", prop, "0");
2033     mRawDump = atoi(prop);
2034 }
2035 
~QCamera3RawChannel()2036 QCamera3RawChannel::~QCamera3RawChannel()
2037 {
2038 }
2039 
2040 /*===========================================================================
2041  * FUNCTION   : initialize
2042  *
2043  * DESCRIPTION: Initialize and add camera channel & stream
2044  *
2045  * PARAMETERS :
2046  * @isType    : image stabilization type on the stream
2047  *
2048  * RETURN     : int32_t type of status
2049  *              NO_ERROR  -- success
2050  *              none-zero failure code
2051  *==========================================================================*/
2052 
initialize(cam_is_type_t isType)2053 int32_t QCamera3RawChannel::initialize(cam_is_type_t isType)
2054 {
2055     return QCamera3RegularChannel::initialize(isType);
2056 }
2057 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2058 void QCamera3RawChannel::streamCbRoutine(
2059                         mm_camera_super_buf_t *super_frame,
2060                         QCamera3Stream * stream)
2061 {
2062     ATRACE_CALL();
2063     /* Move this back down once verified */
2064     if (mRawDump)
2065         dumpRawSnapshot(super_frame->bufs[0]);
2066 
2067     if (mIsRaw16) {
2068         if (getStreamDefaultFormat(CAM_STREAM_TYPE_RAW) ==
2069                 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
2070             convertMipiToRaw16(super_frame->bufs[0]);
2071         else
2072             convertLegacyToRaw16(super_frame->bufs[0]);
2073     }
2074 
2075     //Make sure cache coherence because extra processing is done
2076     mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
2077 
2078     QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
2079     return;
2080 }
2081 
dumpRawSnapshot(mm_camera_buf_def_t * frame)2082 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2083 {
2084    QCamera3Stream *stream = getStreamByIndex(0);
2085    if (stream != NULL) {
2086        char buf[FILENAME_MAX];
2087        memset(buf, 0, sizeof(buf));
2088        cam_dimension_t dim;
2089        memset(&dim, 0, sizeof(dim));
2090        stream->getFrameDimension(dim);
2091 
2092        cam_frame_len_offset_t offset;
2093        memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2094        stream->getFrameOffset(offset);
2095        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
2096                 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
2097 
2098        int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
2099        if (file_fd >= 0) {
2100           ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
2101           LOGD("written number of bytes %zd", written_len);
2102           close(file_fd);
2103        } else {
2104           LOGE("failed to open file to dump image");
2105        }
2106    } else {
2107        LOGE("Could not find stream");
2108    }
2109 
2110 }
2111 
convertLegacyToRaw16(mm_camera_buf_def_t * frame)2112 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2113 {
2114     // Convert image buffer from Opaque raw format to RAW16 format
2115     // 10bit Opaque raw is stored in the format of:
2116     // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2117     // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2118     // 4 bits are 0s. Each 64bit word contains 6 pixels.
2119 
2120   QCamera3Stream *stream = getStreamByIndex(0);
2121   if (stream != NULL) {
2122       cam_dimension_t dim;
2123       memset(&dim, 0, sizeof(dim));
2124       stream->getFrameDimension(dim);
2125 
2126       cam_frame_len_offset_t offset;
2127       memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2128       stream->getFrameOffset(offset);
2129 
2130       uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2131       uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2132 
2133       // In-place format conversion.
2134       // Raw16 format always occupy more memory than opaque raw10.
2135       // Convert to Raw16 by iterating through all pixels from bottom-right
2136       // to top-left of the image.
2137       // One special notes:
2138       // 1. Cross-platform raw16's stride is 16 pixels.
2139       // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2140       for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2141           uint32_t y = (uint32_t)ys;
2142           uint64_t* row_start = (uint64_t *)frame->buffer +
2143                   y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2144           for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2145               uint32_t x = (uint32_t)xs;
2146               uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2147               raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2148           }
2149       }
2150   } else {
2151       LOGE("Could not find stream");
2152   }
2153 
2154 }
2155 
convertMipiToRaw16(mm_camera_buf_def_t * frame)2156 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2157 {
2158     // Convert image buffer from mipi10 raw format to RAW16 format
2159     // mipi10 opaque raw is stored in the format of:
2160     // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2161     // 4 pixels occupy 5 bytes, no padding needed
2162 
2163     QCamera3Stream *stream = getStreamByIndex(0);
2164     if (stream != NULL) {
2165         cam_dimension_t dim;
2166         memset(&dim, 0, sizeof(dim));
2167         stream->getFrameDimension(dim);
2168 
2169         cam_frame_len_offset_t offset;
2170         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2171         stream->getFrameOffset(offset);
2172 
2173         uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2174         uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2175 
2176         // In-place format conversion.
2177         // Raw16 format always occupy more memory than opaque raw10.
2178         // Convert to Raw16 by iterating through all pixels from bottom-right
2179         // to top-left of the image.
2180         // One special notes:
2181         // 1. Cross-platform raw16's stride is 16 pixels.
2182         // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2183         for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2184             uint32_t y = (uint32_t)ys;
2185             uint8_t* row_start = (uint8_t *)frame->buffer +
2186                     y * (uint32_t)offset.mp[0].stride_in_bytes;
2187             for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2188                 uint32_t x = (uint32_t)xs;
2189                 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2190                 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
2191                 uint16_t raw16_pixel =
2192                         (uint16_t)(((uint16_t)upper_8bit)<<2 |
2193                         (uint16_t)lower_2bit);
2194                 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2195             }
2196         }
2197     } else {
2198         LOGE("Could not find stream");
2199     }
2200 
2201 }
2202 
2203 /*===========================================================================
2204  * FUNCTION   : getReprocessType
2205  *
2206  * DESCRIPTION: get the type of reprocess output supported by this channel
2207  *
2208  * PARAMETERS : NONE
2209  *
2210  * RETURN     : reprocess_type_t : type of reprocess
2211  *==========================================================================*/
getReprocessType()2212 reprocess_type_t QCamera3RawChannel::getReprocessType()
2213 {
2214     return REPROCESS_TYPE_RAW;
2215 }
2216 
2217 
2218 /*************************************************************************************/
2219 // RAW Dump Channel related functions
2220 
2221 /*===========================================================================
2222  * FUNCTION   : QCamera3RawDumpChannel
2223  *
2224  * DESCRIPTION: Constructor for RawDumpChannel
2225  *
2226  * PARAMETERS :
2227  *   @cam_handle    : Handle for Camera
2228  *   @cam_ops       : Function pointer table
2229  *   @rawDumpSize   : Dimensions for the Raw stream
2230  *   @paddinginfo   : Padding information for stream
2231  *   @userData      : Cookie for parent
2232  *   @pp mask       : PP feature mask for this stream
2233  *   @numBuffers    : number of max dequeued buffers
2234  *
2235  * RETURN           : NA
2236  *==========================================================================*/
QCamera3RawDumpChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,cam_dimension_t rawDumpSize,cam_padding_info_t * paddingInfo,void * userData,uint32_t postprocess_mask,uint32_t numBuffers)2237 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2238                     uint32_t channel_handle,
2239                     mm_camera_ops_t *cam_ops,
2240                     cam_dimension_t rawDumpSize,
2241                     cam_padding_info_t *paddingInfo,
2242                     void *userData,
2243                     uint32_t postprocess_mask, uint32_t numBuffers) :
2244                         QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2245                                 paddingInfo, postprocess_mask,
2246                                 userData, numBuffers),
2247                         mDim(rawDumpSize),
2248                         mMemory(NULL)
2249 {
2250     char prop[PROPERTY_VALUE_MAX];
2251     property_get("persist.camera.raw.dump", prop, "0");
2252     mRawDump = atoi(prop);
2253 }
2254 
2255 /*===========================================================================
2256  * FUNCTION   : QCamera3RawDumpChannel
2257  *
2258  * DESCRIPTION: Destructor for RawDumpChannel
2259  *
2260  * PARAMETERS :
2261  *
2262  * RETURN           : NA
2263  *==========================================================================*/
2264 
~QCamera3RawDumpChannel()2265 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2266 {
2267     destroy();
2268 }
2269 
2270 /*===========================================================================
2271  * FUNCTION   : dumpRawSnapshot
2272  *
2273  * DESCRIPTION: Helper function to dump Raw frames
2274  *
2275  * PARAMETERS :
2276  *  @frame      : stream buf frame to be dumped
2277  *
2278  *  RETURN      : NA
2279  *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2280 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2281 {
2282     QCamera3Stream *stream = getStreamByIndex(0);
2283     if (stream != NULL) {
2284         char buf[FILENAME_MAX];
2285         struct timeval tv;
2286         struct tm timeinfo_data;
2287         struct tm *timeinfo;
2288 
2289         cam_dimension_t dim;
2290         memset(&dim, 0, sizeof(dim));
2291         stream->getFrameDimension(dim);
2292 
2293         cam_frame_len_offset_t offset;
2294         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2295         stream->getFrameOffset(offset);
2296 
2297         gettimeofday(&tv, NULL);
2298         timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2299 
2300         if (NULL != timeinfo) {
2301             memset(buf, 0, sizeof(buf));
2302             snprintf(buf, sizeof(buf),
2303                     QCAMERA_DUMP_FRM_LOCATION
2304                     "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
2305                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2306                     timeinfo->tm_mday, timeinfo->tm_hour,
2307                     timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
2308                     frame->frame_idx, dim.width, dim.height);
2309 
2310             int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2311             if (file_fd >= 0) {
2312                 ssize_t written_len =
2313                         write(file_fd, frame->buffer, offset.frame_len);
2314                 LOGD("written number of bytes %zd", written_len);
2315                 close(file_fd);
2316             } else {
2317                 LOGE("failed to open file to dump image");
2318             }
2319         } else {
2320             LOGE("localtime_r() error");
2321         }
2322     } else {
2323         LOGE("Could not find stream");
2324     }
2325 
2326 }
2327 
2328 /*===========================================================================
2329  * FUNCTION   : streamCbRoutine
2330  *
2331  * DESCRIPTION: Callback routine invoked for each frame generated for
2332  *              Rawdump channel
2333  *
2334  * PARAMETERS :
2335  *   @super_frame  : stream buf frame generated
2336  *   @stream       : Underlying Stream object cookie
2337  *
2338  * RETURN          : NA
2339  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,__unused QCamera3Stream * stream)2340 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2341                                                 __unused QCamera3Stream *stream)
2342 {
2343     LOGD("E");
2344     if (super_frame == NULL || super_frame->num_bufs != 1) {
2345         LOGE("super_frame is not valid");
2346         return;
2347     }
2348 
2349     if (mRawDump)
2350         dumpRawSnapshot(super_frame->bufs[0]);
2351 
2352     bufDone(super_frame);
2353     free(super_frame);
2354 }
2355 
2356 /*===========================================================================
2357  * FUNCTION   : getStreamBufs
2358  *
2359  * DESCRIPTION: Callback function provided to interface to get buffers.
2360  *
2361  * PARAMETERS :
2362  *   @len       : Length of each buffer to be allocated
2363  *
2364  * RETURN     : NULL on buffer allocation failure
2365  *              QCamera3StreamMem object on sucess
2366  *==========================================================================*/
getStreamBufs(uint32_t len)2367 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2368 {
2369     int rc;
2370     mMemory = new QCamera3StreamMem(mNumBuffers);
2371 
2372     if (!mMemory) {
2373         LOGE("unable to create heap memory");
2374         return NULL;
2375     }
2376     rc = mMemory->allocateAll((size_t)len);
2377     if (rc < 0) {
2378         LOGE("unable to allocate heap memory");
2379         delete mMemory;
2380         mMemory = NULL;
2381         return NULL;
2382     }
2383     return mMemory;
2384 }
2385 
2386 /*===========================================================================
2387  * FUNCTION   : putStreamBufs
2388  *
2389  * DESCRIPTION: Callback function provided to interface to return buffers.
2390  *              Although no handles are actually returned, implicitl assumption
2391  *              that interface will no longer use buffers and channel can
2392  *              deallocated if necessary.
2393  *
2394  * PARAMETERS : NA
2395  *
2396  * RETURN     : NA
2397  *==========================================================================*/
putStreamBufs()2398 void QCamera3RawDumpChannel::putStreamBufs()
2399 {
2400     mMemory->deallocate();
2401     delete mMemory;
2402     mMemory = NULL;
2403 }
2404 
2405 /*===========================================================================
2406  * FUNCTION : request
2407  *
2408  * DESCRIPTION: Request function used as trigger
2409  *
2410  * PARAMETERS :
2411  * @recvd_frame : buffer- this will be NULL since this is internal channel
2412  * @frameNumber : Undefined again since this is internal stream
2413  *
2414  * RETURN     : int32_t type of status
2415  *              NO_ERROR  -- success
2416  *              none-zero failure code
2417  *==========================================================================*/
request(buffer_handle_t *,uint32_t)2418 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2419                                                 uint32_t /*frameNumber*/)
2420 {
2421     if (!m_bIsActive) {
2422         return QCamera3Channel::start();
2423     }
2424     else
2425         return 0;
2426 }
2427 
2428 /*===========================================================================
2429  * FUNCTION : intialize
2430  *
2431  * DESCRIPTION: Initializes channel params and creates underlying stream
2432  *
2433  * PARAMETERS :
2434  *    @isType : type of image stabilization required on this stream
2435  *
2436  * RETURN     : int32_t type of status
2437  *              NO_ERROR  -- success
2438  *              none-zero failure code
2439  *==========================================================================*/
initialize(cam_is_type_t isType)2440 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2441 {
2442     int32_t rc;
2443 
2444     mIsType = isType;
2445     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2446         CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2447         mPostProcMask, mIsType);
2448     if (rc < 0) {
2449         LOGE("addStream failed");
2450     }
2451     return rc;
2452 }
2453 /*************************************************************************************/
2454 
2455 /* QCamera3YUVChannel methods */
2456 
2457 /*===========================================================================
2458  * FUNCTION   : QCamera3YUVChannel
2459  *
2460  * DESCRIPTION: constructor of QCamera3YUVChannel
2461  *
2462  * PARAMETERS :
2463  *   @cam_handle : camera handle
2464  *   @cam_ops    : ptr to camera ops table
2465  *   @cb_routine : callback routine to frame aggregator
2466  *   @paddingInfo : padding information for the stream
2467  *   @stream     : camera3_stream_t structure
2468  *   @stream_type: Channel stream type
2469  *   @postprocess_mask: the postprocess mask for streams of this channel
2470  *   @metadataChannel: handle to the metadataChannel
2471  * RETURN     : none
2472  *==========================================================================*/
QCamera3YUVChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,uint32_t postprocess_mask,QCamera3Channel * metadataChannel)2473 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2474         uint32_t channel_handle,
2475         mm_camera_ops_t *cam_ops,
2476         channel_cb_routine cb_routine,
2477         cam_padding_info_t *paddingInfo,
2478         void *userData,
2479         camera3_stream_t *stream,
2480         cam_stream_type_t stream_type,
2481         uint32_t postprocess_mask,
2482         QCamera3Channel *metadataChannel) :
2483             QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2484                     cb_routine, paddingInfo, userData, stream, stream_type,
2485                     postprocess_mask, metadataChannel)
2486 {
2487 
2488     mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2489     mFrameLen = 0;
2490     mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2491     mEdgeMode.sharpness = 0;
2492     mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2493     memset(&mCropRegion, 0, sizeof(mCropRegion));
2494 }
2495 
2496 /*===========================================================================
2497  * FUNCTION   : ~QCamera3YUVChannel
2498  *
2499  * DESCRIPTION: destructor of QCamera3YUVChannel
2500  *
2501  * PARAMETERS : none
2502  *
2503  *
2504  * RETURN     : none
2505  *==========================================================================*/
~QCamera3YUVChannel()2506 QCamera3YUVChannel::~QCamera3YUVChannel()
2507 {
2508    // Deallocation of heap buffers allocated in mMemory is freed
2509    // automatically by its destructor
2510 }
2511 
2512 /*===========================================================================
2513  * FUNCTION   : initialize
2514  *
2515  * DESCRIPTION: Initialize and add camera channel & stream
2516  *
2517  * PARAMETERS :
2518  * @isType    : the image stabilization type
2519  *
2520  * RETURN     : int32_t type of status
2521  *              NO_ERROR  -- success
2522  *              none-zero failure code
2523  *==========================================================================*/
initialize(cam_is_type_t isType)2524 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2525 {
2526     ATRACE_CALL();
2527     int32_t rc = NO_ERROR;
2528     cam_dimension_t streamDim;
2529 
2530     if (NULL == mCamera3Stream) {
2531         LOGE("Camera stream uninitialized");
2532         return NO_INIT;
2533     }
2534 
2535     if (1 <= m_numStreams) {
2536         // Only one stream per channel supported in v3 Hal
2537         return NO_ERROR;
2538     }
2539 
2540     mIsType  = isType;
2541     mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK);
2542     streamDim.width = mCamera3Stream->width;
2543     streamDim.height = mCamera3Stream->height;
2544 
2545     rc = QCamera3Channel::addStream(mStreamType,
2546             mStreamFormat,
2547             streamDim,
2548             ROTATE_0,
2549             mNumBufs,
2550             mPostProcMask,
2551             mIsType);
2552     if (rc < 0) {
2553         LOGE("addStream failed");
2554         return rc;
2555     }
2556 
2557     cam_stream_buf_plane_info_t buf_planes;
2558     cam_padding_info_t paddingInfo = mPaddingInfo;
2559 
2560     memset(&buf_planes, 0, sizeof(buf_planes));
2561     //to ensure a big enough buffer size set the height and width
2562     //padding to max(height padding, width padding)
2563     paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2564     paddingInfo.height_padding = paddingInfo.width_padding;
2565 
2566     rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2567             &buf_planes);
2568     if (rc < 0) {
2569         LOGE("mm_stream_calc_offset_preview failed");
2570         return rc;
2571     }
2572 
2573     mFrameLen = buf_planes.plane_info.frame_len;
2574 
2575     if (NO_ERROR != rc) {
2576         LOGE("Initialize failed, rc = %d", rc);
2577         return rc;
2578     }
2579 
2580     /* initialize offline meta memory for input reprocess */
2581     rc = QCamera3ProcessingChannel::initialize(isType);
2582     if (NO_ERROR != rc) {
2583         LOGE("Processing Channel initialize failed, rc = %d",
2584                  rc);
2585     }
2586 
2587     return rc;
2588 }
2589 
2590 /*===========================================================================
2591  * FUNCTION   : request
2592  *
2593  * DESCRIPTION: entry function for a request on a YUV stream. This function
2594  *              has the logic to service a request based on its type
2595  *
2596  * PARAMETERS :
2597  * @buffer          : pointer to the output buffer
2598  * @frameNumber     : frame number of the request
2599  * @pInputBuffer    : pointer to input buffer if an input request
2600  * @metadata        : parameters associated with the request
2601  *
2602  * RETURN     : 0 on a success start of capture
2603  *              -EINVAL on invalid input
2604  *              -ENODEV on serious error
2605  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata)2606 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2607         uint32_t frameNumber,
2608         camera3_stream_buffer_t* pInputBuffer,
2609         metadata_buffer_t* metadata, bool &needMetadata)
2610 {
2611     int32_t rc = NO_ERROR;
2612     Mutex::Autolock lock(mOfflinePpLock);
2613 
2614     LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2615     if (NULL == buffer || NULL == metadata) {
2616         LOGE("Invalid buffer/metadata in channel request");
2617         return BAD_VALUE;
2618     }
2619 
2620     PpInfo ppInfo;
2621     memset(&ppInfo, 0, sizeof(ppInfo));
2622     ppInfo.frameNumber = frameNumber;
2623     ppInfo.offlinePpFlag = false;
2624     if (mBypass && !pInputBuffer ) {
2625         ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2626         ppInfo.output = buffer;
2627         mOfflinePpInfoList.push_back(ppInfo);
2628     }
2629 
2630     LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2631     needMetadata = ppInfo.offlinePpFlag;
2632     if (!ppInfo.offlinePpFlag) {
2633         // regular request
2634         return QCamera3ProcessingChannel::request(buffer, frameNumber,
2635                 pInputBuffer, metadata);
2636     } else {
2637         if(!m_bIsActive) {
2638             rc = start();
2639             if (NO_ERROR != rc)
2640                 return rc;
2641         } else {
2642             LOGD("Request on an existing stream");
2643         }
2644 
2645         //we need to send this frame through the CPP
2646         //Allocate heap memory, then buf done on the buffer
2647         uint32_t bufIdx;
2648         if (mFreeHeapBufferList.empty()) {
2649             rc = mMemory.allocateOne(mFrameLen);
2650             if (rc < 0) {
2651                 LOGE("Failed allocating heap buffer. Fatal");
2652                 return BAD_VALUE;
2653             } else {
2654                 bufIdx = (uint32_t)rc;
2655             }
2656         } else {
2657             bufIdx = *(mFreeHeapBufferList.begin());
2658             mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2659         }
2660 
2661         /* Configure and start postproc if necessary */
2662         reprocess_config_t reproc_cfg;
2663         cam_dimension_t dim;
2664         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2665         memset(&dim, 0, sizeof(dim));
2666         mStreams[0]->getFrameDimension(dim);
2667         setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2668 
2669         // Start postprocessor without input buffer
2670         startPostProc(reproc_cfg);
2671 
2672         LOGD("erasing %d", bufIdx);
2673 
2674         mMemory.markFrameNumber(bufIdx, frameNumber);
2675         mStreams[0]->bufDone(bufIdx);
2676 
2677     }
2678     return rc;
2679 }
2680 
2681 /*===========================================================================
2682  * FUNCTION   : streamCbRoutine
2683  *
2684  * DESCRIPTION:
2685  *
2686  * PARAMETERS :
2687  * @super_frame : the super frame with filled buffer
2688  * @stream      : stream on which the buffer was requested and filled
2689  *
2690  * RETURN     : none
2691  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2692 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2693         QCamera3Stream *stream)
2694 {
2695     ATRACE_CALL();
2696     uint8_t frameIndex;
2697     int32_t resultFrameNumber;
2698 
2699     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2700         LOGE("Error with the stream callback");
2701         return;
2702     }
2703 
2704     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2705     if(frameIndex >= mNumBufs) {
2706          LOGE("Error, Invalid index for buffer");
2707          stream->bufDone(frameIndex);
2708          return;
2709     }
2710 
2711     if (mBypass) {
2712         List<PpInfo>::iterator ppInfo;
2713 
2714         Mutex::Autolock lock(mOfflinePpLock);
2715         resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2716         for (ppInfo = mOfflinePpInfoList.begin();
2717                 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2718             if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2719                 break;
2720             }
2721         }
2722         LOGD("frame index %d, frame number %d", frameIndex, resultFrameNumber);
2723         //check the reprocessing required flag against the frame number
2724         if (ppInfo == mOfflinePpInfoList.end()) {
2725             LOGE("Error, request for frame number is a reprocess.");
2726             stream->bufDone(frameIndex);
2727             return;
2728         }
2729 
2730         if (ppInfo->offlinePpFlag) {
2731             mm_camera_super_buf_t *frame =
2732                     (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
2733             if (frame == NULL) {
2734                 LOGE("Error allocating memory to save received_frame structure.");
2735                 if(stream) {
2736                     stream->bufDone(frameIndex);
2737                 }
2738                 return;
2739             }
2740 
2741             *frame = *super_frame;
2742             m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
2743             free(super_frame);
2744             return;
2745         } else {
2746             if (ppInfo != mOfflinePpInfoList.begin()) {
2747                 // There is pending reprocess buffer, cache current buffer
2748                 if (ppInfo->callback_buffer != NULL) {
2749                     LOGE("Fatal: cached callback_buffer is already present");
2750                 }
2751                 ppInfo->callback_buffer = super_frame;
2752                 return;
2753             } else {
2754                 mOfflinePpInfoList.erase(ppInfo);
2755             }
2756         }
2757     }
2758 
2759     QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2760     return;
2761 }
2762 
2763 /*===========================================================================
2764  * FUNCTION   : reprocessCbRoutine
2765  *
2766  * DESCRIPTION: callback function for the reprocessed frame. This frame now
2767  *              should be returned to the framework. This same callback is
2768  *              used during input reprocessing or offline postprocessing
2769  *
2770  * PARAMETERS :
2771  * @resultBuffer      : buffer containing the reprocessed data
2772  * @resultFrameNumber : frame number on which the buffer was requested
2773  *
2774  * RETURN     : NONE
2775  *
2776  *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2777 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2778         uint32_t resultFrameNumber)
2779 {
2780     LOGD("E: frame number %d", resultFrameNumber);
2781     Vector<mm_camera_super_buf_t *> pendingCbs;
2782 
2783     /* release the input buffer and input metadata buffer if used */
2784     if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2785         /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2786         int32_t rc = releaseOfflineMemory(resultFrameNumber);
2787         if (NO_ERROR != rc) {
2788             LOGE("Error releasing offline memory rc = %d", rc);
2789         }
2790         /* Since reprocessing is done, send the callback to release the input buffer */
2791         if (mChannelCB) {
2792             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2793         }
2794     }
2795 
2796     if (mBypass) {
2797         int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2798         if (rc != NO_ERROR) {
2799             return;
2800         }
2801     }
2802 
2803     issueChannelCb(resultBuffer, resultFrameNumber);
2804 
2805     // Call all pending callbacks to return buffers
2806     for (size_t i = 0; i < pendingCbs.size(); i++) {
2807         QCamera3ProcessingChannel::streamCbRoutine(
2808                 pendingCbs[i], mStreams[0]);
2809     }
2810 
2811 }
2812 
2813 /*===========================================================================
2814  * FUNCTION   : needsFramePostprocessing
2815  *
2816  * DESCRIPTION:
2817  *
2818  * PARAMETERS :
2819  *
2820  * RETURN     :
2821  *  TRUE if frame needs to be postprocessed
2822  *  FALSE is frame does not need to be postprocessed
2823  *
2824  *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)2825 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
2826 {
2827     bool ppNeeded = false;
2828 
2829     //sharpness
2830     IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
2831             CAM_INTF_META_EDGE_MODE, meta) {
2832         mEdgeMode = *edgeMode;
2833     }
2834 
2835     //wnr
2836     IF_META_AVAILABLE(uint32_t, noiseRedMode,
2837             CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
2838         mNoiseRedMode = *noiseRedMode;
2839     }
2840 
2841     //crop region
2842     IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
2843             CAM_INTF_META_SCALER_CROP_REGION, meta) {
2844         mCropRegion = *scalerCropRegion;
2845     }
2846 
2847     if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
2848             (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
2849         ppNeeded = true;
2850     }
2851     if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
2852             (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
2853             (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
2854         ppNeeded = true;
2855     }
2856     if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
2857             (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
2858         ppNeeded = true;
2859     }
2860 
2861     return ppNeeded;
2862 }
2863 
2864 /*===========================================================================
2865  * FUNCTION   : handleOfflinePpCallback
2866  *
2867  * DESCRIPTION: callback function for the reprocessed frame from offline
2868  *              postprocessing.
2869  *
2870  * PARAMETERS :
2871  * @resultFrameNumber : frame number on which the buffer was requested
2872  * @pendingCbs        : pending buffers to be returned first
2873  *
2874  * RETURN     : int32_t type of status
2875  *              NO_ERROR  -- success
2876  *              none-zero failure code
2877  *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)2878 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
2879             Vector<mm_camera_super_buf_t *>& pendingCbs)
2880 {
2881     Mutex::Autolock lock(mOfflinePpLock);
2882     List<PpInfo>::iterator ppInfo;
2883 
2884     for (ppInfo = mOfflinePpInfoList.begin();
2885             ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2886         if (ppInfo->frameNumber == resultFrameNumber) {
2887             break;
2888         }
2889     }
2890 
2891     if (ppInfo == mOfflinePpInfoList.end()) {
2892         LOGI("Request of frame number %d is reprocessing",
2893                  resultFrameNumber);
2894         return NO_ERROR;
2895     } else if (ppInfo != mOfflinePpInfoList.begin()) {
2896         LOGE("callback for frame number %d should be head of list",
2897                  resultFrameNumber);
2898         return BAD_VALUE;
2899     }
2900 
2901     if (ppInfo->offlinePpFlag) {
2902         // Need to get the input buffer frame index from the
2903         // mMemory object and add that to the free heap buffers list.
2904         int32_t bufferIndex =
2905                 mMemory.getHeapBufferIndex(resultFrameNumber);
2906         if (bufferIndex < 0) {
2907             LOGE("Fatal %d: no buffer index for frame number %d",
2908                      bufferIndex, resultFrameNumber);
2909             return BAD_VALUE;
2910         }
2911         mFreeHeapBufferList.push_back(bufferIndex);
2912         ppInfo = mOfflinePpInfoList.erase(ppInfo);
2913 
2914         // Return pending buffer callbacks
2915         while (ppInfo != mOfflinePpInfoList.end() &&
2916                 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
2917 
2918             // Call stream callbacks for cached buffers
2919             pendingCbs.push_back(ppInfo->callback_buffer);
2920 
2921             ppInfo = mOfflinePpInfoList.erase(ppInfo);
2922         }
2923 
2924     } else {
2925         LOGE("Fatal: request of frame number %d doesn't need"
2926                 " offline postprocessing. However there is"
2927                 " reprocessing callback.",
2928                 resultFrameNumber);
2929         return BAD_VALUE;
2930     }
2931 
2932     return NO_ERROR;
2933 }
2934 
2935 /*===========================================================================
2936  * FUNCTION   : getReprocessType
2937  *
2938  * DESCRIPTION: get the type of reprocess output supported by this channel
2939  *
2940  * PARAMETERS : NONE
2941  *
2942  * RETURN     : reprocess_type_t : type of reprocess
2943  *==========================================================================*/
getReprocessType()2944 reprocess_type_t QCamera3YUVChannel::getReprocessType()
2945 {
2946     return REPROCESS_TYPE_YUV;
2947 }
2948 
2949 /* QCamera3PicChannel methods */
2950 
2951 /*===========================================================================
2952  * FUNCTION   : jpegEvtHandle
2953  *
2954  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
2955                 Construct result payload and call mChannelCb to deliver buffer
2956                 to framework.
2957  *
2958  * PARAMETERS :
2959  *   @status    : status of jpeg job
2960  *   @client_hdl: jpeg client handle
2961  *   @jobId     : jpeg job Id
2962  *   @p_ouput   : ptr to jpeg output result struct
2963  *   @userdata  : user data ptr
2964  *
2965  * RETURN     : none
2966  *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)2967 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
2968                                               uint32_t /*client_hdl*/,
2969                                               uint32_t jobId,
2970                                               mm_jpeg_output_t *p_output,
2971                                               void *userdata)
2972 {
2973     ATRACE_CALL();
2974     buffer_handle_t *resultBuffer = NULL;
2975     buffer_handle_t *jpegBufferHandle = NULL;
2976     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
2977     camera3_stream_buffer_t result;
2978     camera3_jpeg_blob_t jpegHeader;
2979 
2980     KPI_ATRACE_INT("SNAPSHOT", 0);
2981     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
2982     if (obj) {
2983         //Construct payload for process_capture_result. Call mChannelCb
2984 
2985         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
2986 
2987         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
2988             LOGE("Error in jobId: (%d) with status: %d", jobId, status);
2989             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
2990         }
2991 
2992         if (NULL != job) {
2993             uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
2994             LOGD("jpeg out_buf_index: %d", bufIdx);
2995 
2996             //Construct jpeg transient header of type camera3_jpeg_blob_t
2997             //Append at the end of jpeg image of buf_filled_len size
2998 
2999             jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3000             if (JPEG_JOB_STATUS_DONE == status) {
3001                 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3002                 char* jpeg_buf = (char *)p_output->buf_vaddr;
3003 
3004                 ssize_t maxJpegSize = -1;
3005 
3006                 // Gralloc buffer may have additional padding for 4K page size
3007                 // Follow size guidelines based on spec since framework relies
3008                 // on that to reach end of buffer and with it the header
3009 
3010                 //Handle same as resultBuffer, but for readablity
3011                 jpegBufferHandle =
3012                         (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3013 
3014                 if (NULL != jpegBufferHandle) {
3015                     maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3016                     if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3017                         maxJpegSize = obj->mMemory.getSize(bufIdx);
3018                     }
3019 
3020                     size_t jpeg_eof_offset =
3021                             (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3022                     char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3023                     memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3024                     obj->mMemory.cleanInvalidateCache(bufIdx);
3025                 } else {
3026                     LOGE("JPEG buffer not found and index: %d",
3027                             bufIdx);
3028                     resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3029                 }
3030             }
3031 
3032             ////Use below data to issue framework callback
3033             resultBuffer =
3034                     (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3035             int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3036             int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3037             if (NO_ERROR != rc) {
3038                 LOGE("Error %d unregistering stream buffer %d",
3039                      rc, bufIdx);
3040             }
3041 
3042             result.stream = obj->mCamera3Stream;
3043             result.buffer = resultBuffer;
3044             result.status = resultStatus;
3045             result.acquire_fence = -1;
3046             result.release_fence = -1;
3047 
3048             // Release any snapshot buffers before calling
3049             // the user callback. The callback can potentially
3050             // unblock pending requests to snapshot stream.
3051             int32_t snapshotIdx = -1;
3052             mm_camera_super_buf_t* src_frame = NULL;
3053 
3054             if (job->src_reproc_frame)
3055                 src_frame = job->src_reproc_frame;
3056             else
3057                 src_frame = job->src_frame;
3058 
3059             if (src_frame) {
3060                 if (obj->mStreams[0]->getMyHandle() ==
3061                         src_frame->bufs[0]->stream_id) {
3062                     snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
3063                     if (0 <= snapshotIdx) {
3064                         Mutex::Autolock lock(obj->mFreeBuffersLock);
3065                         obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3066                     }
3067                 }
3068             }
3069 
3070             LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3071                     resultFrameNumber, resultStatus);
3072             if (obj->mChannelCB) {
3073                 obj->mChannelCB(NULL,
3074                         &result,
3075                         (uint32_t)resultFrameNumber,
3076                         false,
3077                         obj->mUserData);
3078             }
3079 
3080             // release internal data for jpeg job
3081             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3082                 /* unregister offline input buffer */
3083                 int32_t inputBufIndex =
3084                         obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3085                 if (0 <= inputBufIndex) {
3086                     rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3087                 } else {
3088                     LOGE("could not find the input buf index, frame number %d",
3089                              resultFrameNumber);
3090                 }
3091                 if (NO_ERROR != rc) {
3092                     LOGE("Error %d unregistering input buffer %d",
3093                              rc, bufIdx);
3094                 }
3095 
3096                 /* unregister offline meta buffer */
3097                 int32_t metaBufIndex =
3098                         obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3099                 if (0 <= metaBufIndex) {
3100                     Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3101                     obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3102                 } else {
3103                     LOGE("could not find the input meta buf index, frame number %d",
3104                              resultFrameNumber);
3105                 }
3106             }
3107             obj->m_postprocessor.releaseOfflineBuffers(false);
3108             obj->m_postprocessor.releaseJpegJobData(job);
3109             free(job);
3110         }
3111 
3112         return;
3113         // }
3114     } else {
3115         LOGE("Null userdata in jpeg callback");
3116     }
3117 }
3118 
QCamera3PicChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,uint32_t postprocess_mask,bool is4KVideo,bool isInputStreamConfigured,QCamera3Channel * metadataChannel,uint32_t numBuffers)3119 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3120                     uint32_t channel_handle,
3121                     mm_camera_ops_t *cam_ops,
3122                     channel_cb_routine cb_routine,
3123                     cam_padding_info_t *paddingInfo,
3124                     void *userData,
3125                     camera3_stream_t *stream,
3126                     uint32_t postprocess_mask,
3127                     bool is4KVideo,
3128                     bool isInputStreamConfigured,
3129                     QCamera3Channel *metadataChannel,
3130                     uint32_t numBuffers) :
3131                         QCamera3ProcessingChannel(cam_handle, channel_handle,
3132                                 cam_ops, cb_routine, paddingInfo, userData,
3133                                 stream, CAM_STREAM_TYPE_SNAPSHOT,
3134                                 postprocess_mask, metadataChannel, numBuffers),
3135                         mNumSnapshotBufs(0),
3136                         mInputBufferHint(isInputStreamConfigured),
3137                         mYuvMemory(NULL),
3138                         mFrameLen(0)
3139 {
3140     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3141     m_max_pic_dim = hal_obj->calcMaxJpegDim();
3142     mYuvWidth = stream->width;
3143     mYuvHeight = stream->height;
3144     mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3145     // Use same pixelformat for 4K video case
3146     mStreamFormat = is4KVideo ?
3147             getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO)
3148             :getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT);
3149     int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3150     if (rc != 0) {
3151         LOGE("Init Postprocessor failed");
3152     }
3153 }
3154 
3155 /*===========================================================================
3156  * FUNCTION   : flush
3157  *
3158  * DESCRIPTION: flush pic channel, which will stop all processing within, including
3159  *              the reprocessing channel in postprocessor and YUV stream.
3160  *
3161  * PARAMETERS : none
3162  *
3163  * RETURN     : int32_t type of status
3164  *              NO_ERROR  -- success
3165  *              none-zero failure code
3166  *==========================================================================*/
flush()3167 int32_t QCamera3PicChannel::flush()
3168 {
3169     int32_t rc = NO_ERROR;
3170     if(!m_bIsActive) {
3171         LOGE("Attempt to flush inactive channel");
3172         return NO_INIT;
3173     }
3174 
3175     rc = m_postprocessor.flush();
3176     if (rc == 0) {
3177         LOGE("Postprocessor flush failed, rc = %d", rc);
3178         return rc;
3179     }
3180 
3181     if (0 < mOfflineMetaMemory.getCnt()) {
3182         mOfflineMetaMemory.deallocate();
3183     }
3184     if (0 < mOfflineMemory.getCnt()) {
3185         mOfflineMemory.unregisterBuffers();
3186     }
3187     Mutex::Autolock lock(mFreeBuffersLock);
3188     mFreeBufferList.clear();
3189     for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3190         mFreeBufferList.push_back(i);
3191     }
3192     return rc;
3193 }
3194 
3195 
~QCamera3PicChannel()3196 QCamera3PicChannel::~QCamera3PicChannel()
3197 {
3198 }
3199 
initialize(cam_is_type_t isType)3200 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3201 {
3202     int32_t rc = NO_ERROR;
3203     cam_dimension_t streamDim;
3204     cam_stream_type_t streamType;
3205     cam_format_t streamFormat;
3206 
3207     if (NULL == mCamera3Stream) {
3208         LOGE("Camera stream uninitialized");
3209         return NO_INIT;
3210     }
3211 
3212     if (1 <= m_numStreams) {
3213         // Only one stream per channel supported in v3 Hal
3214         return NO_ERROR;
3215     }
3216 
3217     mIsType = isType;
3218     streamType = mStreamType;
3219     streamFormat = mStreamFormat;
3220     streamDim.width = (int32_t)mYuvWidth;
3221     streamDim.height = (int32_t)mYuvHeight;
3222 
3223     mNumSnapshotBufs = mCamera3Stream->max_buffers;
3224     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3225             ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3226             mIsType);
3227 
3228     if (NO_ERROR != rc) {
3229         LOGE("Initialize failed, rc = %d", rc);
3230         return rc;
3231     }
3232 
3233     /* initialize offline meta memory for input reprocess */
3234     rc = QCamera3ProcessingChannel::initialize(isType);
3235     if (NO_ERROR != rc) {
3236         LOGE("Processing Channel initialize failed, rc = %d",
3237                  rc);
3238     }
3239 
3240     return rc;
3241 }
3242 
3243 /*===========================================================================
3244  * FUNCTION   : request
3245  *
3246  * DESCRIPTION: handle the request - either with an input buffer or a direct
3247  *              output request
3248  *
3249  * PARAMETERS :
3250  * @buffer       : pointer to the output buffer
3251  * @frameNumber  : frame number of the request
3252  * @pInputBuffer : pointer to input buffer if an input request
3253  * @metadata     : parameters associated with the request
3254  *
3255  * RETURN     : 0 on a success start of capture
3256  *              -EINVAL on invalid input
3257  *              -ENODEV on serious error
3258  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata)3259 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3260         uint32_t frameNumber,
3261         camera3_stream_buffer_t *pInputBuffer,
3262         metadata_buffer_t *metadata)
3263 {
3264     ATRACE_CALL();
3265     //FIX ME: Return buffer back in case of failures below.
3266 
3267     int32_t rc = NO_ERROR;
3268 
3269     reprocess_config_t reproc_cfg;
3270     cam_dimension_t dim;
3271     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3272     //make sure to set the correct input stream dim in case of YUV size override
3273     //and recalculate the plane info
3274     dim.width = (int32_t)mYuvWidth;
3275     dim.height = (int32_t)mYuvHeight;
3276     setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3277 
3278     // Picture stream has already been started before any request comes in
3279     if (!m_bIsActive) {
3280         LOGE("Channel not started!!");
3281         return NO_INIT;
3282     }
3283 
3284     int index = mMemory.getMatchBufIndex((void*)buffer);
3285 
3286     if(index < 0) {
3287         rc = registerBuffer(buffer, mIsType);
3288         if (NO_ERROR != rc) {
3289             LOGE("On-the-fly buffer registration failed %d",
3290                      rc);
3291             return rc;
3292         }
3293 
3294         index = mMemory.getMatchBufIndex((void*)buffer);
3295         if (index < 0) {
3296             LOGE("Could not find object among registered buffers");
3297             return DEAD_OBJECT;
3298         }
3299     }
3300     LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3301 
3302     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3303 
3304     // Start postprocessor
3305     startPostProc(reproc_cfg);
3306 
3307     // Queue jpeg settings
3308     rc = queueJpegSetting((uint32_t)index, metadata);
3309 
3310     if (pInputBuffer == NULL) {
3311         Mutex::Autolock lock(mFreeBuffersLock);
3312         uint32_t bufIdx;
3313         if (mFreeBufferList.empty()) {
3314             rc = mYuvMemory->allocateOne(mFrameLen);
3315             if (rc < 0) {
3316                 LOGE("Failed to allocate heap buffer. Fatal");
3317                 return rc;
3318             } else {
3319                 bufIdx = (uint32_t)rc;
3320             }
3321         } else {
3322             List<uint32_t>::iterator it = mFreeBufferList.begin();
3323             bufIdx = *it;
3324             mFreeBufferList.erase(it);
3325         }
3326         mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3327         mStreams[0]->bufDone(bufIdx);
3328     } else {
3329         qcamera_fwk_input_pp_data_t *src_frame = NULL;
3330         src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3331                 sizeof(qcamera_fwk_input_pp_data_t));
3332         if (src_frame == NULL) {
3333             LOGE("No memory for src frame");
3334             return NO_MEMORY;
3335         }
3336         rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3337                 NULL /*fwk output buffer*/, frameNumber);
3338         if (NO_ERROR != rc) {
3339             LOGE("Error %d while setting framework input PP data", rc);
3340             free(src_frame);
3341             return rc;
3342         }
3343         LOGH("Post-process started");
3344         m_postprocessor.processData(src_frame);
3345     }
3346     return rc;
3347 }
3348 
3349 
3350 
3351 /*===========================================================================
3352  * FUNCTION   : dataNotifyCB
3353  *
3354  * DESCRIPTION: Channel Level callback used for super buffer data notify.
3355  *              This function is registered with mm-camera-interface to handle
3356  *              data notify
3357  *
3358  * PARAMETERS :
3359  *   @recvd_frame   : stream frame received
3360  *   userdata       : user data ptr
3361  *
3362  * RETURN     : none
3363  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3364 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3365                                  void *userdata)
3366 {
3367     ATRACE_CALL();
3368     LOGD("E\n");
3369     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3370 
3371     if (channel == NULL) {
3372         LOGE("invalid channel pointer");
3373         return;
3374     }
3375 
3376     if(channel->m_numStreams != 1) {
3377         LOGE("Error: Bug: This callback assumes one stream per channel");
3378         return;
3379     }
3380 
3381 
3382     if(channel->mStreams[0] == NULL) {
3383         LOGE("Error: Invalid Stream object");
3384         return;
3385     }
3386 
3387     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3388 
3389     LOGD("X\n");
3390     return;
3391 }
3392 
3393 /*===========================================================================
3394  * FUNCTION   : streamCbRoutine
3395  *
3396  * DESCRIPTION:
3397  *
3398  * PARAMETERS :
3399  * @super_frame : the super frame with filled buffer
3400  * @stream      : stream on which the buffer was requested and filled
3401  *
3402  * RETURN     : none
3403  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3404 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3405                             QCamera3Stream *stream)
3406 {
3407     ATRACE_CALL();
3408     //TODO
3409     //Used only for getting YUV. Jpeg callback will be sent back from channel
3410     //directly to HWI. Refer to func jpegEvtHandle
3411 
3412     //Got the yuv callback. Calling yuv callback handler in PostProc
3413     uint8_t frameIndex;
3414     mm_camera_super_buf_t* frame = NULL;
3415     cam_dimension_t dim;
3416     cam_frame_len_offset_t offset;
3417 
3418     memset(&dim, 0, sizeof(dim));
3419     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3420 
3421     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3422         LOGE("Error with the stream callback");
3423         return;
3424     }
3425 
3426     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3427     LOGD("recvd buf_idx: %u for further processing",
3428          (uint32_t)frameIndex);
3429     if(frameIndex >= mNumSnapshotBufs) {
3430          LOGE("Error, Invalid index for buffer");
3431          if(stream) {
3432              Mutex::Autolock lock(mFreeBuffersLock);
3433              mFreeBufferList.push_back(frameIndex);
3434              stream->bufDone(frameIndex);
3435          }
3436          return;
3437     }
3438 
3439     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3440     if (frame == NULL) {
3441        LOGE("Error allocating memory to save received_frame structure.");
3442        if(stream) {
3443            Mutex::Autolock lock(mFreeBuffersLock);
3444            mFreeBufferList.push_back(frameIndex);
3445            stream->bufDone(frameIndex);
3446        }
3447        return;
3448     }
3449     *frame = *super_frame;
3450     stream->getFrameDimension(dim);
3451     stream->getFrameOffset(offset);
3452     dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3453 
3454     m_postprocessor.processData(frame);
3455     free(super_frame);
3456     return;
3457 }
3458 
getStreamBufs(uint32_t len)3459 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3460 {
3461     mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3462     if (!mYuvMemory) {
3463         LOGE("unable to create metadata memory");
3464         return NULL;
3465     }
3466     mFrameLen = len;
3467 
3468     return mYuvMemory;
3469 }
3470 
putStreamBufs()3471 void QCamera3PicChannel::putStreamBufs()
3472 {
3473     QCamera3ProcessingChannel::putStreamBufs();
3474 
3475     mYuvMemory->deallocate();
3476     delete mYuvMemory;
3477     mYuvMemory = NULL;
3478     mFreeBufferList.clear();
3479 }
3480 
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3481 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3482 {
3483     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3484     jpeg_settings_t *settings =
3485             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3486 
3487     if (!settings) {
3488         LOGE("out of memory allocating jpeg_settings");
3489         return -ENOMEM;
3490     }
3491 
3492     memset(settings, 0, sizeof(jpeg_settings_t));
3493 
3494     settings->out_buf_index = index;
3495 
3496     settings->jpeg_orientation = 0;
3497     IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3498         settings->jpeg_orientation = *orientation;
3499     }
3500 
3501     settings->jpeg_quality = 85;
3502     IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3503         settings->jpeg_quality = (uint8_t) *quality1;
3504     }
3505 
3506     IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3507         settings->jpeg_thumb_quality = (uint8_t) *quality2;
3508     }
3509 
3510     IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3511         settings->thumbnail_size = *dimension;
3512     }
3513 
3514     settings->gps_timestamp_valid = 0;
3515     IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3516         settings->gps_timestamp = *timestamp;
3517         settings->gps_timestamp_valid = 1;
3518     }
3519 
3520     settings->gps_coordinates_valid = 0;
3521     IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3522         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3523         settings->gps_coordinates_valid = 1;
3524     }
3525 
3526     IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3527         memset(settings->gps_processing_method, 0,
3528                 sizeof(settings->gps_processing_method));
3529         strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3530                 sizeof(settings->gps_processing_method));
3531     }
3532 
3533     // Image description
3534     const char *eepromVersion = hal_obj->getEepromVersionInfo();
3535     const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3536     if ((eepromVersion && strlen(eepromVersion)) ||
3537             ldafCalib) {
3538         int len = 0;
3539         settings->image_desc_valid = true;
3540         if (eepromVersion && strlen(eepromVersion)) {
3541             len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3542                     "M:%s ", eepromVersion);
3543         }
3544         if (ldafCalib) {
3545             snprintf(settings->image_desc + len,
3546                     sizeof(settings->image_desc) - len, "L:%u-%u",
3547                     ldafCalib[0], ldafCalib[1]);
3548         }
3549     }
3550 
3551     return m_postprocessor.processJpegSettingData(settings);
3552 }
3553 
3554 
overrideYuvSize(uint32_t width,uint32_t height)3555 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3556 {
3557    mYuvWidth = width;
3558    mYuvHeight = height;
3559 }
3560 
3561 /*===========================================================================
3562  * FUNCTION   : getReprocessType
3563  *
3564  * DESCRIPTION: get the type of reprocess output supported by this channel
3565  *
3566  * PARAMETERS : NONE
3567  *
3568  * RETURN     : reprocess_type_t : type of reprocess
3569  *==========================================================================*/
getReprocessType()3570 reprocess_type_t QCamera3PicChannel::getReprocessType()
3571 {
3572     /* a picture channel could either use the postprocessor for reprocess+jpeg
3573        or only for reprocess */
3574     reprocess_type_t expectedReprocess;
3575     if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3576         expectedReprocess = REPROCESS_TYPE_JPEG;
3577     } else {
3578         expectedReprocess = REPROCESS_TYPE_NONE;
3579     }
3580     LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
3581     return expectedReprocess;
3582 }
3583 
3584 
3585 /*===========================================================================
3586  * FUNCTION   : QCamera3ReprocessChannel
3587  *
3588  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3589  *
3590  * PARAMETERS :
3591  *   @cam_handle : camera handle
3592  *   @cam_ops    : ptr to camera ops table
3593  *   @pp_mask    : post-proccess feature mask
3594  *
3595  * RETURN     : none
3596  *==========================================================================*/
QCamera3ReprocessChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,void * userData,void * ch_hdl)3597 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3598                                                  uint32_t channel_handle,
3599                                                  mm_camera_ops_t *cam_ops,
3600                                                  channel_cb_routine cb_routine,
3601                                                  cam_padding_info_t *paddingInfo,
3602                                                  uint32_t postprocess_mask,
3603                                                  void *userData, void *ch_hdl) :
3604     /* In case of framework reprocessing, pproc and jpeg operations could be
3605      * parallelized by allowing 1 extra buffer for reprocessing output:
3606      * ch_hdl->getNumBuffers() + 1 */
3607     QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, paddingInfo,
3608                     postprocess_mask, userData,
3609                     ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3610                               + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3611     inputChHandle(ch_hdl),
3612     mOfflineBuffersIndex(-1),
3613     mFrameLen(0),
3614     mReprocessType(REPROCESS_TYPE_NONE),
3615     m_pSrcChannel(NULL),
3616     m_pMetaChannel(NULL),
3617     mMemory(NULL),
3618     mGrallocMemory(0),
3619     mReprocessPerfMode(false)
3620 {
3621     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3622     mOfflineBuffersIndex = mNumBuffers -1;
3623     mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3624 }
3625 
3626 
3627 /*===========================================================================
3628  * FUNCTION   : QCamera3ReprocessChannel
3629  *
3630  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3631  *
3632  * PARAMETERS :
3633  *   @cam_handle : camera handle
3634  *   @cam_ops    : ptr to camera ops table
3635  *   @pp_mask    : post-proccess feature mask
3636  *
3637  * RETURN     : none
3638  *==========================================================================*/
initialize(cam_is_type_t isType)3639 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3640 {
3641     int32_t rc = NO_ERROR;
3642     mm_camera_channel_attr_t attr;
3643 
3644     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3645     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3646     attr.max_unmatched_frames = 1;
3647 
3648     m_handle = m_camOps->add_channel(m_camHandle,
3649                                       &attr,
3650                                       NULL,
3651                                       this);
3652     if (m_handle == 0) {
3653         LOGE("Add channel failed");
3654         return UNKNOWN_ERROR;
3655     }
3656 
3657     mIsType = isType;
3658     return rc;
3659 }
3660 
3661 /*===========================================================================
3662  * FUNCTION   : registerBuffer
3663  *
3664  * DESCRIPTION: register streaming buffer to the channel object
3665  *
3666  * PARAMETERS :
3667  *   @buffer     : buffer to be registered
3668  *   @isType     : the image stabilization type for the buffer
3669  *
3670  * RETURN     : int32_t type of status
3671  *              NO_ERROR  -- success
3672  *              none-zero failure code
3673  *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3674 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3675         cam_is_type_t isType)
3676 {
3677     ATRACE_CALL();
3678     int rc = 0;
3679     mIsType = isType;
3680     cam_stream_type_t streamType;
3681 
3682     if (buffer == NULL) {
3683         LOGE("Error: Cannot register a NULL buffer");
3684         return BAD_VALUE;
3685     }
3686 
3687     if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3688         LOGE("Trying to register more buffers than initially requested");
3689         return BAD_VALUE;
3690     }
3691 
3692     if (0 == m_numStreams) {
3693         rc = initialize(mIsType);
3694         if (rc != NO_ERROR) {
3695             LOGE("Couldn't initialize camera stream %d",
3696                      rc);
3697             return rc;
3698         }
3699     }
3700 
3701     streamType = mStreams[0]->getMyType();
3702     rc = mGrallocMemory.registerBuffer(buffer, streamType);
3703     if (ALREADY_EXISTS == rc) {
3704         return NO_ERROR;
3705     } else if (NO_ERROR != rc) {
3706         LOGE("Buffer %p couldn't be registered %d", buffer, rc);
3707         return rc;
3708     }
3709 
3710     return rc;
3711 }
3712 
3713 /*===========================================================================
3714  * FUNCTION   : QCamera3ReprocessChannel
3715  *
3716  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3717  *
3718  * PARAMETERS :
3719  *   @cam_handle : camera handle
3720  *   @cam_ops    : ptr to camera ops table
3721  *   @pp_mask    : post-proccess feature mask
3722  *
3723  * RETURN     : none
3724  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3725 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3726                                   QCamera3Stream *stream)
3727 {
3728     //Got the pproc data callback. Now send to jpeg encoding
3729     uint8_t frameIndex;
3730     uint32_t resultFrameNumber;
3731     mm_camera_super_buf_t* frame = NULL;
3732     QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
3733     cam_dimension_t dim;
3734     cam_frame_len_offset_t offset;
3735 
3736     memset(&dim, 0, sizeof(dim));
3737     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3738     if(!super_frame) {
3739          LOGE("Invalid Super buffer");
3740          return;
3741     }
3742 
3743     if(super_frame->num_bufs != 1) {
3744          LOGE("Multiple streams are not supported");
3745          return;
3746     }
3747     if(super_frame->bufs[0] == NULL ) {
3748          LOGE("Error, Super buffer frame does not contain valid buffer");
3749          return;
3750     }
3751     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3752 
3753 
3754     if (mReprocessType == REPROCESS_TYPE_JPEG) {
3755         resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
3756         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3757         if (frame == NULL) {
3758            LOGE("Error allocating memory to save received_frame structure.");
3759            if(stream) {
3760                stream->bufDone(frameIndex);
3761            }
3762            return;
3763         }
3764         LOGI("bufIndex: %u recvd from post proc",
3765                  (uint32_t)frameIndex);
3766         *frame = *super_frame;
3767 
3768         stream->getFrameDimension(dim);
3769         stream->getFrameOffset(offset);
3770         dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
3771         /* Since reprocessing is done, send the callback to release the input buffer */
3772         if (mChannelCB) {
3773             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
3774         }
3775         obj->m_postprocessor.processPPData(frame);
3776     } else {
3777         buffer_handle_t *resultBuffer;
3778         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3779         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
3780         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
3781         int32_t rc = stream->bufRelease(frameIndex);
3782         if (NO_ERROR != rc) {
3783             LOGE("Error %d releasing stream buffer %d",
3784                      rc, frameIndex);
3785         }
3786         rc = mGrallocMemory.unregisterBuffer(frameIndex);
3787         if (NO_ERROR != rc) {
3788             LOGE("Error %d unregistering stream buffer %d",
3789                      rc, frameIndex);
3790         }
3791         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
3792 
3793         obj->m_postprocessor.releaseOfflineBuffers(false);
3794         qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
3795         if (pp_job != NULL) {
3796             obj->m_postprocessor.releasePPJobData(pp_job);
3797         }
3798         free(pp_job);
3799         resetToCamPerfNormal(resultFrameNumber);
3800     }
3801     free(super_frame);
3802     return;
3803 }
3804 
3805 /*===========================================================================
3806  * FUNCTION   : resetToCamPerfNormal
3807  *
3808  * DESCRIPTION: Set the perf mode to normal if all the priority frames
3809  *              have been reprocessed
3810  *
3811  * PARAMETERS :
3812  *      @frameNumber: Frame number of the reprocess completed frame
3813  *
3814  * RETURN     : QCamera3StreamMem *
3815  *==========================================================================*/
resetToCamPerfNormal(uint32_t frameNumber)3816 int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
3817 {
3818     int32_t rc = NO_ERROR;
3819     bool resetToPerfNormal = false;
3820     {
3821         Mutex::Autolock lock(mPriorityFramesLock);
3822         /* remove the priority frame number from the list */
3823         for (size_t i = 0; i < mPriorityFrames.size(); i++) {
3824             if (mPriorityFrames[i] == frameNumber) {
3825                 mPriorityFrames.removeAt(i);
3826             }
3827         }
3828         /* reset the perf mode if pending priority frame list is empty */
3829         if (mReprocessPerfMode && mPriorityFrames.empty()) {
3830             resetToPerfNormal = true;
3831         }
3832     }
3833     if (resetToPerfNormal) {
3834         QCamera3Stream *pStream = mStreams[0];
3835         cam_stream_parm_buffer_t param;
3836         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
3837 
3838         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3839         param.perf_mode = CAM_PERF_NORMAL;
3840         rc = pStream->setParameter(param);
3841         {
3842             Mutex::Autolock lock(mPriorityFramesLock);
3843             mReprocessPerfMode = false;
3844         }
3845     }
3846     return rc;
3847 }
3848 
3849 /*===========================================================================
3850  * FUNCTION   : getStreamBufs
3851  *
3852  * DESCRIPTION: register the buffers of the reprocess channel
3853  *
3854  * PARAMETERS : none
3855  *
3856  * RETURN     : QCamera3StreamMem *
3857  *==========================================================================*/
getStreamBufs(uint32_t len)3858 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
3859 {
3860     if (mReprocessType == REPROCESS_TYPE_JPEG) {
3861         mMemory = new QCamera3StreamMem(mNumBuffers, false);
3862         if (!mMemory) {
3863             LOGE("unable to create reproc memory");
3864             return NULL;
3865         }
3866         mFrameLen = len;
3867         return mMemory;
3868     }
3869     return &mGrallocMemory;
3870 }
3871 
3872 /*===========================================================================
3873  * FUNCTION   : putStreamBufs
3874  *
3875  * DESCRIPTION: release the reprocess channel buffers
3876  *
3877  * PARAMETERS : none
3878  *
3879  * RETURN     :
3880  *==========================================================================*/
putStreamBufs()3881 void QCamera3ReprocessChannel::putStreamBufs()
3882 {
3883    if (mReprocessType == REPROCESS_TYPE_JPEG) {
3884        mMemory->deallocate();
3885        delete mMemory;
3886        mMemory = NULL;
3887        mFreeBufferList.clear();
3888    } else {
3889        mGrallocMemory.unregisterBuffers();
3890    }
3891 }
3892 
3893 /*===========================================================================
3894  * FUNCTION   : ~QCamera3ReprocessChannel
3895  *
3896  * DESCRIPTION: destructor of QCamera3ReprocessChannel
3897  *
3898  * PARAMETERS : none
3899  *
3900  * RETURN     : none
3901  *==========================================================================*/
~QCamera3ReprocessChannel()3902 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
3903 {
3904     destroy();
3905 
3906     if (m_handle) {
3907         m_camOps->delete_channel(m_camHandle, m_handle);
3908         LOGD("deleting channel %d", m_handle);
3909         m_handle = 0;
3910     }
3911 }
3912 
3913 /*===========================================================================
3914  * FUNCTION   : start
3915  *
3916  * DESCRIPTION: start reprocess channel.
3917  *
3918  * PARAMETERS :
3919  *
3920  * RETURN     : int32_t type of status
3921  *              NO_ERROR  -- success
3922  *              none-zero failure code
3923  *==========================================================================*/
start()3924 int32_t QCamera3ReprocessChannel::start()
3925 {
3926     ATRACE_CALL();
3927     int32_t rc = NO_ERROR;
3928 
3929     rc = QCamera3Channel::start();
3930 
3931     if (rc == NO_ERROR) {
3932        rc = m_camOps->start_channel(m_camHandle, m_handle);
3933 
3934        // Check failure
3935        if (rc != NO_ERROR) {
3936            LOGE("start_channel failed %d", rc);
3937            QCamera3Channel::stop();
3938        }
3939     }
3940     return rc;
3941 }
3942 
3943 /*===========================================================================
3944  * FUNCTION   : stop
3945  *
3946  * DESCRIPTION: stop reprocess channel.
3947  *
3948  * PARAMETERS : none
3949  *
3950  * RETURN     : int32_t type of status
3951  *              NO_ERROR  -- success
3952  *              none-zero failure code
3953  *==========================================================================*/
stop()3954 int32_t QCamera3ReprocessChannel::stop()
3955 {
3956     ATRACE_CALL();
3957     int32_t rc = NO_ERROR;
3958 
3959     rc = QCamera3Channel::stop();
3960     unmapOfflineBuffers(true);
3961 
3962     rc |= m_camOps->stop_channel(m_camHandle, m_handle);
3963 
3964     return rc;
3965 }
3966 
3967 /*===========================================================================
3968  * FUNCTION   : getStreamBySrcHandle
3969  *
3970  * DESCRIPTION: find reprocess stream by its source stream handle
3971  *
3972  * PARAMETERS :
3973  *   @srcHandle : source stream handle
3974  *
3975  * RETURN     : ptr to reprocess stream if found. NULL if not found
3976  *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)3977 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
3978 {
3979     QCamera3Stream *pStream = NULL;
3980 
3981     for (uint32_t i = 0; i < m_numStreams; i++) {
3982         if (mSrcStreamHandles[i] == srcHandle) {
3983             pStream = mStreams[i];
3984             break;
3985         }
3986     }
3987     return pStream;
3988 }
3989 
3990 /*===========================================================================
3991  * FUNCTION   : getSrcStreamBySrcHandle
3992  *
3993  * DESCRIPTION: find source stream by source stream handle
3994  *
3995  * PARAMETERS :
3996  *   @srcHandle : source stream handle
3997  *
3998  * RETURN     : ptr to reprocess stream if found. NULL if not found
3999  *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)4000 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4001 {
4002     QCamera3Stream *pStream = NULL;
4003 
4004     if (NULL == m_pSrcChannel) {
4005         return NULL;
4006     }
4007 
4008     for (uint32_t i = 0; i < m_numStreams; i++) {
4009         if (mSrcStreamHandles[i] == srcHandle) {
4010             pStream = m_pSrcChannel->getStreamByIndex(i);
4011             break;
4012         }
4013     }
4014     return pStream;
4015 }
4016 
4017 /*===========================================================================
4018  * FUNCTION   : unmapOfflineBuffers
4019  *
4020  * DESCRIPTION: Unmaps offline buffers
4021  *
4022  * PARAMETERS : none
4023  *
4024  * RETURN     : int32_t type of status
4025  *              NO_ERROR  -- success
4026  *              none-zero failure code
4027  *==========================================================================*/
unmapOfflineBuffers(bool all)4028 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4029 {
4030     int rc = NO_ERROR;
4031     if (!mOfflineBuffers.empty()) {
4032         QCamera3Stream *stream = NULL;
4033         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4034         for (; it != mOfflineBuffers.end(); it++) {
4035            stream = (*it).stream;
4036            if (NULL != stream) {
4037                rc = stream->unmapBuf((*it).type,
4038                                      (*it).index,
4039                                         -1);
4040                if (NO_ERROR != rc) {
4041                    LOGE("Error during offline buffer unmap %d",
4042                           rc);
4043                }
4044                LOGD("Unmapped buffer with index %d", (*it).index);
4045            }
4046            if (!all) {
4047                mOfflineBuffers.erase(it);
4048                break;
4049            }
4050         }
4051         if (all) {
4052            mOfflineBuffers.clear();
4053         }
4054     }
4055 
4056     if (!mOfflineMetaBuffers.empty()) {
4057         QCamera3Stream *stream = NULL;
4058         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4059         for (; it != mOfflineMetaBuffers.end(); it++) {
4060            stream = (*it).stream;
4061            if (NULL != stream) {
4062                rc = stream->unmapBuf((*it).type,
4063                                      (*it).index,
4064                                         -1);
4065                if (NO_ERROR != rc) {
4066                    LOGE("Error during offline buffer unmap %d",
4067                           rc);
4068                }
4069                LOGD("Unmapped meta buffer with index %d", (*it).index);
4070            }
4071            if (!all) {
4072                mOfflineMetaBuffers.erase(it);
4073                break;
4074            }
4075         }
4076         if (all) {
4077            mOfflineMetaBuffers.clear();
4078         }
4079     }
4080     return rc;
4081 }
4082 
4083 /*===========================================================================
4084  * FUNCTION   : bufDone
4085  *
4086  * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4087  *              Note that this function doesn't queue buffer back to kernel.
4088  *              It's up to doReprocessOffline to do that instead.
4089  * PARAMETERS :
4090  *   @recvd_frame  : stream buf frame to be returned
4091  *
4092  * RETURN     : int32_t type of status
4093  *              NO_ERROR  -- success
4094  *              none-zero failure code
4095  *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)4096 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4097 {
4098     int rc = NO_ERROR;
4099     if (recvd_frame && recvd_frame->num_bufs == 1) {
4100         Mutex::Autolock lock(mFreeBuffersLock);
4101         uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4102         mFreeBufferList.push_back(buf_idx);
4103 
4104     } else {
4105         LOGE("Fatal. Not supposed to be here");
4106         rc = BAD_VALUE;
4107     }
4108 
4109     return rc;
4110 }
4111 
4112 /*===========================================================================
4113  * FUNCTION   : overrideMetadata
4114  *
4115  * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4116  *
4117  * PARAMETERS :
4118  *   @frame     : input frame from source stream
4119  *   meta_buffer: metadata buffer
4120  *   @metadata  : corresponding metadata
4121  *   @fwk_frame :
4122  *
4123  * RETURN     : int32_t type of status
4124  *              NO_ERROR  -- success
4125  *              none-zero failure code
4126  *==========================================================================*/
overrideMetadata(qcamera_hal3_pp_buffer_t * pp_buffer,mm_camera_buf_def_t * meta_buffer,jpeg_settings_t * jpeg_settings,qcamera_fwk_input_pp_data_t & fwk_frame)4127 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4128         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4129         qcamera_fwk_input_pp_data_t &fwk_frame)
4130 {
4131     int32_t rc = NO_ERROR;
4132     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4133     if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4134             (NULL == hal_obj)) {
4135         return BAD_VALUE;
4136     }
4137 
4138     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4139     mm_camera_super_buf_t *frame = pp_buffer->input;
4140     if (NULL == meta) {
4141         return BAD_VALUE;
4142     }
4143 
4144     for (uint32_t i = 0; i < frame->num_bufs; i++) {
4145         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4146         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4147 
4148         if (pStream != NULL && pSrcStream != NULL) {
4149             if (jpeg_settings) {
4150                 // Find rotation info for reprocess stream
4151                 cam_rotation_info_t rotation_info;
4152                 memset(&rotation_info, 0, sizeof(rotation_info));
4153                 if (jpeg_settings->jpeg_orientation == 0) {
4154                    rotation_info.rotation = ROTATE_0;
4155                 } else if (jpeg_settings->jpeg_orientation == 90) {
4156                    rotation_info.rotation = ROTATE_90;
4157                 } else if (jpeg_settings->jpeg_orientation == 180) {
4158                    rotation_info.rotation = ROTATE_180;
4159                 } else if (jpeg_settings->jpeg_orientation == 270) {
4160                    rotation_info.rotation = ROTATE_270;
4161                 }
4162                 rotation_info.streamId = mStreams[0]->getMyServerID();
4163                 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4164             }
4165 
4166             // Find and insert crop info for reprocess stream
4167             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4168                 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4169                     for (int j = 0; j < crop_data->num_of_streams; j++) {
4170                         if (crop_data->crop_info[j].stream_id ==
4171                                 pSrcStream->getMyServerID()) {
4172 
4173                             // Store crop/roi information for offline reprocess
4174                             // in the reprocess stream slot
4175                             crop_data->crop_info[crop_data->num_of_streams].crop =
4176                                     crop_data->crop_info[j].crop;
4177                             crop_data->crop_info[crop_data->num_of_streams].roi_map =
4178                                     crop_data->crop_info[j].roi_map;
4179                             crop_data->crop_info[crop_data->num_of_streams].stream_id =
4180                                     mStreams[0]->getMyServerID();
4181                             crop_data->num_of_streams++;
4182 
4183                             LOGD("Reprocess stream server id: %d",
4184                                      mStreams[0]->getMyServerID());
4185                             LOGD("Found offline reprocess crop %dx%d %dx%d",
4186                                     crop_data->crop_info[j].crop.left,
4187                                     crop_data->crop_info[j].crop.top,
4188                                     crop_data->crop_info[j].crop.width,
4189                                     crop_data->crop_info[j].crop.height);
4190                             LOGD("Found offline reprocess roimap %dx%d %dx%d",
4191                                     crop_data->crop_info[j].roi_map.left,
4192                                     crop_data->crop_info[j].roi_map.top,
4193                                     crop_data->crop_info[j].roi_map.width,
4194                                     crop_data->crop_info[j].roi_map.height);
4195 
4196                             break;
4197                         }
4198                     }
4199                 } else {
4200                     LOGE("No space to add reprocess stream crop/roi information");
4201                 }
4202             }
4203 
4204             IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4205                 uint8_t cnt = cdsInfo->num_of_streams;
4206                 if (cnt <= MAX_NUM_STREAMS) {
4207                     cam_stream_cds_info_t repro_cds_info;
4208                     memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4209                     repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4210                     for (size_t i = 0; i < cnt; i++) {
4211                         if (cdsInfo->cds_info[i].stream_id ==
4212                                 pSrcStream->getMyServerID()) {
4213                             repro_cds_info.cds_enable =
4214                                     cdsInfo->cds_info[i].cds_enable;
4215                             break;
4216                         }
4217                     }
4218                     cdsInfo->num_of_streams = 1;
4219                     cdsInfo->cds_info[0] = repro_cds_info;
4220                 } else {
4221                     LOGE("No space to add reprocess stream cds information");
4222                 }
4223             }
4224 
4225             fwk_frame.input_buffer = *frame->bufs[i];
4226             fwk_frame.metadata_buffer = *meta_buffer;
4227             fwk_frame.output_buffer = pp_buffer->output;
4228             break;
4229         } else {
4230             LOGE("Source/Re-process streams are invalid");
4231             rc |= BAD_VALUE;
4232         }
4233     }
4234 
4235     return rc;
4236 }
4237 
4238 /*===========================================================================
4239 * FUNCTION : overrideFwkMetadata
4240 *
4241 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4242 *
4243 * PARAMETERS :
4244 * @frame : input frame for reprocessing
4245 *
4246 * RETURN : int32_t type of status
4247 * NO_ERROR -- success
4248 * none-zero failure code
4249 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)4250 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4251         qcamera_fwk_input_pp_data_t *frame)
4252 {
4253     if (NULL == frame) {
4254         LOGE("Incorrect input frame");
4255         return BAD_VALUE;
4256     }
4257 
4258     if (NULL == frame->metadata_buffer.buffer) {
4259         LOGE("No metadata available");
4260         return BAD_VALUE;
4261     }
4262 
4263     // Find and insert crop info for reprocess stream
4264     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4265     IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4266         if (1 == crop_data->num_of_streams) {
4267             // Store crop/roi information for offline reprocess
4268             // in the reprocess stream slot
4269             crop_data->crop_info[crop_data->num_of_streams].crop =
4270                     crop_data->crop_info[0].crop;
4271             crop_data->crop_info[crop_data->num_of_streams].roi_map =
4272                     crop_data->crop_info[0].roi_map;
4273             crop_data->crop_info[crop_data->num_of_streams].stream_id =
4274                     mStreams[0]->getMyServerID();
4275             crop_data->num_of_streams++;
4276 
4277             LOGD("Reprocess stream server id: %d",
4278                      mStreams[0]->getMyServerID());
4279             LOGD("Found offline reprocess crop %dx%d %dx%d",
4280                     crop_data->crop_info[0].crop.left,
4281                     crop_data->crop_info[0].crop.top,
4282                     crop_data->crop_info[0].crop.width,
4283                     crop_data->crop_info[0].crop.height);
4284             LOGD("Found offline reprocess roi map %dx%d %dx%d",
4285                     crop_data->crop_info[0].roi_map.left,
4286                     crop_data->crop_info[0].roi_map.top,
4287                     crop_data->crop_info[0].roi_map.width,
4288                     crop_data->crop_info[0].roi_map.height);
4289         } else {
4290             LOGE("Incorrect number of offline crop data entries %d",
4291                     crop_data->num_of_streams);
4292             return BAD_VALUE;
4293         }
4294     } else {
4295         LOGW("Crop data not present");
4296     }
4297 
4298     IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4299         if (1 == cdsInfo->num_of_streams) {
4300             cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4301         } else {
4302             LOGE("Incorrect number of offline cds info entries %d",
4303                      cdsInfo->num_of_streams);
4304             return BAD_VALUE;
4305         }
4306     }
4307 
4308     return NO_ERROR;
4309 }
4310 
4311 /*===========================================================================
4312  * FUNCTION   : doReprocessOffline
4313  *
4314  * DESCRIPTION: request to do a reprocess on the frame
4315  *
4316  * PARAMETERS :
4317  *   @frame     : input frame for reprocessing
4318  *   @isPriorityFrame: Hint that this frame is of priority, equivalent to
4319  *              real time, even though it is processed in offline mechanism
4320  *
4321  * RETURN     : int32_t type of status
4322  *              NO_ERROR  -- success
4323  *              none-zero failure code
4324  *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame,bool isPriorityFrame)4325  int32_t  QCamera3ReprocessChannel::doReprocessOffline(
4326         qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4327 {
4328     int32_t rc = 0;
4329     int index;
4330     OfflineBuffer mappedBuffer;
4331 
4332     if (m_numStreams < 1) {
4333         LOGE("No reprocess stream is created");
4334         return -1;
4335     }
4336 
4337     if (NULL == frame) {
4338         LOGE("Incorrect input frame");
4339         return BAD_VALUE;
4340     }
4341 
4342     if (NULL == frame->metadata_buffer.buffer) {
4343         LOGE("No metadata available");
4344         return BAD_VALUE;
4345     }
4346 
4347     if (NULL == frame->input_buffer.buffer) {
4348         LOGE("No input buffer available");
4349         return BAD_VALUE;
4350     }
4351 
4352     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4353         LOGE("Reprocess stream not initialized!");
4354         return NO_INIT;
4355     }
4356 
4357     QCamera3Stream *pStream = mStreams[0];
4358 
4359     //qbuf the output buffer if it was allocated by the framework
4360     if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4361         if(!m_bIsActive) {
4362             rc = registerBuffer(frame->output_buffer, mIsType);
4363             if (NO_ERROR != rc) {
4364                 LOGE("On-the-fly buffer registration failed %d",
4365                          rc);
4366                 return rc;
4367             }
4368 
4369             rc = start();
4370             if (NO_ERROR != rc) {
4371                 return rc;
4372             }
4373         }
4374         index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4375         if(index < 0) {
4376             rc = registerBuffer(frame->output_buffer, mIsType);
4377             if (NO_ERROR != rc) {
4378                 LOGE("On-the-fly buffer registration failed %d",
4379                          rc);
4380                 return rc;
4381             }
4382 
4383             index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4384             if (index < 0) {
4385                 LOGE("Could not find object among registered buffers");
4386                 return DEAD_OBJECT;
4387             }
4388         }
4389         rc = pStream->bufDone(index);
4390         if(rc != NO_ERROR) {
4391             LOGE("Failed to Q new buffer to stream");
4392             return rc;
4393         }
4394         rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4395 
4396     } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4397         Mutex::Autolock lock(mFreeBuffersLock);
4398         uint32_t bufIdx;
4399         if (mFreeBufferList.empty()) {
4400             rc = mMemory->allocateOne(mFrameLen);
4401             if (rc < 0) {
4402                 LOGE("Failed allocating heap buffer. Fatal");
4403                 return BAD_VALUE;
4404             } else {
4405                 bufIdx = (uint32_t)rc;
4406             }
4407         } else {
4408             bufIdx = *(mFreeBufferList.begin());
4409             mFreeBufferList.erase(mFreeBufferList.begin());
4410         }
4411 
4412         mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4413         rc = pStream->bufDone(bufIdx);
4414         if (rc != NO_ERROR) {
4415             LOGE("Failed to queue new buffer to stream");
4416             return rc;
4417         }
4418     }
4419 
4420     int32_t max_idx = (int32_t) (mNumBuffers - 1);
4421     //loop back the indices if max burst count reached
4422     if (mOfflineBuffersIndex == max_idx) {
4423        mOfflineBuffersIndex = -1;
4424     }
4425     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4426     rc = pStream->mapBuf(
4427             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4428             buf_idx, -1,
4429             frame->input_buffer.fd, frame->input_buffer.frame_len);
4430     if (NO_ERROR == rc) {
4431         mappedBuffer.index = buf_idx;
4432         mappedBuffer.stream = pStream;
4433         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4434         mOfflineBuffers.push_back(mappedBuffer);
4435         mOfflineBuffersIndex = (int32_t)buf_idx;
4436         LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
4437     }
4438 
4439     max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4440     //loop back the indices if max burst count reached
4441     if (mOfflineMetaIndex == max_idx) {
4442        mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4443     }
4444     uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4445     rc |= pStream->mapBuf(
4446             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4447             meta_buf_idx, -1,
4448             frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
4449     if (NO_ERROR == rc) {
4450         mappedBuffer.index = meta_buf_idx;
4451         mappedBuffer.stream = pStream;
4452         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4453         mOfflineMetaBuffers.push_back(mappedBuffer);
4454         mOfflineMetaIndex = (int32_t)meta_buf_idx;
4455         LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
4456     }
4457 
4458     if (rc == NO_ERROR) {
4459         cam_stream_parm_buffer_t param;
4460         uint32_t numPendingPriorityFrames = 0;
4461 
4462         if(isPriorityFrame && (mReprocessType != REPROCESS_TYPE_JPEG)) {
4463             Mutex::Autolock lock(mPriorityFramesLock);
4464             /* read the length before pushing the frame number to check if
4465              * vector is empty */
4466             numPendingPriorityFrames = mPriorityFrames.size();
4467             mPriorityFrames.push(frame->frameNumber);
4468         }
4469 
4470         if(isPriorityFrame && !numPendingPriorityFrames &&
4471             (mReprocessType != REPROCESS_TYPE_JPEG)) {
4472             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4473             param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4474             param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
4475             rc = pStream->setParameter(param);
4476             if (rc != NO_ERROR) {
4477                 ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
4478                     __func__);
4479             }
4480             {
4481                 Mutex::Autolock lock(mPriorityFramesLock);
4482                 mReprocessPerfMode = true;
4483             }
4484         }
4485 
4486         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4487         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4488         param.reprocess.buf_index = buf_idx;
4489         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4490         param.reprocess.meta_present = 1;
4491         param.reprocess.meta_buf_index = meta_buf_idx;
4492 
4493         LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
4494                     param.reprocess.frame_idx, param.reprocess.buf_index,
4495                     param.reprocess.meta_buf_index);
4496         rc = pStream->setParameter(param);
4497         if (rc != NO_ERROR) {
4498             LOGE("stream setParameter for reprocess failed");
4499             resetToCamPerfNormal(frame->frameNumber);
4500         }
4501     } else {
4502         LOGE("Input buffer memory map failed: %d", rc);
4503     }
4504 
4505     return rc;
4506 }
4507 
4508 /*===========================================================================
4509  * FUNCTION   : doReprocess
4510  *
4511  * DESCRIPTION: request to do a reprocess on the frame
4512  *
4513  * PARAMETERS :
4514  *   @buf_fd     : fd to the input buffer that needs reprocess
4515  *   @buf_lenght : length of the input buffer
4516  *   @ret_val    : result of reprocess.
4517  *                 Example: Could be faceID in case of register face image.
4518  *   @meta_frame : metadata frame.
4519  *
4520  * RETURN     : int32_t type of status
4521  *              NO_ERROR  -- success
4522  *              none-zero failure code
4523  *==========================================================================*/
doReprocess(int buf_fd,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4524 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length,
4525         int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4526 {
4527     int32_t rc = 0;
4528     if (m_numStreams < 1) {
4529         LOGE("No reprocess stream is created");
4530         return -1;
4531     }
4532     if (meta_frame == NULL) {
4533         LOGE("Did not get corresponding metadata in time");
4534         return -1;
4535     }
4536 
4537     uint8_t buf_idx = 0;
4538     for (uint32_t i = 0; i < m_numStreams; i++) {
4539         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4540                                  buf_idx, -1,
4541                                  buf_fd, buf_length);
4542 
4543         if (rc == NO_ERROR) {
4544             cam_stream_parm_buffer_t param;
4545             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4546             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4547             param.reprocess.buf_index = buf_idx;
4548             param.reprocess.meta_present = 1;
4549             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4550             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4551 
4552             LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
4553                     param.reprocess.frame_idx, param.reprocess.buf_index,
4554                     param.reprocess.meta_buf_index);
4555             rc = mStreams[i]->setParameter(param);
4556             if (rc == NO_ERROR) {
4557                 ret_val = param.reprocess.ret_val;
4558             }
4559             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4560                                   buf_idx, -1);
4561         }
4562     }
4563     return rc;
4564 }
4565 
4566 /*===========================================================================
4567  * FUNCTION   : addReprocStreamsFromSource
4568  *
4569  * DESCRIPTION: add reprocess streams from input source channel
4570  *
4571  * PARAMETERS :
4572  *   @config         : pp feature configuration
4573  *   @src_config     : source reprocess configuration
4574  *   @isType         : type of image stabilization required on this stream
4575  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
4576  *
4577  *
4578  * RETURN     : int32_t type of status
4579  *              NO_ERROR  -- success
4580  *              none-zero failure code
4581  *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4582 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4583         const reprocess_config_t &src_config , cam_is_type_t is_type,
4584         QCamera3Channel *pMetaChannel)
4585 {
4586     int32_t rc = 0;
4587     cam_stream_reproc_config_t reprocess_config;
4588     cam_stream_type_t streamType;
4589 
4590     cam_dimension_t streamDim = src_config.output_stream_dim;
4591 
4592     if (NULL != src_config.src_channel) {
4593         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4594         if (pSrcStream == NULL) {
4595            LOGE("source channel doesn't have a stream");
4596            return BAD_VALUE;
4597         }
4598         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4599     }
4600 
4601     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4602     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4603 
4604     reprocess_config.offline.input_fmt = src_config.stream_format;
4605     reprocess_config.offline.input_dim = src_config.input_stream_dim;
4606     reprocess_config.offline.input_buf_planes.plane_info =
4607             src_config.input_stream_plane_info.plane_info;
4608     reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4609     reprocess_config.offline.input_type = src_config.stream_type;
4610 
4611     reprocess_config.pp_feature_config = pp_config;
4612     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4613             m_handle,
4614             m_camOps,
4615             &mPaddingInfo,
4616             (QCamera3Channel*)this);
4617     if (pStream == NULL) {
4618         LOGE("No mem for Stream");
4619         return NO_MEMORY;
4620     }
4621 
4622     rc = pStream->init(streamType, src_config.stream_format,
4623             streamDim, ROTATE_0, &reprocess_config,
4624             (uint8_t)mNumBuffers,
4625             reprocess_config.pp_feature_config.feature_mask,
4626             is_type,
4627             0,/* batchSize */
4628             QCamera3Channel::streamCbRoutine, this);
4629 
4630     if (rc == 0) {
4631         mStreams[m_numStreams] = pStream;
4632         m_numStreams++;
4633     } else {
4634         LOGE("failed to create reprocess stream");
4635         delete pStream;
4636     }
4637 
4638     if (rc == NO_ERROR) {
4639         m_pSrcChannel = src_config.src_channel;
4640         m_pMetaChannel = pMetaChannel;
4641         mReprocessType = src_config.reprocess_type;
4642         LOGD("mReprocessType is %d", mReprocessType);
4643     }
4644     mm_camera_req_buf_t buf;
4645     memset(&buf, 0x0, sizeof(buf));
4646     buf.type = MM_CAMERA_REQ_SUPER_BUF;
4647     buf.num_buf_requested = 1;
4648     if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
4649         LOGE("Request for super buffer failed");
4650     }
4651     return rc;
4652 }
4653 
4654 /* QCamera3SupportChannel methods */
4655 
4656 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4657 
QCamera3SupportChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,cam_stream_type_t streamType,cam_dimension_t * dim,cam_format_t streamFormat,uint8_t hw_analysis_supported,void * userData,uint32_t numBuffers)4658 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4659                     uint32_t channel_handle,
4660                     mm_camera_ops_t *cam_ops,
4661                     cam_padding_info_t *paddingInfo,
4662                     uint32_t postprocess_mask,
4663                     cam_stream_type_t streamType,
4664                     cam_dimension_t *dim,
4665                     cam_format_t streamFormat,
4666                     uint8_t hw_analysis_supported,
4667                     void *userData, uint32_t numBuffers) :
4668                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
4669                                 NULL, paddingInfo, postprocess_mask,
4670                                 userData, numBuffers),
4671                         mMemory(NULL)
4672 {
4673     memcpy(&mDim, dim, sizeof(cam_dimension_t));
4674     mStreamType = streamType;
4675     mStreamFormat = streamFormat;
4676    // Make Analysis same as Preview format
4677    if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
4678         mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW);
4679    }
4680 }
4681 
~QCamera3SupportChannel()4682 QCamera3SupportChannel::~QCamera3SupportChannel()
4683 {
4684     destroy();
4685 
4686     if (mMemory) {
4687         mMemory->deallocate();
4688         delete mMemory;
4689         mMemory = NULL;
4690     }
4691 }
4692 
initialize(cam_is_type_t isType)4693 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4694 {
4695     int32_t rc;
4696 
4697     if (mMemory || m_numStreams > 0) {
4698         LOGE("metadata channel already initialized");
4699         return -EINVAL;
4700     }
4701 
4702     mIsType = isType;
4703     rc = QCamera3Channel::addStream(mStreamType,
4704             mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4705             mPostProcMask, mIsType);
4706     if (rc < 0) {
4707         LOGE("addStream failed");
4708     }
4709     return rc;
4710 }
4711 
request(buffer_handle_t *,uint32_t)4712 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4713                                                 uint32_t /*frameNumber*/)
4714 {
4715     return NO_ERROR;
4716 }
4717 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)4718 void QCamera3SupportChannel::streamCbRoutine(
4719                         mm_camera_super_buf_t *super_frame,
4720                         QCamera3Stream * /*stream*/)
4721 {
4722     if (super_frame == NULL || super_frame->num_bufs != 1) {
4723         LOGE("super_frame is not valid");
4724         return;
4725     }
4726     bufDone(super_frame);
4727     free(super_frame);
4728 }
4729 
getStreamBufs(uint32_t len)4730 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4731 {
4732     int rc;
4733     mMemory = new QCamera3StreamMem(mNumBuffers);
4734     if (!mMemory) {
4735         LOGE("unable to create heap memory");
4736         return NULL;
4737     }
4738     rc = mMemory->allocateAll(len);
4739     if (rc < 0) {
4740         LOGE("unable to allocate heap memory");
4741         delete mMemory;
4742         mMemory = NULL;
4743         return NULL;
4744     }
4745     return mMemory;
4746 }
4747 
putStreamBufs()4748 void QCamera3SupportChannel::putStreamBufs()
4749 {
4750     mMemory->deallocate();
4751     delete mMemory;
4752     mMemory = NULL;
4753 }
4754 
4755 }; // namespace qcamera
4756