1/* Copyright (c) 2012-2013, 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 LOG_TAG "QCameraChannel"
31
32#include <utils/Errors.h>
33#include "QCameraParameters.h"
34#include "QCamera2HWI.h"
35#include "QCameraChannel.h"
36
37using namespace android;
38
39namespace qcamera {
40
41/*===========================================================================
42 * FUNCTION   : QCameraChannel
43 *
44 * DESCRIPTION: constrcutor of QCameraChannel
45 *
46 * PARAMETERS :
47 *   @cam_handle : camera handle
48 *   @cam_ops    : ptr to camera ops table
49 *
50 * RETURN     : none
51 *==========================================================================*/
52QCameraChannel::QCameraChannel(uint32_t cam_handle,
53                               mm_camera_ops_t *cam_ops)
54{
55    m_camHandle = cam_handle;
56    m_camOps = cam_ops;
57    m_bIsActive = false;
58
59    m_handle = 0;
60    m_numStreams = 0;
61    memset(mStreams, 0, sizeof(mStreams));
62}
63
64/*===========================================================================
65 * FUNCTION   : QCameraChannel
66 *
67 * DESCRIPTION: default constrcutor of QCameraChannel
68 *
69 * PARAMETERS : none
70 *
71 * RETURN     : none
72 *==========================================================================*/
73QCameraChannel::QCameraChannel()
74{
75    m_camHandle = 0;
76    m_camOps = NULL;
77    m_bIsActive = false;
78
79    m_handle = 0;
80    m_numStreams = 0;
81    memset(mStreams, 0, sizeof(mStreams));
82}
83
84/*===========================================================================
85 * FUNCTION   : ~QCameraChannel
86 *
87 * DESCRIPTION: destructor of QCameraChannel
88 *
89 * PARAMETERS : none
90 *
91 * RETURN     : none
92 *==========================================================================*/
93QCameraChannel::~QCameraChannel()
94{
95    if (m_bIsActive) {
96        stop();
97    }
98
99    for (int i = 0; i < m_numStreams; i++) {
100        if (mStreams[i] != NULL) {
101            delete mStreams[i];
102            mStreams[i] = 0;
103        }
104    }
105    m_numStreams = 0;
106    m_camOps->delete_channel(m_camHandle, m_handle);
107    m_handle = 0;
108}
109
110/*===========================================================================
111 * FUNCTION   : init
112 *
113 * DESCRIPTION: initialization of channel
114 *
115 * PARAMETERS :
116 *   @attr    : channel bundle attribute setting
117 *   @dataCB  : data notify callback
118 *   @userData: user data ptr
119 *
120 * RETURN     : int32_t type of status
121 *              NO_ERROR  -- success
122 *              none-zero failure code
123 *==========================================================================*/
124int32_t QCameraChannel::init(mm_camera_channel_attr_t *attr,
125                             mm_camera_buf_notify_t dataCB,
126                             void *userData)
127{
128    m_handle = m_camOps->add_channel(m_camHandle,
129                                      attr,
130                                      dataCB,
131                                      userData);
132    if (m_handle == 0) {
133        ALOGE("%s: Add channel failed", __func__);
134        return UNKNOWN_ERROR;
135    }
136    return NO_ERROR;
137}
138
139/*===========================================================================
140 * FUNCTION   : addStream
141 *
142 * DESCRIPTION: add a stream into channel
143 *
144 * PARAMETERS :
145 *   @allocator      : stream related buffer allocator
146 *   @streamInfoBuf  : ptr to buf that constains stream info
147 *   @minStreamBufNum: number of stream buffers needed
148 *   @paddingInfo    : padding information
149 *   @stream_cb      : stream data notify callback
150 *   @userdata       : user data ptr
151 *
152 * RETURN     : int32_t type of status
153 *              NO_ERROR  -- success
154 *              none-zero failure code
155 *==========================================================================*/
156int32_t QCameraChannel::addStream(QCameraAllocator &allocator,
157                                  QCameraHeapMemory *streamInfoBuf,
158                                  uint8_t minStreamBufNum,
159                                  cam_padding_info_t *paddingInfo,
160                                  stream_cb_routine stream_cb,
161                                  void *userdata)
162{
163    int32_t rc = NO_ERROR;
164    if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
165        ALOGE("%s: stream number (%d) exceeds max limit (%d)",
166              __func__, m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
167        return BAD_VALUE;
168    }
169    QCameraStream *pStream = new QCameraStream(allocator,
170                                               m_camHandle,
171                                               m_handle,
172                                               m_camOps,
173                                               paddingInfo);
174    if (pStream == NULL) {
175        ALOGE("%s: No mem for Stream", __func__);
176        return NO_MEMORY;
177    }
178
179    rc = pStream->init(streamInfoBuf, minStreamBufNum, stream_cb, userdata);
180    if (rc == 0) {
181        mStreams[m_numStreams] = pStream;
182        m_numStreams++;
183    } else {
184        delete pStream;
185    }
186    return rc;
187}
188
189/*===========================================================================
190 * FUNCTION   : start
191 *
192 * DESCRIPTION: start channel, which will start all streams belong to this channel
193 *
194 * PARAMETERS : None
195 *
196 * RETURN     : int32_t type of status
197 *              NO_ERROR  -- success
198 *              none-zero failure code
199 *==========================================================================*/
200int32_t QCameraChannel::start()
201{
202    int32_t rc = NO_ERROR;
203
204    if (m_numStreams > 1) {
205        // there is more than one stream in the channel
206        // we need to notify mctl that all streams in this channel need to be bundled
207        cam_bundle_config_t bundleInfo;
208        memset(&bundleInfo, 0, sizeof(bundleInfo));
209        rc = m_camOps->get_bundle_info(m_camHandle, m_handle, &bundleInfo);
210        if (rc != NO_ERROR) {
211            ALOGE("%s: get_bundle_info failed", __func__);
212            return rc;
213        }
214        if (bundleInfo.num_of_streams > 1) {
215            for (int i = 0; i < bundleInfo.num_of_streams; i++) {
216                QCameraStream *pStream = getStreamByServerID(bundleInfo.stream_ids[i]);
217                if (pStream != NULL) {
218                    if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
219                        // Skip metadata for reprocess now because PP module cannot handle meta data
220                        // May need furthur discussion if Imaginglib need meta data
221                        continue;
222                    }
223
224                    cam_stream_parm_buffer_t param;
225                    memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
226                    param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
227                    param.bundleInfo = bundleInfo;
228                    rc = pStream->setParameter(param);
229                    if (rc != NO_ERROR) {
230                        ALOGE("%s: stream setParameter for set bundle failed", __func__);
231                        return rc;
232                    }
233                }
234            }
235        }
236    }
237
238    for (int i = 0; i < m_numStreams; i++) {
239        if (mStreams[i] != NULL) {
240            mStreams[i]->start();
241        }
242    }
243    rc = m_camOps->start_channel(m_camHandle, m_handle);
244
245    if (rc != NO_ERROR) {
246        for (int i = 0; i < m_numStreams; i++) {
247            if (mStreams[i] != NULL) {
248                mStreams[i]->stop();
249            }
250        }
251    } else {
252        m_bIsActive = true;
253    }
254
255    return rc;
256}
257
258/*===========================================================================
259 * FUNCTION   : stop
260 *
261 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
262 *
263 * PARAMETERS : none
264 *
265 * RETURN     : int32_t type of status
266 *              NO_ERROR  -- success
267 *              none-zero failure code
268 *==========================================================================*/
269int32_t QCameraChannel::stop()
270{
271    int32_t rc = NO_ERROR;
272    rc = m_camOps->stop_channel(m_camHandle, m_handle);
273
274    for (int i = 0; i < m_numStreams; i++) {
275        if (mStreams[i] != NULL) {
276            mStreams[i]->stop();
277        }
278    }
279
280    m_bIsActive = false;
281    return rc;
282}
283
284/*===========================================================================
285 * FUNCTION   : bufDone
286 *
287 * DESCRIPTION: return a stream buf back to kernel
288 *
289 * PARAMETERS :
290 *   @recvd_frame  : stream buf frame to be returned
291 *
292 * RETURN     : int32_t type of status
293 *              NO_ERROR  -- success
294 *              none-zero failure code
295 *==========================================================================*/
296int32_t QCameraChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
297{
298    int32_t rc = NO_ERROR;
299    for (int i = 0; i < recvd_frame->num_bufs; i++) {
300         if (recvd_frame->bufs[i] != NULL) {
301             for (int j = 0; j < m_numStreams; j++) {
302                 if (mStreams[j] != NULL &&
303                     mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
304                     rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
305                     break; // break loop j
306                 }
307             }
308         }
309    }
310
311    return rc;
312}
313
314/*===========================================================================
315 * FUNCTION   : processZoomDone
316 *
317 * DESCRIPTION: process zoom done event
318 *
319 * PARAMETERS :
320 *   @previewWindoe : ptr to preview window ops table, needed to set preview
321 *                    crop information
322 *   @crop_info     : crop info as a result of zoom operation
323 *
324 * RETURN     : int32_t type of status
325 *              NO_ERROR  -- success
326 *              none-zero failure code
327 *==========================================================================*/
328int32_t QCameraChannel::processZoomDone(preview_stream_ops_t *previewWindow,
329                                        cam_crop_data_t &crop_info)
330{
331    int32_t rc = NO_ERROR;
332    for (int i = 0; i < m_numStreams; i++) {
333        if (mStreams[i] != NULL) {
334            rc = mStreams[i]->processZoomDone(previewWindow, crop_info);
335        }
336    }
337    return rc;
338}
339
340/*===========================================================================
341 * FUNCTION   : getStreamByHandle
342 *
343 * DESCRIPTION: return stream object by stream handle
344 *
345 * PARAMETERS :
346 *   @streamHandle : stream handle
347 *
348 * RETURN     : stream object. NULL if not found
349 *==========================================================================*/
350QCameraStream *QCameraChannel::getStreamByHandle(uint32_t streamHandle)
351{
352    for (int i = 0; i < m_numStreams; i++) {
353        if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
354            return mStreams[i];
355        }
356    }
357    return NULL;
358}
359
360/*===========================================================================
361 * FUNCTION   : getStreamByServerID
362 *
363 * DESCRIPTION: return stream object by stream server ID from daemon
364 *
365 * PARAMETERS :
366 *   @serverID : stream server ID
367 *
368 * RETURN     : stream object. NULL if not found
369 *==========================================================================*/
370QCameraStream *QCameraChannel::getStreamByServerID(uint32_t serverID)
371{
372    for (int i = 0; i < m_numStreams; i++) {
373        if (mStreams[i] != NULL && mStreams[i]->getMyServerID() == serverID) {
374            return mStreams[i];
375        }
376    }
377    return NULL;
378}
379
380/*===========================================================================
381 * FUNCTION   : getStreamByIndex
382 *
383 * DESCRIPTION: return stream object by index of streams in the channel
384 *
385 * PARAMETERS :
386 *   @index : index of stream in the channel
387 *
388 * RETURN     : stream object. NULL if not found
389 *==========================================================================*/
390QCameraStream *QCameraChannel::getStreamByIndex(uint8_t index)
391{
392    if (index < m_numStreams) {
393        return mStreams[index];
394    }
395    return NULL;
396}
397
398/*===========================================================================
399 * FUNCTION   : QCameraPicChannel
400 *
401 * DESCRIPTION: constructor of QCameraPicChannel
402 *
403 * PARAMETERS :
404 *   @cam_handle : camera handle
405 *   @cam_ops    : ptr to camera ops table
406 *
407 * RETURN     : none
408 *==========================================================================*/
409QCameraPicChannel::QCameraPicChannel(uint32_t cam_handle,
410                                     mm_camera_ops_t *cam_ops) :
411    QCameraChannel(cam_handle, cam_ops)
412{
413}
414
415/*===========================================================================
416 * FUNCTION   : QCameraPicChannel
417 *
418 * DESCRIPTION: default constructor of QCameraPicChannel
419 *
420 * PARAMETERS : none
421 *
422 * RETURN     : none
423 *==========================================================================*/
424QCameraPicChannel::QCameraPicChannel()
425{
426}
427
428/*===========================================================================
429 * FUNCTION   : ~QCameraPicChannel
430 *
431 * DESCRIPTION: destructor of QCameraPicChannel
432 *
433 * PARAMETERS : none
434 *
435 * RETURN     : none
436 *==========================================================================*/
437QCameraPicChannel::~QCameraPicChannel()
438{
439}
440
441/*===========================================================================
442 * FUNCTION   : takePicture
443 *
444 * DESCRIPTION: send request for queued snapshot frames
445 *
446 * PARAMETERS :
447 *   @num_of_snapshot : number of snapshot frames requested
448 *
449 * RETURN     : int32_t type of status
450 *              NO_ERROR  -- success
451 *              none-zero failure code
452 *==========================================================================*/
453int32_t QCameraPicChannel::takePicture(uint8_t num_of_snapshot)
454{
455    int32_t rc = m_camOps->request_super_buf(m_camHandle,
456                                             m_handle,
457                                             num_of_snapshot);
458    return rc;
459}
460
461/*===========================================================================
462 * FUNCTION   : cancelPicture
463 *
464 * DESCRIPTION: cancel request for queued snapshot frames
465 *
466 * PARAMETERS : none
467 *
468 * RETURN     : int32_t type of status
469 *              NO_ERROR  -- success
470 *              none-zero failure code
471 *==========================================================================*/
472int32_t QCameraPicChannel::cancelPicture()
473{
474    int32_t rc = m_camOps->cancel_super_buf_request(m_camHandle, m_handle);
475    return rc;
476}
477
478/*===========================================================================
479 * FUNCTION   : QCameraVideoChannel
480 *
481 * DESCRIPTION: constructor of QCameraVideoChannel
482 *
483 * PARAMETERS :
484 *   @cam_handle : camera handle
485 *   @cam_ops    : ptr to camera ops table
486 *
487 * RETURN     : none
488 *==========================================================================*/
489QCameraVideoChannel::QCameraVideoChannel(uint32_t cam_handle,
490                                         mm_camera_ops_t *cam_ops) :
491    QCameraChannel(cam_handle, cam_ops)
492{
493}
494
495/*===========================================================================
496 * FUNCTION   : QCameraVideoChannel
497 *
498 * DESCRIPTION: default constructor of QCameraVideoChannel
499 *
500 * PARAMETERS : none
501 *
502 * RETURN     : none
503 *==========================================================================*/
504QCameraVideoChannel::QCameraVideoChannel()
505{
506}
507
508/*===========================================================================
509 * FUNCTION   : ~QCameraVideoChannel
510 *
511 * DESCRIPTION: destructor of QCameraVideoChannel
512 *
513 * PARAMETERS : none
514 *
515 * RETURN     : none
516 *==========================================================================*/
517QCameraVideoChannel::~QCameraVideoChannel()
518{
519}
520
521/*===========================================================================
522 * FUNCTION   : releaseFrame
523 *
524 * DESCRIPTION: return video frame from app
525 *
526 * PARAMETERS :
527 *   @opaque     : ptr to video frame to be returned
528 *   @isMetaData : if frame is a metadata or real frame
529 *
530 * RETURN     : int32_t type of status
531 *              NO_ERROR  -- success
532 *              none-zero failure code
533 *==========================================================================*/
534int32_t QCameraVideoChannel::releaseFrame(const void * opaque, bool isMetaData)
535{
536    QCameraStream *pVideoStream = NULL;
537    for (int i = 0; i < m_numStreams; i++) {
538        if (mStreams[i] != NULL && mStreams[i]->isTypeOf(CAM_STREAM_TYPE_VIDEO)) {
539            pVideoStream = mStreams[i];
540            break;
541        }
542    }
543
544    if (NULL == pVideoStream) {
545        ALOGE("%s: No video stream in the channel", __func__);
546        return BAD_VALUE;
547    }
548
549    int32_t rc = pVideoStream->bufDone(opaque, isMetaData);
550    return rc;
551}
552
553/*===========================================================================
554 * FUNCTION   : QCameraReprocessChannel
555 *
556 * DESCRIPTION: constructor of QCameraReprocessChannel
557 *
558 * PARAMETERS :
559 *   @cam_handle : camera handle
560 *   @cam_ops    : ptr to camera ops table
561 *   @pp_mask    : post-proccess feature mask
562 *
563 * RETURN     : none
564 *==========================================================================*/
565QCameraReprocessChannel::QCameraReprocessChannel(uint32_t cam_handle,
566                                                 mm_camera_ops_t *cam_ops) :
567    QCameraChannel(cam_handle, cam_ops),
568    m_pSrcChannel(NULL)
569{
570    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
571}
572
573/*===========================================================================
574 * FUNCTION   : QCameraReprocessChannel
575 *
576 * DESCRIPTION: default constructor of QCameraReprocessChannel
577 *
578 * PARAMETERS : none
579 *
580 * RETURN     : none
581 *==========================================================================*/
582QCameraReprocessChannel::QCameraReprocessChannel() :
583    m_pSrcChannel(NULL)
584{
585}
586
587/*===========================================================================
588 * FUNCTION   : ~QCameraReprocessChannel
589 *
590 * DESCRIPTION: destructor of QCameraReprocessChannel
591 *
592 * PARAMETERS : none
593 *
594 * RETURN     : none
595 *==========================================================================*/
596QCameraReprocessChannel::~QCameraReprocessChannel()
597{
598}
599
600/*===========================================================================
601 * FUNCTION   : addReprocStreamsFromSource
602 *
603 * DESCRIPTION: add reprocess streams from input source channel
604 *
605 * PARAMETERS :
606 *   @allocator      : stream related buffer allocator
607 *   @config         : pp feature configuration
608 *   @pSrcChannel    : ptr to input source channel that needs reprocess
609 *   @minStreamBufNum: number of stream buffers needed
610 *   @paddingInfo    : padding information
611 *
612 * RETURN     : int32_t type of status
613 *              NO_ERROR  -- success
614 *              none-zero failure code
615 *==========================================================================*/
616int32_t QCameraReprocessChannel::addReprocStreamsFromSource(QCameraAllocator& allocator,
617                                                            cam_pp_feature_config_t &config,
618                                                            QCameraChannel *pSrcChannel,
619                                                            uint8_t minStreamBufNum,
620                                                            cam_padding_info_t *paddingInfo)
621{
622    int32_t rc = 0;
623    QCameraStream *pStream = NULL;
624    QCameraHeapMemory *pStreamInfoBuf = NULL;
625    cam_stream_info_t *streamInfo = NULL;
626
627    memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
628
629    for (int i = 0; i < pSrcChannel->getNumOfStreams(); i++) {
630        pStream = pSrcChannel->getStreamByIndex(i);
631        if (pStream != NULL) {
632            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
633                // Skip metadata for reprocess now because PP module cannot handle meta data
634                // May need furthur discussion if Imaginglib need meta data
635                continue;
636            }
637
638            pStreamInfoBuf = allocator.allocateStreamInfoBuf(CAM_STREAM_TYPE_OFFLINE_PROC);
639            if (pStreamInfoBuf == NULL) {
640                ALOGE("%s: no mem for stream info buf", __func__);
641                rc = NO_MEMORY;
642                break;
643            }
644
645            streamInfo = (cam_stream_info_t *)pStreamInfoBuf->getPtr(0);
646            memset(streamInfo, 0, sizeof(cam_stream_info_t));
647            streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
648            rc = pStream->getFormat(streamInfo->fmt);
649            rc = pStream->getFrameDimension(streamInfo->dim);
650            streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
651            streamInfo->num_of_burst = minStreamBufNum;
652
653            streamInfo->reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
654            streamInfo->reprocess_config.online.input_stream_id = pStream->getMyServerID();
655            streamInfo->reprocess_config.online.input_stream_type = pStream->getMyType();
656            streamInfo->reprocess_config.pp_feature_config = config;
657
658            if (!(pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
659                pStream->isTypeOf(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT) ||
660                pStream->isOrignalTypeOf(CAM_STREAM_TYPE_SNAPSHOT) ||
661                pStream->isOrignalTypeOf(CAM_STREAM_TYPE_NON_ZSL_SNAPSHOT))) {
662                streamInfo->reprocess_config.pp_feature_config.feature_mask &= ~CAM_QCOM_FEATURE_CAC;
663            }
664            if (streamInfo->reprocess_config.pp_feature_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
665                if (streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_90 ||
666                    streamInfo->reprocess_config.pp_feature_config.rotation == ROTATE_270) {
667                    // rotated by 90 or 270, need to switch width and height
668                    int32_t temp = streamInfo->dim.height;
669                    streamInfo->dim.height = streamInfo->dim.width;
670                    streamInfo->dim.width = temp;
671                }
672            }
673
674            // save source stream handler
675            mSrcStreamHandles[m_numStreams] = pStream->getMyHandle();
676
677            // add reprocess stream
678            rc = addStream(allocator,
679                           pStreamInfoBuf, minStreamBufNum,
680                           paddingInfo,
681                           NULL, NULL);
682            if (rc != NO_ERROR) {
683                ALOGE("%s: add reprocess stream failed, ret = %d", __func__, rc);
684                break;
685            }
686        }
687    }
688
689    if (rc == NO_ERROR) {
690        m_pSrcChannel = pSrcChannel;
691    }
692    return rc;
693}
694
695/*===========================================================================
696 * FUNCTION   : getStreamBySrouceHandle
697 *
698 * DESCRIPTION: find reprocess stream by its source stream handle
699 *
700 * PARAMETERS :
701 *   @srcHandle : source stream handle
702 *
703 * RETURN     : ptr to reprocess stream if found. NULL if not found
704 *==========================================================================*/
705QCameraStream * QCameraReprocessChannel::getStreamBySrouceHandle(uint32_t srcHandle)
706{
707    QCameraStream *pStream = NULL;
708
709    for (int i = 0; i < m_numStreams; i++) {
710        if (mSrcStreamHandles[i] == srcHandle) {
711            pStream = mStreams[i];
712            break;
713        }
714    }
715
716    return pStream;
717}
718
719/*===========================================================================
720 * FUNCTION   : doReprocess
721 *
722 * DESCRIPTION: request to do a reprocess on the frame
723 *
724 * PARAMETERS :
725 *   @frame   : frame to be performed a reprocess
726 *
727 * RETURN     : int32_t type of status
728 *              NO_ERROR  -- success
729 *              none-zero failure code
730 *==========================================================================*/
731int32_t QCameraReprocessChannel::doReprocess(mm_camera_super_buf_t *frame)
732{
733    int32_t rc = 0;
734    if (m_numStreams < 1) {
735        ALOGE("%s: No reprocess stream is created", __func__);
736        return -1;
737    }
738    if (m_pSrcChannel == NULL) {
739        ALOGE("%s: No source channel for reprocess", __func__);
740        return -1;
741    }
742
743    // find meta data stream and index of meta data frame in the superbuf
744    QCameraStream *pMetaStream = NULL;
745    uint8_t meta_buf_index = 0;
746    for (int i = 0; i < frame->num_bufs; i++) {
747        QCameraStream *pStream = m_pSrcChannel->getStreamByHandle(frame->bufs[i]->stream_id);
748        if (pStream != NULL) {
749            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
750                meta_buf_index = frame->bufs[i]->buf_idx;
751                pMetaStream = pStream;
752                break;
753            }
754        }
755    }
756
757    for (int i = 0; i < frame->num_bufs; i++) {
758        QCameraStream *pStream = getStreamBySrouceHandle(frame->bufs[i]->stream_id);
759        if (pStream != NULL) {
760            if (pStream->isTypeOf(CAM_STREAM_TYPE_METADATA)) {
761                // Skip metadata for reprocess now because PP module cannot handle meta data
762                // May need furthur discussion if Imaginglib need meta data
763                continue;
764            }
765
766            cam_stream_parm_buffer_t param;
767            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
768            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
769            param.reprocess.buf_index = frame->bufs[i]->buf_idx;
770            param.reprocess.frame_idx = frame->bufs[i]->frame_idx;
771            if (pMetaStream != NULL) {
772                // we have meta data frame bundled, sent together with reprocess frame
773                param.reprocess.meta_present = 1;
774                param.reprocess.meta_stream_handle = pMetaStream->getMyServerID();
775                param.reprocess.meta_buf_index = meta_buf_index;
776            }
777            rc = pStream->setParameter(param);
778            if (rc != NO_ERROR) {
779                ALOGE("%s: stream setParameter for reprocess failed", __func__);
780                break;
781            }
782        }
783    }
784    return rc;
785}
786
787/*===========================================================================
788 * FUNCTION   : doReprocess
789 *
790 * DESCRIPTION: request to do a reprocess on the frame
791 *
792 * PARAMETERS :
793 *   @buf_fd     : fd to the input buffer that needs reprocess
794 *   @buf_lenght : length of the input buffer
795 *   @ret_val    : result of reprocess.
796 *                 Example: Could be faceID in case of register face image.
797 *
798 * RETURN     : int32_t type of status
799 *              NO_ERROR  -- success
800 *              none-zero failure code
801 *==========================================================================*/
802int32_t QCameraReprocessChannel::doReprocess(int buf_fd,
803                                             uint32_t buf_length,
804                                             int32_t &ret_val)
805{
806    int32_t rc = 0;
807    if (m_numStreams < 1) {
808        ALOGE("%s: No reprocess stream is created", __func__);
809        return -1;
810    }
811
812    uint32_t buf_idx = 0;
813    for (int i = 0; i < m_numStreams; i++) {
814        rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
815                                 buf_idx, -1,
816                                 buf_fd, buf_length);
817
818        if (rc == NO_ERROR) {
819            cam_stream_parm_buffer_t param;
820            memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
821            param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
822            param.reprocess.buf_index = buf_idx;
823            rc = mStreams[i]->setParameter(param);
824            if (rc == NO_ERROR) {
825                ret_val = param.reprocess.ret_val;
826            }
827            mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
828                                  buf_idx, -1);
829        }
830    }
831    return rc;
832}
833
834}; // namespace qcamera
835