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 LOG_TAG "QCamera3Stream"
31 //#define LOG_NDEBUG 0
32 
33 #include <utils/Log.h>
34 #include <utils/Errors.h>
35 #include "QCamera3HWI.h"
36 #include "QCamera3Stream.h"
37 #include "QCamera3Channel.h"
38 
39 using namespace android;
40 
41 namespace qcamera {
42 
43 /*===========================================================================
44  * FUNCTION   : get_bufs
45  *
46  * DESCRIPTION: static function entry to allocate stream buffers
47  *
48  * PARAMETERS :
49  *   @offset     : offset info of stream buffers
50  *   @num_bufs   : number of buffers allocated
51  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
52  *                      at kernel initially
53  *   @bufs       : output of allocated buffers
54  *   @ops_tbl    : ptr to buf mapping/unmapping ops
55  *   @user_data  : user data ptr of ops_tbl
56  *
57  * RETURN     : int32_t type of status
58  *              NO_ERROR  -- success
59  *              none-zero failure code
60  *==========================================================================*/
get_bufs(cam_frame_len_offset_t * offset,uint8_t * num_bufs,uint8_t ** initial_reg_flag,mm_camera_buf_def_t ** bufs,mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)61 int32_t QCamera3Stream::get_bufs(
62                      cam_frame_len_offset_t *offset,
63                      uint8_t *num_bufs,
64                      uint8_t **initial_reg_flag,
65                      mm_camera_buf_def_t **bufs,
66                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
67                      void *user_data)
68 {
69     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
70     if (!stream) {
71         ALOGE("getBufs invalid stream pointer");
72         return NO_MEMORY;
73     }
74     return stream->getBufs(offset, num_bufs, initial_reg_flag, bufs, ops_tbl);
75 }
76 
77 /*===========================================================================
78  * FUNCTION   : put_bufs
79  *
80  * DESCRIPTION: static function entry to deallocate stream buffers
81  *
82  * PARAMETERS :
83  *   @ops_tbl    : ptr to buf mapping/unmapping ops
84  *   @user_data  : user data ptr of ops_tbl
85  *
86  * RETURN     : int32_t type of status
87  *              NO_ERROR  -- success
88  *              none-zero failure code
89  *==========================================================================*/
put_bufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)90 int32_t QCamera3Stream::put_bufs(
91                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
92                      void *user_data)
93 {
94     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
95     if (!stream) {
96         ALOGE("putBufs invalid stream pointer");
97         return NO_MEMORY;
98     }
99     return stream->putBufs(ops_tbl);
100 }
101 
102 /*===========================================================================
103  * FUNCTION   : invalidate_buf
104  *
105  * DESCRIPTION: static function entry to invalidate a specific stream buffer
106  *
107  * PARAMETERS :
108  *   @index      : index of the stream buffer to invalidate
109  *   @user_data  : user data ptr of ops_tbl
110  *
111  * RETURN     : int32_t type of status
112  *              NO_ERROR  -- success
113  *              none-zero failure code
114  *==========================================================================*/
invalidate_buf(int index,void * user_data)115 int32_t QCamera3Stream::invalidate_buf(int index, void *user_data)
116 {
117     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
118     if (!stream) {
119         ALOGE("invalid stream pointer");
120         return NO_MEMORY;
121     }
122     return stream->invalidateBuf(index);
123 }
124 
125 /*===========================================================================
126  * FUNCTION   : clean_invalidate_buf
127  *
128  * DESCRIPTION: static function entry to clean and invalidate a specific stream buffer
129  *
130  * PARAMETERS :
131  *   @index      : index of the stream buffer to invalidate
132  *   @user_data  : user data ptr of ops_tbl
133  *
134  * RETURN     : int32_t type of status
135  *              NO_ERROR  -- success
136  *              none-zero failure code
137  *==========================================================================*/
clean_invalidate_buf(int index,void * user_data)138 int32_t QCamera3Stream::clean_invalidate_buf(int index, void *user_data)
139 {
140     QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
141     if (!stream) {
142         ALOGE("invalid stream pointer");
143         return NO_MEMORY;
144     }
145     return stream->cleanInvalidateBuf(index);
146 }
147 
148 /*===========================================================================
149  * FUNCTION   : QCamera3Stream
150  *
151  * DESCRIPTION: constructor of QCamera3Stream
152  *
153  * PARAMETERS :
154  *   @allocator  : memory allocator obj
155  *   @camHandle  : camera handle
156  *   @chId       : channel handle
157  *   @camOps     : ptr to camera ops table
158  *   @paddingInfo: ptr to padding info
159  *
160  * RETURN     : None
161  *==========================================================================*/
QCamera3Stream(uint32_t camHandle,uint32_t chId,mm_camera_ops_t * camOps,cam_padding_info_t * paddingInfo,QCamera3Channel * channel)162 QCamera3Stream::QCamera3Stream(uint32_t camHandle,
163                              uint32_t chId,
164                              mm_camera_ops_t *camOps,
165                              cam_padding_info_t *paddingInfo,
166                              QCamera3Channel *channel) :
167         mCamHandle(camHandle),
168         mChannelHandle(chId),
169         mHandle(0),
170         mCamOps(camOps),
171         mStreamInfo(NULL),
172         mMemOps(NULL),
173         mNumBufs(0),
174         mDataCB(NULL),
175         mUserData(NULL),
176         mDataQ(releaseFrameData, this),
177         mStreamInfoBuf(NULL),
178         mStreamBufs(NULL),
179         mBufDefs(NULL),
180         mChannel(channel)
181 {
182     mMemVtbl.user_data = this;
183     mMemVtbl.get_bufs = get_bufs;
184     mMemVtbl.put_bufs = put_bufs;
185     mMemVtbl.invalidate_buf = invalidate_buf;
186     mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
187     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
188     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
189 }
190 
191 /*===========================================================================
192  * FUNCTION   : ~QCamera3Stream
193  *
194  * DESCRIPTION: deconstructor of QCamera3Stream
195  *
196  * PARAMETERS : None
197  *
198  * RETURN     : None
199  *==========================================================================*/
~QCamera3Stream()200 QCamera3Stream::~QCamera3Stream()
201 {
202     if (mStreamInfoBuf != NULL) {
203         int rc = mCamOps->unmap_stream_buf(mCamHandle,
204                     mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
205         if (rc < 0) {
206             ALOGE("Failed to un-map stream info buffer");
207         }
208         mStreamInfoBuf->deallocate();
209         delete mStreamInfoBuf;
210         mStreamInfoBuf = NULL;
211     }
212 
213     // delete stream
214     if (mHandle > 0) {
215         mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
216         mHandle = 0;
217     }
218 }
219 
220 /*===========================================================================
221  * FUNCTION   : init
222  *
223  * DESCRIPTION: initialize stream obj
224  *
225  * PARAMETERS :
226  *   @streamDim     : dimensions of the stream
227  *   @stream_cb     : stream data notify callback. Can be NULL if not needed
228  *   @userdata      : user data ptr
229  *
230  * RETURN     : int32_t type of status
231  *              NO_ERROR  -- success
232  *              none-zero failure code
233  *==========================================================================*/
init(cam_stream_type_t streamType,cam_format_t streamFormat,cam_dimension_t streamDim,cam_rotation_t streamRotation,cam_stream_reproc_config_t * reprocess_config,uint8_t minNumBuffers,uint32_t postprocess_mask,cam_is_type_t is_type,hal3_stream_cb_routine stream_cb,void * userdata)234 int32_t QCamera3Stream::init(cam_stream_type_t streamType,
235                             cam_format_t streamFormat,
236                             cam_dimension_t streamDim,
237                             cam_rotation_t streamRotation,
238                             cam_stream_reproc_config_t* reprocess_config,
239                             uint8_t minNumBuffers,
240                             uint32_t postprocess_mask,
241                             cam_is_type_t is_type,
242                             hal3_stream_cb_routine stream_cb,
243                             void *userdata)
244 {
245     int32_t rc = OK;
246     mm_camera_stream_config_t stream_config;
247 
248     mHandle = mCamOps->add_stream(mCamHandle, mChannelHandle);
249     if (!mHandle) {
250         ALOGE("add_stream failed");
251         rc = UNKNOWN_ERROR;
252         goto done;
253     }
254 
255     // allocate and map stream info memory
256     mStreamInfoBuf = new QCamera3HeapMemory();
257     if (mStreamInfoBuf == NULL) {
258         ALOGE("%s: no memory for stream info buf obj", __func__);
259         rc = -ENOMEM;
260         goto err1;
261     }
262     rc = mStreamInfoBuf->allocate(1, sizeof(cam_stream_info_t), false);
263     if (rc < 0) {
264         ALOGE("%s: no memory for stream info", __func__);
265         rc = -ENOMEM;
266         goto err2;
267     }
268 
269     mStreamInfo =
270         reinterpret_cast<cam_stream_info_t *>(mStreamInfoBuf->getPtr(0));
271     memset(mStreamInfo, 0, sizeof(cam_stream_info_t));
272     mStreamInfo->stream_type = streamType;
273     mStreamInfo->fmt = streamFormat;
274     mStreamInfo->dim = streamDim;
275     mStreamInfo->num_bufs = minNumBuffers;
276     mStreamInfo->pp_config.feature_mask = postprocess_mask;
277     mStreamInfo->pp_config.rotation = streamRotation;
278     ALOGV("%s: stream_type is %d, feature_mask is %d",
279           __func__, mStreamInfo->stream_type, mStreamInfo->pp_config.feature_mask);
280     mStreamInfo->is_type = is_type;
281     rc = mCamOps->map_stream_buf(mCamHandle,
282             mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO,
283             0, -1, mStreamInfoBuf->getFd(0), mStreamInfoBuf->getSize(0));
284     if (rc < 0) {
285         ALOGE("Failed to map stream info buffer");
286         goto err3;
287     }
288 
289     mNumBufs = minNumBuffers;
290     if (reprocess_config != NULL) {
291        mStreamInfo->reprocess_config = *reprocess_config;
292        mStreamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
293        //mStreamInfo->num_of_burst = reprocess_config->offline.num_of_bufs;
294        mStreamInfo->num_of_burst = 1;
295        ALOGI("%s: num_of_burst is %d", __func__, mStreamInfo->num_of_burst);
296     } else {
297        mStreamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
298     }
299 
300     // Configure the stream
301     stream_config.stream_info = mStreamInfo;
302     stream_config.mem_vtbl = mMemVtbl;
303     stream_config.padding_info = mPaddingInfo;
304     stream_config.userdata = this;
305     stream_config.stream_cb = dataNotifyCB;
306 
307     rc = mCamOps->config_stream(mCamHandle,
308             mChannelHandle, mHandle, &stream_config);
309     if (rc < 0) {
310         ALOGE("Failed to config stream, rc = %d", rc);
311         goto err4;
312     }
313 
314     mDataCB = stream_cb;
315     mUserData = userdata;
316     return 0;
317 
318 err4:
319     mCamOps->unmap_stream_buf(mCamHandle,
320             mChannelHandle, mHandle, CAM_MAPPING_BUF_TYPE_STREAM_INFO, 0, -1);
321 err3:
322     mStreamInfoBuf->deallocate();
323 err2:
324     delete mStreamInfoBuf;
325     mStreamInfoBuf = NULL;
326     mStreamInfo = NULL;
327 err1:
328     mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
329     mHandle = 0;
330     mNumBufs = 0;
331 done:
332     return rc;
333 }
334 
335 /*===========================================================================
336  * FUNCTION   : start
337  *
338  * DESCRIPTION: start stream. Will start main stream thread to handle stream
339  *              related ops.
340  *
341  * PARAMETERS : none
342  *
343  * RETURN     : int32_t type of status
344  *              NO_ERROR  -- success
345  *              none-zero failure code
346  *==========================================================================*/
start()347 int32_t QCamera3Stream::start()
348 {
349     int32_t rc = 0;
350 
351     mDataQ.init();
352     rc = mProcTh.launch(dataProcRoutine, this);
353     return rc;
354 }
355 
356 /*===========================================================================
357  * FUNCTION   : stop
358  *
359  * DESCRIPTION: stop stream. Will stop main stream thread
360  *
361  * PARAMETERS : none
362  *
363  * RETURN     : int32_t type of status
364  *              NO_ERROR  -- success
365  *              none-zero failure code
366  *==========================================================================*/
stop()367 int32_t QCamera3Stream::stop()
368 {
369     int32_t rc = 0;
370     rc = mProcTh.exit();
371     return rc;
372 }
373 
374 /*===========================================================================
375  * FUNCTION   : processDataNotify
376  *
377  * DESCRIPTION: process stream data notify
378  *
379  * PARAMETERS :
380  *   @frame   : stream frame received
381  *
382  * RETURN     : int32_t type of status
383  *              NO_ERROR  -- success
384  *              none-zero failure code
385  *==========================================================================*/
processDataNotify(mm_camera_super_buf_t * frame)386 int32_t QCamera3Stream::processDataNotify(mm_camera_super_buf_t *frame)
387 {
388     CDBG("%s: E\n", __func__);
389     int32_t rc;
390     if (mDataQ.enqueue((void *)frame)) {
391         rc = mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
392     } else {
393         ALOGD("%s: Stream thread is not active, no ops here", __func__);
394         bufDone(frame->bufs[0]->buf_idx);
395         free(frame);
396         rc = NO_ERROR;
397     }
398     CDBG("%s: X\n", __func__);
399     return rc;
400 }
401 
402 /*===========================================================================
403  * FUNCTION   : dataNotifyCB
404  *
405  * DESCRIPTION: callback for data notify. This function is registered with
406  *              mm-camera-interface to handle data notify
407  *
408  * PARAMETERS :
409  *   @recvd_frame   : stream frame received
410  *   userdata       : user data ptr
411  *
412  * RETURN     : none
413  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)414 void QCamera3Stream::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
415                                  void *userdata)
416 {
417     CDBG("%s: E\n", __func__);
418     QCamera3Stream* stream = (QCamera3Stream *)userdata;
419     if (stream == NULL ||
420         recvd_frame == NULL ||
421         recvd_frame->bufs[0] == NULL ||
422         recvd_frame->bufs[0]->stream_id != stream->getMyHandle()) {
423         ALOGE("%s: Not a valid stream to handle buf", __func__);
424         return;
425     }
426 
427     mm_camera_super_buf_t *frame =
428         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
429     if (frame == NULL) {
430         ALOGE("%s: No mem for mm_camera_buf_def_t", __func__);
431         stream->bufDone(recvd_frame->bufs[0]->buf_idx);
432         return;
433     }
434     *frame = *recvd_frame;
435     stream->processDataNotify(frame);
436     return;
437 }
438 
439 /*===========================================================================
440  * FUNCTION   : dataProcRoutine
441  *
442  * DESCRIPTION: function to process data in the main stream thread
443  *
444  * PARAMETERS :
445  *   @data    : user data ptr
446  *
447  * RETURN     : none
448  *==========================================================================*/
dataProcRoutine(void * data)449 void *QCamera3Stream::dataProcRoutine(void *data)
450 {
451     int running = 1;
452     int ret;
453     QCamera3Stream *pme = (QCamera3Stream *)data;
454     QCameraCmdThread *cmdThread = &pme->mProcTh;
455     cmdThread->setName("cam_stream_proc");
456 
457     CDBG("%s: E", __func__);
458     do {
459         do {
460             ret = cam_sem_wait(&cmdThread->cmd_sem);
461             if (ret != 0 && errno != EINVAL) {
462                 ALOGE("%s: cam_sem_wait error (%s)",
463                       __func__, strerror(errno));
464                 return NULL;
465             }
466         } while (ret != 0);
467 
468         // we got notified about new cmd avail in cmd queue
469         camera_cmd_type_t cmd = cmdThread->getCmd();
470         switch (cmd) {
471         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
472             {
473                 CDBG("%s: Do next job", __func__);
474                 mm_camera_super_buf_t *frame =
475                     (mm_camera_super_buf_t *)pme->mDataQ.dequeue();
476                 if (NULL != frame) {
477                     if (pme->mDataCB != NULL) {
478                         pme->mDataCB(frame, pme, pme->mUserData);
479                     } else {
480                         // no data cb routine, return buf here
481                         pme->bufDone(frame->bufs[0]->buf_idx);
482                     }
483                 }
484             }
485             break;
486         case CAMERA_CMD_TYPE_EXIT:
487             CDBG_HIGH("%s: Exit", __func__);
488             /* flush data buf queue */
489             pme->mDataQ.flush();
490             running = 0;
491             break;
492         default:
493             break;
494         }
495     } while (running);
496     CDBG("%s: X", __func__);
497     return NULL;
498 }
499 
500 /*===========================================================================
501  * FUNCTION   : bufDone
502  *
503  * DESCRIPTION: return stream buffer to kernel
504  *
505  * PARAMETERS :
506  *   @index   : index of buffer to be returned
507  *
508  * RETURN     : int32_t type of status
509  *              NO_ERROR  -- success
510  *              none-zero failure code
511  *==========================================================================*/
bufDone(int index)512 int32_t QCamera3Stream::bufDone(int index)
513 {
514     int32_t rc = NO_ERROR;
515     Mutex::Autolock lock(mLock);
516 
517     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
518         return BAD_INDEX;
519     }
520 
521     if( NULL == mBufDefs[index].mem_info) {
522         if (NULL == mMemOps) {
523             ALOGE("%s: Camera operations not initialized", __func__);
524             return NO_INIT;
525         }
526 
527         rc = mMemOps->map_ops(index, -1, mStreamBufs->getFd(index),
528                 mStreamBufs->getSize(index), mMemOps->userdata);
529         if (rc < 0) {
530             ALOGE("%s: Failed to map camera buffer %d", __func__, index);
531             return rc;
532         }
533 
534         rc = mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[index], index);
535         if (NO_ERROR != rc) {
536             ALOGE("%s: Couldn't find camera buffer definition", __func__);
537             mMemOps->unmap_ops(index, -1, mMemOps->userdata);
538             return rc;
539         }
540     }
541 
542     rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
543     if (rc < 0) {
544         return FAILED_TRANSACTION;
545     }
546 
547     return rc;
548 }
549 
550 /*===========================================================================
551  * FUNCTION   : bufRelease
552  *
553  * DESCRIPTION: release all resources associated with this buffer
554  *
555  * PARAMETERS :
556  *   @index   : index of buffer to be released
557  *
558  * RETURN     : int32_t type of status
559  *              NO_ERROR  -- success
560  *              none-zero failure code
561  *==========================================================================*/
bufRelease(int32_t index)562 int32_t QCamera3Stream::bufRelease(int32_t index)
563 {
564     int32_t rc = NO_ERROR;
565     Mutex::Autolock lock(mLock);
566 
567     if ((index >= mNumBufs) || (mBufDefs == NULL)) {
568         return BAD_INDEX;
569     }
570 
571     if (NULL != mBufDefs[index].mem_info) {
572         if (NULL == mMemOps) {
573             ALOGE("%s: Camera operations not initialized", __func__);
574             return NO_INIT;
575         }
576 
577         rc = mMemOps->unmap_ops(index, -1, mMemOps->userdata);
578         if (rc < 0) {
579             ALOGE("%s: Failed to un-map camera buffer %d", __func__, index);
580             return rc;
581         }
582 
583         mBufDefs[index].mem_info = NULL;
584     } else {
585         ALOGE("%s: Buffer at index %d not registered", __func__, index);
586         return BAD_INDEX;
587     }
588 
589     return rc;
590 }
591 
592 /*===========================================================================
593  * FUNCTION   : getBufs
594  *
595  * DESCRIPTION: allocate stream buffers
596  *
597  * PARAMETERS :
598  *   @offset     : offset info of stream buffers
599  *   @num_bufs   : number of buffers allocated
600  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
601  *                      at kernel initially
602  *   @bufs       : output of allocated buffers
603  *   @ops_tbl    : ptr to buf mapping/unmapping ops
604  *
605  * RETURN     : int32_t type of status
606  *              NO_ERROR  -- success
607  *              none-zero failure code
608  *==========================================================================*/
getBufs(cam_frame_len_offset_t * offset,uint8_t * num_bufs,uint8_t ** initial_reg_flag,mm_camera_buf_def_t ** bufs,mm_camera_map_unmap_ops_tbl_t * ops_tbl)609 int32_t QCamera3Stream::getBufs(cam_frame_len_offset_t *offset,
610                      uint8_t *num_bufs,
611                      uint8_t **initial_reg_flag,
612                      mm_camera_buf_def_t **bufs,
613                      mm_camera_map_unmap_ops_tbl_t *ops_tbl)
614 {
615     int rc = NO_ERROR;
616     uint8_t *regFlags;
617     Mutex::Autolock lock(mLock);
618 
619     if (!ops_tbl) {
620         ALOGE("%s: ops_tbl is NULL", __func__);
621         return INVALID_OPERATION;
622     }
623 
624     mFrameLenOffset = *offset;
625     mMemOps = ops_tbl;
626 
627     mStreamBufs = mChannel->getStreamBufs(mFrameLenOffset.frame_len);
628     if (!mStreamBufs) {
629         ALOGE("%s: Failed to allocate stream buffers", __func__);
630         return NO_MEMORY;
631     }
632 
633     int registeredBuffers = mStreamBufs->getCnt();
634     for (int i = 0; i < registeredBuffers; i++) {
635         rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
636                 mStreamBufs->getSize(i), ops_tbl->userdata);
637         if (rc < 0) {
638             ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
639             for (int j = 0; j < i; j++) {
640                 ops_tbl->unmap_ops(j, -1, ops_tbl->userdata);
641             }
642             return INVALID_OPERATION;
643         }
644     }
645 
646     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
647     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
648     if (!regFlags) {
649         ALOGE("%s: Out of memory", __func__);
650         for (int i = 0; i < registeredBuffers; i++) {
651             ops_tbl->unmap_ops(i, -1, ops_tbl->userdata);
652         }
653         return NO_MEMORY;
654     }
655     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
656 
657     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
658     if (mBufDefs == NULL) {
659         ALOGE("%s: Failed to allocate mm_camera_buf_def_t %d", __func__, rc);
660         for (int i = 0; i < registeredBuffers; i++) {
661             ops_tbl->unmap_ops(i, -1, ops_tbl->userdata);
662         }
663         free(regFlags);
664         regFlags = NULL;
665         return INVALID_OPERATION;
666     }
667     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
668     for (int i = 0; i < registeredBuffers; i++) {
669         mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
670     }
671 
672     rc = mStreamBufs->getRegFlags(regFlags);
673     if (rc < 0) {
674         ALOGE("%s: getRegFlags failed %d", __func__, rc);
675         for (int i = 0; i < registeredBuffers; i++) {
676             ops_tbl->unmap_ops(i, -1, ops_tbl->userdata);
677         }
678         free(mBufDefs);
679         mBufDefs = NULL;
680         free(regFlags);
681         regFlags = NULL;
682         return INVALID_OPERATION;
683     }
684 
685     *num_bufs = mNumBufs;
686     *initial_reg_flag = regFlags;
687     *bufs = mBufDefs;
688     return NO_ERROR;
689 }
690 
691 /*===========================================================================
692  * FUNCTION   : putBufs
693  *
694  * DESCRIPTION: deallocate stream buffers
695  *
696  * PARAMETERS :
697  *   @ops_tbl    : ptr to buf mapping/unmapping ops
698  *
699  * RETURN     : int32_t type of status
700  *              NO_ERROR  -- success
701  *              none-zero failure code
702  *==========================================================================*/
putBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)703 int32_t QCamera3Stream::putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
704 {
705     int rc = NO_ERROR;
706     Mutex::Autolock lock(mLock);
707 
708     for (int i = 0; i < mNumBufs; i++) {
709         if (NULL != mBufDefs[i].mem_info) {
710             rc = ops_tbl->unmap_ops(i, -1, ops_tbl->userdata);
711             if (rc < 0) {
712                 ALOGE("%s: un-map stream buf failed: %d", __func__, rc);
713             }
714         }
715     }
716     mBufDefs = NULL; // mBufDefs just keep a ptr to the buffer
717                      // mm-camera-interface own the buffer, so no need to free
718     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
719     mChannel->putStreamBufs();
720 
721     return rc;
722 }
723 
724 /*===========================================================================
725  * FUNCTION   : invalidateBuf
726  *
727  * DESCRIPTION: invalidate a specific stream buffer
728  *
729  * PARAMETERS :
730  *   @index   : index of the buffer to invalidate
731  *
732  * RETURN     : int32_t type of status
733  *              NO_ERROR  -- success
734  *              none-zero failure code
735  *==========================================================================*/
invalidateBuf(int index)736 int32_t QCamera3Stream::invalidateBuf(int index)
737 {
738     return mStreamBufs->invalidateCache(index);
739 }
740 
741 /*===========================================================================
742  * FUNCTION   : cleanInvalidateBuf
743  *
744  * DESCRIPTION: clean and invalidate a specific stream buffer
745  *
746  * PARAMETERS :
747  *   @index   : index of the buffer to invalidate
748  *
749  * RETURN     : int32_t type of status
750  *              NO_ERROR  -- success
751  *              none-zero failure code
752  *==========================================================================*/
cleanInvalidateBuf(int index)753 int32_t QCamera3Stream::cleanInvalidateBuf(int index)
754 {
755     return mStreamBufs->cleanInvalidateCache(index);
756 }
757 
758 /*===========================================================================
759  * FUNCTION   : getFrameOffset
760  *
761  * DESCRIPTION: query stream buffer frame offset info
762  *
763  * PARAMETERS :
764  *   @offset  : reference to struct to store the queried frame offset info
765  *
766  * RETURN     : int32_t type of status
767  *              NO_ERROR  -- success
768  *              none-zero failure code
769  *==========================================================================*/
getFrameOffset(cam_frame_len_offset_t & offset)770 int32_t QCamera3Stream::getFrameOffset(cam_frame_len_offset_t &offset)
771 {
772     offset = mFrameLenOffset;
773     return 0;
774 }
775 
776 /*===========================================================================
777  * FUNCTION   : getFrameDimension
778  *
779  * DESCRIPTION: query stream frame dimension info
780  *
781  * PARAMETERS :
782  *   @dim     : reference to struct to store the queried frame dimension
783  *
784  * RETURN     : int32_t type of status
785  *              NO_ERROR  -- success
786  *              none-zero failure code
787  *==========================================================================*/
getFrameDimension(cam_dimension_t & dim)788 int32_t QCamera3Stream::getFrameDimension(cam_dimension_t &dim)
789 {
790     if (mStreamInfo != NULL) {
791         dim = mStreamInfo->dim;
792         return 0;
793     }
794     return -1;
795 }
796 
797 /*===========================================================================
798  * FUNCTION   : getFormat
799  *
800  * DESCRIPTION: query stream format
801  *
802  * PARAMETERS :
803  *   @fmt     : reference to stream format
804  *
805  * RETURN     : int32_t type of status
806  *              NO_ERROR  -- success
807  *              none-zero failure code
808  *==========================================================================*/
getFormat(cam_format_t & fmt)809 int32_t QCamera3Stream::getFormat(cam_format_t &fmt)
810 {
811     if (mStreamInfo != NULL) {
812         fmt = mStreamInfo->fmt;
813         return 0;
814     }
815     return -1;
816 }
817 
818 /*===========================================================================
819  * FUNCTION   : getMyServerID
820  *
821  * DESCRIPTION: query server stream ID
822  *
823  * PARAMETERS : None
824  *
825  * RETURN     : stream ID from server
826  *==========================================================================*/
getMyServerID()827 uint32_t QCamera3Stream::getMyServerID() {
828     if (mStreamInfo != NULL) {
829         return mStreamInfo->stream_svr_id;
830     } else {
831         return 0;
832     }
833 }
834 
835 /*===========================================================================
836  * FUNCTION   : getMyType
837  *
838  * DESCRIPTION: query stream type
839  *
840  * PARAMETERS : None
841  *
842  * RETURN     : type of stream
843  *==========================================================================*/
getMyType() const844 cam_stream_type_t QCamera3Stream::getMyType() const
845 {
846     if (mStreamInfo != NULL) {
847         return mStreamInfo->stream_type;
848     } else {
849         return CAM_STREAM_TYPE_MAX;
850     }
851 }
852 
853 /*===========================================================================
854  * FUNCTION   : mapBuf
855  *
856  * DESCRIPTION: map stream related buffer to backend server
857  *
858  * PARAMETERS :
859  *   @buf_type : mapping type of buffer
860  *   @buf_idx  : index of buffer
861  *   @plane_idx: plane index
862  *   @fd       : fd of the buffer
863  *   @size     : lenght of the buffer
864  *
865  * RETURN     : int32_t type of status
866  *              NO_ERROR  -- success
867  *              none-zero failure code
868  *==========================================================================*/
mapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,uint32_t size)869 int32_t QCamera3Stream::mapBuf(uint8_t buf_type,
870                               uint32_t buf_idx,
871                               int32_t plane_idx,
872                               int fd,
873                               uint32_t size)
874 {
875     return mCamOps->map_stream_buf(mCamHandle, mChannelHandle,
876                                    mHandle, buf_type,
877                                    buf_idx, plane_idx,
878                                    fd, size);
879 
880 }
881 
882 /*===========================================================================
883  * FUNCTION   : unmapBuf
884  *
885  * DESCRIPTION: unmap stream related buffer to backend server
886  *
887  * PARAMETERS :
888  *   @buf_type : mapping type of buffer
889  *   @buf_idx  : index of buffer
890  *   @plane_idx: plane index
891  *
892  * RETURN     : int32_t type of status
893  *              NO_ERROR  -- success
894  *              none-zero failure code
895  *==========================================================================*/
unmapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)896 int32_t QCamera3Stream::unmapBuf(uint8_t buf_type, uint32_t buf_idx, int32_t plane_idx)
897 {
898     return mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle,
899                                      mHandle, buf_type,
900                                      buf_idx, plane_idx);
901 }
902 
903 /*===========================================================================
904  * FUNCTION   : setParameter
905  *
906  * DESCRIPTION: set stream based parameters
907  *
908  * PARAMETERS :
909  *   @param   : ptr to parameters to be set
910  *
911  * RETURN     : int32_t type of status
912  *              NO_ERROR  -- success
913  *              none-zero failure code
914  *==========================================================================*/
setParameter(cam_stream_parm_buffer_t & param)915 int32_t QCamera3Stream::setParameter(cam_stream_parm_buffer_t &param)
916 {
917     int32_t rc = NO_ERROR;
918     mStreamInfo->parm_buf = param;
919     rc = mCamOps->set_stream_parms(mCamHandle,
920                                    mChannelHandle,
921                                    mHandle,
922                                    &mStreamInfo->parm_buf);
923     if (rc == NO_ERROR) {
924         param = mStreamInfo->parm_buf;
925     }
926     return rc;
927 }
928 
929 /*===========================================================================
930  * FUNCTION   : releaseFrameData
931  *
932  * DESCRIPTION: callback function to release frame data node
933  *
934  * PARAMETERS :
935  *   @data      : ptr to post process input data
936  *   @user_data : user data ptr (QCameraReprocessor)
937  *
938  * RETURN     : None
939  *==========================================================================*/
releaseFrameData(void * data,void * user_data)940 void QCamera3Stream::releaseFrameData(void *data, void *user_data)
941 {
942     QCamera3Stream *pme = (QCamera3Stream *)user_data;
943     mm_camera_super_buf_t *frame = (mm_camera_super_buf_t *)data;
944     if (NULL != pme) {
945         pme->bufDone(frame->bufs[0]->buf_idx);
946     }
947 }
948 
949 }; // namespace qcamera
950