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