• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29 
30 
31 #define LOG_TAG "QCamera3Channel"
32 
33 // To remove
34 #include <cutils/properties.h>
35 
36 // System dependencies
37 #include <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     mYUVDump = property_get_int32("persist.camera.dumpimg", 0);
101 }
102 
103 /*===========================================================================
104  * FUNCTION   : ~QCamera3Channel
105  *
106  * DESCRIPTION: destructor of QCamera3Channel
107  *
108  * PARAMETERS : none
109  *
110  * RETURN     : none
111  *==========================================================================*/
~QCamera3Channel()112 QCamera3Channel::~QCamera3Channel()
113 {
114 }
115 
116 /*===========================================================================
117  * FUNCTION   : destroy
118  *
119  * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
120  *              this destructor will call pure virtual functions.  stop will eventuall call
121  *              QCamera3Stream::putBufs.  The putBufs function will
122  *              call QCamera3Channel::putStreamBufs which is pure virtual
123  *
124  * PARAMETERS : none
125  *
126  * RETURN     : none
127  *==========================================================================*/
destroy()128 void QCamera3Channel::destroy()
129 {
130     if (m_bIsActive)
131         stop();
132 
133     for (uint32_t i = 0; i < m_numStreams; i++) {
134         if (mStreams[i] != NULL) {
135             delete mStreams[i];
136             mStreams[i] = 0;
137         }
138     }
139     m_numStreams = 0;
140 }
141 
142 /*===========================================================================
143  * FUNCTION   : addStream
144  *
145  * DESCRIPTION: add a stream into channel
146  *
147  * PARAMETERS :
148  *   @streamType     : stream type
149  *   @streamFormat   : stream format
150  *   @streamDim      : stream dimension
151  *   @streamRotation : rotation of the stream
152  *   @minStreamBufNum : minimal buffer count for particular stream type
153  *   @postprocessMask : post-proccess feature mask
154  *   @isType         : type of image stabilization required on the stream
155  *
156  * RETURN     : int32_t type of status
157  *              NO_ERROR  -- success
158  *              none-zero failure code
159  *==========================================================================*/
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)160 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
161                                   cam_format_t streamFormat,
162                                   cam_dimension_t streamDim,
163                                   cam_rotation_t streamRotation,
164                                   uint8_t minStreamBufNum,
165                                   cam_feature_mask_t postprocessMask,
166                                   cam_is_type_t isType,
167                                   uint32_t batchSize)
168 {
169     int32_t rc = NO_ERROR;
170 
171     if (m_numStreams >= 1) {
172         LOGE("Only one stream per channel supported in v3 Hal");
173         return BAD_VALUE;
174     }
175 
176     if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
177         LOGE("stream number (%d) exceeds max limit (%d)",
178                m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
179         return BAD_VALUE;
180     }
181     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
182                                                m_handle,
183                                                m_camOps,
184                                                &mPaddingInfo,
185                                                this);
186     if (pStream == NULL) {
187         LOGE("No mem for Stream");
188         return NO_MEMORY;
189     }
190     LOGD("batch size is %d", batchSize);
191 
192     rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
193             NULL, minStreamBufNum, postprocessMask, isType, batchSize,
194             streamCbRoutine, this);
195     if (rc == 0) {
196         mStreams[m_numStreams] = pStream;
197         m_numStreams++;
198     } else {
199         delete pStream;
200     }
201     return rc;
202 }
203 
204 /*===========================================================================
205  * FUNCTION   : start
206  *
207  * DESCRIPTION: start channel, which will start all streams belong to this channel
208  *
209  * PARAMETERS :
210  *
211  * RETURN     : int32_t type of status
212  *              NO_ERROR  -- success
213  *              none-zero failure code
214  *==========================================================================*/
start()215 int32_t QCamera3Channel::start()
216 {
217     ATRACE_CALL();
218     int32_t rc = NO_ERROR;
219 
220     if (m_numStreams > 1) {
221         LOGW("bundle not supported");
222     } else if (m_numStreams == 0) {
223         return NO_INIT;
224     }
225 
226     if(m_bIsActive) {
227         LOGW("Attempt to start active channel");
228         return rc;
229     }
230 
231     for (uint32_t i = 0; i < m_numStreams; i++) {
232         if (mStreams[i] != NULL) {
233             mStreams[i]->start();
234         }
235     }
236 
237     m_bIsActive = true;
238 
239     return rc;
240 }
241 
242 /*===========================================================================
243  * FUNCTION   : stop
244  *
245  * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
246  *
247  * PARAMETERS : none
248  *
249  * RETURN     : int32_t type of status
250  *              NO_ERROR  -- success
251  *              none-zero failure code
252  *==========================================================================*/
stop()253 int32_t QCamera3Channel::stop()
254 {
255     ATRACE_CALL();
256     int32_t rc = NO_ERROR;
257     if(!m_bIsActive) {
258         LOGE("Attempt to stop inactive channel");
259         return rc;
260     }
261 
262     for (uint32_t i = 0; i < m_numStreams; i++) {
263         if (mStreams[i] != NULL) {
264             mStreams[i]->stop();
265         }
266     }
267 
268     m_bIsActive = false;
269     return rc;
270 }
271 
272 /*===========================================================================
273  * FUNCTION   : setBatchSize
274  *
275  * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
276  *              for the base class
277  *
278  * PARAMETERS :
279  *   @batchSize  : Number of image buffers in a batch
280  *
281  * RETURN     : int32_t type of status
282  *              NO_ERROR  -- success always
283  *              none-zero failure code
284  *==========================================================================*/
setBatchSize(uint32_t batchSize)285 int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
286 {
287     LOGD("Dummy method. batchSize: %d unused ", batchSize);
288     return NO_ERROR;
289 }
290 
291 /*===========================================================================
292  * FUNCTION   : queueBatchBuf
293  *
294  * DESCRIPTION: This is a dummy implementation for the base class
295  *
296  * PARAMETERS :
297  *
298  * RETURN     : int32_t type of status
299  *              NO_ERROR  -- success always
300  *              none-zero failure code
301  *==========================================================================*/
queueBatchBuf()302 int32_t QCamera3Channel::queueBatchBuf()
303 {
304     LOGD("Dummy method. Unused ");
305     return NO_ERROR;
306 }
307 
308 /*===========================================================================
309  * FUNCTION   : setPerFrameMapUnmap
310  *
311  * DESCRIPTION: Sets internal enable flag
312  *
313  * PARAMETERS :
314  *  @enable : Bool value for the enable flag
315  *
316  * RETURN     : int32_t type of status
317  *              NO_ERROR  -- success always
318  *              none-zero failure code
319  *==========================================================================*/
setPerFrameMapUnmap(bool enable)320 int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
321 {
322     mPerFrameMapUnmapEnable = enable;
323     return NO_ERROR;
324 }
325 
326 /*===========================================================================
327  * FUNCTION   : flush
328  *
329  * DESCRIPTION: flush a channel
330  *
331  * PARAMETERS : none
332  *
333  * RETURN     : int32_t type of status
334  *              NO_ERROR  -- success
335  *              none-zero failure code
336  *==========================================================================*/
flush()337 int32_t QCamera3Channel::flush()
338 {
339     ATRACE_CALL();
340     return NO_ERROR;
341 }
342 
343 /*===========================================================================
344  * FUNCTION   : bufDone
345  *
346  * DESCRIPTION: return a stream buf back to kernel
347  *
348  * PARAMETERS :
349  *   @recvd_frame  : stream buf frame to be returned
350  *
351  * RETURN     : int32_t type of status
352  *              NO_ERROR  -- success
353  *              none-zero failure code
354  *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)355 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
356 {
357     int32_t rc = NO_ERROR;
358     for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
359          if (recvd_frame->bufs[i] != NULL) {
360              for (uint32_t j = 0; j < m_numStreams; j++) {
361                  if (mStreams[j] != NULL &&
362                      mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
363                      rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
364                      break; // break loop j
365                  }
366              }
367          }
368     }
369 
370     return rc;
371 }
372 
setBundleInfo(const cam_bundle_config_t & bundleInfo)373 int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
374 {
375     int32_t rc = NO_ERROR;
376     cam_stream_parm_buffer_t param;
377     memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
378     param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
379     param.bundleInfo = bundleInfo;
380     rc = mStreams[0]->setParameter(param);
381     if (rc != NO_ERROR) {
382         LOGE("stream setParameter for set bundle failed");
383     }
384 
385     return rc;
386 }
387 
388 /*===========================================================================
389  * FUNCTION   : getStreamTypeMask
390  *
391  * DESCRIPTION: Get bit mask of all stream types in this channel
392  *
393  * PARAMETERS : None
394  *
395  * RETURN     : Bit mask of all stream types in this channel
396  *==========================================================================*/
getStreamTypeMask()397 uint32_t QCamera3Channel::getStreamTypeMask()
398 {
399     uint32_t mask = 0;
400     for (uint32_t i = 0; i < m_numStreams; i++) {
401        mask |= (1U << mStreams[i]->getMyType());
402     }
403     return mask;
404 }
405 
406 /*===========================================================================
407  * FUNCTION   : getStreamID
408  *
409  * DESCRIPTION: Get StreamID of requested stream type
410  *
411  * PARAMETERS : streamMask
412  *
413  * RETURN     : Stream ID
414  *==========================================================================*/
getStreamID(uint32_t streamMask)415 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
416 {
417     uint32_t streamID = 0;
418     for (uint32_t i = 0; i < m_numStreams; i++) {
419         if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
420             streamID = mStreams[i]->getMyServerID();
421             break;
422         }
423     }
424     return streamID;
425 }
426 
427 /*===========================================================================
428  * FUNCTION   : getStreamByHandle
429  *
430  * DESCRIPTION: return stream object by stream handle
431  *
432  * PARAMETERS :
433  *   @streamHandle : stream handle
434  *
435  * RETURN     : stream object. NULL if not found
436  *==========================================================================*/
getStreamByHandle(uint32_t streamHandle)437 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
438 {
439     for (uint32_t i = 0; i < m_numStreams; i++) {
440         if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
441             return mStreams[i];
442         }
443     }
444     return NULL;
445 }
446 
447 /*===========================================================================
448  * FUNCTION   : getStreamByIndex
449  *
450  * DESCRIPTION: return stream object by index
451  *
452  * PARAMETERS :
453  *   @streamHandle : stream handle
454  *
455  * RETURN     : stream object. NULL if not found
456  *==========================================================================*/
getStreamByIndex(uint32_t index)457 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
458 {
459     if (index < m_numStreams) {
460         return mStreams[index];
461     }
462     return NULL;
463 }
464 
465 /*===========================================================================
466  * FUNCTION   : streamCbRoutine
467  *
468  * DESCRIPTION: callback routine for stream
469  *
470  * PARAMETERS :
471  *   @streamHandle : stream handle
472  *
473  * RETURN     : stream object. NULL if not found
474  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream,void * userdata)475 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
476                 QCamera3Stream *stream, void *userdata)
477 {
478     QCamera3Channel *channel = (QCamera3Channel *)userdata;
479     if (channel == NULL) {
480         LOGE("invalid channel pointer");
481         return;
482     }
483     channel->streamCbRoutine(super_frame, stream);
484 }
485 
486 /*===========================================================================
487  * FUNCTION   : dumpYUV
488  *
489  * DESCRIPTION: function to dump the YUV data from ISP/pproc
490  *
491  * PARAMETERS :
492  *   @frame   : frame to be dumped
493  *   @dim     : dimension of the stream
494  *   @offset  : offset of the data
495  *   @name    : 1 if it is ISP output/pproc input, 2 if it is pproc output
496  *
497  * RETURN  :
498  *==========================================================================*/
dumpYUV(mm_camera_buf_def_t * frame,cam_dimension_t dim,cam_frame_len_offset_t offset,uint8_t dump_type)499 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
500         cam_frame_len_offset_t offset, uint8_t dump_type)
501 {
502     char buf[FILENAME_MAX];
503     memset(buf, 0, sizeof(buf));
504     static int counter = 0;
505     if (mYUVDump & dump_type) {
506         mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
507         if (mFrmNum == 0) {
508             mFrmNum = 10;
509         }
510         if (mFrmNum > 256) {
511             mFrmNum = 256;
512         }
513         mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
514         if (mSkipMode == 0) {
515             mSkipMode = 1;
516         }
517         if (mDumpSkipCnt == 0) {
518             mDumpSkipCnt = 1;
519         }
520         if (mDumpSkipCnt % mSkipMode == 0) {
521             if (mDumpFrmCnt <= mFrmNum) {
522                 /* Note that the image dimension will be the unrotated stream dimension.
523                 * If you feel that the image would have been rotated during reprocess
524                 * then swap the dimensions while opening the file
525                 * */
526                 switch (dump_type) {
527                     case QCAMERA_DUMP_FRM_PREVIEW:
528                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
529                             counter, frame->frame_idx, dim.width, dim.height);
530                     break;
531                     case QCAMERA_DUMP_FRM_VIDEO:
532                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
533                             counter, frame->frame_idx, dim.width, dim.height);
534                     break;
535                     case QCAMERA_DUMP_FRM_SNAPSHOT:
536                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
537                             counter, frame->frame_idx, dim.width, dim.height);
538                     break;
539                     case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
540                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
541                             counter, frame->frame_idx, dim.width, dim.height);
542                     break;
543                     case QCAMERA_DUMP_FRM_CALLBACK:
544                         snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
545                             counter, frame->frame_idx, dim.width, dim.height);
546                     break;
547                     default :
548                         LOGE("dumping not enabled for stream type %d",dump_type);
549                     break;
550                 }
551                 counter++;
552                 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
553                 ssize_t written_len = 0;
554                 if (file_fd >= 0) {
555                     void *data = NULL;
556                     fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
557                     for (uint32_t i = 0; i < offset.num_planes; i++) {
558                         uint32_t index = offset.mp[i].offset;
559                         if (i > 0) {
560                             index += offset.mp[i-1].len;
561                         }
562                         for (int j = 0; j < offset.mp[i].height; j++) {
563                             data = (void *)((uint8_t *)frame->buffer + index);
564                             written_len += write(file_fd, data,
565                                     (size_t)offset.mp[i].width);
566                             index += (uint32_t)offset.mp[i].stride;
567                         }
568                     }
569                     LOGH("written number of bytes %ld\n", written_len);
570                     mDumpFrmCnt++;
571                     frame->cache_flags |= CPU_HAS_READ;
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         //Make sure cache coherence because extra processing is done
2199         mMemory.cleanCache(super_frame->bufs[0]->buf_idx);
2200     }
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           frame->cache_flags |= CPU_HAS_READ;
2227           close(file_fd);
2228        } else {
2229           LOGE("failed to open file to dump image");
2230        }
2231    } else {
2232        LOGE("Could not find stream");
2233    }
2234 
2235 }
2236 
convertLegacyToRaw16(mm_camera_buf_def_t * frame)2237 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2238 {
2239     // Convert image buffer from Opaque raw format to RAW16 format
2240     // 10bit Opaque raw is stored in the format of:
2241     // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2242     // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2243     // 4 bits are 0s. Each 64bit word contains 6 pixels.
2244 
2245   QCamera3Stream *stream = getStreamByIndex(0);
2246   if (stream != NULL) {
2247       cam_dimension_t dim;
2248       memset(&dim, 0, sizeof(dim));
2249       stream->getFrameDimension(dim);
2250 
2251       cam_frame_len_offset_t offset;
2252       memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2253       stream->getFrameOffset(offset);
2254 
2255       uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2256       uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2257 
2258       // In-place format conversion.
2259       // Raw16 format always occupy more memory than opaque raw10.
2260       // Convert to Raw16 by iterating through all pixels from bottom-right
2261       // to top-left of the image.
2262       // One special notes:
2263       // 1. Cross-platform raw16's stride is 16 pixels.
2264       // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2265       for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2266           uint32_t y = (uint32_t)ys;
2267           uint64_t* row_start = (uint64_t *)frame->buffer +
2268                   y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2269           for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2270               uint32_t x = (uint32_t)xs;
2271               uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2272               raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2273           }
2274       }
2275   } else {
2276       LOGE("Could not find stream");
2277   }
2278 
2279 }
2280 
convertMipiToRaw16(mm_camera_buf_def_t * frame)2281 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2282 {
2283     // Convert image buffer from mipi10 raw format to RAW16 format
2284     // mipi10 opaque raw is stored in the format of:
2285     // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2286     // 4 pixels occupy 5 bytes, no padding needed
2287 
2288     QCamera3Stream *stream = getStreamByIndex(0);
2289     if (stream != NULL) {
2290         cam_dimension_t dim;
2291         memset(&dim, 0, sizeof(dim));
2292         stream->getFrameDimension(dim);
2293 
2294         cam_frame_len_offset_t offset;
2295         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2296         stream->getFrameOffset(offset);
2297 
2298         uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2299         uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2300         uint8_t first_quintuple[5];
2301         memcpy(first_quintuple, raw16_buffer, sizeof(first_quintuple));
2302 
2303         // In-place format conversion.
2304         // Raw16 format always occupy more memory than opaque raw10.
2305         // Convert to Raw16 by iterating through all pixels from bottom-right
2306         // to top-left of the image.
2307         // One special notes:
2308         // 1. Cross-platform raw16's stride is 16 pixels.
2309         // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2310         for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2311             uint32_t y = (uint32_t)ys;
2312             uint8_t* row_start = (uint8_t *)frame->buffer +
2313                     y * (uint32_t)offset.mp[0].stride_in_bytes;
2314             for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2315                 uint32_t x = (uint32_t)xs;
2316                 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2317                 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> ((x%4) << 1)) & 0x3);
2318                 uint16_t raw16_pixel =
2319                         (uint16_t)(((uint16_t)upper_8bit)<<2 |
2320                         (uint16_t)lower_2bit);
2321                 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2322             }
2323         }
2324 
2325         // Re-convert the first 2 pixels of the buffer because the loop above messes
2326         // them up by reading the first quintuple while modifying it.
2327         raw16_buffer[0] = ((uint16_t)first_quintuple[0]<<2) | (first_quintuple[4] & 0x3);
2328         raw16_buffer[1] = ((uint16_t)first_quintuple[1]<<2) | ((first_quintuple[4] >> 2) & 0x3);
2329 
2330     } else {
2331         LOGE("Could not find stream");
2332     }
2333 
2334 }
2335 
2336 /*===========================================================================
2337  * FUNCTION   : getReprocessType
2338  *
2339  * DESCRIPTION: get the type of reprocess output supported by this channel
2340  *
2341  * PARAMETERS : NONE
2342  *
2343  * RETURN     : reprocess_type_t : type of reprocess
2344  *==========================================================================*/
getReprocessType()2345 reprocess_type_t QCamera3RawChannel::getReprocessType()
2346 {
2347     return REPROCESS_TYPE_RAW;
2348 }
2349 
2350 
2351 /*************************************************************************************/
2352 // RAW Dump Channel related functions
2353 
2354 /*===========================================================================
2355  * FUNCTION   : QCamera3RawDumpChannel
2356  *
2357  * DESCRIPTION: Constructor for RawDumpChannel
2358  *
2359  * PARAMETERS :
2360  *   @cam_handle    : Handle for Camera
2361  *   @cam_ops       : Function pointer table
2362  *   @rawDumpSize   : Dimensions for the Raw stream
2363  *   @paddinginfo   : Padding information for stream
2364  *   @userData      : Cookie for parent
2365  *   @pp mask       : PP feature mask for this stream
2366  *   @numBuffers    : number of max dequeued buffers
2367  *
2368  * RETURN           : NA
2369  *==========================================================================*/
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)2370 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2371                     uint32_t channel_handle,
2372                     mm_camera_ops_t *cam_ops,
2373                     cam_dimension_t rawDumpSize,
2374                     cam_padding_info_t *paddingInfo,
2375                     void *userData,
2376                     cam_feature_mask_t postprocess_mask, uint32_t numBuffers) :
2377                         QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2378                                 NULL, paddingInfo, postprocess_mask,
2379                                 userData, numBuffers),
2380                         mDim(rawDumpSize),
2381                         mMemory(NULL)
2382 {
2383     char prop[PROPERTY_VALUE_MAX];
2384     property_get("persist.camera.raw.dump", prop, "0");
2385     mRawDump = atoi(prop);
2386 }
2387 
2388 /*===========================================================================
2389  * FUNCTION   : QCamera3RawDumpChannel
2390  *
2391  * DESCRIPTION: Destructor for RawDumpChannel
2392  *
2393  * PARAMETERS :
2394  *
2395  * RETURN           : NA
2396  *==========================================================================*/
2397 
~QCamera3RawDumpChannel()2398 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2399 {
2400     destroy();
2401 }
2402 
2403 /*===========================================================================
2404  * FUNCTION   : dumpRawSnapshot
2405  *
2406  * DESCRIPTION: Helper function to dump Raw frames
2407  *
2408  * PARAMETERS :
2409  *  @frame      : stream buf frame to be dumped
2410  *
2411  *  RETURN      : NA
2412  *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2413 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2414 {
2415     QCamera3Stream *stream = getStreamByIndex(0);
2416     if (stream != NULL) {
2417         char buf[FILENAME_MAX];
2418         struct timeval tv;
2419         struct tm timeinfo_data;
2420         struct tm *timeinfo;
2421 
2422         cam_dimension_t dim;
2423         memset(&dim, 0, sizeof(dim));
2424         stream->getFrameDimension(dim);
2425 
2426         cam_frame_len_offset_t offset;
2427         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2428         stream->getFrameOffset(offset);
2429 
2430         gettimeofday(&tv, NULL);
2431         timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2432 
2433         if (NULL != timeinfo) {
2434             memset(buf, 0, sizeof(buf));
2435             /* Consistent naming for Jpeg+meta+raw: Raw name */
2436             snprintf(buf, sizeof(buf),
2437                     QCAMERA_DUMP_FRM_LOCATION
2438                     "IMG_%04d%02d%02d_%02d%02d%02d_%dx%d.raw",
2439                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2440                     timeinfo->tm_mday, timeinfo->tm_hour,
2441                     timeinfo->tm_min, timeinfo->tm_sec,
2442                     dim.width, dim.height);
2443             /* Consistent naming for Jpeg+meta+raw: Raw name end*/
2444             int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2445             if (file_fd >= 0) {
2446                 ssize_t written_len =
2447                         write(file_fd, frame->buffer, offset.frame_len);
2448                 LOGD("written number of bytes %zd", written_len);
2449                 frame->cache_flags |= CPU_HAS_READ;
2450                 close(file_fd);
2451             } else {
2452                 LOGE("failed to open file to dump image");
2453             }
2454         } else {
2455             LOGE("localtime_r() error");
2456         }
2457     } else {
2458         LOGE("Could not find stream");
2459     }
2460 
2461 }
2462 
2463 /*===========================================================================
2464  * FUNCTION   : streamCbRoutine
2465  *
2466  * DESCRIPTION: Callback routine invoked for each frame generated for
2467  *              Rawdump channel
2468  *
2469  * PARAMETERS :
2470  *   @super_frame  : stream buf frame generated
2471  *   @stream       : Underlying Stream object cookie
2472  *
2473  * RETURN          : NA
2474  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,__unused QCamera3Stream * stream)2475 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2476                                                 __unused QCamera3Stream *stream)
2477 {
2478     LOGD("E");
2479     if (super_frame == NULL || super_frame->num_bufs != 1) {
2480         LOGE("super_frame is not valid");
2481         return;
2482     }
2483 
2484     if (mRawDump)
2485         dumpRawSnapshot(super_frame->bufs[0]);
2486 
2487     bufDone(super_frame);
2488     free(super_frame);
2489 }
2490 
2491 /*===========================================================================
2492  * FUNCTION   : getStreamBufs
2493  *
2494  * DESCRIPTION: Callback function provided to interface to get buffers.
2495  *
2496  * PARAMETERS :
2497  *   @len       : Length of each buffer to be allocated
2498  *
2499  * RETURN     : NULL on buffer allocation failure
2500  *              QCamera3StreamMem object on sucess
2501  *==========================================================================*/
getStreamBufs(uint32_t len)2502 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2503 {
2504     int rc;
2505     mMemory = new QCamera3StreamMem(mNumBuffers);
2506 
2507     if (!mMemory) {
2508         LOGE("unable to create heap memory");
2509         return NULL;
2510     }
2511     rc = mMemory->allocateAll((size_t)len);
2512     if (rc < 0) {
2513         LOGE("unable to allocate heap memory");
2514         delete mMemory;
2515         mMemory = NULL;
2516         return NULL;
2517     }
2518     return mMemory;
2519 }
2520 
2521 /*===========================================================================
2522  * FUNCTION   : putStreamBufs
2523  *
2524  * DESCRIPTION: Callback function provided to interface to return buffers.
2525  *              Although no handles are actually returned, implicitl assumption
2526  *              that interface will no longer use buffers and channel can
2527  *              deallocated if necessary.
2528  *
2529  * PARAMETERS : NA
2530  *
2531  * RETURN     : NA
2532  *==========================================================================*/
putStreamBufs()2533 void QCamera3RawDumpChannel::putStreamBufs()
2534 {
2535     mMemory->deallocate();
2536     delete mMemory;
2537     mMemory = NULL;
2538 }
2539 
2540 /*===========================================================================
2541  * FUNCTION : request
2542  *
2543  * DESCRIPTION: Request function used as trigger
2544  *
2545  * PARAMETERS :
2546  * @recvd_frame : buffer- this will be NULL since this is internal channel
2547  * @frameNumber : Undefined again since this is internal stream
2548  *
2549  * RETURN     : int32_t type of status
2550  *              NO_ERROR  -- success
2551  *              none-zero failure code
2552  *==========================================================================*/
request(buffer_handle_t *,uint32_t,int &)2553 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2554                                                 uint32_t /*frameNumber*/,
2555                                                 int & /*indexUsed*/)
2556 {
2557     if (!m_bIsActive) {
2558         return QCamera3Channel::start();
2559     }
2560     else
2561         return 0;
2562 }
2563 
2564 /*===========================================================================
2565  * FUNCTION : intialize
2566  *
2567  * DESCRIPTION: Initializes channel params and creates underlying stream
2568  *
2569  * PARAMETERS :
2570  *    @isType : type of image stabilization required on this stream
2571  *
2572  * RETURN     : int32_t type of status
2573  *              NO_ERROR  -- success
2574  *              none-zero failure code
2575  *==========================================================================*/
initialize(cam_is_type_t isType)2576 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2577 {
2578     int32_t rc;
2579 
2580     mIsType = isType;
2581     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2582         CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2583         mPostProcMask, mIsType);
2584     if (rc < 0) {
2585         LOGE("addStream failed");
2586     }
2587     return rc;
2588 }
2589 /*************************************************************************************/
2590 
2591 /* QCamera3YUVChannel methods */
2592 
2593 /*===========================================================================
2594  * FUNCTION   : QCamera3YUVChannel
2595  *
2596  * DESCRIPTION: constructor of QCamera3YUVChannel
2597  *
2598  * PARAMETERS :
2599  *   @cam_handle : camera handle
2600  *   @cam_ops    : ptr to camera ops table
2601  *   @cb_routine : callback routine to frame aggregator
2602  *   @paddingInfo : padding information for the stream
2603  *   @stream     : camera3_stream_t structure
2604  *   @stream_type: Channel stream type
2605  *   @postprocess_mask: the postprocess mask for streams of this channel
2606  *   @metadataChannel: handle to the metadataChannel
2607  * RETURN     : none
2608  *==========================================================================*/
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)2609 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2610         uint32_t channel_handle,
2611         mm_camera_ops_t *cam_ops,
2612         channel_cb_routine cb_routine,
2613         channel_cb_buffer_err cb_buf_err,
2614         cam_padding_info_t *paddingInfo,
2615         void *userData,
2616         camera3_stream_t *stream,
2617         cam_stream_type_t stream_type,
2618         cam_feature_mask_t postprocess_mask,
2619         QCamera3Channel *metadataChannel) :
2620             QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2621                     cb_routine, cb_buf_err, paddingInfo, userData, stream, stream_type,
2622                     postprocess_mask, metadataChannel)
2623 {
2624 
2625     mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2626     mFrameLen = 0;
2627     mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2628     mEdgeMode.sharpness = 0;
2629     mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2630     memset(&mCropRegion, 0, sizeof(mCropRegion));
2631 }
2632 
2633 /*===========================================================================
2634  * FUNCTION   : ~QCamera3YUVChannel
2635  *
2636  * DESCRIPTION: destructor of QCamera3YUVChannel
2637  *
2638  * PARAMETERS : none
2639  *
2640  *
2641  * RETURN     : none
2642  *==========================================================================*/
~QCamera3YUVChannel()2643 QCamera3YUVChannel::~QCamera3YUVChannel()
2644 {
2645    // Deallocation of heap buffers allocated in mMemory is freed
2646    // automatically by its destructor
2647 }
2648 
2649 /*===========================================================================
2650  * FUNCTION   : initialize
2651  *
2652  * DESCRIPTION: Initialize and add camera channel & stream
2653  *
2654  * PARAMETERS :
2655  * @isType    : the image stabilization type
2656  *
2657  * RETURN     : int32_t type of status
2658  *              NO_ERROR  -- success
2659  *              none-zero failure code
2660  *==========================================================================*/
initialize(cam_is_type_t isType)2661 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2662 {
2663     ATRACE_CALL();
2664     int32_t rc = NO_ERROR;
2665     cam_dimension_t streamDim;
2666 
2667     if (NULL == mCamera3Stream) {
2668         LOGE("Camera stream uninitialized");
2669         return NO_INIT;
2670     }
2671 
2672     if (1 <= m_numStreams) {
2673         // Only one stream per channel supported in v3 Hal
2674         return NO_ERROR;
2675     }
2676 
2677     mIsType  = isType;
2678     mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
2679             mCamera3Stream->width, mCamera3Stream->height);
2680     streamDim.width = mCamera3Stream->width;
2681     streamDim.height = mCamera3Stream->height;
2682 
2683     rc = QCamera3Channel::addStream(mStreamType,
2684             mStreamFormat,
2685             streamDim,
2686             ROTATE_0,
2687             mNumBufs,
2688             mPostProcMask,
2689             mIsType);
2690     if (rc < 0) {
2691         LOGE("addStream failed");
2692         return rc;
2693     }
2694 
2695     cam_stream_buf_plane_info_t buf_planes;
2696     cam_padding_info_t paddingInfo = mPaddingInfo;
2697 
2698     memset(&buf_planes, 0, sizeof(buf_planes));
2699     //to ensure a big enough buffer size set the height and width
2700     //padding to max(height padding, width padding)
2701     paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2702     paddingInfo.height_padding = paddingInfo.width_padding;
2703 
2704     rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2705             &buf_planes);
2706     if (rc < 0) {
2707         LOGE("mm_stream_calc_offset_preview failed");
2708         return rc;
2709     }
2710 
2711     mFrameLen = buf_planes.plane_info.frame_len;
2712 
2713     if (NO_ERROR != rc) {
2714         LOGE("Initialize failed, rc = %d", rc);
2715         return rc;
2716     }
2717 
2718     /* initialize offline meta memory for input reprocess */
2719     rc = QCamera3ProcessingChannel::initialize(isType);
2720     if (NO_ERROR != rc) {
2721         LOGE("Processing Channel initialize failed, rc = %d",
2722                  rc);
2723     }
2724 
2725     return rc;
2726 }
2727 
2728 /*===========================================================================
2729  * FUNCTION   : request
2730  *
2731  * DESCRIPTION: entry function for a request on a YUV stream. This function
2732  *              has the logic to service a request based on its type
2733  *
2734  * PARAMETERS :
2735  * @buffer          : pointer to the output buffer
2736  * @frameNumber     : frame number of the request
2737  * @pInputBuffer    : pointer to input buffer if an input request
2738  * @metadata        : parameters associated with the request
2739  *
2740  * RETURN     : 0 on a success start of capture
2741  *              -EINVAL on invalid input
2742  *              -ENODEV on serious error
2743  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata,int & indexUsed)2744 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2745         uint32_t frameNumber,
2746         camera3_stream_buffer_t* pInputBuffer,
2747         metadata_buffer_t* metadata, bool &needMetadata,
2748         int &indexUsed)
2749 {
2750     int32_t rc = NO_ERROR;
2751     Mutex::Autolock lock(mOfflinePpLock);
2752 
2753     LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2754     if (NULL == buffer || NULL == metadata) {
2755         LOGE("Invalid buffer/metadata in channel request");
2756         return BAD_VALUE;
2757     }
2758 
2759     PpInfo ppInfo;
2760     memset(&ppInfo, 0, sizeof(ppInfo));
2761     ppInfo.frameNumber = frameNumber;
2762     ppInfo.offlinePpFlag = false;
2763     if (mBypass && !pInputBuffer ) {
2764         ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2765         ppInfo.output = buffer;
2766         mOfflinePpInfoList.push_back(ppInfo);
2767     }
2768 
2769     LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2770     needMetadata = ppInfo.offlinePpFlag;
2771     if (!ppInfo.offlinePpFlag) {
2772         // regular request
2773         return QCamera3ProcessingChannel::request(buffer, frameNumber,
2774                 pInputBuffer, metadata, indexUsed);
2775     } else {
2776         if(!m_bIsActive) {
2777             rc = start();
2778             if (NO_ERROR != rc)
2779                 return rc;
2780         } else {
2781             LOGD("Request on an existing stream");
2782         }
2783 
2784         //we need to send this frame through the CPP
2785         //Allocate heap memory, then buf done on the buffer
2786         uint32_t bufIdx;
2787         if (mFreeHeapBufferList.empty()) {
2788             rc = mMemory.allocateOne(mFrameLen);
2789             if (rc < 0) {
2790                 LOGE("Failed allocating heap buffer. Fatal");
2791                 return BAD_VALUE;
2792             } else {
2793                 bufIdx = (uint32_t)rc;
2794             }
2795         } else {
2796             bufIdx = *(mFreeHeapBufferList.begin());
2797             mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2798         }
2799 
2800         /* Configure and start postproc if necessary */
2801         reprocess_config_t reproc_cfg;
2802         cam_dimension_t dim;
2803         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2804         memset(&dim, 0, sizeof(dim));
2805         mStreams[0]->getFrameDimension(dim);
2806         setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2807 
2808         // Start postprocessor without input buffer
2809         startPostProc(reproc_cfg);
2810 
2811         LOGD("erasing %d", bufIdx);
2812 
2813         mMemory.markFrameNumber(bufIdx, frameNumber);
2814         indexUsed = bufIdx;
2815         mStreams[0]->bufDone(bufIdx);
2816 
2817     }
2818     return rc;
2819 }
2820 
2821 /*===========================================================================
2822  * FUNCTION   : streamCbRoutine
2823  *
2824  * DESCRIPTION:
2825  *
2826  * PARAMETERS :
2827  * @super_frame : the super frame with filled buffer
2828  * @stream      : stream on which the buffer was requested and filled
2829  *
2830  * RETURN     : none
2831  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2832 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2833         QCamera3Stream *stream)
2834 {
2835     ATRACE_CALL();
2836     uint8_t frameIndex;
2837     int32_t resultFrameNumber;
2838 
2839     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2840         LOGE("Error with the stream callback");
2841         return;
2842     }
2843 
2844     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2845     if(frameIndex >= mNumBufs) {
2846          LOGE("Error, Invalid index for buffer");
2847          stream->bufDone(frameIndex);
2848          return;
2849     }
2850 
2851     if (mBypass) {
2852         {
2853             List<PpInfo>::iterator ppInfo;
2854 
2855             Mutex::Autolock lock(mOfflinePpLock);
2856             resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2857             for (ppInfo = mOfflinePpInfoList.begin();
2858                     ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2859                 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2860                     break;
2861                 }
2862             }
2863             LOGD("frame index %d, frame number %d", frameIndex,
2864                     resultFrameNumber);
2865             //check the reprocessing required flag against the frame number
2866             if (ppInfo == mOfflinePpInfoList.end()) {
2867                 LOGE("Error, request for frame number is a reprocess.");
2868                 stream->bufDone(frameIndex);
2869                 return;
2870             }
2871 
2872             if (ppInfo->offlinePpFlag) {
2873                 mm_camera_super_buf_t *frame =
2874                         (mm_camera_super_buf_t *)malloc(sizeof(
2875                                 mm_camera_super_buf_t));
2876                 if (frame == NULL) {
2877                     LOGE("Error allocating memory to save received_frame structure.");
2878                     if(stream) {
2879                         stream->bufDone(frameIndex);
2880                     }
2881                     return;
2882                 }
2883 
2884                 *frame = *super_frame;
2885                 m_postprocessor.processData(frame, ppInfo->output,
2886                         resultFrameNumber);
2887                 free(super_frame);
2888                 return;
2889             } else {
2890                 if (ppInfo != mOfflinePpInfoList.begin()) {
2891                     // There is pending reprocess buffer, cache current buffer
2892                     if (ppInfo->callback_buffer != NULL) {
2893                         LOGE("Fatal: cached callback_buffer is already present");
2894                     }
2895                     ppInfo->callback_buffer = super_frame;
2896                     return;
2897                 } else {
2898                     mOfflinePpInfoList.erase(ppInfo);
2899                 }
2900             }
2901         }
2902 
2903         if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
2904             mChannelCbBufErr(this, resultFrameNumber,
2905                             CAMERA3_BUFFER_STATUS_ERROR, mUserData);
2906         }
2907 
2908     }
2909 
2910     QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2911 
2912     /* return any pending buffers that were received out of order earlier */
2913     while((super_frame = getNextPendingCbBuffer())) {
2914         QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2915     }
2916 
2917     return;
2918 }
2919 
2920 /*===========================================================================
2921  * FUNCTION   : getNextPendingCbBuffer
2922  *
2923  * DESCRIPTION: Returns the callback_buffer from the first entry of
2924  *              mOfflinePpInfoList
2925  *
2926  * PARAMETERS : none
2927  *
2928  * RETURN     : callback_buffer
2929  *==========================================================================*/
getNextPendingCbBuffer()2930 mm_camera_super_buf_t* QCamera3YUVChannel::getNextPendingCbBuffer() {
2931     mm_camera_super_buf_t* super_frame = NULL;
2932     if (mOfflinePpInfoList.size()) {
2933         if ((super_frame = mOfflinePpInfoList.begin()->callback_buffer)) {
2934             mOfflinePpInfoList.erase(mOfflinePpInfoList.begin());
2935         }
2936     }
2937     return super_frame;
2938 }
2939 
2940 /*===========================================================================
2941  * FUNCTION   : reprocessCbRoutine
2942  *
2943  * DESCRIPTION: callback function for the reprocessed frame. This frame now
2944  *              should be returned to the framework. This same callback is
2945  *              used during input reprocessing or offline postprocessing
2946  *
2947  * PARAMETERS :
2948  * @resultBuffer      : buffer containing the reprocessed data
2949  * @resultFrameNumber : frame number on which the buffer was requested
2950  *
2951  * RETURN     : NONE
2952  *
2953  *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2954 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2955         uint32_t resultFrameNumber)
2956 {
2957     LOGD("E: frame number %d", resultFrameNumber);
2958     Vector<mm_camera_super_buf_t *> pendingCbs;
2959 
2960     /* release the input buffer and input metadata buffer if used */
2961     if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2962         /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2963         int32_t rc = releaseOfflineMemory(resultFrameNumber);
2964         if (NO_ERROR != rc) {
2965             LOGE("Error releasing offline memory rc = %d", rc);
2966         }
2967         /* Since reprocessing is done, send the callback to release the input buffer */
2968         if (mChannelCB) {
2969             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2970         }
2971     }
2972 
2973     if (mBypass) {
2974         int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2975         if (rc != NO_ERROR) {
2976             return;
2977         }
2978     }
2979 
2980     issueChannelCb(resultBuffer, resultFrameNumber);
2981 
2982     // Call all pending callbacks to return buffers
2983     for (size_t i = 0; i < pendingCbs.size(); i++) {
2984         QCamera3ProcessingChannel::streamCbRoutine(
2985                 pendingCbs[i], mStreams[0]);
2986     }
2987 
2988 }
2989 
2990 /*===========================================================================
2991  * FUNCTION   : needsFramePostprocessing
2992  *
2993  * DESCRIPTION:
2994  *
2995  * PARAMETERS :
2996  *
2997  * RETURN     :
2998  *  TRUE if frame needs to be postprocessed
2999  *  FALSE is frame does not need to be postprocessed
3000  *
3001  *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)3002 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
3003 {
3004     bool ppNeeded = false;
3005 
3006     //sharpness
3007     IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
3008             CAM_INTF_META_EDGE_MODE, meta) {
3009         mEdgeMode = *edgeMode;
3010     }
3011 
3012     //wnr
3013     IF_META_AVAILABLE(uint32_t, noiseRedMode,
3014             CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
3015         mNoiseRedMode = *noiseRedMode;
3016     }
3017 
3018     //crop region
3019     IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
3020             CAM_INTF_META_SCALER_CROP_REGION, meta) {
3021         mCropRegion = *scalerCropRegion;
3022     }
3023 
3024     if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
3025             (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
3026         ppNeeded = true;
3027     }
3028     if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
3029             (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
3030             (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
3031         ppNeeded = true;
3032     }
3033     if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
3034             (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
3035         ppNeeded = true;
3036     }
3037 
3038     return ppNeeded;
3039 }
3040 
3041 /*===========================================================================
3042  * FUNCTION   : handleOfflinePpCallback
3043  *
3044  * DESCRIPTION: callback function for the reprocessed frame from offline
3045  *              postprocessing.
3046  *
3047  * PARAMETERS :
3048  * @resultFrameNumber : frame number on which the buffer was requested
3049  * @pendingCbs        : pending buffers to be returned first
3050  *
3051  * RETURN     : int32_t type of status
3052  *              NO_ERROR  -- success
3053  *              none-zero failure code
3054  *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)3055 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
3056             Vector<mm_camera_super_buf_t *>& pendingCbs)
3057 {
3058     Mutex::Autolock lock(mOfflinePpLock);
3059     List<PpInfo>::iterator ppInfo;
3060 
3061     for (ppInfo = mOfflinePpInfoList.begin();
3062             ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
3063         if (ppInfo->frameNumber == resultFrameNumber) {
3064             break;
3065         }
3066     }
3067 
3068     if (ppInfo == mOfflinePpInfoList.end()) {
3069         LOGI("Request of frame number %d is reprocessing",
3070                  resultFrameNumber);
3071         return NO_ERROR;
3072     } else if (ppInfo != mOfflinePpInfoList.begin()) {
3073         LOGE("callback for frame number %d should be head of list",
3074                  resultFrameNumber);
3075         return BAD_VALUE;
3076     }
3077 
3078     if (ppInfo->offlinePpFlag) {
3079         // Need to get the input buffer frame index from the
3080         // mMemory object and add that to the free heap buffers list.
3081         int32_t bufferIndex =
3082                 mMemory.getHeapBufferIndex(resultFrameNumber);
3083         if (bufferIndex < 0) {
3084             LOGE("Fatal %d: no buffer index for frame number %d",
3085                      bufferIndex, resultFrameNumber);
3086             return BAD_VALUE;
3087         }
3088         mMemory.markFrameNumber(bufferIndex, -1);
3089         mFreeHeapBufferList.push_back(bufferIndex);
3090         //Move heap buffer into free pool and invalidate the frame number
3091         ppInfo = mOfflinePpInfoList.erase(ppInfo);
3092 
3093         /* return any pending buffers that were received out of order
3094             earlier */
3095         mm_camera_super_buf_t* super_frame;
3096         while((super_frame = getNextPendingCbBuffer())) {
3097             pendingCbs.push_back(super_frame);
3098         }
3099     } else {
3100         LOGE("Fatal: request of frame number %d doesn't need"
3101                 " offline postprocessing. However there is"
3102                 " reprocessing callback.",
3103                 resultFrameNumber);
3104         return BAD_VALUE;
3105     }
3106 
3107     return NO_ERROR;
3108 }
3109 
3110 /*===========================================================================
3111  * FUNCTION   : getReprocessType
3112  *
3113  * DESCRIPTION: get the type of reprocess output supported by this channel
3114  *
3115  * PARAMETERS : NONE
3116  *
3117  * RETURN     : reprocess_type_t : type of reprocess
3118  *==========================================================================*/
getReprocessType()3119 reprocess_type_t QCamera3YUVChannel::getReprocessType()
3120 {
3121     return REPROCESS_TYPE_YUV;
3122 }
3123 
3124 /* QCamera3PicChannel methods */
3125 
3126 /*===========================================================================
3127  * FUNCTION   : jpegEvtHandle
3128  *
3129  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
3130                 Construct result payload and call mChannelCb to deliver buffer
3131                 to framework.
3132  *
3133  * PARAMETERS :
3134  *   @status    : status of jpeg job
3135  *   @client_hdl: jpeg client handle
3136  *   @jobId     : jpeg job Id
3137  *   @p_ouput   : ptr to jpeg output result struct
3138  *   @userdata  : user data ptr
3139  *
3140  * RETURN     : none
3141  *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)3142 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
3143                                               uint32_t /*client_hdl*/,
3144                                               uint32_t jobId,
3145                                               mm_jpeg_output_t *p_output,
3146                                               void *userdata)
3147 {
3148     ATRACE_CALL();
3149     buffer_handle_t *resultBuffer = NULL;
3150     buffer_handle_t *jpegBufferHandle = NULL;
3151     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
3152     camera3_stream_buffer_t result;
3153     camera3_jpeg_blob_t jpegHeader;
3154 
3155     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
3156     if (obj) {
3157         //Construct payload for process_capture_result. Call mChannelCb
3158 
3159         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
3160 
3161         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
3162             LOGE("Error in jobId: (%d) with status: %d", jobId, status);
3163             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3164         }
3165 
3166         if (NULL != job) {
3167             uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
3168             LOGD("jpeg out_buf_index: %d", bufIdx);
3169 
3170             //Construct jpeg transient header of type camera3_jpeg_blob_t
3171             //Append at the end of jpeg image of buf_filled_len size
3172 
3173             jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3174             if (JPEG_JOB_STATUS_DONE == status) {
3175                 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3176                 char* jpeg_buf = (char *)p_output->buf_vaddr;
3177 
3178                 ssize_t maxJpegSize = -1;
3179 
3180                 // Gralloc buffer may have additional padding for 4K page size
3181                 // Follow size guidelines based on spec since framework relies
3182                 // on that to reach end of buffer and with it the header
3183 
3184                 //Handle same as resultBuffer, but for readablity
3185                 jpegBufferHandle =
3186                         (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3187 
3188                 if (NULL != jpegBufferHandle) {
3189                     maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3190                     if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3191                         maxJpegSize = obj->mMemory.getSize(bufIdx);
3192                     }
3193 
3194                     size_t jpeg_eof_offset =
3195                             (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3196                     char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3197                     memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3198                     obj->mMemory.cleanInvalidateCache(bufIdx);
3199                     bool jpegDump = false;
3200                     char prop[PROPERTY_VALUE_MAX];
3201                     property_get("persist.camera.jpeg.dump", prop, "0");
3202                     jpegDump = atoi(prop);
3203                     if (jpegDump) {
3204                         char buf[FILENAME_MAX];
3205                         char timeBuf[FILENAME_MAX];
3206                         memset(buf, 0, sizeof(buf));
3207                         memset(timeBuf, 0, sizeof(timeBuf));
3208                         time_t current_time;
3209                         struct tm * timeinfo;
3210                         time (&current_time);
3211                         timeinfo = localtime (&current_time);
3212                         if (timeinfo != NULL) {
3213                             /* Consistent naming for Jpeg+meta+raw: meta name */
3214                             strftime (timeBuf, sizeof(timeBuf),
3215                                     QCAMERA_DUMP_FRM_LOCATION"IMG_%Y%m%d_%H%M%S", timeinfo);
3216                             /* Consistent naming for Jpeg+meta+raw: meta name end*/
3217                         }
3218                         String8 filePath(timeBuf);
3219                         snprintf(buf, sizeof(buf), "_%d.jpg",
3220                                 obj->mMemory.getFrameNumber(bufIdx));
3221                         filePath.append(buf);
3222                         int file_fd = open(filePath.string(), O_RDWR | O_CREAT, 0777);
3223                         ssize_t written_len = 0;
3224                         if (file_fd >= 0) {
3225                             fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
3226                             written_len += write(file_fd, jpeg_buf,
3227                                     (size_t)maxJpegSize);
3228                             LOGI("written number of bytes %ld attempted: %ld\n", written_len,
3229                                 maxJpegSize);
3230                             close(file_fd);
3231                         } else {
3232                             LOGE("failed to open file to dump image");
3233                         }
3234 
3235                     }
3236                 } else {
3237                     LOGE("JPEG buffer not found and index: %d",
3238                             bufIdx);
3239                     resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3240                 }
3241             }
3242 
3243             ////Use below data to issue framework callback
3244             resultBuffer =
3245                     (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3246             int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3247             int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3248             if (NO_ERROR != rc) {
3249                 LOGE("Error %d unregistering stream buffer %d",
3250                      rc, bufIdx);
3251             }
3252 
3253             result.stream = obj->mCamera3Stream;
3254             result.buffer = resultBuffer;
3255             result.status = resultStatus;
3256             result.acquire_fence = -1;
3257             result.release_fence = -1;
3258 
3259             // Release any snapshot buffers before calling
3260             // the user callback. The callback can potentially
3261             // unblock pending requests to snapshot stream.
3262             int32_t snapshotIdx = -1;
3263             mm_camera_super_buf_t* src_frame = NULL;
3264 
3265             if (job->src_reproc_frame)
3266                 src_frame = job->src_reproc_frame;
3267             else
3268                 src_frame = job->src_frame;
3269 
3270             if (src_frame) {
3271                 if (obj->mStreams[0]->getMyHandle() ==
3272                         src_frame->bufs[0]->stream_id) {
3273                     snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
3274                     if (0 <= snapshotIdx) {
3275                         Mutex::Autolock lock(obj->mFreeBuffersLock);
3276                         obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3277                     }
3278                 }
3279             }
3280 
3281             LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3282                     resultFrameNumber, resultStatus);
3283             KPI_ATRACE_ASYNC_END("SNAPSHOT", resultFrameNumber);
3284             if (obj->mChannelCB) {
3285                 obj->mChannelCB(NULL,
3286                         &result,
3287                         (uint32_t)resultFrameNumber,
3288                         false,
3289                         obj->mUserData);
3290             }
3291 
3292             // release internal data for jpeg job
3293             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3294                 /* unregister offline input buffer */
3295                 int32_t inputBufIndex =
3296                         obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3297                 if (0 <= inputBufIndex) {
3298                     rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3299                 } else {
3300                     LOGE("could not find the input buf index, frame number %d",
3301                              resultFrameNumber);
3302                 }
3303                 if (NO_ERROR != rc) {
3304                     LOGE("Error %d unregistering input buffer %d",
3305                              rc, bufIdx);
3306                 }
3307 
3308                 /* unregister offline meta buffer */
3309                 int32_t metaBufIndex =
3310                         obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3311                 if (0 <= metaBufIndex) {
3312                     Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3313                     obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3314                 } else {
3315                     LOGE("could not find the input meta buf index, frame number %d",
3316                              resultFrameNumber);
3317                 }
3318             }
3319             obj->m_postprocessor.releaseOfflineBuffers(false);
3320             obj->m_postprocessor.releaseJpegJobData(job);
3321             free(job);
3322         }
3323 
3324         obj->resetCppPerfParam();
3325         return;
3326         // }
3327     } else {
3328         LOGE("Null userdata in jpeg callback");
3329     }
3330 }
3331 
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)3332 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3333                     uint32_t channel_handle,
3334                     mm_camera_ops_t *cam_ops,
3335                     channel_cb_routine cb_routine,
3336                     channel_cb_buffer_err cb_buf_err,
3337                     cam_padding_info_t *paddingInfo,
3338                     void *userData,
3339                     camera3_stream_t *stream,
3340                     cam_feature_mask_t postprocess_mask,
3341                     __unused bool is4KVideo,
3342                     bool isInputStreamConfigured,
3343                     QCamera3Channel *metadataChannel,
3344                     uint32_t numBuffers) :
3345                         QCamera3ProcessingChannel(cam_handle, channel_handle,
3346                                 cam_ops, cb_routine, cb_buf_err, paddingInfo, userData,
3347                                 stream, CAM_STREAM_TYPE_SNAPSHOT,
3348                                 postprocess_mask, metadataChannel, numBuffers),
3349                         mNumSnapshotBufs(0),
3350                         mInputBufferHint(isInputStreamConfigured),
3351                         mYuvMemory(NULL),
3352                         mFrameLen(0)
3353 {
3354     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3355     m_max_pic_dim = hal_obj->calcMaxJpegDim();
3356     mYuvWidth = stream->width;
3357     mYuvHeight = stream->height;
3358     mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3359     mPendingLiveSnapshotFrames = 0;
3360     // Use same pixelformat for 4K video case
3361     mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
3362             stream->width, stream->height);
3363     int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3364     if (rc != 0) {
3365         LOGE("Init Postprocessor failed");
3366     }
3367 }
3368 
3369 /*===========================================================================
3370  * FUNCTION   : flush
3371  *
3372  * DESCRIPTION: flush pic channel, which will stop all processing within, including
3373  *              the reprocessing channel in postprocessor and YUV stream.
3374  *
3375  * PARAMETERS : none
3376  *
3377  * RETURN     : int32_t type of status
3378  *              NO_ERROR  -- success
3379  *              none-zero failure code
3380  *==========================================================================*/
flush()3381 int32_t QCamera3PicChannel::flush()
3382 {
3383     int32_t rc = NO_ERROR;
3384     if(!m_bIsActive) {
3385         LOGE("Attempt to flush inactive channel");
3386         return NO_INIT;
3387     }
3388 
3389     rc = m_postprocessor.flush();
3390     if (rc == 0) {
3391         LOGE("Postprocessor flush failed, rc = %d", rc);
3392         return rc;
3393     }
3394 
3395     if (0 < mOfflineMetaMemory.getCnt()) {
3396         mOfflineMetaMemory.deallocate();
3397     }
3398     if (0 < mOfflineMemory.getCnt()) {
3399         mOfflineMemory.unregisterBuffers();
3400     }
3401     Mutex::Autolock lock(mFreeBuffersLock);
3402     mFreeBufferList.clear();
3403     for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3404         mFreeBufferList.push_back(i);
3405     }
3406     return rc;
3407 }
3408 
3409 
~QCamera3PicChannel()3410 QCamera3PicChannel::~QCamera3PicChannel()
3411 {
3412 }
3413 
initialize(cam_is_type_t isType)3414 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3415 {
3416     int32_t rc = NO_ERROR;
3417     cam_dimension_t streamDim;
3418     cam_stream_type_t streamType;
3419     cam_format_t streamFormat;
3420 
3421     if (NULL == mCamera3Stream) {
3422         LOGE("Camera stream uninitialized");
3423         return NO_INIT;
3424     }
3425 
3426     if (1 <= m_numStreams) {
3427         // Only one stream per channel supported in v3 Hal
3428         return NO_ERROR;
3429     }
3430 
3431     mIsType = isType;
3432     streamType = mStreamType;
3433     streamFormat = mStreamFormat;
3434     streamDim.width = (int32_t)mYuvWidth;
3435     streamDim.height = (int32_t)mYuvHeight;
3436 
3437     mNumSnapshotBufs = mCamera3Stream->max_buffers;
3438     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3439             ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3440             mIsType);
3441 
3442     if (NO_ERROR != rc) {
3443         LOGE("Initialize failed, rc = %d", rc);
3444         return rc;
3445     }
3446 
3447     /* initialize offline meta memory for input reprocess */
3448     rc = QCamera3ProcessingChannel::initialize(isType);
3449     if (NO_ERROR != rc) {
3450         LOGE("Processing Channel initialize failed, rc = %d",
3451                  rc);
3452     }
3453 
3454     return rc;
3455 }
3456 
3457 /*===========================================================================
3458  * FUNCTION   : request
3459  *
3460  * DESCRIPTION: handle the request - either with an input buffer or a direct
3461  *              output request
3462  *
3463  * PARAMETERS :
3464  * @buffer       : pointer to the output buffer
3465  * @frameNumber  : frame number of the request
3466  * @pInputBuffer : pointer to input buffer if an input request
3467  * @metadata     : parameters associated with the request
3468  *
3469  * RETURN     : 0 on a success start of capture
3470  *              -EINVAL on invalid input
3471  *              -ENODEV on serious error
3472  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,int & indexUsed)3473 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3474         uint32_t frameNumber,
3475         camera3_stream_buffer_t *pInputBuffer,
3476         metadata_buffer_t *metadata, int &indexUsed)
3477 {
3478     ATRACE_CALL();
3479     //FIX ME: Return buffer back in case of failures below.
3480 
3481     int32_t rc = NO_ERROR;
3482 
3483     reprocess_config_t reproc_cfg;
3484     cam_dimension_t dim;
3485     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3486     //make sure to set the correct input stream dim in case of YUV size override
3487     //and recalculate the plane info
3488     dim.width = (int32_t)mYuvWidth;
3489     dim.height = (int32_t)mYuvHeight;
3490     setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3491 
3492     // Picture stream has already been started before any request comes in
3493     if (!m_bIsActive) {
3494         LOGE("Channel not started!!");
3495         return NO_INIT;
3496     }
3497 
3498     int index = mMemory.getMatchBufIndex((void*)buffer);
3499 
3500     if(index < 0) {
3501         rc = registerBuffer(buffer, mIsType);
3502         if (NO_ERROR != rc) {
3503             LOGE("On-the-fly buffer registration failed %d",
3504                      rc);
3505             return rc;
3506         }
3507 
3508         index = mMemory.getMatchBufIndex((void*)buffer);
3509         if (index < 0) {
3510             LOGE("Could not find object among registered buffers");
3511             return DEAD_OBJECT;
3512         }
3513     }
3514     LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3515 
3516     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3517 
3518     // Start postprocessor
3519     startPostProc(reproc_cfg);
3520 
3521     // Only set the perf mode for online cpp processing
3522     if (reproc_cfg.reprocess_type == REPROCESS_TYPE_NONE) {
3523         setCppPerfParam();
3524     }
3525 
3526     // Queue jpeg settings
3527     rc = queueJpegSetting((uint32_t)index, metadata);
3528 
3529     if (pInputBuffer == NULL) {
3530         Mutex::Autolock lock(mFreeBuffersLock);
3531         uint32_t bufIdx;
3532         if (mFreeBufferList.empty()) {
3533             rc = mYuvMemory->allocateOne(mFrameLen);
3534             if (rc < 0) {
3535                 LOGE("Failed to allocate heap buffer. Fatal");
3536                 return rc;
3537             } else {
3538                 bufIdx = (uint32_t)rc;
3539             }
3540         } else {
3541             List<uint32_t>::iterator it = mFreeBufferList.begin();
3542             bufIdx = *it;
3543             mFreeBufferList.erase(it);
3544         }
3545         mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3546         mStreams[0]->bufDone(bufIdx);
3547         indexUsed = bufIdx;
3548     } else {
3549         qcamera_fwk_input_pp_data_t *src_frame = NULL;
3550         src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3551                 sizeof(qcamera_fwk_input_pp_data_t));
3552         if (src_frame == NULL) {
3553             LOGE("No memory for src frame");
3554             return NO_MEMORY;
3555         }
3556         rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3557                 NULL /*fwk output buffer*/, frameNumber);
3558         if (NO_ERROR != rc) {
3559             LOGE("Error %d while setting framework input PP data", rc);
3560             free(src_frame);
3561             return rc;
3562         }
3563         LOGH("Post-process started");
3564         m_postprocessor.processData(src_frame);
3565     }
3566     return rc;
3567 }
3568 
3569 
3570 
3571 /*===========================================================================
3572  * FUNCTION   : dataNotifyCB
3573  *
3574  * DESCRIPTION: Channel Level callback used for super buffer data notify.
3575  *              This function is registered with mm-camera-interface to handle
3576  *              data notify
3577  *
3578  * PARAMETERS :
3579  *   @recvd_frame   : stream frame received
3580  *   userdata       : user data ptr
3581  *
3582  * RETURN     : none
3583  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3584 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3585                                  void *userdata)
3586 {
3587     ATRACE_CALL();
3588     LOGD("E\n");
3589     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3590 
3591     if (channel == NULL) {
3592         LOGE("invalid channel pointer");
3593         return;
3594     }
3595 
3596     if(channel->m_numStreams != 1) {
3597         LOGE("Error: Bug: This callback assumes one stream per channel");
3598         return;
3599     }
3600 
3601 
3602     if(channel->mStreams[0] == NULL) {
3603         LOGE("Error: Invalid Stream object");
3604         return;
3605     }
3606 
3607     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3608 
3609     LOGD("X\n");
3610     return;
3611 }
3612 
3613 /*===========================================================================
3614  * FUNCTION   : streamCbRoutine
3615  *
3616  * DESCRIPTION:
3617  *
3618  * PARAMETERS :
3619  * @super_frame : the super frame with filled buffer
3620  * @stream      : stream on which the buffer was requested and filled
3621  *
3622  * RETURN     : none
3623  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3624 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3625                             QCamera3Stream *stream)
3626 {
3627     ATRACE_CALL();
3628     //TODO
3629     //Used only for getting YUV. Jpeg callback will be sent back from channel
3630     //directly to HWI. Refer to func jpegEvtHandle
3631 
3632     //Got the yuv callback. Calling yuv callback handler in PostProc
3633     uint8_t frameIndex;
3634     mm_camera_super_buf_t* frame = NULL;
3635     cam_dimension_t dim;
3636     cam_frame_len_offset_t offset;
3637 
3638     memset(&dim, 0, sizeof(dim));
3639     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3640 
3641     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3642         LOGE("Error with the stream callback");
3643         return;
3644     }
3645 
3646     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3647     LOGD("recvd buf_idx: %u for further processing",
3648          (uint32_t)frameIndex);
3649     if(frameIndex >= mNumSnapshotBufs) {
3650          LOGE("Error, Invalid index for buffer");
3651          if(stream) {
3652              Mutex::Autolock lock(mFreeBuffersLock);
3653              mFreeBufferList.push_back(frameIndex);
3654              stream->bufDone(frameIndex);
3655          }
3656          return;
3657     }
3658 
3659     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3660     if (frame == NULL) {
3661        LOGE("Error allocating memory to save received_frame structure.");
3662        if(stream) {
3663            Mutex::Autolock lock(mFreeBuffersLock);
3664            mFreeBufferList.push_back(frameIndex);
3665            stream->bufDone(frameIndex);
3666        }
3667        return;
3668     }
3669     *frame = *super_frame;
3670     stream->getFrameDimension(dim);
3671     stream->getFrameOffset(offset);
3672     dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3673 
3674     if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
3675         mChannelCbBufErr(this, mYuvMemory->getFrameNumber(frameIndex),
3676                             CAMERA3_BUFFER_STATUS_ERROR, mUserData);
3677     }
3678 
3679     m_postprocessor.processData(frame);
3680     free(super_frame);
3681     return;
3682 }
3683 
getStreamBufs(uint32_t len)3684 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3685 {
3686     mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3687     if (!mYuvMemory) {
3688         LOGE("unable to create metadata memory");
3689         return NULL;
3690     }
3691     mFrameLen = len;
3692 
3693     return mYuvMemory;
3694 }
3695 
putStreamBufs()3696 void QCamera3PicChannel::putStreamBufs()
3697 {
3698     QCamera3ProcessingChannel::putStreamBufs();
3699 
3700     mYuvMemory->deallocate();
3701     delete mYuvMemory;
3702     mYuvMemory = NULL;
3703     mFreeBufferList.clear();
3704 }
3705 
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3706 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3707 {
3708     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3709     jpeg_settings_t *settings =
3710             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3711 
3712     if (!settings) {
3713         LOGE("out of memory allocating jpeg_settings");
3714         return -ENOMEM;
3715     }
3716 
3717     memset(settings, 0, sizeof(jpeg_settings_t));
3718 
3719     settings->out_buf_index = index;
3720 
3721     settings->jpeg_orientation = 0;
3722     IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3723         settings->jpeg_orientation = *orientation;
3724     }
3725 
3726     settings->jpeg_quality = 85;
3727     IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3728         settings->jpeg_quality = (uint8_t) *quality1;
3729     }
3730 
3731     IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3732         settings->jpeg_thumb_quality = (uint8_t) *quality2;
3733     }
3734 
3735     IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3736         settings->thumbnail_size = *dimension;
3737     }
3738 
3739     settings->gps_timestamp_valid = 0;
3740     IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3741         settings->gps_timestamp = *timestamp;
3742         settings->gps_timestamp_valid = 1;
3743     }
3744 
3745     settings->gps_coordinates_valid = 0;
3746     IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3747         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3748         settings->gps_coordinates_valid = 1;
3749     }
3750 
3751     IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3752         memset(settings->gps_processing_method, 0,
3753                 sizeof(settings->gps_processing_method));
3754         strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3755                 sizeof(settings->gps_processing_method));
3756     }
3757 
3758     // Image description
3759     const char *eepromVersion = hal_obj->getEepromVersionInfo();
3760     const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3761     if ((eepromVersion && strlen(eepromVersion)) ||
3762             ldafCalib) {
3763         int len = 0;
3764         settings->image_desc_valid = true;
3765         if (eepromVersion && strlen(eepromVersion)) {
3766             len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3767                     "M:%s ", eepromVersion);
3768         }
3769         if (ldafCalib) {
3770             snprintf(settings->image_desc + len,
3771                     sizeof(settings->image_desc) - len, "L:%u-%u",
3772                     ldafCalib[0], ldafCalib[1]);
3773         }
3774     }
3775 
3776     return m_postprocessor.processJpegSettingData(settings);
3777 }
3778 
3779 
overrideYuvSize(uint32_t width,uint32_t height)3780 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3781 {
3782    mYuvWidth = width;
3783    mYuvHeight = height;
3784 }
3785 
3786 /*===========================================================================
3787  * FUNCTION   : getReprocessType
3788  *
3789  * DESCRIPTION: get the type of reprocess output supported by this channel
3790  *
3791  * PARAMETERS : NONE
3792  *
3793  * RETURN     : reprocess_type_t : type of reprocess
3794  *==========================================================================*/
getReprocessType()3795 reprocess_type_t QCamera3PicChannel::getReprocessType()
3796 {
3797     /* a picture channel could either use the postprocessor for reprocess+jpeg
3798        or only for reprocess */
3799     reprocess_type_t expectedReprocess;
3800     if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3801         expectedReprocess = REPROCESS_TYPE_JPEG;
3802     } else {
3803         expectedReprocess = REPROCESS_TYPE_NONE;
3804     }
3805     LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
3806     return expectedReprocess;
3807 }
3808 
3809 /*===========================================================================
3810  * FUNCTION   : setCppPerfParam
3811  *
3812  * DESCRIPTION: set the performance related stream params
3813  *
3814  * PARAMETERS : NONE
3815  *
3816  * RETURN     : NONE
3817  *==========================================================================*/
3818 
setCppPerfParam()3819 void QCamera3PicChannel::setCppPerfParam()
3820 {
3821     if (mPendingLiveSnapshotFrames == 0) {
3822         int32_t rc = 0;
3823         QCamera3Stream *pStream = mStreams[0];
3824         cam_stream_parm_buffer_t param;
3825         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
3826         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3827         param.perf_mode = CAM_PERF_SET;
3828         rc = pStream->setParameter(param);
3829         if (rc != NO_ERROR) {
3830             LOGE("%s: setParameter for CAM_PERF_SET failed",
3831                 __func__);
3832         }
3833     }
3834     mPendingLiveSnapshotFrames++;
3835 }
3836 
3837 /*===========================================================================
3838  * FUNCTION   : resetCppPerfParam
3839  *
3840  * DESCRIPTION: reset the performance related stream params
3841  *
3842  * PARAMETERS : NONE
3843  *
3844  * RETURN     : NONE
3845  *==========================================================================*/
3846 
resetCppPerfParam()3847 void QCamera3PicChannel::resetCppPerfParam()
3848 {
3849     if (mPendingLiveSnapshotFrames > 0) {
3850         int32_t rc = NO_ERROR;
3851         QCamera3Stream *pStream = mStreams[0];
3852         cam_stream_parm_buffer_t param;
3853         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
3854         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3855         param.perf_mode = CAM_PERF_RESET;
3856         rc = pStream->setParameter(param);
3857         if (rc != NO_ERROR) {
3858             LOGE("%s: setParameter for CAM_PERF_RESET failed",
3859                 __func__);
3860         }
3861         mPendingLiveSnapshotFrames--;
3862     }
3863 }
3864 
3865 /*===========================================================================
3866  * FUNCTION   : timeoutFrame
3867  *
3868  * DESCRIPTION: Method to indicate to channel that a given frame has take too
3869  *              long to be generated
3870  *
3871  * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
3872  *
3873  * RETURN     : int32_t type of status
3874  *              NO_ERROR  -- success
3875  *              none-zero failure code
3876  *==========================================================================*/
timeoutFrame(uint32_t frameNumber)3877 int32_t QCamera3PicChannel::timeoutFrame(uint32_t frameNumber)
3878 {
3879     int32_t bufIdx;
3880 
3881     bufIdx = mYuvMemory->getBufferIndex(frameNumber);
3882 
3883     if (bufIdx < 0) {
3884         ALOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
3885         return -1;
3886     }
3887 
3888     mStreams[0]->timeoutFrame(bufIdx);
3889 
3890     return NO_ERROR;
3891 }
3892 
3893 /*===========================================================================
3894  * FUNCTION   : QCamera3ReprocessChannel
3895  *
3896  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3897  *
3898  * PARAMETERS :
3899  *   @cam_handle : camera handle
3900  *   @cam_ops    : ptr to camera ops table
3901  *   @pp_mask    : post-proccess feature mask
3902  *
3903  * RETURN     : none
3904  *==========================================================================*/
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)3905 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3906                                                  uint32_t channel_handle,
3907                                                  mm_camera_ops_t *cam_ops,
3908                                                  channel_cb_routine cb_routine,
3909                                                  channel_cb_buffer_err cb_buf_err,
3910                                                  cam_padding_info_t *paddingInfo,
3911                                                  cam_feature_mask_t postprocess_mask,
3912                                                  void *userData, void *ch_hdl) :
3913     /* In case of framework reprocessing, pproc and jpeg operations could be
3914      * parallelized by allowing 1 extra buffer for reprocessing output:
3915      * ch_hdl->getNumBuffers() + 1 */
3916     QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, cb_buf_err, paddingInfo,
3917                     postprocess_mask, userData,
3918                     ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3919                               + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3920     inputChHandle(ch_hdl),
3921     mOfflineBuffersIndex(-1),
3922     mFrameLen(0),
3923     mReprocessType(REPROCESS_TYPE_NONE),
3924     m_pSrcChannel(NULL),
3925     m_pMetaChannel(NULL),
3926     mMemory(NULL),
3927     mGrallocMemory(0),
3928     mReprocessPerfMode(false)
3929 {
3930     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3931     mOfflineBuffersIndex = mNumBuffers -1;
3932     mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3933 }
3934 
3935 
3936 /*===========================================================================
3937  * FUNCTION   : QCamera3ReprocessChannel
3938  *
3939  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3940  *
3941  * PARAMETERS :
3942  *   @cam_handle : camera handle
3943  *   @cam_ops    : ptr to camera ops table
3944  *   @pp_mask    : post-proccess feature mask
3945  *
3946  * RETURN     : none
3947  *==========================================================================*/
initialize(cam_is_type_t isType)3948 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3949 {
3950     int32_t rc = NO_ERROR;
3951     mm_camera_channel_attr_t attr;
3952 
3953     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3954     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3955     attr.max_unmatched_frames = 1;
3956 
3957     m_handle = m_camOps->add_channel(m_camHandle,
3958                                       &attr,
3959                                       NULL,
3960                                       this);
3961     if (m_handle == 0) {
3962         LOGE("Add channel failed");
3963         return UNKNOWN_ERROR;
3964     }
3965 
3966     mIsType = isType;
3967     return rc;
3968 }
3969 
3970 /*===========================================================================
3971  * FUNCTION   : registerBuffer
3972  *
3973  * DESCRIPTION: register streaming buffer to the channel object
3974  *
3975  * PARAMETERS :
3976  *   @buffer     : buffer to be registered
3977  *   @isType     : the image stabilization type for the buffer
3978  *
3979  * RETURN     : int32_t type of status
3980  *              NO_ERROR  -- success
3981  *              none-zero failure code
3982  *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3983 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3984         cam_is_type_t isType)
3985 {
3986     ATRACE_CALL();
3987     int rc = 0;
3988     mIsType = isType;
3989     cam_stream_type_t streamType;
3990 
3991     if (buffer == NULL) {
3992         LOGE("Error: Cannot register a NULL buffer");
3993         return BAD_VALUE;
3994     }
3995 
3996     if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3997         LOGE("Trying to register more buffers than initially requested");
3998         return BAD_VALUE;
3999     }
4000 
4001     if (0 == m_numStreams) {
4002         rc = initialize(mIsType);
4003         if (rc != NO_ERROR) {
4004             LOGE("Couldn't initialize camera stream %d",
4005                      rc);
4006             return rc;
4007         }
4008     }
4009 
4010     streamType = mStreams[0]->getMyType();
4011     rc = mGrallocMemory.registerBuffer(buffer, streamType);
4012     if (ALREADY_EXISTS == rc) {
4013         return NO_ERROR;
4014     } else if (NO_ERROR != rc) {
4015         LOGE("Buffer %p couldn't be registered %d", buffer, rc);
4016         return rc;
4017     }
4018 
4019     return rc;
4020 }
4021 
4022 /*===========================================================================
4023  * FUNCTION   : QCamera3ReprocessChannel
4024  *
4025  * DESCRIPTION: constructor of QCamera3ReprocessChannel
4026  *
4027  * PARAMETERS :
4028  *   @cam_handle : camera handle
4029  *   @cam_ops    : ptr to camera ops table
4030  *   @pp_mask    : post-proccess feature mask
4031  *
4032  * RETURN     : none
4033  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)4034 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
4035                                   QCamera3Stream *stream)
4036 {
4037     //Got the pproc data callback. Now send to jpeg encoding
4038     uint8_t frameIndex;
4039     uint32_t resultFrameNumber;
4040     ATRACE_CALL();
4041     mm_camera_super_buf_t* frame = NULL;
4042     QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
4043     cam_dimension_t dim;
4044     cam_frame_len_offset_t offset;
4045 
4046     memset(&dim, 0, sizeof(dim));
4047     memset(&offset, 0, sizeof(cam_frame_len_offset_t));
4048     if(!super_frame) {
4049          LOGE("Invalid Super buffer");
4050          return;
4051     }
4052 
4053     if(super_frame->num_bufs != 1) {
4054          LOGE("Multiple streams are not supported");
4055          return;
4056     }
4057     if(super_frame->bufs[0] == NULL ) {
4058          LOGE("Error, Super buffer frame does not contain valid buffer");
4059          return;
4060     }
4061     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4062 
4063 
4064     if (mReprocessType == REPROCESS_TYPE_JPEG) {
4065         resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
4066         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
4067         if (frame == NULL) {
4068            LOGE("Error allocating memory to save received_frame structure.");
4069            if(stream) {
4070                stream->bufDone(frameIndex);
4071            }
4072            return;
4073         }
4074         LOGI("bufIndex: %u recvd from post proc",
4075                  (uint32_t)frameIndex);
4076         *frame = *super_frame;
4077 
4078         stream->getFrameDimension(dim);
4079         stream->getFrameOffset(offset);
4080         dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
4081         /* Since reprocessing is done, send the callback to release the input buffer */
4082         // Release offline buffers.
4083         obj->releaseOfflineMemory(resultFrameNumber);
4084         if (mChannelCB) {
4085             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
4086         }
4087         obj->m_postprocessor.processPPData(frame);
4088     } else {
4089         buffer_handle_t *resultBuffer;
4090         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4091         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
4092         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
4093         int32_t rc = stream->bufRelease(frameIndex);
4094         if (NO_ERROR != rc) {
4095             LOGE("Error %d releasing stream buffer %d",
4096                      rc, frameIndex);
4097         }
4098         rc = mGrallocMemory.unregisterBuffer(frameIndex);
4099         if (NO_ERROR != rc) {
4100             LOGE("Error %d unregistering stream buffer %d",
4101                      rc, frameIndex);
4102         }
4103         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
4104 
4105         obj->m_postprocessor.releaseOfflineBuffers(false);
4106         qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
4107         if (pp_job != NULL) {
4108             obj->m_postprocessor.releasePPJobData(pp_job);
4109         }
4110         free(pp_job);
4111     }
4112     resetToCamPerfNormal(resultFrameNumber);
4113     free(super_frame);
4114     return;
4115 }
4116 
4117 /*===========================================================================
4118  * FUNCTION   : resetToCamPerfNormal
4119  *
4120  * DESCRIPTION: Set the perf mode to normal if all the priority frames
4121  *              have been reprocessed
4122  *
4123  * PARAMETERS :
4124  *      @frameNumber: Frame number of the reprocess completed frame
4125  *
4126  * RETURN     : QCamera3StreamMem *
4127  *==========================================================================*/
resetToCamPerfNormal(uint32_t frameNumber)4128 int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
4129 {
4130     int32_t rc = NO_ERROR;
4131     bool resetToPerfNormal = false;
4132     {
4133         Mutex::Autolock lock(mPriorityFramesLock);
4134         /* remove the priority frame number from the list */
4135         for (size_t i = 0; i < mPriorityFrames.size(); i++) {
4136             if (mPriorityFrames[i] == frameNumber) {
4137                 mPriorityFrames.removeAt(i);
4138             }
4139         }
4140         /* reset the perf mode if pending priority frame list is empty */
4141         if (mReprocessPerfMode && mPriorityFrames.empty()) {
4142             resetToPerfNormal = true;
4143         }
4144     }
4145     if (resetToPerfNormal) {
4146         QCamera3Stream *pStream = mStreams[0];
4147         cam_stream_parm_buffer_t param;
4148         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4149 
4150         param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4151         param.perf_mode = CAM_PERF_NORMAL;
4152         rc = pStream->setParameter(param);
4153         {
4154             Mutex::Autolock lock(mPriorityFramesLock);
4155             mReprocessPerfMode = false;
4156         }
4157     }
4158     return rc;
4159 }
4160 
4161 /*===========================================================================
4162  * FUNCTION   : getStreamBufs
4163  *
4164  * DESCRIPTION: register the buffers of the reprocess channel
4165  *
4166  * PARAMETERS : none
4167  *
4168  * RETURN     : QCamera3StreamMem *
4169  *==========================================================================*/
getStreamBufs(uint32_t len)4170 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
4171 {
4172     if (mReprocessType == REPROCESS_TYPE_JPEG) {
4173         mMemory = new QCamera3StreamMem(mNumBuffers, false);
4174         if (!mMemory) {
4175             LOGE("unable to create reproc memory");
4176             return NULL;
4177         }
4178         mFrameLen = len;
4179         return mMemory;
4180     }
4181     return &mGrallocMemory;
4182 }
4183 
4184 /*===========================================================================
4185  * FUNCTION   : putStreamBufs
4186  *
4187  * DESCRIPTION: release the reprocess channel buffers
4188  *
4189  * PARAMETERS : none
4190  *
4191  * RETURN     :
4192  *==========================================================================*/
putStreamBufs()4193 void QCamera3ReprocessChannel::putStreamBufs()
4194 {
4195    if (mReprocessType == REPROCESS_TYPE_JPEG) {
4196        mMemory->deallocate();
4197        delete mMemory;
4198        mMemory = NULL;
4199        mFreeBufferList.clear();
4200    } else {
4201        mGrallocMemory.unregisterBuffers();
4202    }
4203 }
4204 
4205 /*===========================================================================
4206  * FUNCTION   : ~QCamera3ReprocessChannel
4207  *
4208  * DESCRIPTION: destructor of QCamera3ReprocessChannel
4209  *
4210  * PARAMETERS : none
4211  *
4212  * RETURN     : none
4213  *==========================================================================*/
~QCamera3ReprocessChannel()4214 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
4215 {
4216     destroy();
4217 
4218     if (m_handle) {
4219         m_camOps->delete_channel(m_camHandle, m_handle);
4220         LOGD("deleting channel %d", m_handle);
4221         m_handle = 0;
4222     }
4223 }
4224 
4225 /*===========================================================================
4226  * FUNCTION   : start
4227  *
4228  * DESCRIPTION: start reprocess channel.
4229  *
4230  * PARAMETERS :
4231  *
4232  * RETURN     : int32_t type of status
4233  *              NO_ERROR  -- success
4234  *              none-zero failure code
4235  *==========================================================================*/
start()4236 int32_t QCamera3ReprocessChannel::start()
4237 {
4238     ATRACE_CALL();
4239     int32_t rc = NO_ERROR;
4240 
4241     rc = QCamera3Channel::start();
4242 
4243     if (rc == NO_ERROR) {
4244        rc = m_camOps->start_channel(m_camHandle, m_handle);
4245 
4246        // Check failure
4247        if (rc != NO_ERROR) {
4248            LOGE("start_channel failed %d", rc);
4249            QCamera3Channel::stop();
4250        }
4251     }
4252     return rc;
4253 }
4254 
4255 /*===========================================================================
4256  * FUNCTION   : stop
4257  *
4258  * DESCRIPTION: stop reprocess channel.
4259  *
4260  * PARAMETERS : none
4261  *
4262  * RETURN     : int32_t type of status
4263  *              NO_ERROR  -- success
4264  *              none-zero failure code
4265  *==========================================================================*/
stop()4266 int32_t QCamera3ReprocessChannel::stop()
4267 {
4268     ATRACE_CALL();
4269     int32_t rc = NO_ERROR;
4270 
4271     rc = QCamera3Channel::stop();
4272     unmapOfflineBuffers(true);
4273 
4274     rc |= m_camOps->stop_channel(m_camHandle, m_handle);
4275 
4276     return rc;
4277 }
4278 
4279 /*===========================================================================
4280  * FUNCTION   : getStreamBySrcHandle
4281  *
4282  * DESCRIPTION: find reprocess stream by its source stream handle
4283  *
4284  * PARAMETERS :
4285  *   @srcHandle : source stream handle
4286  *
4287  * RETURN     : ptr to reprocess stream if found. NULL if not found
4288  *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)4289 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
4290 {
4291     QCamera3Stream *pStream = NULL;
4292 
4293     for (uint32_t i = 0; i < m_numStreams; i++) {
4294         if (mSrcStreamHandles[i] == srcHandle) {
4295             pStream = mStreams[i];
4296             break;
4297         }
4298     }
4299     return pStream;
4300 }
4301 
4302 /*===========================================================================
4303  * FUNCTION   : getSrcStreamBySrcHandle
4304  *
4305  * DESCRIPTION: find source stream by source stream handle
4306  *
4307  * PARAMETERS :
4308  *   @srcHandle : source stream handle
4309  *
4310  * RETURN     : ptr to reprocess stream if found. NULL if not found
4311  *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)4312 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4313 {
4314     QCamera3Stream *pStream = NULL;
4315 
4316     if (NULL == m_pSrcChannel) {
4317         return NULL;
4318     }
4319 
4320     for (uint32_t i = 0; i < m_numStreams; i++) {
4321         if (mSrcStreamHandles[i] == srcHandle) {
4322             pStream = m_pSrcChannel->getStreamByIndex(i);
4323             break;
4324         }
4325     }
4326     return pStream;
4327 }
4328 
4329 /*===========================================================================
4330  * FUNCTION   : unmapOfflineBuffers
4331  *
4332  * DESCRIPTION: Unmaps offline buffers
4333  *
4334  * PARAMETERS : none
4335  *
4336  * RETURN     : int32_t type of status
4337  *              NO_ERROR  -- success
4338  *              none-zero failure code
4339  *==========================================================================*/
unmapOfflineBuffers(bool all)4340 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4341 {
4342     int rc = NO_ERROR;
4343     Mutex::Autolock l(mOfflineBuffersLock);
4344     if (!mOfflineBuffers.empty()) {
4345         QCamera3Stream *stream = NULL;
4346         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4347         for (; it != mOfflineBuffers.end(); it++) {
4348            stream = (*it).stream;
4349            if (NULL != stream) {
4350                rc = stream->unmapBuf((*it).type,
4351                                      (*it).index,
4352                                         -1);
4353                if (NO_ERROR != rc) {
4354                    LOGE("Error during offline buffer unmap %d",
4355                           rc);
4356                }
4357                LOGD("Unmapped buffer with index %d", (*it).index);
4358            }
4359            if (!all) {
4360                mOfflineBuffers.erase(it);
4361                break;
4362            }
4363         }
4364         if (all) {
4365            mOfflineBuffers.clear();
4366         }
4367     }
4368 
4369     if (!mOfflineMetaBuffers.empty()) {
4370         QCamera3Stream *stream = NULL;
4371         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4372         for (; it != mOfflineMetaBuffers.end(); it++) {
4373            stream = (*it).stream;
4374            if (NULL != stream) {
4375                rc = stream->unmapBuf((*it).type,
4376                                      (*it).index,
4377                                         -1);
4378                if (NO_ERROR != rc) {
4379                    LOGE("Error during offline buffer unmap %d",
4380                           rc);
4381                }
4382                LOGD("Unmapped meta buffer with index %d", (*it).index);
4383            }
4384            if (!all) {
4385                mOfflineMetaBuffers.erase(it);
4386                break;
4387            }
4388         }
4389         if (all) {
4390            mOfflineMetaBuffers.clear();
4391         }
4392     }
4393     return rc;
4394 }
4395 
4396 /*===========================================================================
4397  * FUNCTION   : bufDone
4398  *
4399  * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4400  *              Note that this function doesn't queue buffer back to kernel.
4401  *              It's up to doReprocessOffline to do that instead.
4402  * PARAMETERS :
4403  *   @recvd_frame  : stream buf frame to be returned
4404  *
4405  * RETURN     : int32_t type of status
4406  *              NO_ERROR  -- success
4407  *              none-zero failure code
4408  *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)4409 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4410 {
4411     int rc = NO_ERROR;
4412     if (recvd_frame && recvd_frame->num_bufs == 1) {
4413         Mutex::Autolock lock(mFreeBuffersLock);
4414         uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4415         mFreeBufferList.push_back(buf_idx);
4416 
4417     } else {
4418         LOGE("Fatal. Not supposed to be here");
4419         rc = BAD_VALUE;
4420     }
4421 
4422     return rc;
4423 }
4424 
4425 /*===========================================================================
4426  * FUNCTION   : overrideMetadata
4427  *
4428  * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4429  *
4430  * PARAMETERS :
4431  *   @frame     : input frame from source stream
4432  *   meta_buffer: metadata buffer
4433  *   @metadata  : corresponding metadata
4434  *   @fwk_frame :
4435  *
4436  * RETURN     : int32_t type of status
4437  *              NO_ERROR  -- success
4438  *              none-zero failure code
4439  *==========================================================================*/
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)4440 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4441         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4442         qcamera_fwk_input_pp_data_t &fwk_frame)
4443 {
4444     int32_t rc = NO_ERROR;
4445     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4446     if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4447             (NULL == hal_obj)) {
4448         return BAD_VALUE;
4449     }
4450 
4451     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4452     mm_camera_super_buf_t *frame = pp_buffer->input;
4453     if (NULL == meta) {
4454         return BAD_VALUE;
4455     }
4456 
4457     for (uint32_t i = 0; i < frame->num_bufs; i++) {
4458         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4459         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4460 
4461         if (pStream != NULL && pSrcStream != NULL) {
4462             if (jpeg_settings) {
4463                 // Find rotation info for reprocess stream
4464                 cam_rotation_info_t rotation_info;
4465                 memset(&rotation_info, 0, sizeof(rotation_info));
4466                 if (jpeg_settings->jpeg_orientation == 0) {
4467                    rotation_info.rotation = ROTATE_0;
4468                 } else if (jpeg_settings->jpeg_orientation == 90) {
4469                    rotation_info.rotation = ROTATE_90;
4470                 } else if (jpeg_settings->jpeg_orientation == 180) {
4471                    rotation_info.rotation = ROTATE_180;
4472                 } else if (jpeg_settings->jpeg_orientation == 270) {
4473                    rotation_info.rotation = ROTATE_270;
4474                 }
4475                 rotation_info.device_rotation = ROTATE_0;
4476                 rotation_info.streamId = mStreams[0]->getMyServerID();
4477                 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4478             }
4479 
4480             // Find and insert crop info for reprocess stream
4481             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4482                 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4483                     for (int j = 0; j < crop_data->num_of_streams; j++) {
4484                         if (crop_data->crop_info[j].stream_id ==
4485                                 pSrcStream->getMyServerID()) {
4486 
4487                             // Store crop/roi information for offline reprocess
4488                             // in the reprocess stream slot
4489                             crop_data->crop_info[crop_data->num_of_streams].crop =
4490                                     crop_data->crop_info[j].crop;
4491                             crop_data->crop_info[crop_data->num_of_streams].roi_map =
4492                                     crop_data->crop_info[j].roi_map;
4493                             crop_data->crop_info[crop_data->num_of_streams].stream_id =
4494                                     mStreams[0]->getMyServerID();
4495                             crop_data->num_of_streams++;
4496 
4497                             LOGD("Reprocess stream server id: %d",
4498                                      mStreams[0]->getMyServerID());
4499                             LOGD("Found offline reprocess crop %dx%d %dx%d",
4500                                     crop_data->crop_info[j].crop.left,
4501                                     crop_data->crop_info[j].crop.top,
4502                                     crop_data->crop_info[j].crop.width,
4503                                     crop_data->crop_info[j].crop.height);
4504                             LOGD("Found offline reprocess roimap %dx%d %dx%d",
4505                                     crop_data->crop_info[j].roi_map.left,
4506                                     crop_data->crop_info[j].roi_map.top,
4507                                     crop_data->crop_info[j].roi_map.width,
4508                                     crop_data->crop_info[j].roi_map.height);
4509 
4510                             break;
4511                         }
4512                     }
4513                 } else {
4514                     LOGE("No space to add reprocess stream crop/roi information");
4515                 }
4516             }
4517 
4518             IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4519                 uint8_t cnt = cdsInfo->num_of_streams;
4520                 if (cnt <= MAX_NUM_STREAMS) {
4521                     cam_stream_cds_info_t repro_cds_info;
4522                     memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4523                     repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4524                     for (size_t i = 0; i < cnt; i++) {
4525                         if (cdsInfo->cds_info[i].stream_id ==
4526                                 pSrcStream->getMyServerID()) {
4527                             repro_cds_info.cds_enable =
4528                                     cdsInfo->cds_info[i].cds_enable;
4529                             break;
4530                         }
4531                     }
4532                     cdsInfo->num_of_streams = 1;
4533                     cdsInfo->cds_info[0] = repro_cds_info;
4534                 } else {
4535                     LOGE("No space to add reprocess stream cds information");
4536                 }
4537             }
4538 
4539             fwk_frame.input_buffer = *frame->bufs[i];
4540             fwk_frame.metadata_buffer = *meta_buffer;
4541             fwk_frame.output_buffer = pp_buffer->output;
4542             break;
4543         } else {
4544             LOGE("Source/Re-process streams are invalid");
4545             rc |= BAD_VALUE;
4546         }
4547     }
4548 
4549     return rc;
4550 }
4551 
4552 /*===========================================================================
4553 * FUNCTION : overrideFwkMetadata
4554 *
4555 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4556 *
4557 * PARAMETERS :
4558 * @frame : input frame for reprocessing
4559 *
4560 * RETURN : int32_t type of status
4561 * NO_ERROR -- success
4562 * none-zero failure code
4563 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)4564 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4565         qcamera_fwk_input_pp_data_t *frame)
4566 {
4567     if (NULL == frame) {
4568         LOGE("Incorrect input frame");
4569         return BAD_VALUE;
4570     }
4571 
4572     if (NULL == frame->metadata_buffer.buffer) {
4573         LOGE("No metadata available");
4574         return BAD_VALUE;
4575     }
4576 
4577     // Find and insert crop info for reprocess stream
4578     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4579     IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4580         if (1 == crop_data->num_of_streams) {
4581             // Store crop/roi information for offline reprocess
4582             // in the reprocess stream slot
4583             crop_data->crop_info[crop_data->num_of_streams].crop =
4584                     crop_data->crop_info[0].crop;
4585             crop_data->crop_info[crop_data->num_of_streams].roi_map =
4586                     crop_data->crop_info[0].roi_map;
4587             crop_data->crop_info[crop_data->num_of_streams].stream_id =
4588                     mStreams[0]->getMyServerID();
4589             crop_data->num_of_streams++;
4590 
4591             LOGD("Reprocess stream server id: %d",
4592                      mStreams[0]->getMyServerID());
4593             LOGD("Found offline reprocess crop %dx%d %dx%d",
4594                     crop_data->crop_info[0].crop.left,
4595                     crop_data->crop_info[0].crop.top,
4596                     crop_data->crop_info[0].crop.width,
4597                     crop_data->crop_info[0].crop.height);
4598             LOGD("Found offline reprocess roi map %dx%d %dx%d",
4599                     crop_data->crop_info[0].roi_map.left,
4600                     crop_data->crop_info[0].roi_map.top,
4601                     crop_data->crop_info[0].roi_map.width,
4602                     crop_data->crop_info[0].roi_map.height);
4603         } else {
4604             LOGE("Incorrect number of offline crop data entries %d",
4605                     crop_data->num_of_streams);
4606             return BAD_VALUE;
4607         }
4608     } else {
4609         LOGW("Crop data not present");
4610     }
4611 
4612     IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4613         if (1 == cdsInfo->num_of_streams) {
4614             cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4615         } else {
4616             LOGE("Incorrect number of offline cds info entries %d",
4617                      cdsInfo->num_of_streams);
4618             return BAD_VALUE;
4619         }
4620     }
4621 
4622     return NO_ERROR;
4623 }
4624 
4625 /*===========================================================================
4626  * FUNCTION   : doReprocessOffline
4627  *
4628  * DESCRIPTION: request to do a reprocess on the frame
4629  *
4630  * PARAMETERS :
4631  *   @frame     : input frame for reprocessing
4632  *   @isPriorityFrame: Hint that this frame is of priority, equivalent to
4633  *              real time, even though it is processed in offline mechanism
4634  *
4635  * RETURN     : int32_t type of status
4636  *              NO_ERROR  -- success
4637  *              none-zero failure code
4638  *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame,bool isPriorityFrame)4639  int32_t  QCamera3ReprocessChannel::doReprocessOffline(
4640         qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4641 {
4642     int32_t rc = 0;
4643     int index;
4644     OfflineBuffer mappedBuffer;
4645     ATRACE_CALL();
4646 
4647     if (m_numStreams < 1) {
4648         LOGE("No reprocess stream is created");
4649         return -1;
4650     }
4651 
4652     if (NULL == frame) {
4653         LOGE("Incorrect input frame");
4654         return BAD_VALUE;
4655     }
4656 
4657     if (NULL == frame->metadata_buffer.buffer) {
4658         LOGE("No metadata available");
4659         return BAD_VALUE;
4660     }
4661 
4662     if (NULL == frame->input_buffer.buffer) {
4663         LOGE("No input buffer available");
4664         return BAD_VALUE;
4665     }
4666 
4667     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4668         LOGE("Reprocess stream not initialized!");
4669         return NO_INIT;
4670     }
4671 
4672     QCamera3Stream *pStream = mStreams[0];
4673 
4674     //qbuf the output buffer if it was allocated by the framework
4675     if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4676         if(!m_bIsActive) {
4677             rc = registerBuffer(frame->output_buffer, mIsType);
4678             if (NO_ERROR != rc) {
4679                 LOGE("On-the-fly buffer registration failed %d",
4680                          rc);
4681                 return rc;
4682             }
4683 
4684             rc = start();
4685             if (NO_ERROR != rc) {
4686                 return rc;
4687             }
4688         }
4689         index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4690         if(index < 0) {
4691             rc = registerBuffer(frame->output_buffer, mIsType);
4692             if (NO_ERROR != rc) {
4693                 LOGE("On-the-fly buffer registration failed %d",
4694                          rc);
4695                 return rc;
4696             }
4697 
4698             index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4699             if (index < 0) {
4700                 LOGE("Could not find object among registered buffers");
4701                 return DEAD_OBJECT;
4702             }
4703         }
4704         rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4705         if(rc != NO_ERROR) {
4706             LOGE("Failed to mark frame#:%d, index:%d",frame->frameNumber,index);
4707             return rc;
4708         }
4709         rc = pStream->bufDone(index);
4710         if(rc != NO_ERROR) {
4711             LOGE("Failed to Q new buffer to stream");
4712             mGrallocMemory.markFrameNumber(index, -1);
4713             return rc;
4714         }
4715 
4716     } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4717         Mutex::Autolock lock(mFreeBuffersLock);
4718         uint32_t bufIdx;
4719         if (mFreeBufferList.empty()) {
4720             rc = mMemory->allocateOne(mFrameLen);
4721             if (rc < 0) {
4722                 LOGE("Failed allocating heap buffer. Fatal");
4723                 return BAD_VALUE;
4724             } else {
4725                 bufIdx = (uint32_t)rc;
4726             }
4727         } else {
4728             bufIdx = *(mFreeBufferList.begin());
4729             mFreeBufferList.erase(mFreeBufferList.begin());
4730         }
4731 
4732         mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4733         rc = pStream->bufDone(bufIdx);
4734         if (rc != NO_ERROR) {
4735             LOGE("Failed to queue new buffer to stream");
4736             return rc;
4737         }
4738     }
4739 
4740     int32_t max_idx = (int32_t) (mNumBuffers - 1);
4741     //loop back the indices if max burst count reached
4742     if (mOfflineBuffersIndex == max_idx) {
4743        mOfflineBuffersIndex = -1;
4744     }
4745     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4746 
4747     //Do cache ops before sending for reprocess
4748     if (mMemory != NULL) {
4749         mMemory->cleanInvalidateCache(buf_idx);
4750     }
4751 
4752     rc = pStream->mapBuf(
4753             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4754             buf_idx, -1,
4755             frame->input_buffer.fd, frame->input_buffer.buffer,
4756             frame->input_buffer.frame_len);
4757     if (NO_ERROR == rc) {
4758         Mutex::Autolock l(mOfflineBuffersLock);
4759         mappedBuffer.index = buf_idx;
4760         mappedBuffer.stream = pStream;
4761         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4762         mOfflineBuffers.push_back(mappedBuffer);
4763         mOfflineBuffersIndex = (int32_t)buf_idx;
4764         LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
4765     }
4766 
4767     max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4768     //loop back the indices if max burst count reached
4769     if (mOfflineMetaIndex == max_idx) {
4770        mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4771     }
4772     uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4773     rc |= pStream->mapBuf(
4774             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4775             meta_buf_idx, -1,
4776             frame->metadata_buffer.fd, frame->metadata_buffer.buffer,
4777             frame->metadata_buffer.frame_len);
4778     if (NO_ERROR == rc) {
4779         Mutex::Autolock l(mOfflineBuffersLock);
4780         mappedBuffer.index = meta_buf_idx;
4781         mappedBuffer.stream = pStream;
4782         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4783         mOfflineMetaBuffers.push_back(mappedBuffer);
4784         mOfflineMetaIndex = (int32_t)meta_buf_idx;
4785         LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
4786     }
4787 
4788     if (rc == NO_ERROR) {
4789         cam_stream_parm_buffer_t param;
4790         uint32_t numPendingPriorityFrames = 0;
4791 
4792         if(isPriorityFrame) {
4793             Mutex::Autolock lock(mPriorityFramesLock);
4794             /* read the length before pushing the frame number to check if
4795              * vector is empty */
4796             numPendingPriorityFrames = mPriorityFrames.size();
4797             mPriorityFrames.push(frame->frameNumber);
4798         }
4799 
4800         if(isPriorityFrame && !numPendingPriorityFrames) {
4801             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4802             param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4803             param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
4804             rc = pStream->setParameter(param);
4805 
4806             if (rc != NO_ERROR) {
4807                 ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
4808                     __func__);
4809             }
4810             {
4811                 Mutex::Autolock lock(mPriorityFramesLock);
4812                 mReprocessPerfMode = true;
4813             }
4814         }
4815 
4816         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4817         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4818         param.reprocess.buf_index = buf_idx;
4819         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4820         param.reprocess.meta_present = 1;
4821         param.reprocess.meta_buf_index = meta_buf_idx;
4822 
4823         LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
4824                     param.reprocess.frame_idx, param.reprocess.buf_index,
4825                     param.reprocess.meta_buf_index);
4826         rc = pStream->setParameter(param);
4827         if (rc != NO_ERROR) {
4828             LOGE("stream setParameter for reprocess failed");
4829             resetToCamPerfNormal(frame->frameNumber);
4830         }
4831     } else {
4832         LOGE("Input buffer memory map failed: %d", rc);
4833     }
4834 
4835     return rc;
4836 }
4837 
4838 /*===========================================================================
4839  * FUNCTION   : doReprocess
4840  *
4841  * DESCRIPTION: request to do a reprocess on the frame
4842  *
4843  * PARAMETERS :
4844  *   @buf_fd     : fd to the input buffer that needs reprocess
4845  *   @buffer     : Buffer ptr
4846  *   @buf_lenght : length of the input buffer
4847  *   @ret_val    : result of reprocess.
4848  *                 Example: Could be faceID in case of register face image.
4849  *   @meta_frame : metadata frame.
4850  *
4851  * RETURN     : int32_t type of status
4852  *              NO_ERROR  -- success
4853  *              none-zero failure code
4854  *==========================================================================*/
doReprocess(int buf_fd,void * buffer,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4855 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t buf_length,
4856         int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4857 {
4858     int32_t rc = 0;
4859     if (m_numStreams < 1) {
4860         LOGE("No reprocess stream is created");
4861         return -1;
4862     }
4863     if (meta_frame == NULL) {
4864         LOGE("Did not get corresponding metadata in time");
4865         return -1;
4866     }
4867 
4868     uint8_t buf_idx = 0;
4869     for (uint32_t i = 0; i < m_numStreams; i++) {
4870         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4871                                  buf_idx, -1,
4872                                  buf_fd, buffer, buf_length);
4873 
4874         //Do cache ops before sending for reprocess
4875         if (mMemory != NULL) {
4876             mMemory->cleanInvalidateCache(buf_idx);
4877         }
4878 
4879         if (rc == NO_ERROR) {
4880             cam_stream_parm_buffer_t param;
4881             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4882             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4883             param.reprocess.buf_index = buf_idx;
4884             param.reprocess.meta_present = 1;
4885             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4886             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4887 
4888             LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
4889                     param.reprocess.frame_idx, param.reprocess.buf_index,
4890                     param.reprocess.meta_buf_index);
4891             rc = mStreams[i]->setParameter(param);
4892             if (rc == NO_ERROR) {
4893                 ret_val = param.reprocess.ret_val;
4894             }
4895             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4896                                   buf_idx, -1);
4897         }
4898     }
4899     return rc;
4900 }
4901 
4902 /*===========================================================================
4903  * FUNCTION   : addReprocStreamsFromSource
4904  *
4905  * DESCRIPTION: add reprocess streams from input source channel
4906  *
4907  * PARAMETERS :
4908  *   @config         : pp feature configuration
4909  *   @src_config     : source reprocess configuration
4910  *   @isType         : type of image stabilization required on this stream
4911  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
4912  *
4913  *
4914  * RETURN     : int32_t type of status
4915  *              NO_ERROR  -- success
4916  *              none-zero failure code
4917  *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4918 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4919         const reprocess_config_t &src_config , cam_is_type_t is_type,
4920         QCamera3Channel *pMetaChannel)
4921 {
4922     int32_t rc = 0;
4923     cam_stream_reproc_config_t reprocess_config;
4924     cam_stream_type_t streamType;
4925 
4926     cam_dimension_t streamDim = src_config.output_stream_dim;
4927 
4928     if (NULL != src_config.src_channel) {
4929         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4930         if (pSrcStream == NULL) {
4931            LOGE("source channel doesn't have a stream");
4932            return BAD_VALUE;
4933         }
4934         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4935     }
4936 
4937     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4938     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4939 
4940     reprocess_config.offline.input_fmt = src_config.stream_format;
4941     reprocess_config.offline.input_dim = src_config.input_stream_dim;
4942     reprocess_config.offline.input_buf_planes.plane_info =
4943             src_config.input_stream_plane_info.plane_info;
4944     reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4945     reprocess_config.offline.input_type = src_config.stream_type;
4946 
4947     reprocess_config.pp_feature_config = pp_config;
4948     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4949             m_handle,
4950             m_camOps,
4951             &mPaddingInfo,
4952             (QCamera3Channel*)this);
4953     if (pStream == NULL) {
4954         LOGE("No mem for Stream");
4955         return NO_MEMORY;
4956     }
4957 
4958     rc = pStream->init(streamType, src_config.stream_format,
4959             streamDim, ROTATE_0, &reprocess_config,
4960             (uint8_t)mNumBuffers,
4961             reprocess_config.pp_feature_config.feature_mask,
4962             is_type,
4963             0,/* batchSize */
4964             QCamera3Channel::streamCbRoutine, this);
4965 
4966     if (rc == 0) {
4967         mStreams[m_numStreams] = pStream;
4968         m_numStreams++;
4969     } else {
4970         LOGE("failed to create reprocess stream");
4971         delete pStream;
4972     }
4973 
4974     if (rc == NO_ERROR) {
4975         m_pSrcChannel = src_config.src_channel;
4976         m_pMetaChannel = pMetaChannel;
4977         mReprocessType = src_config.reprocess_type;
4978         LOGD("mReprocessType is %d", mReprocessType);
4979     }
4980     mm_camera_req_buf_t buf;
4981     memset(&buf, 0x0, sizeof(buf));
4982     buf.type = MM_CAMERA_REQ_SUPER_BUF;
4983     buf.num_buf_requested = 1;
4984     if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
4985         LOGE("Request for super buffer failed");
4986     }
4987     return rc;
4988 }
4989 
4990 /* QCamera3SupportChannel methods */
4991 
4992 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4993 
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)4994 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4995                     uint32_t channel_handle,
4996                     mm_camera_ops_t *cam_ops,
4997                     cam_padding_info_t *paddingInfo,
4998                     cam_feature_mask_t postprocess_mask,
4999                     cam_stream_type_t streamType,
5000                     cam_dimension_t *dim,
5001                     cam_format_t streamFormat,
5002                     uint8_t hw_analysis_supported,
5003                     void *userData, uint32_t numBuffers) :
5004                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
5005                                 NULL, NULL, paddingInfo, postprocess_mask,
5006                                 userData, numBuffers),
5007                         mMemory(NULL)
5008 {
5009     memcpy(&mDim, dim, sizeof(cam_dimension_t));
5010     mStreamType = streamType;
5011     mStreamFormat = streamFormat;
5012    // Make Analysis same as Preview format
5013    if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
5014         mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
5015                 dim->width, dim->height);
5016    }
5017 }
5018 
~QCamera3SupportChannel()5019 QCamera3SupportChannel::~QCamera3SupportChannel()
5020 {
5021     destroy();
5022 
5023     if (mMemory) {
5024         mMemory->deallocate();
5025         delete mMemory;
5026         mMemory = NULL;
5027     }
5028 }
5029 
initialize(cam_is_type_t isType)5030 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
5031 {
5032     int32_t rc;
5033 
5034     if (mMemory || m_numStreams > 0) {
5035         LOGE("metadata channel already initialized");
5036         return -EINVAL;
5037     }
5038 
5039     mIsType = isType;
5040     rc = QCamera3Channel::addStream(mStreamType,
5041             mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
5042             mPostProcMask, mIsType);
5043     if (rc < 0) {
5044         LOGE("addStream failed");
5045     }
5046     return rc;
5047 }
5048 
request(buffer_handle_t *,uint32_t,int &)5049 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
5050                                                 uint32_t /*frameNumber*/,
5051                                                 int & /*indexUsed*/)
5052 {
5053     return NO_ERROR;
5054 }
5055 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)5056 void QCamera3SupportChannel::streamCbRoutine(
5057                         mm_camera_super_buf_t *super_frame,
5058                         QCamera3Stream * /*stream*/)
5059 {
5060     if (super_frame == NULL || super_frame->num_bufs != 1) {
5061         LOGE("super_frame is not valid");
5062         return;
5063     }
5064     bufDone(super_frame);
5065     free(super_frame);
5066 }
5067 
getStreamBufs(uint32_t len)5068 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
5069 {
5070     int rc;
5071     mMemory = new QCamera3StreamMem(mNumBuffers);
5072     if (!mMemory) {
5073         LOGE("unable to create heap memory");
5074         return NULL;
5075     }
5076     rc = mMemory->allocateAll(len);
5077     if (rc < 0) {
5078         LOGE("unable to allocate heap memory");
5079         delete mMemory;
5080         mMemory = NULL;
5081         return NULL;
5082     }
5083     return mMemory;
5084 }
5085 
putStreamBufs()5086 void QCamera3SupportChannel::putStreamBufs()
5087 {
5088     mMemory->deallocate();
5089     delete mMemory;
5090     mMemory = NULL;
5091 }
5092 
5093 }; // namespace qcamera
5094