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