• 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 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)1804 void QCamera3RawChannel::streamCbRoutine(
1805                         mm_camera_super_buf_t *super_frame,
1806                         QCamera3Stream * stream)
1807 {
1808     ATRACE_CALL();
1809     /* Move this back down once verified */
1810     if (mRawDump)
1811         dumpRawSnapshot(super_frame->bufs[0]);
1812 
1813     if (mIsRaw16) {
1814         if (RAW_FORMAT == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
1815             convertMipiToRaw16(super_frame->bufs[0]);
1816         else
1817             convertLegacyToRaw16(super_frame->bufs[0]);
1818     }
1819 
1820     //Make sure cache coherence because extra processing is done
1821     mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
1822 
1823     QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
1824     return;
1825 }
1826 
dumpRawSnapshot(mm_camera_buf_def_t * frame)1827 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
1828 {
1829    QCamera3Stream *stream = getStreamByIndex(0);
1830    if (stream != NULL) {
1831        char buf[FILENAME_MAX];
1832        memset(buf, 0, sizeof(buf));
1833        cam_dimension_t dim;
1834        memset(&dim, 0, sizeof(dim));
1835        stream->getFrameDimension(dim);
1836 
1837        cam_frame_len_offset_t offset;
1838        memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1839        stream->getFrameOffset(offset);
1840        snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
1841                 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
1842 
1843        int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
1844        if (file_fd >= 0) {
1845           ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
1846           ALOGE("%s: written number of bytes %zd", __func__, written_len);
1847           close(file_fd);
1848        } else {
1849           ALOGE("%s: failed to open file to dump image", __func__);
1850        }
1851    } else {
1852        ALOGE("%s: Could not find stream", __func__);
1853    }
1854 
1855 }
1856 
convertLegacyToRaw16(mm_camera_buf_def_t * frame)1857 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
1858 {
1859     // Convert image buffer from Opaque raw format to RAW16 format
1860     // 10bit Opaque raw is stored in the format of:
1861     // 0000 - p5 - p4 - p3 - p2 - p1 - p0
1862     // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
1863     // 4 bits are 0s. Each 64bit word contains 6 pixels.
1864 
1865   QCamera3Stream *stream = getStreamByIndex(0);
1866   if (stream != NULL) {
1867       cam_dimension_t dim;
1868       memset(&dim, 0, sizeof(dim));
1869       stream->getFrameDimension(dim);
1870 
1871       cam_frame_len_offset_t offset;
1872       memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1873       stream->getFrameOffset(offset);
1874 
1875       uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
1876       uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
1877 
1878       // In-place format conversion.
1879       // Raw16 format always occupy more memory than opaque raw10.
1880       // Convert to Raw16 by iterating through all pixels from bottom-right
1881       // to top-left of the image.
1882       // One special notes:
1883       // 1. Cross-platform raw16's stride is 16 pixels.
1884       // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
1885       for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
1886           uint32_t y = (uint32_t)ys;
1887           uint64_t* row_start = (uint64_t *)frame->buffer +
1888                   y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
1889           for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
1890               uint32_t x = (uint32_t)xs;
1891               uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
1892               raw16_buffer[y*raw16_stride+x] = raw16_pixel;
1893           }
1894       }
1895   } else {
1896       ALOGE("%s: Could not find stream", __func__);
1897   }
1898 
1899 }
1900 
convertMipiToRaw16(mm_camera_buf_def_t * frame)1901 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
1902 {
1903     // Convert image buffer from mipi10 raw format to RAW16 format
1904     // mipi10 opaque raw is stored in the format of:
1905     // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
1906     // 4 pixels occupy 5 bytes, no padding needed
1907 
1908     QCamera3Stream *stream = getStreamByIndex(0);
1909     if (stream != NULL) {
1910         cam_dimension_t dim;
1911         memset(&dim, 0, sizeof(dim));
1912         stream->getFrameDimension(dim);
1913 
1914         cam_frame_len_offset_t offset;
1915         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1916         stream->getFrameOffset(offset);
1917 
1918         uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
1919         uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
1920 
1921         // Some raw processing may be needed prior to conversion.
1922         static bool raw_proc_lib_load_attempted = false;
1923         static void *raw_proc_lib = NULL;
1924         static void *raw_proc_fn = NULL;
1925         if (! raw_proc_lib && ! raw_proc_lib_load_attempted) {
1926             raw_proc_lib_load_attempted = true;
1927             raw_proc_lib = dlopen("libgoog_rownr.so", RTLD_NOW);
1928             if (raw_proc_lib) {
1929                 *(void **)&raw_proc_fn = dlsym(raw_proc_lib, "rownr_process_bayer10");
1930             }
1931         }
1932         if (raw_proc_fn) {
1933             int (*raw_proc)(unsigned char*,int,int,int,int) =
1934                       (int (*)(unsigned char*,int,int,int,int))(raw_proc_fn);
1935             raw_proc((unsigned char*)(frame->buffer), 0, dim.width, dim.height,
1936                        offset.mp[0].stride_in_bytes);
1937         }
1938 
1939         // In-place format conversion.
1940         // Raw16 format always occupy more memory than opaque raw10.
1941         // Convert to Raw16 by iterating through all pixels from bottom-right
1942         // to top-left of the image.
1943         // One special notes:
1944         // 1. Cross-platform raw16's stride is 16 pixels.
1945         // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
1946         for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
1947             uint32_t y = (uint32_t)ys;
1948             uint8_t* row_start = (uint8_t *)frame->buffer +
1949                     y * (uint32_t)offset.mp[0].stride_in_bytes;
1950             for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
1951                 uint32_t x = (uint32_t)xs;
1952                 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
1953                 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
1954                 uint16_t raw16_pixel =
1955                         (uint16_t)(((uint16_t)upper_8bit)<<2 |
1956                         (uint16_t)lower_2bit);
1957                 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
1958             }
1959         }
1960     } else {
1961         ALOGE("%s: Could not find stream", __func__);
1962     }
1963 
1964 }
1965 
1966 /*===========================================================================
1967  * FUNCTION   : getReprocessType
1968  *
1969  * DESCRIPTION: get the type of reprocess output supported by this channel
1970  *
1971  * PARAMETERS : NONE
1972  *
1973  * RETURN     : reprocess_type_t : type of reprocess
1974  *==========================================================================*/
getReprocessType()1975 reprocess_type_t QCamera3RawChannel::getReprocessType()
1976 {
1977     return REPROCESS_TYPE_RAW;
1978 }
1979 
1980 
1981 /*************************************************************************************/
1982 // RAW Dump Channel related functions
1983 
1984 /*===========================================================================
1985  * FUNCTION   : QCamera3RawDumpChannel
1986  *
1987  * DESCRIPTION: Constructor for RawDumpChannel
1988  *
1989  * PARAMETERS :
1990  *   @cam_handle    : Handle for Camera
1991  *   @cam_ops       : Function pointer table
1992  *   @rawDumpSize   : Dimensions for the Raw stream
1993  *   @paddinginfo   : Padding information for stream
1994  *   @userData      : Cookie for parent
1995  *   @pp mask       : PP feature mask for this stream
1996  *   @numBuffers    : number of max dequeued buffers
1997  *
1998  * RETURN           : NA
1999  *==========================================================================*/
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)2000 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2001                     uint32_t channel_handle,
2002                     mm_camera_ops_t *cam_ops,
2003                     cam_dimension_t rawDumpSize,
2004                     cam_padding_info_t *paddingInfo,
2005                     void *userData,
2006                     uint32_t postprocess_mask, uint32_t numBuffers) :
2007                         QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2008                                 paddingInfo, postprocess_mask,
2009                                 userData, numBuffers),
2010                         mDim(rawDumpSize),
2011                         mMemory(NULL)
2012 {
2013     char prop[PROPERTY_VALUE_MAX];
2014     property_get("persist.camera.raw.dump", prop, "0");
2015     mRawDump = atoi(prop);
2016 }
2017 
2018 /*===========================================================================
2019  * FUNCTION   : QCamera3RawDumpChannel
2020  *
2021  * DESCRIPTION: Destructor for RawDumpChannel
2022  *
2023  * PARAMETERS :
2024  *
2025  * RETURN           : NA
2026  *==========================================================================*/
2027 
~QCamera3RawDumpChannel()2028 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2029 {
2030 }
2031 
2032 /*===========================================================================
2033  * FUNCTION   : dumpRawSnapshot
2034  *
2035  * DESCRIPTION: Helper function to dump Raw frames
2036  *
2037  * PARAMETERS :
2038  *  @frame      : stream buf frame to be dumped
2039  *
2040  *  RETURN      : NA
2041  *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2042 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2043 {
2044     QCamera3Stream *stream = getStreamByIndex(0);
2045     if (stream != NULL) {
2046         char buf[FILENAME_MAX];
2047         struct timeval tv;
2048         struct tm timeinfo_data;
2049         struct tm *timeinfo;
2050 
2051         cam_dimension_t dim;
2052         memset(&dim, 0, sizeof(dim));
2053         stream->getFrameDimension(dim);
2054 
2055         cam_frame_len_offset_t offset;
2056         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2057         stream->getFrameOffset(offset);
2058 
2059         gettimeofday(&tv, NULL);
2060         timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2061 
2062         if (NULL != timeinfo) {
2063             memset(buf, 0, sizeof(buf));
2064             snprintf(buf, sizeof(buf),
2065                     QCAMERA_DUMP_FRM_LOCATION
2066                     "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
2067                     timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2068                     timeinfo->tm_mday, timeinfo->tm_hour,
2069                     timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
2070                     frame->frame_idx, dim.width, dim.height);
2071 
2072             int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2073             if (file_fd >= 0) {
2074                 ssize_t written_len =
2075                         write(file_fd, frame->buffer, offset.frame_len);
2076                 CDBG("%s: written number of bytes %zd", __func__, written_len);
2077                 close(file_fd);
2078             } else {
2079                 ALOGE("%s: failed to open file to dump image", __func__);
2080             }
2081         } else {
2082             ALOGE("%s: localtime_r() error", __func__);
2083         }
2084     } else {
2085         ALOGE("%s: Could not find stream", __func__);
2086     }
2087 
2088 }
2089 
2090 /*===========================================================================
2091  * FUNCTION   : streamCbRoutine
2092  *
2093  * DESCRIPTION: Callback routine invoked for each frame generated for
2094  *              Rawdump channel
2095  *
2096  * PARAMETERS :
2097  *   @super_frame  : stream buf frame generated
2098  *   @stream       : Underlying Stream object cookie
2099  *
2100  * RETURN          : NA
2101  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2102 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2103                                                 QCamera3Stream *stream)
2104 {
2105     CDBG("%s: E",__func__);
2106     if (super_frame == NULL || super_frame->num_bufs != 1) {
2107         ALOGE("%s: super_frame is not valid", __func__);
2108         return;
2109     }
2110 
2111     if (mRawDump)
2112         dumpRawSnapshot(super_frame->bufs[0]);
2113 
2114     bufDone(super_frame);
2115     free(super_frame);
2116 }
2117 
2118 /*===========================================================================
2119  * FUNCTION   : getStreamBufs
2120  *
2121  * DESCRIPTION: Callback function provided to interface to get buffers.
2122  *
2123  * PARAMETERS :
2124  *   @len       : Length of each buffer to be allocated
2125  *
2126  * RETURN     : NULL on buffer allocation failure
2127  *              QCamera3StreamMem object on sucess
2128  *==========================================================================*/
getStreamBufs(uint32_t len)2129 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2130 {
2131     int rc;
2132     mMemory = new QCamera3StreamMem(mNumBuffers);
2133 
2134     if (!mMemory) {
2135         ALOGE("%s: unable to create heap memory", __func__);
2136         return NULL;
2137     }
2138     rc = mMemory->allocateAll((size_t)len);
2139     if (rc < 0) {
2140         ALOGE("%s: unable to allocate heap memory", __func__);
2141         delete mMemory;
2142         mMemory = NULL;
2143         return NULL;
2144     }
2145     return mMemory;
2146 }
2147 
2148 /*===========================================================================
2149  * FUNCTION   : putStreamBufs
2150  *
2151  * DESCRIPTION: Callback function provided to interface to return buffers.
2152  *              Although no handles are actually returned, implicitl assumption
2153  *              that interface will no longer use buffers and channel can
2154  *              deallocated if necessary.
2155  *
2156  * PARAMETERS : NA
2157  *
2158  * RETURN     : NA
2159  *==========================================================================*/
putStreamBufs()2160 void QCamera3RawDumpChannel::putStreamBufs()
2161 {
2162     mMemory->deallocate();
2163     delete mMemory;
2164     mMemory = NULL;
2165 }
2166 
2167 /*===========================================================================
2168  * FUNCTION : request
2169  *
2170  * DESCRIPTION: Request function used as trigger
2171  *
2172  * PARAMETERS :
2173  * @recvd_frame : buffer- this will be NULL since this is internal channel
2174  * @frameNumber : Undefined again since this is internal stream
2175  *
2176  * RETURN     : int32_t type of status
2177  *              NO_ERROR  -- success
2178  *              none-zero failure code
2179  *==========================================================================*/
request(buffer_handle_t *,uint32_t)2180 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2181                                                 uint32_t /*frameNumber*/)
2182 {
2183     if (!m_bIsActive) {
2184         return QCamera3Channel::start();
2185     }
2186     else
2187         return 0;
2188 }
2189 
2190 /*===========================================================================
2191  * FUNCTION : intialize
2192  *
2193  * DESCRIPTION: Initializes channel params and creates underlying stream
2194  *
2195  * PARAMETERS :
2196  *    @isType : type of image stabilization required on this stream
2197  *
2198  * RETURN     : int32_t type of status
2199  *              NO_ERROR  -- success
2200  *              none-zero failure code
2201  *==========================================================================*/
initialize(cam_is_type_t isType)2202 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2203 {
2204     int32_t rc;
2205 
2206     mIsType = isType;
2207     rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2208         CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2209         mPostProcMask, mIsType);
2210     if (rc < 0) {
2211         ALOGE("%s: addStream failed", __func__);
2212     }
2213     return rc;
2214 }
2215 /*************************************************************************************/
2216 
2217 /* QCamera3YUVChannel methods */
2218 
2219 /*===========================================================================
2220  * FUNCTION   : QCamera3YUVChannel
2221  *
2222  * DESCRIPTION: constructor of QCamera3YUVChannel
2223  *
2224  * PARAMETERS :
2225  *   @cam_handle : camera handle
2226  *   @cam_ops    : ptr to camera ops table
2227  *   @cb_routine : callback routine to frame aggregator
2228  *   @paddingInfo : padding information for the stream
2229  *   @stream     : camera3_stream_t structure
2230  *   @stream_type: Channel stream type
2231  *   @postprocess_mask: the postprocess mask for streams of this channel
2232  *   @metadataChannel: handle to the metadataChannel
2233  * RETURN     : none
2234  *==========================================================================*/
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)2235 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2236         uint32_t channel_handle,
2237         mm_camera_ops_t *cam_ops,
2238         channel_cb_routine cb_routine,
2239         cam_padding_info_t *paddingInfo,
2240         void *userData,
2241         camera3_stream_t *stream,
2242         cam_stream_type_t stream_type,
2243         uint32_t postprocess_mask,
2244         QCamera3Channel *metadataChannel) :
2245             QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2246                     cb_routine, paddingInfo, userData, stream, stream_type,
2247                     postprocess_mask, metadataChannel)
2248 {
2249 
2250     mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2251     mFrameLen = 0;
2252     mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2253     mEdgeMode.sharpness = 0;
2254     mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2255     memset(&mCropRegion, 0, sizeof(mCropRegion));
2256 }
2257 
2258 /*===========================================================================
2259  * FUNCTION   : ~QCamera3YUVChannel
2260  *
2261  * DESCRIPTION: destructor of QCamera3YUVChannel
2262  *
2263  * PARAMETERS : none
2264  *
2265  *
2266  * RETURN     : none
2267  *==========================================================================*/
~QCamera3YUVChannel()2268 QCamera3YUVChannel::~QCamera3YUVChannel()
2269 {
2270    // Deallocation of heap buffers allocated in mMemory is freed
2271    // automatically by its destructor
2272 }
2273 
2274 /*===========================================================================
2275  * FUNCTION   : initialize
2276  *
2277  * DESCRIPTION: Initialize and add camera channel & stream
2278  *
2279  * PARAMETERS :
2280  * @isType    : the image stabilization type
2281  *
2282  * RETURN     : int32_t type of status
2283  *              NO_ERROR  -- success
2284  *              none-zero failure code
2285  *==========================================================================*/
initialize(cam_is_type_t isType)2286 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2287 {
2288     ATRACE_CALL();
2289     int32_t rc = NO_ERROR;
2290     cam_dimension_t streamDim;
2291 
2292     if (NULL == mCamera3Stream) {
2293         ALOGE("%s: Camera stream uninitialized", __func__);
2294         return NO_INIT;
2295     }
2296 
2297     if (1 <= m_numStreams) {
2298         // Only one stream per channel supported in v3 Hal
2299         return NO_ERROR;
2300     }
2301 
2302     mIsType  = isType;
2303     mStreamFormat = CALLBACK_FORMAT;
2304     streamDim.width = mCamera3Stream->width;
2305     streamDim.height = mCamera3Stream->height;
2306 
2307     rc = QCamera3Channel::addStream(mStreamType,
2308             mStreamFormat,
2309             streamDim,
2310             ROTATE_0,
2311             mNumBufs,
2312             mPostProcMask,
2313             mIsType);
2314     if (rc < 0) {
2315         ALOGE("%s: addStream failed", __func__);
2316         return rc;
2317     }
2318 
2319     cam_stream_buf_plane_info_t buf_planes;
2320     cam_padding_info_t paddingInfo = *mPaddingInfo;
2321 
2322     memset(&buf_planes, 0, sizeof(buf_planes));
2323     //to ensure a big enough buffer size set the height and width
2324     //padding to max(height padding, width padding)
2325     paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2326     paddingInfo.height_padding = paddingInfo.width_padding;
2327 
2328     rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2329             &buf_planes);
2330     if (rc < 0) {
2331         ALOGE("%s: mm_stream_calc_offset_preview failed", __func__);
2332         return rc;
2333     }
2334 
2335     mFrameLen = buf_planes.plane_info.frame_len;
2336 
2337     if (NO_ERROR != rc) {
2338         ALOGE("%s: Initialize failed, rc = %d", __func__, rc);
2339         return rc;
2340     }
2341 
2342     /* initialize offline meta memory for input reprocess */
2343     rc = QCamera3ProcessingChannel::initialize(isType);
2344     if (NO_ERROR != rc) {
2345         ALOGE("%s: Processing Channel initialize failed, rc = %d",
2346                 __func__, rc);
2347     }
2348 
2349     return rc;
2350 }
2351 
2352 /*===========================================================================
2353  * FUNCTION   : request
2354  *
2355  * DESCRIPTION: entry function for a request on a YUV stream. This function
2356  *              has the logic to service a request based on its type
2357  *
2358  * PARAMETERS :
2359  * @buffer          : pointer to the output buffer
2360  * @frameNumber     : frame number of the request
2361  * @pInputBuffer    : pointer to input buffer if an input request
2362  * @metadata        : parameters associated with the request
2363  *
2364  * RETURN     : 0 on a success start of capture
2365  *              -EINVAL on invalid input
2366  *              -ENODEV on serious error
2367  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata)2368 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2369         uint32_t frameNumber,
2370         camera3_stream_buffer_t* pInputBuffer,
2371         metadata_buffer_t* metadata, bool &needMetadata)
2372 {
2373     int32_t rc = NO_ERROR;
2374     int index;
2375     Mutex::Autolock lock(mOfflinePpLock);
2376 
2377     CDBG("%s: pInputBuffer is %p", __func__, pInputBuffer);
2378     CDBG("%s, frame number %d", __func__, frameNumber);
2379     if (NULL == buffer || NULL == metadata) {
2380         ALOGE("%s: Invalid buffer/metadata in channel request", __func__);
2381         return BAD_VALUE;
2382     }
2383 
2384     PpInfo ppInfo;
2385     memset(&ppInfo, 0, sizeof(ppInfo));
2386     ppInfo.frameNumber = frameNumber;
2387     ppInfo.offlinePpFlag = false;
2388     if (mBypass && !pInputBuffer ) {
2389         ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2390         ppInfo.output = buffer;
2391         mOfflinePpInfoList.push_back(ppInfo);
2392     }
2393 
2394     CDBG("%s: offlinePpFlag is %d", __func__, ppInfo.offlinePpFlag);
2395     needMetadata = ppInfo.offlinePpFlag;
2396     if (!ppInfo.offlinePpFlag) {
2397         // regular request
2398         return QCamera3ProcessingChannel::request(buffer, frameNumber,
2399                 pInputBuffer, metadata);
2400     } else {
2401         if(!m_bIsActive) {
2402             rc = start();
2403             if (NO_ERROR != rc)
2404                 return rc;
2405         } else {
2406             CDBG("%s: Request on an existing stream",__func__);
2407         }
2408 
2409         //we need to send this frame through the CPP
2410         //Allocate heap memory, then buf done on the buffer
2411         uint32_t bufIdx;
2412         if (mFreeHeapBufferList.empty()) {
2413             rc = mMemory.allocateOne(mFrameLen);
2414             if (rc < 0) {
2415                 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
2416                 return BAD_VALUE;
2417             } else {
2418                 bufIdx = (uint32_t)rc;
2419             }
2420         } else {
2421             bufIdx = *(mFreeHeapBufferList.begin());
2422             mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2423         }
2424 
2425         /* Configure and start postproc if necessary */
2426         reprocess_config_t reproc_cfg;
2427         cam_dimension_t dim;
2428         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2429         memset(&dim, 0, sizeof(dim));
2430         mStreams[0]->getFrameDimension(dim);
2431         setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2432 
2433         // Start postprocessor without input buffer
2434         startPostProc(reproc_cfg);
2435 
2436         CDBG("%s: erasing %d", __func__, bufIdx);
2437 
2438         mMemory.markFrameNumber(bufIdx, frameNumber);
2439         mStreams[0]->bufDone(bufIdx);
2440 
2441     }
2442     return rc;
2443 }
2444 
2445 /*===========================================================================
2446  * FUNCTION   : streamCbRoutine
2447  *
2448  * DESCRIPTION:
2449  *
2450  * PARAMETERS :
2451  * @super_frame : the super frame with filled buffer
2452  * @stream      : stream on which the buffer was requested and filled
2453  *
2454  * RETURN     : none
2455  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2456 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2457         QCamera3Stream *stream)
2458 {
2459     ATRACE_CALL();
2460     uint8_t frameIndex;
2461     int32_t resultFrameNumber;
2462 
2463     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2464         ALOGE("%s: Error with the stream callback", __func__);
2465         return;
2466     }
2467 
2468     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2469     if(frameIndex >= mNumBufs) {
2470          ALOGE("%s: Error, Invalid index for buffer",__func__);
2471          stream->bufDone(frameIndex);
2472          return;
2473     }
2474 
2475     if (mBypass) {
2476         List<PpInfo>::iterator ppInfo;
2477 
2478         Mutex::Autolock lock(mOfflinePpLock);
2479         resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2480         for (ppInfo = mOfflinePpInfoList.begin();
2481                 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2482             if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2483                 break;
2484             }
2485         }
2486         CDBG("%s, frame index %d, frame number %d", __func__, frameIndex, resultFrameNumber);
2487         //check the reprocessing required flag against the frame number
2488         if (ppInfo == mOfflinePpInfoList.end()) {
2489             ALOGE("%s: Error, request for frame number is a reprocess.", __func__);
2490             stream->bufDone(frameIndex);
2491             return;
2492         }
2493 
2494         if (ppInfo->offlinePpFlag) {
2495             mm_camera_super_buf_t *frame =
2496                     (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
2497             if (frame == NULL) {
2498                 ALOGE("%s: Error allocating memory to save received_frame structure.",
2499                         __func__);
2500                 if(stream) {
2501                     stream->bufDone(frameIndex);
2502                 }
2503                 return;
2504             }
2505 
2506             *frame = *super_frame;
2507             m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
2508             free(super_frame);
2509             return;
2510         } else {
2511             if (ppInfo != mOfflinePpInfoList.begin()) {
2512                 // There is pending reprocess buffer, cache current buffer
2513                 if (ppInfo->callback_buffer != NULL) {
2514                     ALOGE("%s: Fatal: cached callback_buffer is already present",
2515                         __func__);
2516 
2517                 }
2518                 ppInfo->callback_buffer = super_frame;
2519                 return;
2520             } else {
2521                 mOfflinePpInfoList.erase(ppInfo);
2522             }
2523         }
2524     }
2525 
2526     QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2527     return;
2528 }
2529 
2530 /*===========================================================================
2531  * FUNCTION   : reprocessCbRoutine
2532  *
2533  * DESCRIPTION: callback function for the reprocessed frame. This frame now
2534  *              should be returned to the framework. This same callback is
2535  *              used during input reprocessing or offline postprocessing
2536  *
2537  * PARAMETERS :
2538  * @resultBuffer      : buffer containing the reprocessed data
2539  * @resultFrameNumber : frame number on which the buffer was requested
2540  *
2541  * RETURN     : NONE
2542  *
2543  *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2544 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2545         uint32_t resultFrameNumber)
2546 {
2547     CDBG("%s E: frame number %d", __func__, resultFrameNumber);
2548     Vector<mm_camera_super_buf_t *> pendingCbs;
2549 
2550     /* release the input buffer and input metadata buffer if used */
2551     if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2552         /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2553         int32_t rc = releaseOfflineMemory(resultFrameNumber);
2554         if (NO_ERROR != rc) {
2555             ALOGE("%s: Error releasing offline memory rc = %d", __func__, rc);
2556         }
2557         /* Since reprocessing is done, send the callback to release the input buffer */
2558         if (mChannelCB) {
2559             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2560         }
2561     }
2562 
2563     if (mBypass) {
2564         int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2565         if (rc != NO_ERROR) {
2566             return;
2567         }
2568     }
2569 
2570     issueChannelCb(resultBuffer, resultFrameNumber);
2571 
2572     // Call all pending callbacks to return buffers
2573     for (size_t i = 0; i < pendingCbs.size(); i++) {
2574         QCamera3ProcessingChannel::streamCbRoutine(
2575                 pendingCbs[i], mStreams[0]);
2576     }
2577 
2578 }
2579 
2580 /*===========================================================================
2581  * FUNCTION   : needsFramePostprocessing
2582  *
2583  * DESCRIPTION:
2584  *
2585  * PARAMETERS :
2586  *
2587  * RETURN     :
2588  *  TRUE if frame needs to be postprocessed
2589  *  FALSE is frame does not need to be postprocessed
2590  *
2591  *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)2592 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
2593 {
2594     bool ppNeeded = false;
2595 
2596     //sharpness
2597     IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
2598             CAM_INTF_META_EDGE_MODE, meta) {
2599         mEdgeMode = *edgeMode;
2600     }
2601 
2602     //wnr
2603     IF_META_AVAILABLE(uint32_t, noiseRedMode,
2604             CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
2605         mNoiseRedMode = *noiseRedMode;
2606     }
2607 
2608     //crop region
2609     IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
2610             CAM_INTF_META_SCALER_CROP_REGION, meta) {
2611         mCropRegion = *scalerCropRegion;
2612     }
2613 
2614     if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
2615             (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
2616         ppNeeded = true;
2617     }
2618     if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
2619             (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
2620             (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
2621         ppNeeded = true;
2622     }
2623     if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
2624             (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
2625         ppNeeded = true;
2626     }
2627 
2628     return ppNeeded;
2629 }
2630 
2631 /*===========================================================================
2632  * FUNCTION   : handleOfflinePpCallback
2633  *
2634  * DESCRIPTION: callback function for the reprocessed frame from offline
2635  *              postprocessing.
2636  *
2637  * PARAMETERS :
2638  * @resultFrameNumber : frame number on which the buffer was requested
2639  * @pendingCbs        : pending buffers to be returned first
2640  *
2641  * RETURN     : int32_t type of status
2642  *              NO_ERROR  -- success
2643  *              none-zero failure code
2644  *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)2645 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
2646             Vector<mm_camera_super_buf_t *>& pendingCbs)
2647 {
2648     Mutex::Autolock lock(mOfflinePpLock);
2649     List<PpInfo>::iterator ppInfo;
2650 
2651     for (ppInfo = mOfflinePpInfoList.begin();
2652             ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2653         if (ppInfo->frameNumber == resultFrameNumber) {
2654             break;
2655         }
2656     }
2657 
2658     if (ppInfo == mOfflinePpInfoList.end()) {
2659         ALOGI("%s: Request of frame number %d is reprocessing",
2660                 __func__, resultFrameNumber);
2661         return NO_ERROR;
2662     } else if (ppInfo != mOfflinePpInfoList.begin()) {
2663         ALOGE("%s: callback for frame number %d should be head of list",
2664                 __func__, resultFrameNumber);
2665         return BAD_VALUE;
2666     }
2667 
2668     if (ppInfo->offlinePpFlag) {
2669         // Need to get the input buffer frame index from the
2670         // mMemory object and add that to the free heap buffers list.
2671         int32_t bufferIndex =
2672                 mMemory.getHeapBufferIndex(resultFrameNumber);
2673         if (bufferIndex < 0) {
2674             ALOGE("%s: Fatal %d: no buffer index for frame number %d",
2675                     __func__, bufferIndex, resultFrameNumber);
2676             return BAD_VALUE;
2677         }
2678         mFreeHeapBufferList.push_back(bufferIndex);
2679         ppInfo = mOfflinePpInfoList.erase(ppInfo);
2680 
2681         // Return pending buffer callbacks
2682         while (ppInfo != mOfflinePpInfoList.end() &&
2683                 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
2684 
2685             // Call stream callbacks for cached buffers
2686             pendingCbs.push_back(ppInfo->callback_buffer);
2687 
2688             ppInfo = mOfflinePpInfoList.erase(ppInfo);
2689         }
2690 
2691     } else {
2692         ALOGE("%s: Fatal: request of frame number %d doesn't need"
2693                 " offline postprocessing. However there is"
2694                 " reprocessing callback.", __func__,
2695                 resultFrameNumber);
2696         return BAD_VALUE;
2697     }
2698 
2699     return NO_ERROR;
2700 }
2701 
2702 /*===========================================================================
2703  * FUNCTION   : getReprocessType
2704  *
2705  * DESCRIPTION: get the type of reprocess output supported by this channel
2706  *
2707  * PARAMETERS : NONE
2708  *
2709  * RETURN     : reprocess_type_t : type of reprocess
2710  *==========================================================================*/
getReprocessType()2711 reprocess_type_t QCamera3YUVChannel::getReprocessType()
2712 {
2713     return REPROCESS_TYPE_YUV;
2714 }
2715 
2716 /* QCamera3PicChannel methods */
2717 
2718 /*===========================================================================
2719  * FUNCTION   : jpegEvtHandle
2720  *
2721  * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
2722                 Construct result payload and call mChannelCb to deliver buffer
2723                 to framework.
2724  *
2725  * PARAMETERS :
2726  *   @status    : status of jpeg job
2727  *   @client_hdl: jpeg client handle
2728  *   @jobId     : jpeg job Id
2729  *   @p_ouput   : ptr to jpeg output result struct
2730  *   @userdata  : user data ptr
2731  *
2732  * RETURN     : none
2733  *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)2734 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
2735                                               uint32_t /*client_hdl*/,
2736                                               uint32_t jobId,
2737                                               mm_jpeg_output_t *p_output,
2738                                               void *userdata)
2739 {
2740     ATRACE_CALL();
2741     buffer_handle_t *resultBuffer = NULL;
2742     buffer_handle_t *jpegBufferHandle = NULL;
2743     int resultStatus = CAMERA3_BUFFER_STATUS_OK;
2744     camera3_stream_buffer_t result;
2745     camera3_jpeg_blob_t jpegHeader;
2746 
2747     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
2748     if (obj) {
2749         //Construct payload for process_capture_result. Call mChannelCb
2750 
2751         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
2752 
2753         if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
2754             ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
2755             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
2756         }
2757 
2758         if (NULL != job) {
2759             uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
2760             CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx);
2761 
2762             //Construct jpeg transient header of type camera3_jpeg_blob_t
2763             //Append at the end of jpeg image of buf_filled_len size
2764 
2765             jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
2766             if (JPEG_JOB_STATUS_DONE == status) {
2767                 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
2768                 char* jpeg_buf = (char *)p_output->buf_vaddr;
2769 
2770                 ssize_t maxJpegSize = -1;
2771 
2772                 // Gralloc buffer may have additional padding for 4K page size
2773                 // Follow size guidelines based on spec since framework relies
2774                 // on that to reach end of buffer and with it the header
2775 
2776                 //Handle same as resultBuffer, but for readablity
2777                 jpegBufferHandle =
2778                         (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
2779 
2780                 if (NULL != jpegBufferHandle) {
2781                     maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
2782                     if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
2783                         maxJpegSize = obj->mMemory.getSize(bufIdx);
2784                     }
2785 
2786                     size_t jpeg_eof_offset =
2787                             (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
2788                     char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
2789                     memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
2790                     obj->mMemory.cleanInvalidateCache(bufIdx);
2791                 } else {
2792                     ALOGE("%s: JPEG buffer not found and index: %d",
2793                             __func__,
2794                             bufIdx);
2795                     resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
2796                 }
2797             }
2798 
2799             ////Use below data to issue framework callback
2800             resultBuffer =
2801                     (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
2802             int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
2803             int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
2804             if (NO_ERROR != rc) {
2805                 ALOGE("%s: Error %d unregistering stream buffer %d",
2806                     __func__, rc, bufIdx);
2807             }
2808 
2809             result.stream = obj->mCamera3Stream;
2810             result.buffer = resultBuffer;
2811             result.status = resultStatus;
2812             result.acquire_fence = -1;
2813             result.release_fence = -1;
2814 
2815             // Release any snapshot buffers before calling
2816             // the user callback. The callback can potentially
2817             // unblock pending requests to snapshot stream.
2818             int32_t snapshotIdx = -1;
2819             mm_camera_super_buf_t* src_frame = NULL;
2820 
2821             if (job->src_reproc_frame)
2822                 src_frame = job->src_reproc_frame;
2823             else
2824                 src_frame = job->src_frame;
2825 
2826             if (src_frame) {
2827                 if (obj->mStreams[0]->getMyHandle() ==
2828                         src_frame->bufs[0]->stream_id) {
2829                     snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
2830                 } else {
2831                     ALOGE("%s: Snapshot stream id %d and source frame %d don't match!",
2832                             __func__, obj->mStreams[0]->getMyHandle(),
2833                             src_frame->bufs[0]->stream_id);
2834                 }
2835             }
2836             if (0 <= snapshotIdx) {
2837                 Mutex::Autolock lock(obj->mFreeBuffersLock);
2838                 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
2839             } else {
2840                 ALOGE("%s: Snapshot buffer not found!", __func__);
2841             }
2842 
2843             CDBG("%s: Issue Callback", __func__);
2844             if (obj->mChannelCB) {
2845                 obj->mChannelCB(NULL,
2846                         &result,
2847                         (uint32_t)resultFrameNumber,
2848                         false,
2849                         obj->mUserData);
2850             }
2851 
2852             // release internal data for jpeg job
2853             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
2854                 /* unregister offline input buffer */
2855                 int32_t inputBufIndex =
2856                         obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
2857                 if (0 <= inputBufIndex) {
2858                     rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
2859                 } else {
2860                     ALOGE("%s: could not find the input buf index, frame number %d",
2861                             __func__, resultFrameNumber);
2862                 }
2863                 if (NO_ERROR != rc) {
2864                     ALOGE("%s: Error %d unregistering input buffer %d",
2865                             __func__, rc, bufIdx);
2866                 }
2867 
2868                 /* unregister offline meta buffer */
2869                 int32_t metaBufIndex =
2870                         obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
2871                 if (0 <= metaBufIndex) {
2872                     Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
2873                     obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
2874                 } else {
2875                     ALOGE("%s: could not find the input meta buf index, frame number %d",
2876                             __func__, resultFrameNumber);
2877                 }
2878             }
2879             obj->m_postprocessor.releaseOfflineBuffers();
2880             obj->m_postprocessor.releaseJpegJobData(job);
2881             free(job);
2882         }
2883 
2884         return;
2885         // }
2886     } else {
2887         ALOGE("%s: Null userdata in jpeg callback", __func__);
2888     }
2889 }
2890 
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)2891 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
2892                     uint32_t channel_handle,
2893                     mm_camera_ops_t *cam_ops,
2894                     channel_cb_routine cb_routine,
2895                     cam_padding_info_t *paddingInfo,
2896                     void *userData,
2897                     camera3_stream_t *stream,
2898                     uint32_t postprocess_mask,
2899                     bool is4KVideo,
2900                     bool isInputStreamConfigured,
2901                     QCamera3Channel *metadataChannel,
2902                     uint32_t numBuffers) :
2903                         QCamera3ProcessingChannel(cam_handle, channel_handle,
2904                                 cam_ops, cb_routine, paddingInfo, userData,
2905                                 stream, CAM_STREAM_TYPE_SNAPSHOT,
2906                                 postprocess_mask, metadataChannel, numBuffers),
2907                         mNumSnapshotBufs(0),
2908                         mInputBufferHint(isInputStreamConfigured),
2909                         mYuvMemory(NULL),
2910                         mFrameLen(0)
2911 {
2912     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
2913     m_max_pic_dim = hal_obj->calcMaxJpegDim();
2914     mYuvWidth = stream->width;
2915     mYuvHeight = stream->height;
2916     mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
2917     // Use same pixelformat for 4K video case
2918     mStreamFormat = is4KVideo ? VIDEO_FORMAT : SNAPSHOT_FORMAT;
2919     int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
2920     if (rc != 0) {
2921         ALOGE("Init Postprocessor failed");
2922     }
2923 }
2924 
~QCamera3PicChannel()2925 QCamera3PicChannel::~QCamera3PicChannel()
2926 {
2927 }
2928 
initialize(cam_is_type_t isType)2929 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
2930 {
2931     int32_t rc = NO_ERROR;
2932     cam_dimension_t streamDim;
2933     cam_stream_type_t streamType;
2934     cam_format_t streamFormat;
2935     mm_camera_channel_attr_t attr;
2936 
2937     if (NULL == mCamera3Stream) {
2938         ALOGE("%s: Camera stream uninitialized", __func__);
2939         return NO_INIT;
2940     }
2941 
2942     if (1 <= m_numStreams) {
2943         // Only one stream per channel supported in v3 Hal
2944         return NO_ERROR;
2945     }
2946 
2947     mIsType = isType;
2948     streamType = mStreamType;
2949     streamFormat = mStreamFormat;
2950     streamDim.width = (int32_t)mYuvWidth;
2951     streamDim.height = (int32_t)mYuvHeight;
2952 
2953     mNumSnapshotBufs = mCamera3Stream->max_buffers;
2954     rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
2955             ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
2956             mIsType);
2957 
2958     if (NO_ERROR != rc) {
2959         ALOGE("%s: Initialize failed, rc = %d", __func__, rc);
2960         return rc;
2961     }
2962 
2963     /* initialize offline meta memory for input reprocess */
2964     rc = QCamera3ProcessingChannel::initialize(isType);
2965     if (NO_ERROR != rc) {
2966         ALOGE("%s: Processing Channel initialize failed, rc = %d",
2967                 __func__, rc);
2968     }
2969 
2970     return rc;
2971 }
2972 
2973 /*===========================================================================
2974  * FUNCTION   : request
2975  *
2976  * DESCRIPTION: handle the request - either with an input buffer or a direct
2977  *              output request
2978  *
2979  * PARAMETERS :
2980  * @buffer       : pointer to the output buffer
2981  * @frameNumber  : frame number of the request
2982  * @pInputBuffer : pointer to input buffer if an input request
2983  * @metadata     : parameters associated with the request
2984  *
2985  * RETURN     : 0 on a success start of capture
2986  *              -EINVAL on invalid input
2987  *              -ENODEV on serious error
2988  *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata)2989 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
2990         uint32_t frameNumber,
2991         camera3_stream_buffer_t *pInputBuffer,
2992         metadata_buffer_t *metadata)
2993 {
2994     ATRACE_CALL();
2995     //FIX ME: Return buffer back in case of failures below.
2996 
2997     int32_t rc = NO_ERROR;
2998 
2999     reprocess_config_t reproc_cfg;
3000     cam_dimension_t dim;
3001     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3002     //make sure to set the correct input stream dim in case of YUV size override
3003     //and recalculate the plane info
3004     dim.width = (int32_t)mYuvWidth;
3005     dim.height = (int32_t)mYuvHeight;
3006     setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3007 
3008     // Picture stream has already been started before any request comes in
3009     if (!m_bIsActive) {
3010         ALOGE("%s: Channel not started!!", __func__);
3011         return NO_INIT;
3012     }
3013 
3014     int index = mMemory.getMatchBufIndex((void*)buffer);
3015 
3016     if(index < 0) {
3017         rc = registerBuffer(buffer, mIsType);
3018         if (NO_ERROR != rc) {
3019             ALOGE("%s: On-the-fly buffer registration failed %d",
3020                     __func__, rc);
3021             return rc;
3022         }
3023 
3024         index = mMemory.getMatchBufIndex((void*)buffer);
3025         if (index < 0) {
3026             ALOGE("%s: Could not find object among registered buffers",__func__);
3027             return DEAD_OBJECT;
3028         }
3029     }
3030     CDBG("%s: buffer index %d, frameNumber: %u", __func__, index, frameNumber);
3031 
3032     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3033 
3034     // Start postprocessor
3035     startPostProc(reproc_cfg);
3036 
3037     // Queue jpeg settings
3038     rc = queueJpegSetting((uint32_t)index, metadata);
3039 
3040     if (pInputBuffer == NULL) {
3041         Mutex::Autolock lock(mFreeBuffersLock);
3042         uint32_t bufIdx;
3043         if (mFreeBufferList.empty()) {
3044             rc = mYuvMemory->allocateOne(mFrameLen);
3045             if (rc < 0) {
3046                 ALOGE("%s: Failed to allocate heap buffer. Fatal", __func__);
3047                 return rc;
3048             } else {
3049                 bufIdx = (uint32_t)rc;
3050             }
3051         } else {
3052             List<uint32_t>::iterator it = mFreeBufferList.begin();
3053             bufIdx = *it;
3054             mFreeBufferList.erase(it);
3055         }
3056         mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3057         mStreams[0]->bufDone(bufIdx);
3058     } else {
3059         qcamera_fwk_input_pp_data_t *src_frame = NULL;
3060         src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3061                 sizeof(qcamera_fwk_input_pp_data_t));
3062         if (src_frame == NULL) {
3063             ALOGE("%s: No memory for src frame", __func__);
3064             return NO_MEMORY;
3065         }
3066         rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3067                 NULL /*fwk output buffer*/, frameNumber);
3068         if (NO_ERROR != rc) {
3069             ALOGE("%s: Error %d while setting framework input PP data", __func__, rc);
3070             free(src_frame);
3071             return rc;
3072         }
3073         CDBG_HIGH("%s: Post-process started", __func__);
3074         CDBG_HIGH("%s: Issue call to reprocess", __func__);
3075         m_postprocessor.processData(src_frame);
3076     }
3077     return rc;
3078 }
3079 
3080 
3081 /*===========================================================================
3082  * FUNCTION   : dataNotifyCB
3083  *
3084  * DESCRIPTION: Channel Level callback used for super buffer data notify.
3085  *              This function is registered with mm-camera-interface to handle
3086  *              data notify
3087  *
3088  * PARAMETERS :
3089  *   @recvd_frame   : stream frame received
3090  *   userdata       : user data ptr
3091  *
3092  * RETURN     : none
3093  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3094 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3095                                  void *userdata)
3096 {
3097     ATRACE_CALL();
3098     CDBG("%s: E\n", __func__);
3099     QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3100 
3101     if (channel == NULL) {
3102         ALOGE("%s: invalid channel pointer", __func__);
3103         return;
3104     }
3105 
3106     if(channel->m_numStreams != 1) {
3107         ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
3108         return;
3109     }
3110 
3111 
3112     if(channel->mStreams[0] == NULL) {
3113         ALOGE("%s: Error: Invalid Stream object",__func__);
3114         return;
3115     }
3116 
3117     channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3118 
3119     CDBG("%s: X\n", __func__);
3120     return;
3121 }
3122 
3123 /*===========================================================================
3124  * FUNCTION   : streamCbRoutine
3125  *
3126  * DESCRIPTION:
3127  *
3128  * PARAMETERS :
3129  * @super_frame : the super frame with filled buffer
3130  * @stream      : stream on which the buffer was requested and filled
3131  *
3132  * RETURN     : none
3133  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3134 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3135                             QCamera3Stream *stream)
3136 {
3137     ATRACE_CALL();
3138     //TODO
3139     //Used only for getting YUV. Jpeg callback will be sent back from channel
3140     //directly to HWI. Refer to func jpegEvtHandle
3141 
3142     //Got the yuv callback. Calling yuv callback handler in PostProc
3143     uint8_t frameIndex;
3144     mm_camera_super_buf_t* frame = NULL;
3145 
3146     if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3147         ALOGE("%s: Error with the stream callback", __func__);
3148         return;
3149     }
3150 
3151     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3152     CDBG("%s: recvd buf_idx: %u for further processing",
3153         __func__, (uint32_t)frameIndex);
3154     if(frameIndex >= mNumSnapshotBufs) {
3155          ALOGE("%s: Error, Invalid index for buffer",__func__);
3156          if(stream) {
3157              Mutex::Autolock lock(mFreeBuffersLock);
3158              mFreeBufferList.push_back(frameIndex);
3159              stream->bufDone(frameIndex);
3160          }
3161          return;
3162     }
3163 
3164     frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3165     if (frame == NULL) {
3166        ALOGE("%s: Error allocating memory to save received_frame structure.",
3167                                                                     __func__);
3168        if(stream) {
3169            Mutex::Autolock lock(mFreeBuffersLock);
3170            mFreeBufferList.push_back(frameIndex);
3171            stream->bufDone(frameIndex);
3172        }
3173        return;
3174     }
3175     *frame = *super_frame;
3176 
3177     if (mYUVDump) {
3178         cam_dimension_t dim;
3179         memset(&dim, 0, sizeof(dim));
3180         stream->getFrameDimension(dim);
3181         cam_frame_len_offset_t offset;
3182         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3183         stream->getFrameOffset(offset);
3184         dumpYUV(frame->bufs[0], dim, offset, 1);
3185     }
3186 
3187     m_postprocessor.processData(frame);
3188     free(super_frame);
3189     return;
3190 }
3191 
getStreamBufs(uint32_t len)3192 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3193 {
3194     int rc = 0;
3195 
3196     mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3197     if (!mYuvMemory) {
3198         ALOGE("%s: unable to create metadata memory", __func__);
3199         return NULL;
3200     }
3201     mFrameLen = len;
3202 
3203     return mYuvMemory;
3204 }
3205 
putStreamBufs()3206 void QCamera3PicChannel::putStreamBufs()
3207 {
3208     QCamera3ProcessingChannel::putStreamBufs();
3209 
3210     mYuvMemory->deallocate();
3211     delete mYuvMemory;
3212     mYuvMemory = NULL;
3213     mFreeBufferList.clear();
3214 }
3215 
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3216 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3217 {
3218     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3219     jpeg_settings_t *settings =
3220             (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3221 
3222     if (!settings) {
3223         ALOGE("%s: out of memory allocating jpeg_settings", __func__);
3224         return -ENOMEM;
3225     }
3226 
3227     memset(settings, 0, sizeof(jpeg_settings_t));
3228 
3229     settings->out_buf_index = index;
3230 
3231     settings->jpeg_orientation = 0;
3232     IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3233         settings->jpeg_orientation = *orientation;
3234     }
3235 
3236     settings->jpeg_quality = 85;
3237     IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3238         settings->jpeg_quality = (uint8_t) *quality1;
3239     }
3240 
3241     IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3242         settings->jpeg_thumb_quality = (uint8_t) *quality2;
3243     }
3244 
3245     IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3246         settings->thumbnail_size = *dimension;
3247     }
3248 
3249     settings->gps_timestamp_valid = 0;
3250     IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3251         settings->gps_timestamp = *timestamp;
3252         settings->gps_timestamp_valid = 1;
3253     }
3254 
3255     settings->gps_coordinates_valid = 0;
3256     IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3257         memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3258         settings->gps_coordinates_valid = 1;
3259     }
3260 
3261     IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3262         memset(settings->gps_processing_method, 0,
3263                 sizeof(settings->gps_processing_method));
3264         strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3265                 sizeof(settings->gps_processing_method));
3266     }
3267 
3268     // Image description
3269     const char *eepromVersion = hal_obj->getEepromVersionInfo();
3270     const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3271     if ((eepromVersion && strlen(eepromVersion)) ||
3272             ldafCalib) {
3273         int len = 0;
3274         settings->image_desc_valid = true;
3275         if (eepromVersion && strlen(eepromVersion)) {
3276             len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3277                     "M:%s ", eepromVersion);
3278         }
3279         if (ldafCalib) {
3280             snprintf(settings->image_desc + len,
3281                     sizeof(settings->image_desc) - len, "L:%u-%u",
3282                     ldafCalib[0], ldafCalib[1]);
3283         }
3284     }
3285 
3286     return m_postprocessor.processJpegSettingData(settings);
3287 }
3288 
3289 /*===========================================================================
3290  * FUNCTION   : overrideYuvSize
3291  *
3292  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3293  *
3294  * PARAMETERS :
3295  *   @width     : new width
3296  *   @height    : new height
3297  *
3298  * RETURN     : none
3299  *==========================================================================*/
overrideYuvSize(uint32_t width,uint32_t height)3300 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3301 {
3302    mYuvWidth = width;
3303    mYuvHeight = height;
3304 }
3305 
3306 /*===========================================================================
3307  * FUNCTION   : getReprocessType
3308  *
3309  * DESCRIPTION: get the type of reprocess output supported by this channel
3310  *
3311  * PARAMETERS : NONE
3312  *
3313  * RETURN     : reprocess_type_t : type of reprocess
3314  *==========================================================================*/
getReprocessType()3315 reprocess_type_t QCamera3PicChannel::getReprocessType()
3316 {
3317     /* a picture channel could either use the postprocessor for reprocess+jpeg
3318        or only for reprocess */
3319     reprocess_type_t expectedReprocess;
3320     if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3321         expectedReprocess = REPROCESS_TYPE_JPEG;
3322     } else {
3323         expectedReprocess = REPROCESS_TYPE_NONE;
3324     }
3325     CDBG_HIGH("%s: expectedReprocess from Pic Channel is %d", __func__, expectedReprocess);
3326     return expectedReprocess;
3327 }
3328 
3329 /* Reprocess Channel methods */
3330 
3331 /*===========================================================================
3332  * FUNCTION   : QCamera3ReprocessChannel
3333  *
3334  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3335  *
3336  * PARAMETERS :
3337  *   @cam_handle : camera handle
3338  *   @cam_ops    : ptr to camera ops table
3339  *   @pp_mask    : post-proccess feature mask
3340  *
3341  * RETURN     : none
3342  *==========================================================================*/
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)3343 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3344                                                  uint32_t channel_handle,
3345                                                  mm_camera_ops_t *cam_ops,
3346                                                  channel_cb_routine cb_routine,
3347                                                  cam_padding_info_t *paddingInfo,
3348                                                  uint32_t postprocess_mask,
3349                                                  void *userData, void *ch_hdl) :
3350     /* In case of framework reprocessing, pproc and jpeg operations could be
3351      * parallelized by allowing 1 extra buffer for reprocessing output:
3352      * ch_hdl->getNumBuffers() + 1 */
3353     QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, paddingInfo,
3354                     postprocess_mask, userData,
3355                     ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3356                               + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3357     inputChHandle(ch_hdl),
3358     mOfflineBuffersIndex(-1),
3359     mFrameLen(0),
3360     mReprocessType(REPROCESS_TYPE_NONE),
3361     m_pSrcChannel(NULL),
3362     m_pMetaChannel(NULL),
3363     mMemory(NULL),
3364     mGrallocMemory(0)
3365 {
3366     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3367     mOfflineBuffersIndex = mNumBuffers -1;
3368     mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3369 }
3370 
3371 
3372 /*===========================================================================
3373  * FUNCTION   : QCamera3ReprocessChannel
3374  *
3375  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3376  *
3377  * PARAMETERS :
3378  *   @cam_handle : camera handle
3379  *   @cam_ops    : ptr to camera ops table
3380  *   @pp_mask    : post-proccess feature mask
3381  *
3382  * RETURN     : none
3383  *==========================================================================*/
initialize(cam_is_type_t isType)3384 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3385 {
3386     int32_t rc = NO_ERROR;
3387     mm_camera_channel_attr_t attr;
3388 
3389     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3390     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3391     attr.max_unmatched_frames = 1;
3392 
3393     m_handle = m_camOps->add_channel(m_camHandle,
3394                                       &attr,
3395                                       NULL,
3396                                       this);
3397     if (m_handle == 0) {
3398         ALOGE("%s: Add channel failed", __func__);
3399         return UNKNOWN_ERROR;
3400     }
3401 
3402     mIsType = isType;
3403     return rc;
3404 }
3405 
3406 /*===========================================================================
3407  * FUNCTION   : registerBuffer
3408  *
3409  * DESCRIPTION: register streaming buffer to the channel object
3410  *
3411  * PARAMETERS :
3412  *   @buffer     : buffer to be registered
3413  *   @isType     : the image stabilization type for the buffer
3414  *
3415  * RETURN     : int32_t type of status
3416  *              NO_ERROR  -- success
3417  *              none-zero failure code
3418  *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3419 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3420         cam_is_type_t isType)
3421 {
3422     ATRACE_CALL();
3423     int rc = 0;
3424     mIsType = isType;
3425     cam_stream_type_t streamType;
3426 
3427     if (buffer == NULL) {
3428         ALOGE("%s: Error: Cannot register a NULL buffer", __func__);
3429         return BAD_VALUE;
3430     }
3431 
3432     if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3433         ALOGE("%s: Trying to register more buffers than initially requested",
3434                 __func__);
3435         return BAD_VALUE;
3436     }
3437 
3438     if (0 == m_numStreams) {
3439         rc = initialize(mIsType);
3440         if (rc != NO_ERROR) {
3441             ALOGE("%s: Couldn't initialize camera stream %d",
3442                     __func__, rc);
3443             return rc;
3444         }
3445     }
3446 
3447     streamType = mStreams[0]->getMyType();
3448     rc = mGrallocMemory.registerBuffer(buffer, streamType);
3449     if (ALREADY_EXISTS == rc) {
3450         return NO_ERROR;
3451     } else if (NO_ERROR != rc) {
3452         ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
3453         return rc;
3454     }
3455 
3456     return rc;
3457 }
3458 
3459 /*===========================================================================
3460  * FUNCTION   : QCamera3ReprocessChannel
3461  *
3462  * DESCRIPTION: constructor of QCamera3ReprocessChannel
3463  *
3464  * PARAMETERS :
3465  *   @cam_handle : camera handle
3466  *   @cam_ops    : ptr to camera ops table
3467  *   @pp_mask    : post-proccess feature mask
3468  *
3469  * RETURN     : none
3470  *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3471 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3472                                   QCamera3Stream *stream)
3473 {
3474     //Got the pproc data callback. Now send to jpeg encoding
3475     uint8_t frameIndex;
3476     uint32_t resultFrameNumber;
3477     mm_camera_super_buf_t* frame = NULL;
3478     QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
3479 
3480     if(!super_frame) {
3481          ALOGE("%s: Invalid Super buffer",__func__);
3482          return;
3483     }
3484 
3485     if(super_frame->num_bufs != 1) {
3486          ALOGE("%s: Multiple streams are not supported",__func__);
3487          return;
3488     }
3489     if(super_frame->bufs[0] == NULL ) {
3490          ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
3491                   __func__);
3492          return;
3493     }
3494     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3495 
3496     if (mYUVDump) {
3497         cam_dimension_t dim;
3498         memset(&dim, 0, sizeof(dim));
3499         stream->getFrameDimension(dim);
3500         cam_frame_len_offset_t offset;
3501         memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3502         stream->getFrameOffset(offset);
3503         dumpYUV(super_frame->bufs[0], dim, offset, 2);
3504     }
3505 
3506     if (mReprocessType == REPROCESS_TYPE_JPEG) {
3507         resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
3508         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3509         if (frame == NULL) {
3510            ALOGE("%s: Error allocating memory to save received_frame structure.",
3511                                                                         __func__);
3512            if(stream) {
3513                stream->bufDone(frameIndex);
3514            }
3515            return;
3516         }
3517         CDBG("%s: bufIndex: %u recvd from post proc",
3518             __func__, (uint32_t)frameIndex);
3519         *frame = *super_frame;
3520 
3521         /* Since reprocessing is done, send the callback to release the input buffer */
3522         if (mChannelCB) {
3523             mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
3524         }
3525         obj->m_postprocessor.processPPData(frame);
3526     } else {
3527         buffer_handle_t *resultBuffer;
3528         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3529         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
3530         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
3531         int32_t rc = stream->bufRelease(frameIndex);
3532         if (NO_ERROR != rc) {
3533             ALOGE("%s: Error %d releasing stream buffer %d",
3534                     __func__, rc, frameIndex);
3535         }
3536         rc = mGrallocMemory.unregisterBuffer(frameIndex);
3537         if (NO_ERROR != rc) {
3538             ALOGE("%s: Error %d unregistering stream buffer %d",
3539                     __func__, rc, frameIndex);
3540         }
3541         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
3542 
3543         obj->m_postprocessor.releaseOfflineBuffers();
3544         qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
3545         if (pp_job != NULL) {
3546             obj->m_postprocessor.releasePPJobData(pp_job);
3547         }
3548         free(pp_job);
3549     }
3550     free(super_frame);
3551     return;
3552 }
3553 
3554 /*===========================================================================
3555  * FUNCTION   : getStreamBufs
3556  *
3557  * DESCRIPTION: register the buffers of the reprocess channel
3558  *
3559  * PARAMETERS : none
3560  *
3561  * RETURN     : QCamera3StreamMem *
3562  *==========================================================================*/
getStreamBufs(uint32_t len)3563 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
3564 {
3565     int rc = 0;
3566     if (mReprocessType == REPROCESS_TYPE_JPEG) {
3567         mMemory = new QCamera3StreamMem(mNumBuffers, false);
3568         if (!mMemory) {
3569             ALOGE("%s: unable to create reproc memory", __func__);
3570             return NULL;
3571         }
3572         mFrameLen = len;
3573         return mMemory;
3574     }
3575     return &mGrallocMemory;
3576 }
3577 
3578 /*===========================================================================
3579  * FUNCTION   : putStreamBufs
3580  *
3581  * DESCRIPTION: release the reprocess channel buffers
3582  *
3583  * PARAMETERS : none
3584  *
3585  * RETURN     :
3586  *==========================================================================*/
putStreamBufs()3587 void QCamera3ReprocessChannel::putStreamBufs()
3588 {
3589    if (mReprocessType == REPROCESS_TYPE_JPEG) {
3590        mMemory->deallocate();
3591        delete mMemory;
3592        mMemory = NULL;
3593        mFreeBufferList.clear();
3594    } else {
3595        mGrallocMemory.unregisterBuffers();
3596    }
3597 }
3598 
3599 /*===========================================================================
3600  * FUNCTION   : ~QCamera3ReprocessChannel
3601  *
3602  * DESCRIPTION: destructor of QCamera3ReprocessChannel
3603  *
3604  * PARAMETERS : none
3605  *
3606  * RETURN     : none
3607  *==========================================================================*/
~QCamera3ReprocessChannel()3608 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
3609 {
3610     if (m_bIsActive)
3611         stop();
3612 
3613     for (uint32_t i = 0; i < m_numStreams; i++) {
3614         if (mStreams[i] != NULL) {
3615             delete mStreams[i];
3616             mStreams[i] = 0;
3617         }
3618     }
3619     if (m_handle) {
3620         m_camOps->delete_channel(m_camHandle, m_handle);
3621         ALOGE("%s: deleting channel %d", __func__, m_handle);
3622         m_handle = 0;
3623     }
3624     m_numStreams = 0;
3625 }
3626 
3627 /*===========================================================================
3628  * FUNCTION   : start
3629  *
3630  * DESCRIPTION: start reprocess channel.
3631  *
3632  * PARAMETERS :
3633  *
3634  * RETURN     : int32_t type of status
3635  *              NO_ERROR  -- success
3636  *              none-zero failure code
3637  *==========================================================================*/
start()3638 int32_t QCamera3ReprocessChannel::start()
3639 {
3640     ATRACE_CALL();
3641     int32_t rc = NO_ERROR;
3642 
3643     rc = QCamera3Channel::start();
3644 
3645     if (rc == NO_ERROR) {
3646        rc = m_camOps->start_channel(m_camHandle, m_handle);
3647 
3648        // Check failure
3649        if (rc != NO_ERROR) {
3650            ALOGE("%s: start_channel failed %d", __func__, rc);
3651            QCamera3Channel::stop();
3652        }
3653     }
3654     return rc;
3655 }
3656 
3657 /*===========================================================================
3658  * FUNCTION   : stop
3659  *
3660  * DESCRIPTION: stop reprocess channel.
3661  *
3662  * PARAMETERS : none
3663  *
3664  * RETURN     : int32_t type of status
3665  *              NO_ERROR  -- success
3666  *              none-zero failure code
3667  *==========================================================================*/
stop()3668 int32_t QCamera3ReprocessChannel::stop()
3669 {
3670     ATRACE_CALL();
3671     int32_t rc = NO_ERROR;
3672 
3673     rc = QCamera3Channel::stop();
3674 
3675     rc != m_camOps->stop_channel(m_camHandle, m_handle);
3676 
3677     unmapOfflineBuffers(true);
3678 
3679     return rc;
3680 }
3681 
3682 /*===========================================================================
3683  * FUNCTION   : getStreamBySrcHandle
3684  *
3685  * DESCRIPTION: find reprocess stream by its source stream handle
3686  *
3687  * PARAMETERS :
3688  *   @srcHandle : source stream handle
3689  *
3690  * RETURN     : ptr to reprocess stream if found. NULL if not found
3691  *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)3692 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
3693 {
3694     QCamera3Stream *pStream = NULL;
3695 
3696     for (uint32_t i = 0; i < m_numStreams; i++) {
3697         if (mSrcStreamHandles[i] == srcHandle) {
3698             pStream = mStreams[i];
3699             break;
3700         }
3701     }
3702     return pStream;
3703 }
3704 
3705 /*===========================================================================
3706  * FUNCTION   : getSrcStreamBySrcHandle
3707  *
3708  * DESCRIPTION: find source stream by source stream handle
3709  *
3710  * PARAMETERS :
3711  *   @srcHandle : source stream handle
3712  *
3713  * RETURN     : ptr to reprocess stream if found. NULL if not found
3714  *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)3715 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
3716 {
3717     QCamera3Stream *pStream = NULL;
3718 
3719     if (NULL == m_pSrcChannel) {
3720         return NULL;
3721     }
3722 
3723     for (uint32_t i = 0; i < m_numStreams; i++) {
3724         if (mSrcStreamHandles[i] == srcHandle) {
3725             pStream = m_pSrcChannel->getStreamByIndex(i);
3726             break;
3727         }
3728     }
3729     return pStream;
3730 }
3731 
3732 /*===========================================================================
3733  * FUNCTION   : unmapOfflineBuffers
3734  *
3735  * DESCRIPTION: Unmaps offline buffers
3736  *
3737  * PARAMETERS : none
3738  *
3739  * RETURN     : int32_t type of status
3740  *              NO_ERROR  -- success
3741  *              none-zero failure code
3742  *==========================================================================*/
unmapOfflineBuffers(bool all)3743 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
3744 {
3745     int rc = NO_ERROR;
3746     if (!mOfflineBuffers.empty()) {
3747         QCamera3Stream *stream = NULL;
3748         List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
3749         for (; it != mOfflineBuffers.end(); it++) {
3750            stream = (*it).stream;
3751            if (NULL != stream) {
3752                rc = stream->unmapBuf((*it).type,
3753                                      (*it).index,
3754                                         -1);
3755                if (NO_ERROR != rc) {
3756                    ALOGE("%s: Error during offline buffer unmap %d",
3757                          __func__, rc);
3758                }
3759                CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index);
3760            }
3761            if (!all) {
3762                mOfflineBuffers.erase(it);
3763                break;
3764            }
3765         }
3766         if (all) {
3767            mOfflineBuffers.clear();
3768         }
3769     }
3770 
3771     if (!mOfflineMetaBuffers.empty()) {
3772         QCamera3Stream *stream = NULL;
3773         List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
3774         for (; it != mOfflineMetaBuffers.end(); it++) {
3775            stream = (*it).stream;
3776            if (NULL != stream) {
3777                rc = stream->unmapBuf((*it).type,
3778                                      (*it).index,
3779                                         -1);
3780                if (NO_ERROR != rc) {
3781                    ALOGE("%s: Error during offline buffer unmap %d",
3782                          __func__, rc);
3783                }
3784                CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index);
3785            }
3786            if (!all) {
3787                mOfflineMetaBuffers.erase(it);
3788                break;
3789            }
3790         }
3791         if (all) {
3792            mOfflineMetaBuffers.clear();
3793         }
3794     }
3795     return rc;
3796 }
3797 
3798 /*===========================================================================
3799  * FUNCTION   : bufDone
3800  *
3801  * DESCRIPTION: Return reprocess stream buffer to free buffer list.
3802  *              Note that this function doesn't queue buffer back to kernel.
3803  *              It's up to doReprocessOffline to do that instead.
3804  * PARAMETERS :
3805  *   @recvd_frame  : stream buf frame to be returned
3806  *
3807  * RETURN     : int32_t type of status
3808  *              NO_ERROR  -- success
3809  *              none-zero failure code
3810  *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)3811 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
3812 {
3813     int rc = NO_ERROR;
3814     if (recvd_frame && recvd_frame->num_bufs == 1) {
3815         Mutex::Autolock lock(mFreeBuffersLock);
3816         uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
3817         mFreeBufferList.push_back(buf_idx);
3818 
3819     } else {
3820         ALOGE("%s: Fatal. Not supposed to be here", __func__);
3821         rc = BAD_VALUE;
3822     }
3823 
3824     return rc;
3825 }
3826 
3827 /*===========================================================================
3828  * FUNCTION   : overrideMetadata
3829  *
3830  * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
3831  *
3832  * PARAMETERS :
3833  *   @frame     : input frame from source stream
3834  *   meta_buffer: metadata buffer
3835  *   @metadata  : corresponding metadata
3836  *   @fwk_frame :
3837  *
3838  * RETURN     : int32_t type of status
3839  *              NO_ERROR  -- success
3840  *              none-zero failure code
3841  *==========================================================================*/
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)3842 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
3843         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
3844         qcamera_fwk_input_pp_data_t &fwk_frame)
3845 {
3846     int32_t rc = NO_ERROR;
3847     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3848     if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
3849             (NULL == hal_obj)) {
3850         return BAD_VALUE;
3851     }
3852 
3853     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
3854     mm_camera_super_buf_t *frame = pp_buffer->input;
3855     if (NULL == meta) {
3856         return BAD_VALUE;
3857     }
3858 
3859     for (uint32_t i = 0; i < frame->num_bufs; i++) {
3860         QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
3861         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
3862 
3863         if (pStream != NULL && pSrcStream != NULL) {
3864             if (jpeg_settings) {
3865                 // Find rotation info for reprocess stream
3866                 cam_rotation_info_t rotation_info;
3867                 memset(&rotation_info, 0, sizeof(rotation_info));
3868                 if (jpeg_settings->jpeg_orientation == 0) {
3869                    rotation_info.rotation = ROTATE_0;
3870                 } else if (jpeg_settings->jpeg_orientation == 90) {
3871                    rotation_info.rotation = ROTATE_90;
3872                 } else if (jpeg_settings->jpeg_orientation == 180) {
3873                    rotation_info.rotation = ROTATE_180;
3874                 } else if (jpeg_settings->jpeg_orientation == 270) {
3875                    rotation_info.rotation = ROTATE_270;
3876                 }
3877                 rotation_info.streamId = mStreams[0]->getMyServerID();
3878                 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
3879             }
3880 
3881             // Find and insert crop info for reprocess stream
3882             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
3883                 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
3884                     for (int j = 0; j < crop_data->num_of_streams; j++) {
3885                         if (crop_data->crop_info[j].stream_id ==
3886                                 pSrcStream->getMyServerID()) {
3887 
3888                             // Store crop/roi information for offline reprocess
3889                             // in the reprocess stream slot
3890                             crop_data->crop_info[crop_data->num_of_streams].crop =
3891                                     crop_data->crop_info[j].crop;
3892                             crop_data->crop_info[crop_data->num_of_streams].roi_map =
3893                                     crop_data->crop_info[j].roi_map;
3894                             crop_data->crop_info[crop_data->num_of_streams].stream_id =
3895                                     mStreams[0]->getMyServerID();
3896                             crop_data->num_of_streams++;
3897 
3898                             CDBG("%s: Reprocess stream server id: %d",
3899                                     __func__, mStreams[0]->getMyServerID());
3900                             CDBG("%s: Found offline reprocess crop %dx%d %dx%d",
3901                                     __func__,
3902                                     crop_data->crop_info[j].crop.left,
3903                                     crop_data->crop_info[j].crop.top,
3904                                     crop_data->crop_info[j].crop.width,
3905                                     crop_data->crop_info[j].crop.height);
3906                             CDBG("%s: Found offline reprocess roimap %dx%d %dx%d",
3907                                     __func__,
3908                                     crop_data->crop_info[j].roi_map.left,
3909                                     crop_data->crop_info[j].roi_map.top,
3910                                     crop_data->crop_info[j].roi_map.width,
3911                                     crop_data->crop_info[j].roi_map.height);
3912 
3913                             break;
3914                         }
3915                     }
3916                 } else {
3917                     ALOGE("%s: No space to add reprocess stream crop/roi information",
3918                             __func__);
3919                 }
3920             }
3921 
3922             IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
3923                 uint8_t cnt = cdsInfo->num_of_streams;
3924                 if (cnt <= MAX_NUM_STREAMS) {
3925                     cam_stream_cds_info_t repro_cds_info;
3926                     memset(&repro_cds_info, 0, sizeof(repro_cds_info));
3927                     repro_cds_info.stream_id = mStreams[0]->getMyServerID();
3928                     for (size_t i = 0; i < cnt; i++) {
3929                         if (cdsInfo->cds_info[i].stream_id ==
3930                                 pSrcStream->getMyServerID()) {
3931                             repro_cds_info.cds_enable =
3932                                     cdsInfo->cds_info[i].cds_enable;
3933                             break;
3934                         }
3935                     }
3936                     cdsInfo->num_of_streams = 1;
3937                     cdsInfo->cds_info[0] = repro_cds_info;
3938                 } else {
3939                     ALOGE("%s: No space to add reprocess stream cds information",
3940                             __func__);
3941                 }
3942             }
3943 
3944             fwk_frame.input_buffer = *frame->bufs[i];
3945             fwk_frame.metadata_buffer = *meta_buffer;
3946             fwk_frame.output_buffer = pp_buffer->output;
3947             break;
3948         } else {
3949             ALOGE("%s: Source/Re-process streams are invalid", __func__);
3950             rc |= BAD_VALUE;
3951         }
3952     }
3953 
3954     return rc;
3955 }
3956 
3957 /*===========================================================================
3958 * FUNCTION : overrideFwkMetadata
3959 *
3960 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
3961 *
3962 * PARAMETERS :
3963 * @frame : input frame for reprocessing
3964 *
3965 * RETURN : int32_t type of status
3966 * NO_ERROR -- success
3967 * none-zero failure code
3968 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)3969 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
3970         qcamera_fwk_input_pp_data_t *frame)
3971 {
3972     if (NULL == frame) {
3973         ALOGE("%s: Incorrect input frame", __func__);
3974         return BAD_VALUE;
3975     }
3976 
3977 
3978     if (NULL == frame->metadata_buffer.buffer) {
3979         ALOGE("%s: No metadata available", __func__);
3980         return BAD_VALUE;
3981     }
3982 
3983     // Find and insert crop info for reprocess stream
3984     metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
3985     IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
3986         if (1 == crop_data->num_of_streams) {
3987             // Store crop/roi information for offline reprocess
3988             // in the reprocess stream slot
3989             crop_data->crop_info[crop_data->num_of_streams].crop =
3990                     crop_data->crop_info[0].crop;
3991             crop_data->crop_info[crop_data->num_of_streams].roi_map =
3992                     crop_data->crop_info[0].roi_map;
3993             crop_data->crop_info[crop_data->num_of_streams].stream_id =
3994                     mStreams[0]->getMyServerID();
3995             crop_data->num_of_streams++;
3996 
3997             CDBG("%s: Reprocess stream server id: %d",
3998                     __func__, mStreams[0]->getMyServerID());
3999             CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
4000                     crop_data->crop_info[0].crop.left,
4001                     crop_data->crop_info[0].crop.top,
4002                     crop_data->crop_info[0].crop.width,
4003                     crop_data->crop_info[0].crop.height);
4004             CDBG("%s: Found offline reprocess roi map %dx%d %dx%d", __func__,
4005                     crop_data->crop_info[0].roi_map.left,
4006                     crop_data->crop_info[0].roi_map.top,
4007                     crop_data->crop_info[0].roi_map.width,
4008                     crop_data->crop_info[0].roi_map.height);
4009         } else {
4010             ALOGE("%s: Incorrect number of offline crop data entries %d",
4011                     __func__,
4012                     crop_data->num_of_streams);
4013             return BAD_VALUE;
4014         }
4015     } else {
4016         CDBG_HIGH("%s: Crop data not present", __func__);
4017     }
4018 
4019     IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4020         if (1 == cdsInfo->num_of_streams) {
4021             cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4022         } else {
4023             ALOGE("%s: Incorrect number of offline cds info entries %d",
4024                     __func__, cdsInfo->num_of_streams);
4025             return BAD_VALUE;
4026         }
4027     }
4028 
4029     return NO_ERROR;
4030 }
4031 
4032 /*===========================================================================
4033  * FUNCTION   : doReprocessOffline
4034  *
4035  * DESCRIPTION: request to do a reprocess on the frame
4036  *
4037  * PARAMETERS :
4038  *   @frame     : input frame for reprocessing
4039  *
4040  * RETURN     : int32_t type of status
4041  *              NO_ERROR  -- success
4042  *              none-zero failure code
4043  *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame)4044  int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame)
4045 {
4046     int32_t rc = 0;
4047     int index;
4048     OfflineBuffer mappedBuffer;
4049 
4050     if (m_numStreams < 1) {
4051         ALOGE("%s: No reprocess stream is created", __func__);
4052         return -1;
4053     }
4054 
4055     if (NULL == frame) {
4056         ALOGE("%s: Incorrect input frame", __func__);
4057         return BAD_VALUE;
4058     }
4059 
4060     if (NULL == frame->metadata_buffer.buffer) {
4061         ALOGE("%s: No metadata available", __func__);
4062         return BAD_VALUE;
4063     }
4064 
4065     if (NULL == frame->input_buffer.buffer) {
4066         ALOGE("%s: No input buffer available", __func__);
4067         return BAD_VALUE;
4068     }
4069 
4070     if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4071         ALOGE("%s: Reprocess stream not initialized!", __func__);
4072         return NO_INIT;
4073     }
4074 
4075     QCamera3Stream *pStream = mStreams[0];
4076 
4077     //qbuf the output buffer if it was allocated by the framework
4078     if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4079         if(!m_bIsActive) {
4080             rc = registerBuffer(frame->output_buffer, mIsType);
4081             if (NO_ERROR != rc) {
4082                 ALOGE("%s: On-the-fly buffer registration failed %d",
4083                         __func__, rc);
4084                 return rc;
4085             }
4086 
4087             rc = start();
4088             if (NO_ERROR != rc) {
4089                 return rc;
4090             }
4091         }
4092         index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4093         if(index < 0) {
4094             rc = registerBuffer(frame->output_buffer, mIsType);
4095             if (NO_ERROR != rc) {
4096                 ALOGE("%s: On-the-fly buffer registration failed %d",
4097                         __func__, rc);
4098                 return rc;
4099             }
4100 
4101             index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4102             if (index < 0) {
4103                 ALOGE("%s: Could not find object among registered buffers",
4104                         __func__);
4105                 return DEAD_OBJECT;
4106             }
4107         }
4108         rc = pStream->bufDone(index);
4109         if(rc != NO_ERROR) {
4110             ALOGE("%s: Failed to Q new buffer to stream",__func__);
4111             return rc;
4112         }
4113         rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4114 
4115     } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4116         Mutex::Autolock lock(mFreeBuffersLock);
4117         uint32_t bufIdx;
4118         if (mFreeBufferList.empty()) {
4119             rc = mMemory->allocateOne(mFrameLen);
4120             if (rc < 0) {
4121                 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
4122                 return BAD_VALUE;
4123             } else {
4124                 bufIdx = (uint32_t)rc;
4125             }
4126         } else {
4127             bufIdx = *(mFreeBufferList.begin());
4128             mFreeBufferList.erase(mFreeBufferList.begin());
4129         }
4130 
4131         mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4132         rc = pStream->bufDone(bufIdx);
4133         if (rc != NO_ERROR) {
4134             ALOGE("%s: Failed to queue new buffer to stream", __func__);
4135             return rc;
4136         }
4137     }
4138 
4139     int32_t max_idx = (int32_t) (mNumBuffers - 1);
4140     //loop back the indices if max burst count reached
4141     if (mOfflineBuffersIndex == max_idx) {
4142        mOfflineBuffersIndex = -1;
4143     }
4144     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4145     rc = pStream->mapBuf(
4146             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4147             buf_idx, -1,
4148             frame->input_buffer.fd, frame->input_buffer.frame_len);
4149     if (NO_ERROR == rc) {
4150         mappedBuffer.index = buf_idx;
4151         mappedBuffer.stream = pStream;
4152         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4153         mOfflineBuffers.push_back(mappedBuffer);
4154         mOfflineBuffersIndex = (int32_t)buf_idx;
4155         CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex);
4156     }
4157 
4158     max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4159     //loop back the indices if max burst count reached
4160     if (mOfflineMetaIndex == max_idx) {
4161        mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4162     }
4163     uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4164     rc |= pStream->mapBuf(
4165             CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4166             meta_buf_idx, -1,
4167             frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
4168     if (NO_ERROR == rc) {
4169         mappedBuffer.index = meta_buf_idx;
4170         mappedBuffer.stream = pStream;
4171         mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4172         mOfflineMetaBuffers.push_back(mappedBuffer);
4173         mOfflineMetaIndex = (int32_t)meta_buf_idx;
4174         CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex);
4175     }
4176 
4177     if (rc == NO_ERROR) {
4178         cam_stream_parm_buffer_t param;
4179         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4180         param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4181         param.reprocess.buf_index = buf_idx;
4182         param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4183         param.reprocess.meta_present = 1;
4184         param.reprocess.meta_buf_index = meta_buf_idx;
4185         rc = pStream->setParameter(param);
4186         if (rc != NO_ERROR) {
4187             ALOGE("%s: stream setParameter for reprocess failed", __func__);
4188         }
4189     } else {
4190         ALOGE("%s: Input buffer memory map failed: %d", __func__, rc);
4191     }
4192 
4193     return rc;
4194 }
4195 
4196 /*===========================================================================
4197  * FUNCTION   : doReprocess
4198  *
4199  * DESCRIPTION: request to do a reprocess on the frame
4200  *
4201  * PARAMETERS :
4202  *   @buf_fd     : fd to the input buffer that needs reprocess
4203  *   @buf_lenght : length of the input buffer
4204  *   @ret_val    : result of reprocess.
4205  *                 Example: Could be faceID in case of register face image.
4206  *   @meta_frame : metadata frame.
4207  *
4208  * RETURN     : int32_t type of status
4209  *              NO_ERROR  -- success
4210  *              none-zero failure code
4211  *==========================================================================*/
doReprocess(int buf_fd,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4212 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length,
4213         int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4214 {
4215     int32_t rc = 0;
4216     if (m_numStreams < 1) {
4217         ALOGE("%s: No reprocess stream is created", __func__);
4218         return -1;
4219     }
4220     if (meta_frame == NULL) {
4221         ALOGE("%s: Did not get corresponding metadata in time", __func__);
4222         return -1;
4223     }
4224 
4225     uint8_t buf_idx = 0;
4226     for (uint32_t i = 0; i < m_numStreams; i++) {
4227         rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4228                                  buf_idx, -1,
4229                                  buf_fd, buf_length);
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.meta_present = 1;
4237             param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4238             param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4239             rc = mStreams[i]->setParameter(param);
4240             if (rc == NO_ERROR) {
4241                 ret_val = param.reprocess.ret_val;
4242             }
4243             mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4244                                   buf_idx, -1);
4245         }
4246     }
4247     return rc;
4248 }
4249 
4250 /*===========================================================================
4251  * FUNCTION   : addReprocStreamsFromSource
4252  *
4253  * DESCRIPTION: add reprocess streams from input source channel
4254  *
4255  * PARAMETERS :
4256  *   @config         : pp feature configuration
4257  *   @src_config     : source reprocess configuration
4258  *   @isType         : type of image stabilization required on this stream
4259  *   @pMetaChannel   : ptr to metadata channel to get corresp. metadata
4260  *
4261  *
4262  * RETURN     : int32_t type of status
4263  *              NO_ERROR  -- success
4264  *              none-zero failure code
4265  *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4266 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4267         const reprocess_config_t &src_config , cam_is_type_t is_type,
4268         QCamera3Channel *pMetaChannel)
4269 {
4270     int32_t rc = 0;
4271     cam_stream_reproc_config_t reprocess_config;
4272     cam_stream_type_t streamType;
4273 
4274     cam_dimension_t streamDim = src_config.output_stream_dim;
4275 
4276     if (NULL != src_config.src_channel) {
4277         QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4278         if (pSrcStream == NULL) {
4279            ALOGE("%s: source channel doesn't have a stream", __func__);
4280            return BAD_VALUE;
4281         }
4282         mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4283     }
4284 
4285     streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4286     reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4287 
4288     reprocess_config.offline.input_fmt = src_config.stream_format;
4289     reprocess_config.offline.input_dim = src_config.input_stream_dim;
4290     reprocess_config.offline.input_buf_planes.plane_info =
4291             src_config.input_stream_plane_info.plane_info;
4292     reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4293     reprocess_config.offline.input_type = src_config.stream_type;
4294 
4295     reprocess_config.pp_feature_config = pp_config;
4296     QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4297             m_handle,
4298             m_camOps,
4299             mPaddingInfo,
4300             (QCamera3Channel*)this);
4301     if (pStream == NULL) {
4302         ALOGE("%s: No mem for Stream", __func__);
4303         return NO_MEMORY;
4304     }
4305 
4306     rc = pStream->init(streamType, src_config.stream_format,
4307             streamDim, ROTATE_0, &reprocess_config,
4308             (uint8_t)mNumBuffers,
4309             reprocess_config.pp_feature_config.feature_mask,
4310             is_type,
4311             0,/* batchSize */
4312             QCamera3Channel::streamCbRoutine, this);
4313 
4314     if (rc == 0) {
4315         mStreams[m_numStreams] = pStream;
4316         m_numStreams++;
4317     } else {
4318         ALOGE("%s: failed to create reprocess stream", __func__);
4319         delete pStream;
4320     }
4321 
4322     if (rc == NO_ERROR) {
4323         m_pSrcChannel = src_config.src_channel;
4324         m_pMetaChannel = pMetaChannel;
4325         mReprocessType = src_config.reprocess_type;
4326         CDBG("%s: mReprocessType is %d", __func__, mReprocessType);
4327     }
4328     if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
4329         ALOGE("%s: Request for super buffer failed",__func__);
4330     }
4331     return rc;
4332 }
4333 
4334 /* QCamera3SupportChannel methods */
4335 
4336 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4337 
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)4338 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4339                     uint32_t channel_handle,
4340                     mm_camera_ops_t *cam_ops,
4341                     cam_padding_info_t *paddingInfo,
4342                     uint32_t postprocess_mask,
4343                     cam_stream_type_t streamType,
4344                     cam_dimension_t *dim,
4345                     cam_format_t streamFormat,
4346                     void *userData, uint32_t numBuffers) :
4347                         QCamera3Channel(cam_handle, channel_handle, cam_ops,
4348                                 NULL, paddingInfo, postprocess_mask,
4349                                 userData, numBuffers),
4350                         mMemory(NULL)
4351 {
4352     memcpy(&mDim, dim, sizeof(cam_dimension_t));
4353     mStreamType = streamType;
4354     mStreamFormat = streamFormat;
4355 }
4356 
~QCamera3SupportChannel()4357 QCamera3SupportChannel::~QCamera3SupportChannel()
4358 {
4359     if (m_bIsActive)
4360         stop();
4361 
4362     if (mMemory) {
4363         mMemory->deallocate();
4364         delete mMemory;
4365         mMemory = NULL;
4366     }
4367 }
4368 
initialize(cam_is_type_t isType)4369 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4370 {
4371     int32_t rc;
4372 
4373     if (mMemory || m_numStreams > 0) {
4374         ALOGE("%s: metadata channel already initialized", __func__);
4375         return -EINVAL;
4376     }
4377 
4378     mIsType = isType;
4379     rc = QCamera3Channel::addStream(mStreamType,
4380         mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4381         mPostProcMask, mIsType);
4382     if (rc < 0) {
4383         ALOGE("%s: addStream failed", __func__);
4384     }
4385     return rc;
4386 }
4387 
request(buffer_handle_t *,uint32_t)4388 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4389                                                 uint32_t /*frameNumber*/)
4390 {
4391     return NO_ERROR;
4392 }
4393 
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)4394 void QCamera3SupportChannel::streamCbRoutine(
4395                         mm_camera_super_buf_t *super_frame,
4396                         QCamera3Stream * /*stream*/)
4397 {
4398     if (super_frame == NULL || super_frame->num_bufs != 1) {
4399         ALOGE("%s: super_frame is not valid", __func__);
4400         return;
4401     }
4402     bufDone(super_frame);
4403     free(super_frame);
4404 }
4405 
getStreamBufs(uint32_t len)4406 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4407 {
4408     int rc;
4409     mMemory = new QCamera3StreamMem(mNumBuffers);
4410     if (!mMemory) {
4411         ALOGE("%s: unable to create heap memory", __func__);
4412         return NULL;
4413     }
4414     rc = mMemory->allocateAll(len);
4415     if (rc < 0) {
4416         ALOGE("%s: unable to allocate heap memory", __func__);
4417         delete mMemory;
4418         mMemory = NULL;
4419         return NULL;
4420     }
4421     return mMemory;
4422 }
4423 
putStreamBufs()4424 void QCamera3SupportChannel::putStreamBufs()
4425 {
4426     mMemory->deallocate();
4427     delete mMemory;
4428     mMemory = NULL;
4429 }
4430 
4431 }; // namespace qcamera
4432