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