• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         // Release offline buffers.
3575         obj->releaseOfflineMemory(resultFrameNumber);
3576         if (mChannelCB) {
3577             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
3578         }
3579         obj->m_postprocessor.processPPData(frame);
3580     } else {
3581         buffer_handle_t *resultBuffer;
3582         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3583         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
3584         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
3585         int32_t rc = stream->bufRelease(frameIndex);
3586         if (NO_ERROR != rc) {
3587             ALOGE("%s: Error %d releasing stream buffer %d",
3588                     __func__, rc, frameIndex);
3589         }
3590         rc = mGrallocMemory.unregisterBuffer(frameIndex);
3591         if (NO_ERROR != rc) {
3592             ALOGE("%s: Error %d unregistering stream buffer %d",
3593                     __func__, rc, frameIndex);
3594         }
3595         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
3596 
3597         obj->m_postprocessor.releaseOfflineBuffers();
3598         qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
3599         if (pp_job != NULL) {
3600             obj->m_postprocessor.releasePPJobData(pp_job);
3601         }
3602         free(pp_job);
3603     }
3604     free(super_frame);
3605     return;
3606 }
3607 
3608 /*===========================================================================
3609  * FUNCTION   : getStreamBufs
3610  *
3611  * DESCRIPTION: register the buffers of the reprocess channel
3612  *
3613  * PARAMETERS : none
3614  *
3615  * RETURN     : QCamera3StreamMem *
3616  *==========================================================================*/
getStreamBufs(uint32_t len)3617 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
3618 {
3619     int rc = 0;
3620     if (mReprocessType == REPROCESS_TYPE_JPEG) {
3621         mMemory = new QCamera3StreamMem(mNumBuffers, false);
3622         if (!mMemory) {
3623             ALOGE("%s: unable to create reproc memory", __func__);
3624             return NULL;
3625         }
3626         mFrameLen = len;
3627         return mMemory;
3628     }
3629     return &mGrallocMemory;
3630 }
3631 
3632 /*===========================================================================
3633  * FUNCTION   : putStreamBufs
3634  *
3635  * DESCRIPTION: release the reprocess channel buffers
3636  *
3637  * PARAMETERS : none
3638  *
3639  * RETURN     :
3640  *==========================================================================*/
putStreamBufs()3641 void QCamera3ReprocessChannel::putStreamBufs()
3642 {
3643    if (mReprocessType == REPROCESS_TYPE_JPEG) {
3644        mMemory->deallocate();
3645        delete mMemory;
3646        mMemory = NULL;
3647        mFreeBufferList.clear();
3648    } else {
3649        mGrallocMemory.unregisterBuffers();
3650    }
3651 }
3652 
3653 /*===========================================================================
3654  * FUNCTION   : ~QCamera3ReprocessChannel
3655  *
3656  * DESCRIPTION: destructor of QCamera3ReprocessChannel
3657  *
3658  * PARAMETERS : none
3659  *
3660  * RETURN     : none
3661  *==========================================================================*/
~QCamera3ReprocessChannel()3662 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
3663 {
3664     if (m_bIsActive)
3665         stop();
3666 
3667     for (uint32_t i = 0; i < m_numStreams; i++) {
3668         if (mStreams[i] != NULL) {
3669             delete mStreams[i];
3670             mStreams[i] = 0;
3671         }
3672     }
3673     if (m_handle) {
3674         m_camOps->delete_channel(m_camHandle, m_handle);
3675         ALOGE("%s: deleting channel %d", __func__, m_handle);
3676         m_handle = 0;
3677     }
3678     m_numStreams = 0;
3679 }
3680 
3681 /*===========================================================================
3682  * FUNCTION   : start
3683  *
3684  * DESCRIPTION: start reprocess channel.
3685  *
3686  * PARAMETERS :
3687  *
3688  * RETURN     : int32_t type of status
3689  *              NO_ERROR  -- success
3690  *              none-zero failure code
3691  *==========================================================================*/
start()3692 int32_t QCamera3ReprocessChannel::start()
3693 {
3694     ATRACE_CALL();
3695     int32_t rc = NO_ERROR;
3696 
3697     rc = QCamera3Channel::start();
3698 
3699     if (rc == NO_ERROR) {
3700        rc = m_camOps->start_channel(m_camHandle, m_handle);
3701 
3702        // Check failure
3703        if (rc != NO_ERROR) {
3704            ALOGE("%s: start_channel failed %d", __func__, rc);
3705            QCamera3Channel::stop();
3706        }
3707     }
3708     return rc;
3709 }
3710 
3711 /*===========================================================================
3712  * FUNCTION   : stop
3713  *
3714  * DESCRIPTION: stop reprocess channel.
3715  *
3716  * PARAMETERS : none
3717  *
3718  * RETURN     : int32_t type of status
3719  *              NO_ERROR  -- success
3720  *              none-zero failure code
3721  *==========================================================================*/
stop()3722 int32_t QCamera3ReprocessChannel::stop()
3723 {
3724     ATRACE_CALL();
3725     int32_t rc = NO_ERROR;
3726 
3727     rc = QCamera3Channel::stop();
3728 
3729     rc != m_camOps->stop_channel(m_camHandle, m_handle);
3730 
3731     unmapOfflineBuffers(true);
3732 
3733     return rc;
3734 }
3735 
3736 /*===========================================================================
3737  * FUNCTION   : getStreamBySrcHandle
3738  *
3739  * DESCRIPTION: find reprocess stream by its source stream handle
3740  *
3741  * PARAMETERS :
3742  *   @srcHandle : source stream handle
3743  *
3744  * RETURN     : ptr to reprocess stream if found. NULL if not found
3745  *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)3746 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
3747 {
3748     QCamera3Stream *pStream = NULL;
3749 
3750     for (uint32_t i = 0; i < m_numStreams; i++) {
3751         if (mSrcStreamHandles[i] == srcHandle) {
3752             pStream = mStreams[i];
3753             break;
3754         }
3755     }
3756     return pStream;
3757 }
3758 
3759 /*===========================================================================
3760  * FUNCTION   : getSrcStreamBySrcHandle
3761  *
3762  * DESCRIPTION: find source stream by source stream handle
3763  *
3764  * PARAMETERS :
3765  *   @srcHandle : source stream handle
3766  *
3767  * RETURN     : ptr to reprocess stream if found. NULL if not found
3768  *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)3769 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
3770 {
3771     QCamera3Stream *pStream = NULL;
3772 
3773     if (NULL == m_pSrcChannel) {
3774         return NULL;
3775     }
3776 
3777     for (uint32_t i = 0; i < m_numStreams; i++) {
3778         if (mSrcStreamHandles[i] == srcHandle) {
3779             pStream = m_pSrcChannel->getStreamByIndex(i);
3780             break;
3781         }
3782     }
3783     return pStream;
3784 }
3785 
3786 /*===========================================================================
3787  * FUNCTION   : unmapOfflineBuffers
3788  *
3789  * DESCRIPTION: Unmaps offline buffers
3790  *
3791  * PARAMETERS : none
3792  *
3793  * RETURN     : int32_t type of status
3794  *              NO_ERROR  -- success
3795  *              none-zero failure code
3796  *==========================================================================*/
unmapOfflineBuffers(bool all)3797 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
3798 {
3799     int rc = NO_ERROR;
3800     if (!mOfflineBuffers.empty()) {
3801         QCamera3Stream *stream = NULL;
3802         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
3803         for (; it != mOfflineBuffers.end(); it++) {
3804            stream = (*it).stream;
3805            if (NULL != stream) {
3806                rc = stream->unmapBuf((*it).type,
3807                                      (*it).index,
3808                                         -1);
3809                if (NO_ERROR != rc) {
3810                    ALOGE("%s: Error during offline buffer unmap %d",
3811                          __func__, rc);
3812                }
3813                CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index);
3814            }
3815            if (!all) {
3816                mOfflineBuffers.erase(it);
3817                break;
3818            }
3819         }
3820         if (all) {
3821            mOfflineBuffers.clear();
3822         }
3823     }
3824 
3825     if (!mOfflineMetaBuffers.empty()) {
3826         QCamera3Stream *stream = NULL;
3827         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
3828         for (; it != mOfflineMetaBuffers.end(); it++) {
3829            stream = (*it).stream;
3830            if (NULL != stream) {
3831                rc = stream->unmapBuf((*it).type,
3832                                      (*it).index,
3833                                         -1);
3834                if (NO_ERROR != rc) {
3835                    ALOGE("%s: Error during offline buffer unmap %d",
3836                          __func__, rc);
3837                }
3838                CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index);
3839            }
3840            if (!all) {
3841                mOfflineMetaBuffers.erase(it);
3842                break;
3843            }
3844         }
3845         if (all) {
3846            mOfflineMetaBuffers.clear();
3847         }
3848     }
3849     return rc;
3850 }
3851 
3852 /*===========================================================================
3853  * FUNCTION   : bufDone
3854  *
3855  * DESCRIPTION: Return reprocess stream buffer to free buffer list.
3856  *              Note that this function doesn't queue buffer back to kernel.
3857  *              It's up to doReprocessOffline to do that instead.
3858  * PARAMETERS :
3859  *   @recvd_frame  : stream buf frame to be returned
3860  *
3861  * RETURN     : int32_t type of status
3862  *              NO_ERROR  -- success
3863  *              none-zero failure code
3864  *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)3865 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
3866 {
3867     int rc = NO_ERROR;
3868     if (recvd_frame && recvd_frame->num_bufs == 1) {
3869         Mutex::Autolock lock(mFreeBuffersLock);
3870         uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
3871         mFreeBufferList.push_back(buf_idx);
3872 
3873     } else {
3874         ALOGE("%s: Fatal. Not supposed to be here", __func__);
3875         rc = BAD_VALUE;
3876     }
3877 
3878     return rc;
3879 }
3880 
3881 /*===========================================================================
3882  * FUNCTION   : overrideMetadata
3883  *
3884  * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
3885  *
3886  * PARAMETERS :
3887  *   @frame     : input frame from source stream
3888  *   meta_buffer: metadata buffer
3889  *   @metadata  : corresponding metadata
3890  *   @fwk_frame :
3891  *
3892  * RETURN     : int32_t type of status
3893  *              NO_ERROR  -- success
3894  *              none-zero failure code
3895  *==========================================================================*/
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)3896 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
3897         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
3898         qcamera_fwk_input_pp_data_t &fwk_frame)
3899 {
3900     int32_t rc = NO_ERROR;
3901     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3902     if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
3903             (NULL == hal_obj)) {
3904         return BAD_VALUE;
3905     }
3906 
3907     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
3908     mm_camera_super_buf_t *frame = pp_buffer->input;
3909     if (NULL == meta) {
3910         return BAD_VALUE;
3911     }
3912 
3913     for (uint32_t i = 0; i < frame->num_bufs; i++) {
3914         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
3915         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
3916 
3917         if (pStream != NULL && pSrcStream != NULL) {
3918             if (jpeg_settings) {
3919                 // Find rotation info for reprocess stream
3920                 cam_rotation_info_t rotation_info;
3921                 memset(&rotation_info, 0, sizeof(rotation_info));
3922                 if (jpeg_settings->jpeg_orientation == 0) {
3923                    rotation_info.rotation = ROTATE_0;
3924                 } else if (jpeg_settings->jpeg_orientation == 90) {
3925                    rotation_info.rotation = ROTATE_90;
3926                 } else if (jpeg_settings->jpeg_orientation == 180) {
3927                    rotation_info.rotation = ROTATE_180;
3928                 } else if (jpeg_settings->jpeg_orientation == 270) {
3929                    rotation_info.rotation = ROTATE_270;
3930                 }
3931                 rotation_info.streamId = mStreams[0]->getMyServerID();
3932                 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
3933             }
3934 
3935             // Find and insert crop info for reprocess stream
3936             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
3937                 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
3938                     for (int j = 0; j < crop_data->num_of_streams; j++) {
3939                         if (crop_data->crop_info[j].stream_id ==
3940                                 pSrcStream->getMyServerID()) {
3941 
3942                             // Store crop/roi information for offline reprocess
3943                             // in the reprocess stream slot
3944                             crop_data->crop_info[crop_data->num_of_streams].crop =
3945                                     crop_data->crop_info[j].crop;
3946                             crop_data->crop_info[crop_data->num_of_streams].roi_map =
3947                                     crop_data->crop_info[j].roi_map;
3948                             crop_data->crop_info[crop_data->num_of_streams].stream_id =
3949                                     mStreams[0]->getMyServerID();
3950                             crop_data->num_of_streams++;
3951 
3952                             CDBG("%s: Reprocess stream server id: %d",
3953                                     __func__, mStreams[0]->getMyServerID());
3954                             CDBG("%s: Found offline reprocess crop %dx%d %dx%d",
3955                                     __func__,
3956                                     crop_data->crop_info[j].crop.left,
3957                                     crop_data->crop_info[j].crop.top,
3958                                     crop_data->crop_info[j].crop.width,
3959                                     crop_data->crop_info[j].crop.height);
3960                             CDBG("%s: Found offline reprocess roimap %dx%d %dx%d",
3961                                     __func__,
3962                                     crop_data->crop_info[j].roi_map.left,
3963                                     crop_data->crop_info[j].roi_map.top,
3964                                     crop_data->crop_info[j].roi_map.width,
3965                                     crop_data->crop_info[j].roi_map.height);
3966 
3967                             break;
3968                         }
3969                     }
3970                 } else {
3971                     ALOGE("%s: No space to add reprocess stream crop/roi information",
3972                             __func__);
3973                 }
3974             }
3975 
3976             IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
3977                 uint8_t cnt = cdsInfo->num_of_streams;
3978                 if (cnt <= MAX_NUM_STREAMS) {
3979                     cam_stream_cds_info_t repro_cds_info;
3980                     memset(&repro_cds_info, 0, sizeof(repro_cds_info));
3981                     repro_cds_info.stream_id = mStreams[0]->getMyServerID();
3982                     for (size_t i = 0; i < cnt; i++) {
3983                         if (cdsInfo->cds_info[i].stream_id ==
3984                                 pSrcStream->getMyServerID()) {
3985                             repro_cds_info.cds_enable =
3986                                     cdsInfo->cds_info[i].cds_enable;
3987                             break;
3988                         }
3989                     }
3990                     cdsInfo->num_of_streams = 1;
3991                     cdsInfo->cds_info[0] = repro_cds_info;
3992                 } else {
3993                     ALOGE("%s: No space to add reprocess stream cds information",
3994                             __func__);
3995                 }
3996             }
3997 
3998             fwk_frame.input_buffer = *frame->bufs[i];
3999             fwk_frame.metadata_buffer = *meta_buffer;
4000             fwk_frame.output_buffer = pp_buffer->output;
4001             break;
4002         } else {
4003             ALOGE("%s: Source/Re-process streams are invalid", __func__);
4004             rc |= BAD_VALUE;
4005         }
4006     }
4007 
4008     return rc;
4009 }
4010 
4011 /*===========================================================================
4012 * FUNCTION : overrideFwkMetadata
4013 *
4014 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4015 *
4016 * PARAMETERS :
4017 * @frame : input frame for reprocessing
4018 *
4019 * RETURN : int32_t type of status
4020 * NO_ERROR -- success
4021 * none-zero failure code
4022 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)4023 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4024         qcamera_fwk_input_pp_data_t *frame)
4025 {
4026     if (NULL == frame) {
4027         ALOGE("%s: Incorrect input frame", __func__);
4028         return BAD_VALUE;
4029     }
4030 
4031 
4032     if (NULL == frame->metadata_buffer.buffer) {
4033         ALOGE("%s: No metadata available", __func__);
4034         return BAD_VALUE;
4035     }
4036 
4037     // Find and insert crop info for reprocess stream
4038     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4039     IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4040         if (1 == crop_data->num_of_streams) {
4041             // Store crop/roi information for offline reprocess
4042             // in the reprocess stream slot
4043             crop_data->crop_info[crop_data->num_of_streams].crop =
4044                     crop_data->crop_info[0].crop;
4045             crop_data->crop_info[crop_data->num_of_streams].roi_map =
4046                     crop_data->crop_info[0].roi_map;
4047             crop_data->crop_info[crop_data->num_of_streams].stream_id =
4048                     mStreams[0]->getMyServerID();
4049             crop_data->num_of_streams++;
4050 
4051             CDBG("%s: Reprocess stream server id: %d",
4052                     __func__, mStreams[0]->getMyServerID());
4053             CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
4054                     crop_data->crop_info[0].crop.left,
4055                     crop_data->crop_info[0].crop.top,
4056                     crop_data->crop_info[0].crop.width,
4057                     crop_data->crop_info[0].crop.height);
4058             CDBG("%s: Found offline reprocess roi map %dx%d %dx%d", __func__,
4059                     crop_data->crop_info[0].roi_map.left,
4060                     crop_data->crop_info[0].roi_map.top,
4061                     crop_data->crop_info[0].roi_map.width,
4062                     crop_data->crop_info[0].roi_map.height);
4063         } else {
4064             ALOGE("%s: Incorrect number of offline crop data entries %d",
4065                     __func__,
4066                     crop_data->num_of_streams);
4067             return BAD_VALUE;
4068         }
4069     } else {
4070         CDBG_HIGH("%s: Crop data not present", __func__);
4071     }
4072 
4073     IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4074         if (1 == cdsInfo->num_of_streams) {
4075             cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4076         } else {
4077             ALOGE("%s: Incorrect number of offline cds info entries %d",
4078                     __func__, cdsInfo->num_of_streams);
4079             return BAD_VALUE;
4080         }
4081     }
4082 
4083     return NO_ERROR;
4084 }
4085 
4086 /*===========================================================================
4087  * FUNCTION   : doReprocessOffline
4088  *
4089  * DESCRIPTION: request to do a reprocess on the frame
4090  *
4091  * PARAMETERS :
4092  *   @frame     : input frame for reprocessing
4093  *
4094  * RETURN     : int32_t type of status
4095  *              NO_ERROR  -- success
4096  *              none-zero failure code
4097  *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame)4098  int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame)
4099 {
4100     int32_t rc = 0;
4101     int index;
4102     OfflineBuffer mappedBuffer;
4103 
4104     if (m_numStreams < 1) {
4105         ALOGE("%s: No reprocess stream is created", __func__);
4106         return -1;
4107     }
4108 
4109     if (NULL == frame) {
4110         ALOGE("%s: Incorrect input frame", __func__);
4111         return BAD_VALUE;
4112     }
4113 
4114     if (NULL == frame->metadata_buffer.buffer) {
4115         ALOGE("%s: No metadata available", __func__);
4116         return BAD_VALUE;
4117     }
4118 
4119     if (NULL == frame->input_buffer.buffer) {
4120         ALOGE("%s: No input buffer available", __func__);
4121         return BAD_VALUE;
4122     }
4123 
4124     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4125         ALOGE("%s: Reprocess stream not initialized!", __func__);
4126         return NO_INIT;
4127     }
4128 
4129     QCamera3Stream *pStream = mStreams[0];
4130 
4131     //qbuf the output buffer if it was allocated by the framework
4132     if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4133         if(!m_bIsActive) {
4134             rc = registerBuffer(frame->output_buffer, mIsType);
4135             if (NO_ERROR != rc) {
4136                 ALOGE("%s: On-the-fly buffer registration failed %d",
4137                         __func__, rc);
4138                 return rc;
4139             }
4140 
4141             rc = start();
4142             if (NO_ERROR != rc) {
4143                 return rc;
4144             }
4145         }
4146         index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4147         if(index < 0) {
4148             rc = registerBuffer(frame->output_buffer, mIsType);
4149             if (NO_ERROR != rc) {
4150                 ALOGE("%s: On-the-fly buffer registration failed %d",
4151                         __func__, rc);
4152                 return rc;
4153             }
4154 
4155             index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4156             if (index < 0) {
4157                 ALOGE("%s: Could not find object among registered buffers",
4158                         __func__);
4159                 return DEAD_OBJECT;
4160             }
4161         }
4162         rc = pStream->bufDone(index);
4163         if(rc != NO_ERROR) {
4164             ALOGE("%s: Failed to Q new buffer to stream",__func__);
4165             return rc;
4166         }
4167         rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4168 
4169     } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4170         Mutex::Autolock lock(mFreeBuffersLock);
4171         uint32_t bufIdx;
4172         if (mFreeBufferList.empty()) {
4173             rc = mMemory->allocateOne(mFrameLen);
4174             if (rc < 0) {
4175                 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
4176                 return BAD_VALUE;
4177             } else {
4178                 bufIdx = (uint32_t)rc;
4179             }
4180         } else {
4181             bufIdx = *(mFreeBufferList.begin());
4182             mFreeBufferList.erase(mFreeBufferList.begin());
4183         }
4184 
4185         mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4186         rc = pStream->bufDone(bufIdx);
4187         if (rc != NO_ERROR) {
4188             ALOGE("%s: Failed to queue new buffer to stream", __func__);
4189             return rc;
4190         }
4191     }
4192 
4193     int32_t max_idx = (int32_t) (mNumBuffers - 1);
4194     //loop back the indices if max burst count reached
4195     if (mOfflineBuffersIndex == max_idx) {
4196        mOfflineBuffersIndex = -1;
4197     }
4198     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4199     rc = pStream->mapBuf(
4200             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4201             buf_idx, -1,
4202             frame->input_buffer.fd, frame->input_buffer.frame_len);
4203     if (NO_ERROR == rc) {
4204         mappedBuffer.index = buf_idx;
4205         mappedBuffer.stream = pStream;
4206         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4207         mOfflineBuffers.push_back(mappedBuffer);
4208         mOfflineBuffersIndex = (int32_t)buf_idx;
4209         CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex);
4210     }
4211 
4212     max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4213     //loop back the indices if max burst count reached
4214     if (mOfflineMetaIndex == max_idx) {
4215        mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4216     }
4217     uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4218     rc |= pStream->mapBuf(
4219             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4220             meta_buf_idx, -1,
4221             frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
4222     if (NO_ERROR == rc) {
4223         mappedBuffer.index = meta_buf_idx;
4224         mappedBuffer.stream = pStream;
4225         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4226         mOfflineMetaBuffers.push_back(mappedBuffer);
4227         mOfflineMetaIndex = (int32_t)meta_buf_idx;
4228         CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex);
4229     }
4230 
4231     if (rc == NO_ERROR) {
4232         cam_stream_parm_buffer_t param;
4233         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4234         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4235         param.reprocess.buf_index = buf_idx;
4236         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4237         param.reprocess.meta_present = 1;
4238         param.reprocess.meta_buf_index = meta_buf_idx;
4239         rc = pStream->setParameter(param);
4240         if (rc != NO_ERROR) {
4241             ALOGE("%s: stream setParameter for reprocess failed", __func__);
4242         }
4243     } else {
4244         ALOGE("%s: Input buffer memory map failed: %d", __func__, rc);
4245     }
4246 
4247     if (rc != NO_ERROR) {
4248         //Try to recover by returning input with error status
4249         camera3_stream_buffer_t result;
4250         memset(&result, 0, sizeof(result));
4251         result.status = CAMERA3_BUFFER_STATUS_ERROR;
4252         mChannelCB(NULL, &result, frame->frameNumber, true, mUserData);
4253     }
4254 
4255     return rc;
4256 }
4257 
4258 /*===========================================================================
4259  * FUNCTION   : doReprocess
4260  *
4261  * DESCRIPTION: request to do a reprocess on the frame
4262  *
4263  * PARAMETERS :
4264  *   @buf_fd     : fd to the input buffer that needs reprocess
4265  *   @buf_lenght : length of the input buffer
4266  *   @ret_val    : result of reprocess.
4267  *                 Example: Could be faceID in case of register face image.
4268  *   @meta_frame : metadata frame.
4269  *
4270  * RETURN     : int32_t type of status
4271  *              NO_ERROR  -- success
4272  *              none-zero failure code
4273  *==========================================================================*/
doReprocess(int buf_fd,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4274 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length,
4275         int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4276 {
4277     int32_t rc = 0;
4278     if (m_numStreams < 1) {
4279         ALOGE("%s: No reprocess stream is created", __func__);
4280         return -1;
4281     }
4282     if (meta_frame == NULL) {
4283         ALOGE("%s: Did not get corresponding metadata in time", __func__);
4284         return -1;
4285     }
4286 
4287     uint8_t buf_idx = 0;
4288     for (uint32_t i = 0; i < m_numStreams; i++) {
4289         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4290                                  buf_idx, -1,
4291                                  buf_fd, buf_length);
4292 
4293         if (rc == NO_ERROR) {
4294             cam_stream_parm_buffer_t param;
4295             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4296             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4297             param.reprocess.buf_index = buf_idx;
4298             param.reprocess.meta_present = 1;
4299             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4300             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4301             rc = mStreams[i]->setParameter(param);
4302             if (rc == NO_ERROR) {
4303                 ret_val = param.reprocess.ret_val;
4304             }
4305             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4306                                   buf_idx, -1);
4307         }
4308     }
4309     return rc;
4310 }
4311 
4312 /*===========================================================================
4313  * FUNCTION   : addReprocStreamsFromSource
4314  *
4315  * DESCRIPTION: add reprocess streams from input source channel
4316  *
4317  * PARAMETERS :
4318  *   @config         : pp feature configuration
4319  *   @src_config     : source reprocess configuration
4320  *   @isType         : type of image stabilization required on this stream
4321  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
4322  *
4323  *
4324  * RETURN     : int32_t type of status
4325  *              NO_ERROR  -- success
4326  *              none-zero failure code
4327  *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4328 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4329         const reprocess_config_t &src_config , cam_is_type_t is_type,
4330         QCamera3Channel *pMetaChannel)
4331 {
4332     int32_t rc = 0;
4333     cam_stream_reproc_config_t reprocess_config;
4334     cam_stream_type_t streamType;
4335 
4336     cam_dimension_t streamDim = src_config.output_stream_dim;
4337 
4338     if (NULL != src_config.src_channel) {
4339         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4340         if (pSrcStream == NULL) {
4341            ALOGE("%s: source channel doesn't have a stream", __func__);
4342            return BAD_VALUE;
4343         }
4344         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4345     }
4346 
4347     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4348     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4349 
4350     reprocess_config.offline.input_fmt = src_config.stream_format;
4351     reprocess_config.offline.input_dim = src_config.input_stream_dim;
4352     reprocess_config.offline.input_buf_planes.plane_info =
4353             src_config.input_stream_plane_info.plane_info;
4354     reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4355     reprocess_config.offline.input_type = src_config.stream_type;
4356 
4357     reprocess_config.pp_feature_config = pp_config;
4358     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4359             m_handle,
4360             m_camOps,
4361             mPaddingInfo,
4362             (QCamera3Channel*)this);
4363     if (pStream == NULL) {
4364         ALOGE("%s: No mem for Stream", __func__);
4365         return NO_MEMORY;
4366     }
4367 
4368     rc = pStream->init(streamType, src_config.stream_format,
4369             streamDim, ROTATE_0, &reprocess_config,
4370             (uint8_t)mNumBuffers,
4371             reprocess_config.pp_feature_config.feature_mask,
4372             is_type,
4373             0,/* batchSize */
4374             QCamera3Channel::streamCbRoutine, this);
4375 
4376     if (rc == 0) {
4377         mStreams[m_numStreams] = pStream;
4378         m_numStreams++;
4379     } else {
4380         ALOGE("%s: failed to create reprocess stream", __func__);
4381         delete pStream;
4382     }
4383 
4384     if (rc == NO_ERROR) {
4385         m_pSrcChannel = src_config.src_channel;
4386         m_pMetaChannel = pMetaChannel;
4387         mReprocessType = src_config.reprocess_type;
4388         CDBG("%s: mReprocessType is %d", __func__, mReprocessType);
4389     }
4390     if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
4391         ALOGE("%s: Request for super buffer failed",__func__);
4392     }
4393     return rc;
4394 }
4395 
4396 /* QCamera3SupportChannel methods */
4397 
4398 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4399 
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)4400 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4401                     uint32_t channel_handle,
4402                     mm_camera_ops_t *cam_ops,
4403                     cam_padding_info_t *paddingInfo,
4404                     uint32_t postprocess_mask,
4405                     cam_stream_type_t streamType,
4406                     cam_dimension_t *dim,
4407                     cam_format_t streamFormat,
4408                     void *userData, uint32_t numBuffers) :
4409                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
4410                                 NULL, paddingInfo, postprocess_mask,
4411                                 userData, numBuffers),
4412                         mMemory(NULL)
4413 {
4414     memcpy(&mDim, dim, sizeof(cam_dimension_t));
4415     mStreamType = streamType;
4416     mStreamFormat = streamFormat;
4417 }
4418 
~QCamera3SupportChannel()4419 QCamera3SupportChannel::~QCamera3SupportChannel()
4420 {
4421     if (m_bIsActive)
4422         stop();
4423 
4424     if (mMemory) {
4425         mMemory->deallocate();
4426         delete mMemory;
4427         mMemory = NULL;
4428     }
4429 }
4430 
initialize(cam_is_type_t isType)4431 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4432 {
4433     int32_t rc;
4434 
4435     if (mMemory || m_numStreams > 0) {
4436         ALOGE("%s: metadata channel already initialized", __func__);
4437         return -EINVAL;
4438     }
4439 
4440     mIsType = isType;
4441     rc = QCamera3Channel::addStream(mStreamType,
4442         mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4443         mPostProcMask, mIsType);
4444     if (rc < 0) {
4445         ALOGE("%s: addStream failed", __func__);
4446     }
4447     return rc;
4448 }
4449 
request(buffer_handle_t *,uint32_t)4450 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4451                                                 uint32_t /*frameNumber*/)
4452 {
4453     return NO_ERROR;
4454 }
4455 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)4456 void QCamera3SupportChannel::streamCbRoutine(
4457                         mm_camera_super_buf_t *super_frame,
4458                         QCamera3Stream * /*stream*/)
4459 {
4460     if (super_frame == NULL || super_frame->num_bufs != 1) {
4461         ALOGE("%s: super_frame is not valid", __func__);
4462         return;
4463     }
4464     bufDone(super_frame);
4465     free(super_frame);
4466 }
4467 
getStreamBufs(uint32_t len)4468 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4469 {
4470     int rc;
4471     mMemory = new QCamera3StreamMem(mNumBuffers);
4472     if (!mMemory) {
4473         ALOGE("%s: unable to create heap memory", __func__);
4474         return NULL;
4475     }
4476     rc = mMemory->allocateAll(len);
4477     if (rc < 0) {
4478         ALOGE("%s: unable to allocate heap memory", __func__);
4479         delete mMemory;
4480         mMemory = NULL;
4481         return NULL;
4482     }
4483     return mMemory;
4484 }
4485 
putStreamBufs()4486 void QCamera3SupportChannel::putStreamBufs()
4487 {
4488     mMemory->deallocate();
4489     delete mMemory;
4490     mMemory = NULL;
4491 }
4492 
4493 }; // namespace qcamera
4494