1 /* Copyright (c) 2012-2016, The Linux Foundation. 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 "QCameraStream"
31 
32 // System dependencies
33 #include <utils/Errors.h>
34 
35 // Camera dependencies
36 #include "QCameraBufferMaps.h"
37 #include "QCamera2HWI.h"
38 #include "QCameraStream.h"
39 
40 extern "C" {
41 #include "mm_camera_dbg.h"
42 }
43 
44 #define CAMERA_MIN_ALLOCATED_BUFFERS     3
45 
46 namespace qcamera {
47 
48 /*===========================================================================
49  * FUNCTION   : get_bufs
50  *
51  * DESCRIPTION: static function entry to allocate stream buffers
52  *
53  * PARAMETERS :
54  *   @offset     : offset info of stream buffers
55  *   @num_bufs   : number of buffers allocated
56  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
57  *                      at kernel initially
58  *   @bufs       : output of allocated buffers
59  *   @ops_tbl    : ptr to buf mapping/unmapping ops
60  *   @user_data  : user data ptr of ops_tbl
61  *
62  * RETURN     : int32_t type of status
63  *              NO_ERROR  -- success
64  *              none-zero failure code
65  *==========================================================================*/
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)66 int32_t QCameraStream::get_bufs(
67                      cam_frame_len_offset_t *offset,
68                      uint8_t *num_bufs,
69                      uint8_t **initial_reg_flag,
70                      mm_camera_buf_def_t **bufs,
71                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
72                      void *user_data)
73 {
74     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
75     if (!stream) {
76         LOGE("getBufs invalid stream pointer");
77         return NO_MEMORY;
78     }
79 
80     if (stream->mStreamInfo != NULL
81             && stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
82         //Batch Mode. Allocate Butch buffers
83         return stream->allocateBatchBufs(offset, num_bufs,
84                 initial_reg_flag, bufs, ops_tbl);
85     } else {
86         // Plane Buffer. Allocate plane buffer
87         return stream->getBufs(offset, num_bufs,
88                 initial_reg_flag, bufs, ops_tbl);
89     }
90 }
91 
92 /*===========================================================================
93  * FUNCTION   : get_bufs_deffered
94  *
95  * DESCRIPTION: static function entry to allocate deffered stream buffers
96  *
97  * PARAMETERS :
98  *   @offset     : offset info of stream buffers
99  *   @num_bufs   : number of buffers allocated
100  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
101  *                      at kernel initially
102  *   @bufs       : output of allocated buffers
103  *   @ops_tbl    : ptr to buf mapping/unmapping ops
104  *   @user_data  : user data ptr of ops_tbl
105  *
106  * RETURN     : int32_t type of status
107  *              NO_ERROR  -- success
108  *              none-zero failure code
109  *==========================================================================*/
get_bufs_deffered(cam_frame_len_offset_t *,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)110 int32_t QCameraStream::get_bufs_deffered(
111         cam_frame_len_offset_t * /* offset */,
112         uint8_t *num_bufs,
113         uint8_t **initial_reg_flag,
114         mm_camera_buf_def_t **bufs,
115         mm_camera_map_unmap_ops_tbl_t * ops_tbl,
116         void *user_data)
117 {
118     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
119 
120     if (!stream) {
121         LOGE("getBufs invalid stream pointer");
122         return NO_MEMORY;
123     }
124 
125     return stream->getBufsDeferred(NULL /*offset*/, num_bufs, initial_reg_flag, bufs,
126             ops_tbl);
127 }
128 
129 /*===========================================================================
130  * FUNCTION   : put_bufs
131  *
132  * DESCRIPTION: static function entry to deallocate stream buffers
133  *
134  * PARAMETERS :
135  *   @ops_tbl    : ptr to buf mapping/unmapping ops
136  *   @user_data  : user data ptr of ops_tbl
137  *
138  * RETURN     : int32_t type of status
139  *              NO_ERROR  -- success
140  *              none-zero failure code
141  *==========================================================================*/
put_bufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)142 int32_t QCameraStream::put_bufs(
143         mm_camera_map_unmap_ops_tbl_t *ops_tbl,
144         void *user_data)
145 {
146     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
147     if (!stream) {
148         LOGE("putBufs invalid stream pointer");
149         return NO_MEMORY;
150     }
151 
152     if (stream->mStreamInfo != NULL
153             && stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
154         //Batch Mode. release  Butch buffers
155         return stream->releaseBatchBufs(ops_tbl);
156     } else {
157         // Plane Buffer. release  plane buffer
158         return stream->putBufs(ops_tbl);
159     }
160 
161 }
162 
163 /*===========================================================================
164  * FUNCTION   : put_bufs_deffered
165  *
166  * DESCRIPTION: static function entry to deallocate deffered stream buffers
167  *
168  * PARAMETERS :
169  *   @ops_tbl    : ptr to buf mapping/unmapping ops
170  *   @user_data  : user data ptr of ops_tbl
171  *
172  * RETURN     : int32_t type of status
173  *              NO_ERROR  -- success
174  *              none-zero failure code
175  *==========================================================================*/
put_bufs_deffered(mm_camera_map_unmap_ops_tbl_t *,void * user_data)176 int32_t QCameraStream::put_bufs_deffered(
177         mm_camera_map_unmap_ops_tbl_t * /*ops_tbl */,
178         void * user_data )
179 {
180     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
181 
182     if (!stream) {
183         LOGE("put_bufs_deffered invalid stream pointer");
184         return NO_MEMORY;
185     }
186 
187     return stream->putBufsDeffered();
188 }
189 
190 /*===========================================================================
191  * FUNCTION   : invalidate_buf
192  *
193  * DESCRIPTION: static function entry to invalidate a specific stream buffer
194  *
195  * PARAMETERS :
196  *   @index      : index of the stream buffer to invalidate
197  *   @user_data  : user data ptr of ops_tbl
198  *
199  * RETURN     : int32_t type of status
200  *              NO_ERROR  -- success
201  *              none-zero failure code
202  *==========================================================================*/
invalidate_buf(uint32_t index,void * user_data)203 int32_t QCameraStream::invalidate_buf(uint32_t index, void *user_data)
204 {
205     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
206     if (!stream) {
207         LOGE("invalid stream pointer");
208         return NO_MEMORY;
209     }
210 
211     if (stream->mStreamInfo->is_secure == SECURE){
212         return 0;
213     }
214 
215     if (stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
216         for (int i = 0; i < stream->mBufDefs[index].user_buf.bufs_used; i++) {
217             uint32_t buf_idx = stream->mBufDefs[index].user_buf.buf_idx[i];
218             stream->invalidateBuf(buf_idx);
219         }
220     } else {
221         return stream->invalidateBuf(index);
222     }
223 
224     return 0;
225 }
226 
227 /*===========================================================================
228  * FUNCTION   : clean_invalidate_buf
229  *
230  * DESCRIPTION: static function entry to clean invalidate a specific stream buffer
231  *
232  * PARAMETERS :
233  *   @index      : index of the stream buffer to clean invalidate
234  *   @user_data  : user data ptr of ops_tbl
235  *
236  * RETURN     : int32_t type of status
237  *              NO_ERROR  -- success
238  *              none-zero failure code
239  *==========================================================================*/
clean_invalidate_buf(uint32_t index,void * user_data)240 int32_t QCameraStream::clean_invalidate_buf(uint32_t index, void *user_data)
241 {
242     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
243     if (!stream) {
244         LOGE("invalid stream pointer");
245         return NO_MEMORY;
246     }
247 
248     if (stream->mStreamInfo->is_secure == SECURE){
249         return 0;
250     }
251 
252     if (stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
253         for (int i = 0; i < stream->mBufDefs[index].user_buf.bufs_used; i++) {
254             uint32_t buf_idx = stream->mBufDefs[index].user_buf.buf_idx[i];
255             stream->cleanInvalidateBuf(buf_idx);
256         }
257     } else {
258         return stream->cleanInvalidateBuf(index);
259     }
260 
261     return 0;
262 }
263 
264 /*===========================================================================
265  * FUNCTION   : clean_buf
266  *
267  * DESCRIPTION: static function entry to clean a specific stream buffer
268  *
269  * PARAMETERS :
270  *   @index      : index of the stream buffer to clean invalidate
271  *   @user_data  : user data ptr of ops_tbl
272  *
273  * RETURN     : int32_t type of status
274  *              NO_ERROR  -- success
275  *              none-zero failure code
276  *==========================================================================*/
clean_buf(uint32_t index,void * user_data)277 int32_t QCameraStream::clean_buf(uint32_t index, void *user_data)
278 {
279     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
280     if (!stream) {
281         LOGE("invalid stream pointer");
282         return NO_MEMORY;
283     }
284 
285     if (stream->mStreamInfo->is_secure == SECURE){
286         return 0;
287     }
288 
289     if (stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
290         for (int i = 0; i < stream->mBufDefs[index].user_buf.bufs_used; i++) {
291             uint32_t buf_idx = stream->mBufDefs[index].user_buf.buf_idx[i];
292             stream->cleanBuf(buf_idx);
293         }
294     } else {
295         return stream->cleanBuf(index);
296     }
297 
298     return 0;
299 }
300 
301 
302 /*===========================================================================
303  * FUNCTION   : set_config_ops
304  *
305  * DESCRIPTION: static function update mm-interface ops functions
306  *
307  * PARAMETERS :
308  *   @ops_tbl    : ptr to buf mapping/unmapping ops
309  *   @user_data  : user data ptr of ops_tbl
310  *
311  * RETURN     : int32_t type of status
312  *              NO_ERROR  -- success
313  *              none-zero failure code
314  *==========================================================================*/
set_config_ops(mm_camera_map_unmap_ops_tbl_t * ops_tbl,void * user_data)315 int32_t QCameraStream::set_config_ops(mm_camera_map_unmap_ops_tbl_t *ops_tbl,
316         void *user_data)
317 {
318     QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
319     if (!stream) {
320         LOGE("Stream invalid");
321         return NO_MEMORY;
322     }
323 
324     stream->m_MemOpsTbl = *ops_tbl;
325     return 0;
326 }
327 
328 /*===========================================================================
329  * FUNCTION   : QCameraStream
330  *
331  * DESCRIPTION: constructor of QCameraStream
332  *
333  * PARAMETERS :
334  *   @allocator  : memory allocator obj
335  *   @camHandle  : camera handle
336  *   @chId       : channel handle
337  *   @camOps     : ptr to camera ops table
338  *   @paddingInfo: ptr to padding info
339  *   @deffered   : deferred stream
340  *   @online_rotation: rotation applied online
341  *
342  * RETURN     : None
343  *==========================================================================*/
QCameraStream(QCameraAllocator & allocator,uint32_t camHandle,uint32_t chId,mm_camera_ops_t * camOps,cam_padding_info_t * paddingInfo,bool deffered,cam_rotation_t online_rotation)344 QCameraStream::QCameraStream(QCameraAllocator &allocator,
345         uint32_t camHandle, uint32_t chId,
346         mm_camera_ops_t *camOps, cam_padding_info_t *paddingInfo,
347         bool deffered, cam_rotation_t online_rotation):
348         mDumpFrame(0),
349         mDumpMetaFrame(0),
350         mDumpSkipCnt(0),
351         mStreamTimestamp(0),
352         mCamHandle(camHandle),
353         mChannelHandle(chId),
354         mHandle(0),
355         mCamOps(camOps),
356         mStreamInfo(NULL),
357         mNumBufs(0),
358         mNumPlaneBufs(0),
359         mNumBufsNeedAlloc(0),
360         mRegFlags(NULL),
361         mDataCB(NULL),
362         mSYNCDataCB(NULL),
363         mUserData(NULL),
364         mDataQ(releaseFrameData, this),
365         mStreamInfoBuf(NULL),
366         mMiscBuf(NULL),
367         mStreamBufs(NULL),
368         mStreamBatchBufs(NULL),
369         mAllocator(allocator),
370         mBufDefs(NULL),
371         mPlaneBufDefs(NULL),
372         mOnlineRotation(online_rotation),
373         mStreamBufsAcquired(false),
374         m_bActive(false),
375         mDynBufAlloc(false),
376         mBufAllocPid(0),
377         mDefferedAllocation(deffered),
378         wait_for_cond(false),
379         mAllocTaskId(0),
380         mMapTaskId(0),
381         mSyncCBEnabled(false)
382 {
383     mDualStream = is_dual_camera_by_handle(chId);
384     if (get_main_camera_handle(chId)) {
385         mCamType = MM_CAMERA_TYPE_MAIN;
386     }
387     if (get_aux_camera_handle(chId)) {
388         mCamType |= MM_CAMERA_TYPE_AUX;
389     }
390     mMemVtbl.user_data = this;
391     if ( !deffered ) {
392         mMemVtbl.get_bufs = get_bufs;
393         mMemVtbl.put_bufs = put_bufs;
394     } else {
395         mMemVtbl.get_bufs = get_bufs_deffered;
396         mMemVtbl.put_bufs = put_bufs_deffered;
397     }
398     mMemVtbl.invalidate_buf = invalidate_buf;
399     mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
400     mMemVtbl.clean_buf = clean_buf;
401     mMemVtbl.set_config_ops = set_config_ops;
402     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
403     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
404     memset(&mCropInfo, 0, sizeof(cam_rect_t));
405     memset(&m_MemOpsTbl, 0, sizeof(mm_camera_map_unmap_ops_tbl_t));
406     memset(&m_OutputCrop, 0, sizeof(cam_stream_parm_buffer_t));
407     memset(&m_ImgProp, 0, sizeof(cam_stream_parm_buffer_t));
408     memset(&mAllocTask, 0, sizeof(mAllocTask));
409     memset(&mMapTask, 0, sizeof(mMapTask));
410     pthread_mutex_init(&mCropLock, NULL);
411     pthread_mutex_init(&mParameterLock, NULL);
412     mCurMetaMemory = NULL;
413     mCurBufIndex = -1;
414     mCurMetaIndex = -1;
415     mFirstTimeStamp = 0;
416     memset (&mStreamMetaMemory, 0,
417             (sizeof(MetaMemory) * CAMERA_MIN_VIDEO_BATCH_BUFFERS));
418     pthread_mutex_init(&m_lock, NULL);
419     pthread_cond_init(&m_cond, NULL);
420 }
421 
422 /*===========================================================================
423  * FUNCTION   : ~QCameraStream
424  *
425  * DESCRIPTION: deconstructor of QCameraStream
426  *
427  * PARAMETERS : None
428  *
429  * RETURN     : None
430  *==========================================================================*/
~QCameraStream()431 QCameraStream::~QCameraStream()
432 {
433     pthread_mutex_destroy(&mCropLock);
434     pthread_mutex_destroy(&mParameterLock);
435 
436     mAllocator.waitForBackgroundTask(mAllocTaskId);
437     mAllocator.waitForBackgroundTask(mMapTaskId);
438     if (mBufAllocPid != 0) {
439         cond_signal(true);
440         LOGL("Wait for buf allocation thread dead");
441         // Wait for the allocation of additional stream buffers
442         pthread_join(mBufAllocPid, NULL);
443         mBufAllocPid = 0;
444     }
445 
446     if (mDefferedAllocation) {
447         mStreamBufsAcquired = false;
448         releaseBuffs();
449     }
450 
451     unmapStreamInfoBuf();
452     releaseStreamInfoBuf();
453 
454     if (mMiscBuf) {
455         unMapBuf(mMiscBuf, CAM_MAPPING_BUF_TYPE_MISC_BUF, NULL);
456         releaseMiscBuf();
457     }
458 
459     // delete stream
460     if (mHandle > 0) {
461         mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
462         mHandle = 0;
463     }
464     pthread_mutex_destroy(&m_lock);
465     pthread_cond_destroy(&m_cond);
466     mDualStream = 0;
467 }
468 
469 /*===========================================================================
470  * FUNCTION   : unmapStreamInfoBuf
471  *
472  * DESCRIPTION: Unmap stream info buffer
473  *
474  * PARAMETERS :
475  *
476  * RETURN     : int32_t type of status
477  *              NO_ERROR  -- success
478  *              none-zero failure code
479  *==========================================================================*/
unmapStreamInfoBuf()480 int32_t QCameraStream::unmapStreamInfoBuf()
481 {
482     int rc = NO_ERROR;
483 
484     if (mStreamInfoBuf != NULL) {
485         rc = mCamOps->unmap_stream_buf(mCamHandle,
486             mChannelHandle,
487             mHandle,
488             CAM_MAPPING_BUF_TYPE_STREAM_INFO,
489             0,
490             -1);
491 
492         if (rc < 0) {
493             LOGE("Failed to unmap stream info buffer");
494         }
495     }
496 
497     return rc;
498 }
499 
500 /*===========================================================================
501  * FUNCTION   : releaseMiscBuf
502  *
503  * DESCRIPTION: Release misc buffers
504  *
505  * PARAMETERS :
506  *
507  * RETURN     : int32_t type of status
508  *              NO_ERROR  -- success
509  *              none-zero failure code
510  *==========================================================================*/
releaseMiscBuf()511 int32_t QCameraStream::releaseMiscBuf()
512 {
513     int rc = NO_ERROR;
514 
515     if (mMiscBuf != NULL) {
516         mMiscBuf->deallocate();
517         delete mMiscBuf;
518         mMiscBuf = NULL;
519     }
520 
521     return rc;
522 }
523 
524 /*===========================================================================
525  * FUNCTION   : releaseStreamInfoBuf
526  *
527  * DESCRIPTION: Release stream info buffer
528  *
529  * PARAMETERS :
530  *
531  * RETURN     : int32_t type of status
532  *              NO_ERROR  -- success
533  *              none-zero failure code
534  *==========================================================================*/
releaseStreamInfoBuf()535 int32_t QCameraStream::releaseStreamInfoBuf()
536 {
537     int rc = NO_ERROR;
538 
539     if (mStreamInfoBuf != NULL) {
540         mStreamInfoBuf->deallocate();
541         delete mStreamInfoBuf;
542         mStreamInfoBuf = NULL;
543         mStreamInfo = NULL;
544     }
545 
546     return rc;
547 }
548 
549 /*===========================================================================
550  * FUNCTION   : deleteStream
551  *
552  * DESCRIPTION: Deletes a camera stream
553  *
554  * PARAMETERS : None
555  *
556  * RETURN     : None
557  *==========================================================================*/
deleteStream()558 void QCameraStream::deleteStream()
559 {
560     if (mHandle > 0) {
561         acquireStreamBufs();
562         releaseBuffs();
563         unmapStreamInfoBuf();
564         mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
565     }
566 }
567 
568 /*===========================================================================
569  * FUNCTION   : unMapBuf
570  *
571  * DESCRIPTION: unmaps buffers
572  *
573  * PARAMETERS :
574  *   @heapBuf      : heap buffer handler
575  *   @bufType      : buffer type
576  *   @ops_tbl    : ptr to buf mapping/unmapping ops
577  *
578  * RETURN     : int32_t type of status
579  *              NO_ERROR  -- success
580  *              none-zero failure code
581  *==========================================================================*/
unMapBuf(QCameraMemory * Buf,cam_mapping_buf_type bufType,__unused mm_camera_map_unmap_ops_tbl_t * ops_tbl)582 int32_t QCameraStream::unMapBuf(QCameraMemory *Buf,
583         cam_mapping_buf_type bufType, __unused mm_camera_map_unmap_ops_tbl_t *ops_tbl)
584 {
585     int32_t rc = NO_ERROR;
586     uint8_t cnt;
587     ssize_t bufSize = BAD_INDEX;
588     uint32_t i;
589 
590     cnt = Buf->getCnt();
591     for (i = 0; i < cnt; i++) {
592         bufSize = Buf->getSize(i);
593         if (BAD_INDEX != bufSize) {
594             if (m_MemOpsTbl.unmap_ops == NULL ) {
595                 rc = mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle, mHandle,
596                         bufType, i, -1);
597             } else {
598                 rc = m_MemOpsTbl.unmap_ops(i, -1, bufType, m_MemOpsTbl.userdata);
599             }
600             if (rc < 0) {
601                 LOGE("Failed to unmap buffer");
602                 break;
603             }
604         } else {
605             LOGE("Failed to retrieve buffer size (bad index)");
606             rc = BAD_INDEX;
607             break;
608         }
609     }
610 
611     return rc;
612 }
613 
614 /*===========================================================================
615  * FUNCTION   : mapBufs
616  *
617  * DESCRIPTION: maps buffers
618  *
619  * PARAMETERS :
620  *   @heapBuf      : heap buffer handler
621  *   @bufType      : buffer type
622  *   @ops_tbl    : ptr to buf mapping/unmapping ops
623  *
624  * RETURN     : int32_t type of status
625  *              NO_ERROR  -- success
626  *              none-zero failure code
627  *==========================================================================*/
mapBufs(QCameraMemory * Buf,cam_mapping_buf_type bufType,__unused mm_camera_map_unmap_ops_tbl_t * ops_tbl)628 int32_t QCameraStream::mapBufs(QCameraMemory *Buf,
629         cam_mapping_buf_type bufType, __unused mm_camera_map_unmap_ops_tbl_t *ops_tbl)
630 {
631     int32_t rc = NO_ERROR;
632     uint32_t i = 0;
633     uint32_t activeHandle = mHandle;
634     QCameraBufferMaps bufferMaps;
635 
636     for (i = 0; i < Buf->getCnt(); i++) {
637         ssize_t bufSize = Buf->getSize(i);
638         if (BAD_INDEX == bufSize) {
639             LOGE("Failed to retrieve buffer size (bad index)");
640             return BAD_INDEX;
641         }
642 
643         if ((bufType == CAM_MAPPING_BUF_TYPE_STREAM_INFO)
644                 || (bufType == CAM_MAPPING_BUF_TYPE_MISC_BUF)) {
645             if ((i > 0 && isDualStream()) ||
646                     (mCamType == MM_CAMERA_TYPE_AUX)) {
647                 activeHandle = get_aux_camera_handle(mHandle);
648             } else {
649                 activeHandle = get_main_camera_handle(mHandle);
650             }
651         }
652         rc = bufferMaps.enqueue(bufType, activeHandle, i /*buf index*/, -1 /*plane index*/,
653                 0 /*cookie*/, Buf->getFd(i), bufSize, Buf->getPtr(i));
654 
655         if (rc < 0) {
656             LOGE("Failed to map buffers");
657             return BAD_INDEX;
658         }
659     }
660 
661     cam_buf_map_type_list bufMapList;
662     rc = bufferMaps.getCamBufMapList(bufMapList);
663     if (rc < 0) {
664         LOGE("Failed to map buffers");
665         return BAD_INDEX;
666     }
667 
668     if (m_MemOpsTbl.bundled_map_ops == NULL) {
669         rc = mCamOps->map_stream_bufs(mCamHandle, mChannelHandle, &bufMapList);
670     } else {
671         rc = m_MemOpsTbl.bundled_map_ops(&bufMapList, m_MemOpsTbl.userdata);
672     }
673 
674     if (rc < 0) {
675         LOGE("Failed to map buffer");
676         rc = BAD_INDEX;
677     }
678     return rc;
679 }
680 
681 /*===========================================================================
682  * FUNCTION   : backgroundAllocate
683  *
684  * DESCRIPTION: schedule buffers to be allocated in the background
685  *
686  * PARAMETERS :
687  *
688  * RETURN     : int32_t type of status
689  *              NO_ERROR  -- success
690  *              none-zero failure code
691  *==========================================================================*/
backgroundAllocate(void * data)692 int32_t QCameraStream::backgroundAllocate(void *data) {
693     QCameraStream *stream = (QCameraStream*)data;
694     int32_t rc = stream->allocateBuffers();
695     if (rc != NO_ERROR) {
696         LOGE("Error allocating buffers !!!");
697     }
698     return rc;
699 }
700 
701 /*===========================================================================
702  * FUNCTION   : backgroundMap
703  *
704  * DESCRIPTION: map buffers in the background
705  *
706  * PARAMETERS :
707  *
708  * RETURN     : int32_t type of status
709  *              NO_ERROR  -- success
710  *              none-zero failure code
711  *==========================================================================*/
backgroundMap(void * data)712 int32_t QCameraStream::backgroundMap(void *data) {
713     QCameraStream *stream = (QCameraStream*)data;
714     int32_t rc = stream->mapBuffers();
715     if (rc != NO_ERROR) {
716         LOGE("Error mapping buffers !!!");
717     }
718     return rc;
719 }
720 
721 /*===========================================================================
722  * FUNCTION   : init
723  *
724  * DESCRIPTION: initialize stream obj
725  *
726  * PARAMETERS :
727  *   @streamInfoBuf: ptr to buf that contains stream info
728  *   @miscBuf      : ptr to buf that contains misc bufs
729  *   @stream_cb    : stream data notify callback. Can be NULL if not needed
730  *   @userdata     : user data ptr
731  *   @bDynallocBuf : flag to indicate if buffer allocation can be in 2 steps
732  *
733  * RETURN     : int32_t type of status
734  *              NO_ERROR  -- success
735  *              none-zero failure code
736  *==========================================================================*/
init(QCameraHeapMemory * streamInfoBuf,QCameraHeapMemory * miscBuf,stream_cb_routine stream_cb,void * userdata,bool bDynallocBuf)737 int32_t QCameraStream::init(QCameraHeapMemory *streamInfoBuf,
738         QCameraHeapMemory *miscBuf,
739         stream_cb_routine stream_cb,
740         void *userdata,
741         bool bDynallocBuf)
742 {
743     int32_t rc = OK;
744 
745     // assign and map stream info memory
746     mStreamInfoBuf = streamInfoBuf;
747     mStreamInfo = reinterpret_cast<cam_stream_info_t *>(mStreamInfoBuf->getPtr(0));
748     mNumBufs = mStreamInfo->num_bufs;
749     mDynBufAlloc = bDynallocBuf;
750 
751     // Calculate buffer size for deffered allocation
752     if (mDefferedAllocation) {
753         rc = calcOffset(mStreamInfo);
754         if (rc < 0) {
755             LOGE("Failed to calculate stream offset");
756             goto done;
757         }
758 
759         mAllocTask.bgFunction = backgroundAllocate;
760         mAllocTask.bgArgs = this;
761         mAllocTaskId = mAllocator.scheduleBackgroundTask(&mAllocTask);
762         if (mAllocTaskId == 0) {
763             LOGE("Failed to schedule buffer alloction");
764             rc = -ENOMEM;
765             goto done;
766         }
767     }
768 
769     mHandle = mCamOps->add_stream(mCamHandle, mChannelHandle);
770     if (!mHandle) {
771         LOGE("add_stream failed");
772         rc = UNKNOWN_ERROR;
773         goto done;
774     }
775 
776     mMasterCamera = MM_CAMERA_TYPE_MAIN;
777     if (mCamType & MM_CAMERA_TYPE_MAIN) {
778         mActiveCameras = MM_CAMERA_TYPE_MAIN;
779     }
780     if (mCamType & MM_CAMERA_TYPE_AUX) {
781         mActiveCameras |= MM_CAMERA_TYPE_AUX;
782     }
783     if (isDualStream()) {
784         if (needFrameSync()) {
785             mCamOps->handle_frame_sync_cb(mCamHandle, mChannelHandle,
786                     mHandle, MM_CAMERA_CB_REQ_TYPE_FRAME_SYNC);
787         } else if (!needCbSwitch()) {
788             mCamOps->handle_frame_sync_cb(mCamHandle, mChannelHandle,
789                     mHandle, MM_CAMERA_CB_REQ_TYPE_ALL_CB);
790         }
791     }
792 
793     rc = mapBufs(mStreamInfoBuf, CAM_MAPPING_BUF_TYPE_STREAM_INFO, NULL);
794     if (rc < 0) {
795         LOGE("Failed to map stream info buffer");
796         goto err1;
797     }
798 
799     mMiscBuf = miscBuf;
800     if (miscBuf) {
801         rc = mapBufs(mMiscBuf, CAM_MAPPING_BUF_TYPE_MISC_BUF, NULL);
802         if (rc < 0) {
803             LOGE("Failed to map miscellaneous buffer");
804             releaseMiscBuf();
805             goto err1;
806         }
807     }
808 
809     rc = configStream();
810     if (rc < 0) {
811         LOGE("Failed to config stream ");
812         goto err1;
813     }
814 
815     if (mDefferedAllocation) {
816         mMapTask.bgFunction = backgroundMap;
817         mMapTask.bgArgs = this;
818         mMapTaskId = mAllocator.scheduleBackgroundTask(&mMapTask);
819         if (mMapTaskId == 0) {
820             LOGE("Failed to schedule buffer alloction");
821             rc = -ENOMEM;
822             goto err1;
823         }
824     }
825 
826     mDataCB = stream_cb;
827     mUserData = userdata;
828     return 0;
829 
830 err1:
831     mCamOps->delete_stream(mCamHandle, mChannelHandle, mHandle);
832     mHandle = 0;
833 done:
834     return rc;
835 }
836 
837 /*===========================================================================
838  * FUNCTION   : calcOffset
839  *
840  * DESCRIPTION: calculate frame offset based on format and padding information
841  *
842  * PARAMETERS :
843  *   @streamInfo  : stream information
844  *
845  * RETURN     : int32_t type of status
846  *              0  -- success
847  *              -1 -- failure
848  *==========================================================================*/
calcOffset(cam_stream_info_t * streamInfo)849 int32_t QCameraStream::calcOffset(cam_stream_info_t *streamInfo)
850 {
851     int32_t rc = 0;
852 
853     cam_dimension_t dim = streamInfo->dim;
854     if (streamInfo->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION &&
855             streamInfo->stream_type != CAM_STREAM_TYPE_VIDEO) {
856         if (streamInfo->pp_config.rotation == ROTATE_90 ||
857                 streamInfo->pp_config.rotation == ROTATE_270) {
858             // rotated by 90 or 270, need to switch width and height
859             dim.width = streamInfo->dim.height;
860             dim.height = streamInfo->dim.width;
861         }
862     }
863 
864     switch (streamInfo->stream_type) {
865     case CAM_STREAM_TYPE_PREVIEW:
866     case CAM_STREAM_TYPE_CALLBACK:
867         rc = mm_stream_calc_offset_preview(streamInfo,
868                 &dim,
869                 &mPaddingInfo,
870                 &streamInfo->buf_planes);
871         break;
872     case CAM_STREAM_TYPE_POSTVIEW:
873         rc = mm_stream_calc_offset_post_view(streamInfo,
874                 &dim,
875                 &mPaddingInfo,
876                 &streamInfo->buf_planes);
877         break;
878     case CAM_STREAM_TYPE_SNAPSHOT:
879         rc = mm_stream_calc_offset_snapshot(streamInfo->fmt,
880                 &dim,
881                 &mPaddingInfo,
882                 &streamInfo->buf_planes);
883         break;
884     case CAM_STREAM_TYPE_OFFLINE_PROC:
885         rc = mm_stream_calc_offset_postproc(streamInfo,
886                 &mPaddingInfo,
887                 &streamInfo->buf_planes);
888         break;
889     case CAM_STREAM_TYPE_VIDEO:
890         rc = mm_stream_calc_offset_video(streamInfo->fmt,
891                 &dim, &streamInfo->buf_planes);
892         break;
893     case CAM_STREAM_TYPE_RAW:
894         rc = mm_stream_calc_offset_raw(streamInfo,
895                 &dim,
896                 &mPaddingInfo,
897                 &streamInfo->buf_planes);
898         break;
899     case CAM_STREAM_TYPE_ANALYSIS:
900         rc = mm_stream_calc_offset_analysis(streamInfo->fmt,
901                 &dim,
902                 &mPaddingInfo,
903                 &streamInfo->buf_planes);
904         break;
905     case CAM_STREAM_TYPE_METADATA:
906         rc = mm_stream_calc_offset_metadata(&dim,
907                 &mPaddingInfo,
908                 &streamInfo->buf_planes);
909         break;
910     default:
911         LOGE("not supported for stream type %d",
912                  streamInfo->stream_type);
913         rc = -1;
914         break;
915     }
916     return rc;
917 }
918 
919 /*===========================================================================
920  * FUNCTION   : start
921  *
922  * DESCRIPTION: start stream. Will start main stream thread to handle stream
923  *              related ops.
924  *
925  * PARAMETERS : none
926  *
927  * RETURN     : int32_t type of status
928  *              NO_ERROR  -- success
929  *              none-zero failure code
930  *==========================================================================*/
start()931 int32_t QCameraStream::start()
932 {
933     int32_t rc = 0;
934     mDataQ.init();
935     rc = mProcTh.launch(dataProcRoutine, this);
936     if (rc == NO_ERROR) {
937         m_bActive = true;
938     }
939 
940     mCurMetaMemory = NULL;
941     mCurBufIndex = -1;
942     mCurMetaIndex = -1;
943     mFirstTimeStamp = 0;
944     memset (&mStreamMetaMemory, 0,
945             (sizeof(MetaMemory) * CAMERA_MIN_VIDEO_BATCH_BUFFERS));
946     return rc;
947 }
948 
949 /*===========================================================================
950  * FUNCTION   : stop
951  *
952  * DESCRIPTION: stop stream. Will stop main stream thread
953  *
954  * PARAMETERS : none
955  *
956  * RETURN     : int32_t type of status
957  *              NO_ERROR  -- success
958  *              none-zero failure code
959  *==========================================================================*/
stop()960 int32_t QCameraStream::stop()
961 {
962     int32_t rc = 0;
963     m_bActive = false;
964     mAllocator.waitForBackgroundTask(mAllocTaskId);
965     mAllocator.waitForBackgroundTask(mMapTaskId);
966     rc = mProcTh.exit();
967     return rc;
968 }
969 
970 /*===========================================================================
971  * FUNCTION   : syncRuntimeParams
972  *
973  * DESCRIPTION: query and sync runtime parameters like output crop
974  *              buffer info etc.
975  *
976  * PARAMETERS : none
977  *
978  * RETURN     : int32_t type of status
979  *              NO_ERROR  -- success
980  *              none-zero failure code
981  *==========================================================================*/
syncRuntimeParams()982 int32_t QCameraStream::syncRuntimeParams()
983 {
984     int32_t ret = NO_ERROR;
985 
986     memset(&m_OutputCrop, 0, sizeof(cam_stream_parm_buffer_t));
987     m_OutputCrop.type = CAM_STREAM_PARAM_TYPE_GET_OUTPUT_CROP;
988 
989     ret = getParameter(m_OutputCrop);
990     if (ret != NO_ERROR) {
991         LOGE("stream getParameter for output crop failed");
992         return ret;
993     }
994 
995     memset(&m_ImgProp, 0, sizeof(cam_stream_parm_buffer_t));
996     m_ImgProp.type = CAM_STREAM_PARAM_TYPE_GET_IMG_PROP;
997 
998     ret = getParameter(m_ImgProp);
999     if (ret != NO_ERROR) {
1000         LOGE("stream getParameter for image prop failed");
1001         return ret;
1002     }
1003 
1004     return ret;
1005 }
1006 
1007 /*===========================================================================
1008  * FUNCTION   : processZoomDone
1009  *
1010  * DESCRIPTION: process zoom done event
1011  *
1012  * PARAMETERS :
1013  *   @previewWindoe : preview window ops table to set preview crop window
1014  *   @crop_info     : crop info
1015  *
1016  * RETURN     : int32_t type of status
1017  *              NO_ERROR  -- success
1018  *              none-zero failure code
1019  *==========================================================================*/
processZoomDone(preview_stream_ops_t * previewWindow,cam_crop_data_t & crop_info)1020 int32_t QCameraStream::processZoomDone(preview_stream_ops_t *previewWindow,
1021                                        cam_crop_data_t &crop_info)
1022 {
1023     int32_t rc = 0;
1024 
1025     if (!m_bActive) {
1026         LOGL("Stream not active");
1027         return NO_ERROR;
1028     }
1029 
1030     // get stream param for crop info
1031     for (int i = 0; i < crop_info.num_of_streams; i++) {
1032         if (crop_info.crop_info[i].stream_id == mStreamInfo->stream_svr_id) {
1033             pthread_mutex_lock(&mCropLock);
1034             mCropInfo = crop_info.crop_info[i].crop;
1035             pthread_mutex_unlock(&mCropLock);
1036 
1037             // update preview window crop if it's preview/postview stream
1038             if ( (previewWindow != NULL) &&
1039                  (mStreamInfo->stream_type == CAM_STREAM_TYPE_PREVIEW ||
1040                   mStreamInfo->stream_type == CAM_STREAM_TYPE_POSTVIEW) ) {
1041                 rc = previewWindow->set_crop(previewWindow,
1042                                              mCropInfo.left,
1043                                              mCropInfo.top,
1044                                              mCropInfo.width,
1045                                              mCropInfo.height);
1046             }
1047             break;
1048         }
1049     }
1050     return rc;
1051 }
1052 
1053 /*===========================================================================
1054  * FUNCTION   : processDataNotify
1055  *
1056  * DESCRIPTION: process stream data notify
1057  *
1058  * PARAMETERS :
1059  *   @frame   : stream frame received
1060  *
1061  * RETURN     : int32_t type of status
1062  *              NO_ERROR  -- success
1063  *              none-zero failure code
1064  *==========================================================================*/
processDataNotify(mm_camera_super_buf_t * frame)1065 int32_t QCameraStream::processDataNotify(mm_camera_super_buf_t *frame)
1066 {
1067     LOGD("\n");
1068 
1069     if (mDataQ.enqueue((void *)frame)) {
1070         return mProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
1071     } else {
1072         if (!m_bActive) {
1073             LOGW("Stream thread is not active, no ops here %d", getMyType());
1074         } else {
1075             bufDone(frame);
1076         }
1077         free(frame);
1078         return NO_ERROR;
1079     }
1080 }
1081 
1082 /*===========================================================================
1083  * FUNCTION   : dataNotifySYNCCB
1084  *
1085  * DESCRIPTION: This function registered with interface for
1086  *                        SYNC callback if SYNC callback registered.
1087  *
1088  * PARAMETERS :
1089  *   @recvd_frame   : stream frame received
1090  *   @userdata      : user data ptr
1091  *
1092  * RETURN     : none
1093  *==========================================================================*/
dataNotifySYNCCB(mm_camera_super_buf_t * recvd_frame,void * userdata)1094 void QCameraStream::dataNotifySYNCCB(mm_camera_super_buf_t *recvd_frame,
1095         void *userdata)
1096 {
1097     LOGD("\n");
1098     QCameraStream* stream = (QCameraStream *)userdata;
1099     if (stream == NULL ||
1100             recvd_frame == NULL ||
1101             recvd_frame->bufs[0] == NULL ||
1102             !validate_handle(stream->getMyHandle(),
1103             recvd_frame->bufs[0]->stream_id)) {
1104         LOGE("Not a valid stream to handle buf");
1105         return;
1106     }
1107     if ((stream->mSyncCBEnabled) && (stream->mSYNCDataCB != NULL))
1108         stream->mSYNCDataCB(recvd_frame, stream, stream->mUserData);
1109     return;
1110 }
1111 
1112 /*===========================================================================
1113  * FUNCTION   : dataNotifyCB
1114  *
1115  * DESCRIPTION: callback for data notify. This function is registered with
1116  *              mm-camera-interface to handle data notify
1117  *
1118  * PARAMETERS :
1119  *   @recvd_frame   : stream frame received
1120  *   userdata       : user data ptr
1121  *
1122  * RETURN     : none
1123  *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)1124 void QCameraStream::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
1125                                  void *userdata)
1126 {
1127     LOGD("\n");
1128     QCameraStream* stream = (QCameraStream *)userdata;
1129     if (stream == NULL ||
1130             recvd_frame == NULL ||
1131             recvd_frame->bufs[0] == NULL  ||
1132             !(validate_handle(stream->getMyHandle(),
1133             recvd_frame->bufs[0]->stream_id))) {
1134         LOGE("Not a valid stream to handle buf");
1135         return;
1136     }
1137 
1138     mm_camera_super_buf_t *frame =
1139         (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
1140     if (frame == NULL) {
1141         LOGE("No mem for mm_camera_buf_def_t");
1142         stream->bufDone(recvd_frame);
1143         return;
1144     }
1145     *frame = *recvd_frame;
1146     stream->processDataNotify(frame);
1147     return;
1148 }
1149 
1150 /*===========================================================================
1151  * FUNCTION   : dataProcRoutine
1152  *
1153  * DESCRIPTION: function to process data in the main stream thread
1154  *
1155  * PARAMETERS :
1156  *   @data    : user data ptr
1157  *
1158  * RETURN     : none
1159  *==========================================================================*/
dataProcRoutine(void * data)1160 void *QCameraStream::dataProcRoutine(void *data)
1161 {
1162     int running = 1;
1163     int ret;
1164     QCameraStream *pme = (QCameraStream *)data;
1165     QCameraCmdThread *cmdThread = &pme->mProcTh;
1166     cmdThread->setName("CAM_strmDatProc");
1167 
1168     LOGD("E");
1169     do {
1170         do {
1171             ret = cam_sem_wait(&cmdThread->cmd_sem);
1172             if (ret != 0 && errno != EINVAL) {
1173                 LOGE("cam_sem_wait error (%s)",
1174                        strerror(errno));
1175                 return NULL;
1176             }
1177         } while (ret != 0);
1178 
1179         // we got notified about new cmd avail in cmd queue
1180         camera_cmd_type_t cmd = cmdThread->getCmd();
1181         switch (cmd) {
1182         case CAMERA_CMD_TYPE_DO_NEXT_JOB:
1183             {
1184                 LOGH("Do next job");
1185                 mm_camera_super_buf_t *frame =
1186                     (mm_camera_super_buf_t *)pme->mDataQ.dequeue();
1187                 if (NULL != frame) {
1188                     if (pme->mDataCB != NULL) {
1189                         pme->mDataCB(frame, pme, pme->mUserData);
1190                     } else {
1191                         // no data cb routine, return buf here
1192                         pme->bufDone(frame);
1193                         free(frame);
1194                     }
1195                 }
1196             }
1197             break;
1198         case CAMERA_CMD_TYPE_EXIT:
1199             LOGH("Exit");
1200             /* flush data buf queue */
1201             pme->mDataQ.flush();
1202             running = 0;
1203             break;
1204         default:
1205             break;
1206         }
1207     } while (running);
1208     LOGH("X");
1209     return NULL;
1210 }
1211 
1212 /*===========================================================================
1213  * FUNCTION   : bufDone
1214  *
1215  * DESCRIPTION: return stream buffer to kernel
1216  *
1217  * PARAMETERS :
1218  *   @index   : index of buffer to be returned
1219  *
1220  * RETURN     : int32_t type of status
1221  *              NO_ERROR  -- success
1222  *              none-zero failure code
1223  *==========================================================================*/
bufDone(uint32_t index)1224 int32_t QCameraStream::bufDone(uint32_t index)
1225 {
1226     int32_t rc = NO_ERROR;
1227 
1228     if (index >= mNumBufs || mBufDefs == NULL)
1229         return BAD_INDEX;
1230 
1231     rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
1232 
1233     if (rc < 0)
1234         return rc;
1235 
1236     return rc;
1237 }
1238 
1239 /*===========================================================================
1240  * FUNCTION   : bufDone
1241  *
1242  * DESCRIPTION: return a stream buf back to kernel
1243  *
1244  * PARAMETERS :
1245  *   @super_buf : stream buf frame to be returned
1246  *
1247  * RETURN     : int32_t type of status
1248  *              NO_ERROR  -- success
1249  *              none-zero failure code
1250  *==========================================================================*/
bufDone(mm_camera_super_buf_t * super_buf)1251 int32_t QCameraStream::bufDone (mm_camera_super_buf_t *super_buf)
1252 {
1253     int32_t rc = NO_ERROR;
1254     for (uint32_t i = 0; i < super_buf->num_bufs; i++) {
1255         if (super_buf->bufs[i] != NULL) {
1256             rc |= bufDone(super_buf->bufs[i]->buf_idx);
1257         }
1258     }
1259     return rc;
1260 }
1261 
1262 /*===========================================================================
1263  * FUNCTION   : bufDone
1264  *
1265  * DESCRIPTION: return stream buffer to kernel
1266  *
1267  * PARAMETERS :
1268  *   @opaque    : stream frame/metadata buf to be returned
1269  *   @isMetaData: flag if returned opaque is a metadatabuf or the real frame ptr
1270  *
1271  * RETURN     : int32_t type of status
1272  *              NO_ERROR  -- success
1273  *              none-zero failure code
1274  *==========================================================================*/
bufDone(const void * opaque,bool isMetaData)1275 int32_t QCameraStream::bufDone(const void *opaque, bool isMetaData)
1276 {
1277     int32_t rc = NO_ERROR;
1278     int index = -1;
1279     QCameraVideoMemory *mVideoMem = NULL;
1280     bool needPerfEvet = FALSE;
1281 
1282     if ((mStreamInfo != NULL)
1283             && (mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH)
1284             && (mStreamBatchBufs != NULL)) {
1285         mVideoMem = (QCameraVideoMemory *)mStreamBatchBufs;
1286     } else if (mStreamBufs != NULL){
1287         mVideoMem = (QCameraVideoMemory *)mStreamBufs;
1288     }
1289 
1290     //Close and delete duplicated native handle and FD's.
1291     if (mVideoMem != NULL) {
1292         index = mVideoMem->getMatchBufIndex(opaque, isMetaData);
1293         needPerfEvet = mVideoMem->needPerfEvent(opaque, isMetaData);
1294         rc = mVideoMem->closeNativeHandle(opaque, isMetaData);
1295         if (rc != NO_ERROR) {
1296             LOGE("Invalid video metadata");
1297             return rc;
1298         }
1299     } else {
1300         LOGE("Possible FD leak. Release recording called after stop");
1301     }
1302 
1303     if (index == -1 || index >= mNumBufs || mBufDefs == NULL) {
1304         LOGE("Cannot find buf for opaque data = %p", opaque);
1305         return BAD_INDEX;
1306     }
1307 
1308     if (needPerfEvet == TRUE) {
1309         //Trigger Perf Flush event to back-end
1310         cam_stream_parm_buffer_t param;
1311         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
1312         param.type = CAM_STREAM_PARAM_TYPE_FLUSH_FRAME;
1313         rc = setParameter(param);
1314     }
1315 
1316     if ((CAMERA_MIN_VIDEO_BATCH_BUFFERS > index)
1317             && mStreamMetaMemory[index].numBuffers > 0) {
1318         for (int i= 0; i < mStreamMetaMemory[index].numBuffers; i++) {
1319             uint8_t buf_idx = mStreamMetaMemory[index].buf_index[i];
1320             bufDone((uint32_t)buf_idx);
1321         }
1322         mStreamMetaMemory[index].consumerOwned = FALSE;
1323         mStreamMetaMemory[index].numBuffers = 0;
1324     } else {
1325         LOGH("Buffer Index = %d, Frame Idx = %d", index,
1326                 mBufDefs[index].frame_idx);
1327         rc = bufDone((uint32_t)index);
1328     }
1329 
1330     return rc;
1331 }
1332 
1333 /*===========================================================================
1334  * FUNCTION   : getNumQueuedBuf
1335  *
1336  * DESCRIPTION: return queued buffer count
1337  *
1338  * PARAMETERS : None
1339  *
1340  * RETURN     : queued buffer count
1341  *==========================================================================*/
getNumQueuedBuf()1342 int32_t QCameraStream::getNumQueuedBuf()
1343 {
1344     int32_t rc = -1;
1345     if (mHandle > 0) {
1346         rc = mCamOps->get_queued_buf_count(mCamHandle, mChannelHandle, mHandle);
1347     }
1348     if (rc == -1) {
1349         LOGE("stream is not in active state. Invalid operation");
1350     }
1351     return rc;
1352 }
1353 
1354 /*===========================================================================
1355  * FUNCTION   : getBufs
1356  *
1357  * DESCRIPTION: allocate stream buffers
1358  *
1359  * PARAMETERS :
1360  *   @offset     : offset info of stream buffers
1361  *   @num_bufs   : number of buffers allocated
1362  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
1363  *                      at kernel initially
1364  *   @bufs       : output of allocated buffers
1365  *   @ops_tbl    : ptr to buf mapping/unmapping ops
1366  *
1367  * RETURN     : int32_t type of status
1368  *              NO_ERROR  -- success
1369  *              none-zero failure code
1370  *==========================================================================*/
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)1371 int32_t QCameraStream::getBufs(cam_frame_len_offset_t *offset,
1372         uint8_t *num_bufs,
1373         uint8_t **initial_reg_flag,
1374         mm_camera_buf_def_t **bufs,
1375         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1376 {
1377     int rc = NO_ERROR;
1378     uint8_t *regFlags;
1379 
1380     if (!ops_tbl) {
1381         LOGE("ops_tbl is NULL");
1382         return INVALID_OPERATION;
1383     }
1384 
1385     mFrameLenOffset = *offset;
1386 
1387     uint8_t numBufAlloc = mNumBufs;
1388     mNumBufsNeedAlloc = 0;
1389     if (mDynBufAlloc) {
1390         numBufAlloc = CAMERA_MIN_ALLOCATED_BUFFERS;
1391         if (numBufAlloc > mNumBufs) {
1392             mDynBufAlloc = false;
1393             numBufAlloc = mNumBufs;
1394         } else {
1395             mNumBufsNeedAlloc = (uint8_t)(mNumBufs - numBufAlloc);
1396         }
1397     }
1398 
1399     /* For some stream types, buffer allocation may have already begun
1400      * preemptively. If this is the case, we need to wait for the
1401      * preemptive allocation to complete before proceeding. */
1402     mAllocator.waitForDeferredAlloc(mStreamInfo->stream_type);
1403 
1404     //Allocate stream buffer
1405     mStreamBufs = mAllocator.allocateStreamBuf(mStreamInfo->stream_type,
1406             mFrameLenOffset.frame_len, mFrameLenOffset.mp[0].stride,
1407             mFrameLenOffset.mp[0].scanline, numBufAlloc);
1408     if (!mStreamBufs) {
1409         LOGE("Failed to allocate stream buffers");
1410         return NO_MEMORY;
1411     }
1412 
1413     mNumBufs = (uint8_t)(numBufAlloc + mNumBufsNeedAlloc);
1414     uint8_t numBufsToMap = mStreamBufs->getMappable();
1415 
1416     QCameraBufferMaps bufferMaps;
1417     for (uint32_t i = 0; i < numBufsToMap; i++) {
1418         ssize_t bufSize = mStreamBufs->getSize(i);
1419         if (BAD_INDEX == bufSize) {
1420             LOGE("Failed to retrieve buffer size (bad index)");
1421             return INVALID_OPERATION;
1422         }
1423 
1424         rc = bufferMaps.enqueue(CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1425                 0 /*stream id*/, i /*buf index*/, -1 /*plane index*/,
1426                 0 /*cookie*/, mStreamBufs->getFd(i), bufSize,
1427                 mStreamBufs->getPtr(i));
1428 
1429         if (rc < 0) {
1430             LOGE("Failed to map buffers");
1431             return BAD_INDEX;
1432         }
1433     }
1434 
1435     cam_buf_map_type_list bufMapList;
1436     rc = bufferMaps.getCamBufMapList(bufMapList);
1437     if (rc == NO_ERROR) {
1438         rc = ops_tbl->bundled_map_ops(&bufMapList, ops_tbl->userdata);
1439     }
1440     if (rc < 0) {
1441         LOGE("map_stream_buf failed: %d", rc);
1442         mStreamBufs->deallocate();
1443         delete mStreamBufs;
1444         mStreamBufs = NULL;
1445         return INVALID_OPERATION;
1446     }
1447 
1448     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
1449     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
1450     if (!regFlags) {
1451         LOGE("Out of memory");
1452         for (uint32_t i = 0; i < numBufsToMap; i++) {
1453             ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
1454         }
1455         mStreamBufs->deallocate();
1456         delete mStreamBufs;
1457         mStreamBufs = NULL;
1458         return NO_MEMORY;
1459     }
1460     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
1461 
1462     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
1463     if (mBufDefs == NULL) {
1464         LOGE("getRegFlags failed %d", rc);
1465         for (uint32_t i = 0; i < numBufsToMap; i++) {
1466             ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
1467         }
1468         mStreamBufs->deallocate();
1469         delete mStreamBufs;
1470         mStreamBufs = NULL;
1471         free(regFlags);
1472         regFlags = NULL;
1473         return INVALID_OPERATION;
1474     }
1475     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
1476     for (uint32_t i = 0; i < numBufsToMap; i++) {
1477         mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
1478     }
1479 
1480     rc = mStreamBufs->getRegFlags(regFlags);
1481     if (rc < 0) {
1482         LOGE("getRegFlags failed %d", rc);
1483         for (uint32_t i = 0; i < numBufsToMap; i++) {
1484             ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
1485         }
1486         mStreamBufs->deallocate();
1487         delete mStreamBufs;
1488         mStreamBufs = NULL;
1489         free(mBufDefs);
1490         mBufDefs = NULL;
1491         free(regFlags);
1492         regFlags = NULL;
1493         return INVALID_OPERATION;
1494     }
1495 
1496     *num_bufs = mNumBufs;
1497     *initial_reg_flag = regFlags;
1498     *bufs = mBufDefs;
1499     LOGH("stream type: %d, mRegFlags: 0x%x, numBufs: %d",
1500              mStreamInfo->stream_type, regFlags, mNumBufs);
1501 
1502     if (mNumBufsNeedAlloc > 0) {
1503         pthread_mutex_lock(&m_lock);
1504         wait_for_cond = TRUE;
1505         pthread_mutex_unlock(&m_lock);
1506         LOGH("Still need to allocate %d buffers",
1507                mNumBufsNeedAlloc);
1508         // start another thread to allocate the rest of buffers
1509         pthread_create(&mBufAllocPid,
1510                        NULL,
1511                        BufAllocRoutine,
1512                        this);
1513         pthread_setname_np(mBufAllocPid, "CAM_strmBuf");
1514     }
1515     return NO_ERROR;
1516 }
1517 
1518 /*===========================================================================
1519  * FUNCTION   : getBufsDeferred
1520  *
1521  * DESCRIPTION: allocate deferred stream buffers
1522  *
1523  * PARAMETERS :
1524  *   @offset     : offset info of stream buffers
1525  *   @num_bufs   : number of buffers allocated
1526  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
1527  *                      at kernel initially
1528  *   @bufs       : output of allocated buffers
1529  *   @ops_tbl    : ptr to buf mapping/unmapping ops
1530  *
1531  * RETURN     : int32_t type of status
1532  *              NO_ERROR  -- success
1533  *              none-zero failure code
1534  *==========================================================================*/
getBufsDeferred(__unused cam_frame_len_offset_t * offset,uint8_t * num_bufs,uint8_t ** initial_reg_flag,mm_camera_buf_def_t ** bufs,__unused mm_camera_map_unmap_ops_tbl_t * ops_tbl)1535 int32_t QCameraStream::getBufsDeferred(__unused cam_frame_len_offset_t *offset,
1536         uint8_t *num_bufs,
1537         uint8_t **initial_reg_flag,
1538         mm_camera_buf_def_t **bufs,
1539         __unused mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1540 {
1541     int32_t rc = NO_ERROR;
1542     // wait for allocation
1543     rc = mAllocator.waitForBackgroundTask(mAllocTaskId);
1544     if (rc != NO_ERROR) {
1545         LOGE("Allocation Failed");
1546         return NO_MEMORY;
1547     }
1548 
1549     if (!mRegFlags || !mBufDefs) {
1550         LOGE("reg flags or buf defs uninitialized");
1551         return NO_MEMORY;
1552     }
1553 
1554     *initial_reg_flag   = mRegFlags;
1555     *num_bufs           = mNumBufs;
1556     *bufs               = mBufDefs;
1557 
1558     LOGH("stream type: %d, mRegFlags: 0x%x, numBufs: %d",
1559              getMyType(), mRegFlags, mNumBufs);
1560 
1561     return NO_ERROR;
1562 }
1563 /*===========================================================================
1564  * FUNCTION   : mapNewBuffer
1565  *
1566  * DESCRIPTION: map a new stream buffer
1567  *
1568  * PARAMETERS :
1569  *
1570  * RETURN     : int32_t type of status
1571  *              NO_ERROR  -- success
1572  *              none-zero failure code
1573  *==========================================================================*/
mapNewBuffer(uint32_t index)1574 int32_t QCameraStream::mapNewBuffer(uint32_t index)
1575 {
1576     LOGH("E - index = %d", index);
1577 
1578     int rc = NO_ERROR;
1579 
1580     if (mStreamBufs == NULL) {
1581         LOGE("Invalid Operation");
1582         return INVALID_OPERATION;
1583     }
1584 
1585     ssize_t bufSize = mStreamBufs->getSize(index);
1586     if (BAD_INDEX == bufSize) {
1587         LOGE("Failed to retrieve buffer size (bad index)");
1588         return INVALID_OPERATION;
1589     }
1590 
1591     cam_buf_map_type_list bufMapList;
1592     rc = QCameraBufferMaps::makeSingletonBufMapList(
1593             CAM_MAPPING_BUF_TYPE_STREAM_BUF, 0 /*stream id*/, index,
1594             -1 /*plane index*/, 0 /*cookie*/, mStreamBufs->getFd(index),
1595             bufSize, bufMapList, mStreamBufs->getPtr(index));
1596 
1597     if (rc == NO_ERROR) {
1598         rc = m_MemOpsTbl.bundled_map_ops(&bufMapList, m_MemOpsTbl.userdata);
1599     }
1600     if (rc < 0) {
1601         LOGE("map_stream_buf failed: %d", rc);
1602         rc = INVALID_OPERATION;
1603     } else {
1604         mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[index], index);
1605     }
1606 
1607     LOGH("X - rc = %d", rc);
1608     return rc;
1609 }
1610 
1611 /*===========================================================================
1612  * FUNCTION   : allocateBuffers
1613  *
1614  * DESCRIPTION: allocate stream buffers
1615  *
1616  * PARAMETERS :
1617  *
1618  * RETURN     : int32_t type of status
1619  *              NO_ERROR  -- success
1620  *              none-zero failure code
1621  *==========================================================================*/
allocateBuffers()1622 int32_t QCameraStream::allocateBuffers()
1623 {
1624     int32_t rc = NO_ERROR;
1625 
1626     mFrameLenOffset = mStreamInfo->buf_planes.plane_info;
1627 
1628     if (mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
1629         return allocateBatchBufs(&mFrameLenOffset,
1630                 &mNumBufs, &mRegFlags,
1631                 &mBufDefs, NULL);
1632     }
1633 
1634     /* This allocation is running in the deferred context, so it
1635      * is safe (and necessary) to assume any preemptive allocation
1636      * is already complete. Therefore, no need to wait here. */
1637 
1638     uint8_t numBufAlloc = mNumBufs;
1639     mNumBufsNeedAlloc = 0;
1640     if (mDynBufAlloc) {
1641         numBufAlloc = CAMERA_MIN_ALLOCATED_BUFFERS;
1642         if (numBufAlloc > mNumBufs) {
1643             mDynBufAlloc = false;
1644             numBufAlloc = mNumBufs;
1645         } else {
1646             mNumBufsNeedAlloc = (uint8_t)(mNumBufs - numBufAlloc);
1647         }
1648     }
1649 
1650     //Allocate and map stream info buffer
1651     mStreamBufs = mAllocator.allocateStreamBuf(mStreamInfo->stream_type,
1652             mFrameLenOffset.frame_len,
1653             mFrameLenOffset.mp[0].stride,
1654             mFrameLenOffset.mp[0].scanline,
1655             numBufAlloc);
1656 
1657     if (!mStreamBufs) {
1658         LOGE("Failed to allocate stream buffers");
1659         return NO_MEMORY;
1660     }
1661 
1662     mNumBufs = (uint8_t)(numBufAlloc + mNumBufsNeedAlloc);
1663     uint8_t numBufsToMap = mStreamBufs->getMappable();
1664 
1665     //regFlags array is allocated by us,
1666     // but consumed and freed by mm-camera-interface
1667     mRegFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
1668     if (!mRegFlags) {
1669         LOGE("Out of memory");
1670         for (uint32_t i = 0; i < numBufsToMap; i++) {
1671             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, NULL);
1672         }
1673         mStreamBufs->deallocate();
1674         delete mStreamBufs;
1675         mStreamBufs = NULL;
1676         return NO_MEMORY;
1677     }
1678     memset(mRegFlags, 0, sizeof(uint8_t) * mNumBufs);
1679 
1680     size_t bufDefsSize = mNumBufs * sizeof(mm_camera_buf_def_t);
1681     mBufDefs = (mm_camera_buf_def_t *)malloc(bufDefsSize);
1682     if (mBufDefs == NULL) {
1683         LOGE("getRegFlags failed %d", rc);
1684         for (uint32_t i = 0; i < numBufsToMap; i++) {
1685             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, NULL);
1686         }
1687         mStreamBufs->deallocate();
1688         delete mStreamBufs;
1689         mStreamBufs = NULL;
1690         free(mRegFlags);
1691         mRegFlags = NULL;
1692         return INVALID_OPERATION;
1693     }
1694     memset(mBufDefs, 0, bufDefsSize);
1695     for (uint32_t i = 0; i < numBufsToMap; i++) {
1696         mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
1697     }
1698 
1699     rc = mStreamBufs->getRegFlags(mRegFlags);
1700     if (rc < 0) {
1701         LOGE("getRegFlags failed %d", rc);
1702         for (uint32_t i = 0; i < numBufsToMap; i++) {
1703             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, NULL);
1704         }
1705         mStreamBufs->deallocate();
1706         delete mStreamBufs;
1707         mStreamBufs = NULL;
1708         free(mBufDefs);
1709         mBufDefs = NULL;
1710         free(mRegFlags);
1711         mRegFlags = NULL;
1712         return INVALID_OPERATION;
1713     }
1714 
1715     if (mNumBufsNeedAlloc > 0) {
1716         pthread_mutex_lock(&m_lock);
1717         wait_for_cond = TRUE;
1718         pthread_mutex_unlock(&m_lock);
1719         LOGH("Still need to allocate %d buffers",
1720                mNumBufsNeedAlloc);
1721         // start another thread to allocate the rest of buffers
1722         pthread_create(&mBufAllocPid,
1723                        NULL,
1724                        BufAllocRoutine,
1725                        this);
1726         pthread_setname_np(mBufAllocPid, "CAM_strmBufAlloc");
1727     }
1728     return rc;
1729 }
1730 
1731 /*===========================================================================
1732  * FUNCTION   : mapBuffers
1733  *
1734  * DESCRIPTION: map stream buffers
1735  *
1736  * PARAMETERS :
1737  *
1738  * RETURN     : int32_t type of status
1739  *              NO_ERROR  -- success
1740  *              none-zero failure code
1741  *==========================================================================*/
mapBuffers()1742 int32_t QCameraStream::mapBuffers()
1743 {
1744     int32_t rc = NO_ERROR;
1745     QCameraBufferMaps bufferMaps;
1746 
1747     rc = mAllocator.waitForBackgroundTask(mAllocTaskId);
1748     if (rc != NO_ERROR) {
1749         LOGE("Allocation Failed");
1750         return NO_MEMORY;
1751     }
1752 
1753     if (mStreamBufs == NULL) {
1754         LOGE("Stream buffers not allocated");
1755         return UNKNOWN_ERROR;
1756     }
1757 
1758     uint8_t numBufsToMap = mStreamBufs->getMappable();
1759     for (uint32_t i = 0; i < numBufsToMap; i++) {
1760         ssize_t bufSize = mStreamBufs->getSize(i);
1761         if (BAD_INDEX != bufSize) {
1762             rc = bufferMaps.enqueue(CAM_MAPPING_BUF_TYPE_STREAM_BUF, mHandle,
1763                     i /*buf index*/, -1 /*plane index*/, 0 /*cookie*/,
1764                     mStreamBufs->getFd(i), bufSize,
1765                     mStreamBufs->getPtr(i));
1766 
1767             if (rc < 0) {
1768                 LOGE("Failed to map buffers");
1769                 rc = BAD_INDEX;
1770                 break;
1771             }
1772         } else {
1773             LOGE("Bad index %u", i);
1774             rc = BAD_INDEX;
1775             break;
1776         }
1777     }
1778 
1779     cam_buf_map_type_list bufMapList;
1780     if (rc == NO_ERROR) {
1781         rc = bufferMaps.getCamBufMapList(bufMapList);
1782     }
1783     if (rc == NO_ERROR) {
1784         rc = mapBufs(bufMapList, NULL);
1785     }
1786     return rc;
1787 }
1788 
1789 /*===========================================================================
1790  * FUNCTION   : allocateBatchBufs
1791  *
1792  * DESCRIPTION: allocate stream batch buffers and stream buffers
1793  *
1794  * PARAMETERS :
1795  *   @offset     : offset info of stream buffers
1796  *   @num_bufs   : number of buffers allocated
1797  *   @initial_reg_flag: flag to indicate if buffer needs to be registered
1798  *                      at kernel initially
1799  *   @bufs       : output of allocated buffers
1800  *   @plane_bufs    : output of allocated plane buffers
1801   *   @ops_tbl    : ptr to buf mapping/unmapping ops
1802  *
1803  * RETURN     : int32_t type of status
1804  *              NO_ERROR  -- success
1805  *              none-zero failure code
1806  *==========================================================================*/
allocateBatchBufs(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)1807 int32_t QCameraStream::allocateBatchBufs(cam_frame_len_offset_t *offset,
1808         uint8_t *num_bufs, uint8_t **initial_reg_flag,
1809         mm_camera_buf_def_t **bufs, mm_camera_map_unmap_ops_tbl_t *ops_tbl)
1810 {
1811     int rc = NO_ERROR;
1812     uint8_t *regFlags;
1813     QCameraBufferMaps bufferMaps;
1814     QCameraBufferMaps planeBufferMaps;
1815 
1816     mFrameLenOffset = *offset;
1817 
1818     LOGH("Batch Buffer allocation stream type = %d", getMyType());
1819 
1820     //Allocate stream batch buffer
1821     mStreamBatchBufs = mAllocator.allocateStreamUserBuf (mStreamInfo);
1822     if (!mStreamBatchBufs) {
1823         LOGE("Failed to allocate stream batch buffers");
1824         return NO_MEMORY;
1825     }
1826 
1827     uint8_t numBufsToMap = mStreamBatchBufs->getMappable();
1828 
1829     //map batch buffers
1830     for (uint32_t i = 0; i < numBufsToMap; i++) {
1831         rc = bufferMaps.enqueue(CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF,
1832                 0 /*stream id*/, i /*buf index*/, -1 /*plane index*/,
1833                 0 /*cookie*/, mStreamBatchBufs->getFd(i),
1834                 mNumBufs, mStreamBatchBufs->getPtr(i));
1835 
1836         if (rc < 0) {
1837             LOGE("Failed to map buffers");
1838             rc = BAD_INDEX;
1839             break;
1840         }
1841     }
1842 
1843     cam_buf_map_type_list bufMapList;
1844     if (rc == NO_ERROR) {
1845         rc = bufferMaps.getCamBufMapList(bufMapList);
1846     }
1847     if (rc == NO_ERROR) {
1848         rc = mapBufs(bufMapList, ops_tbl);
1849     }
1850     if (rc < 0) {
1851         LOGE("Failed to map stream batch buffers");
1852         mStreamBatchBufs->deallocate();
1853         delete mStreamBatchBufs;
1854         mStreamBatchBufs = NULL;
1855         return NO_MEMORY;
1856     }
1857 
1858     /*calculate stream Buffer count*/
1859     mNumPlaneBufs =
1860             (mNumBufs * mStreamInfo->user_buf_info.frame_buf_cnt);
1861 
1862     /* For some stream types, buffer allocation may have already begun
1863      * preemptively. If this is the case, we need to wait for the
1864      * preemptive allocation to complete before proceeding. */
1865     mAllocator.waitForDeferredAlloc(mStreamInfo->stream_type);
1866 
1867     //Allocate stream buffer
1868     mStreamBufs = mAllocator.allocateStreamBuf(mStreamInfo->stream_type,
1869             mFrameLenOffset.frame_len,mFrameLenOffset.mp[0].stride,
1870             mFrameLenOffset.mp[0].scanline,mNumPlaneBufs);
1871     if (!mStreamBufs) {
1872         LOGE("Failed to allocate stream buffers");
1873         rc = NO_MEMORY;
1874         goto err1;
1875     }
1876 
1877     //Map plane stream buffers
1878     for (uint32_t i = 0; i < mNumPlaneBufs; i++) {
1879         ssize_t bufSize = mStreamBufs->getSize(i);
1880         if (BAD_INDEX != bufSize) {
1881             rc = planeBufferMaps.enqueue(CAM_MAPPING_BUF_TYPE_STREAM_BUF,
1882                     0 /*stream id*/, i /*buf index*/, -1 /*plane index*/,
1883                     0 /*cookie*/, mStreamBufs->getFd(i), bufSize,
1884                     mStreamBufs->getPtr(i));
1885 
1886             if (rc < 0) {
1887                 LOGE("Failed to map buffers");
1888                 mStreamBufs->deallocate();
1889                 delete mStreamBufs;
1890                 mStreamBufs = NULL;
1891                 rc = INVALID_OPERATION;
1892                 goto err1;
1893             }
1894         } else {
1895             LOGE("Failed to retrieve buffer size (bad index)");
1896             mStreamBufs->deallocate();
1897             delete mStreamBufs;
1898             mStreamBufs = NULL;
1899             rc = INVALID_OPERATION;
1900             goto err1;
1901         }
1902     }
1903 
1904     cam_buf_map_type_list planeBufMapList;
1905     rc = planeBufferMaps.getCamBufMapList(planeBufMapList);
1906     if (rc == NO_ERROR) {
1907         rc = mapBufs(planeBufMapList, ops_tbl);
1908     }
1909 
1910     if (rc < 0) {
1911         LOGE("map_stream_buf failed: %d", rc);
1912         mStreamBufs->deallocate();
1913         delete mStreamBufs;
1914         mStreamBufs = NULL;
1915         rc = INVALID_OPERATION;
1916         goto err1;
1917     }
1918 
1919     LOGD("BATCH Buf Count = %d, Plane Buf Cnt = %d",
1920             mNumBufs, mNumPlaneBufs);
1921 
1922     //regFlags array is allocated by us, but consumed and freed by mm-camera-interface
1923     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
1924     if (!regFlags) {
1925         LOGE("Out of memory");
1926         for (uint32_t i = 0; i < mNumPlaneBufs; i++) {
1927             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, ops_tbl);
1928         }
1929         mStreamBufs->deallocate();
1930         delete mStreamBufs;
1931         mStreamBufs = NULL;
1932         rc = NO_MEMORY;
1933         goto err1;
1934     }
1935     memset(regFlags, 0, sizeof(uint8_t) * mNumBufs);
1936     for (uint32_t i = 0; i < mNumBufs; i++) {
1937         regFlags[i] = 1;
1938     }
1939 
1940     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
1941     if (mBufDefs == NULL) {
1942         LOGE("getRegFlags failed %d", rc);
1943         for (uint32_t i = 0; i < mNumPlaneBufs; i++) {
1944             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, ops_tbl);
1945         }
1946         mStreamBufs->deallocate();
1947         delete mStreamBufs;
1948         mStreamBufs = NULL;
1949         free(regFlags);
1950         regFlags = NULL;
1951         rc = INVALID_OPERATION;
1952         goto err1;
1953     }
1954     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
1955 
1956     mPlaneBufDefs = (mm_camera_buf_def_t *)
1957             malloc(mNumPlaneBufs * (sizeof(mm_camera_buf_def_t)));
1958     if (mPlaneBufDefs == NULL) {
1959         LOGE("No Memory");
1960         free(regFlags);
1961         regFlags = NULL;
1962         free(mBufDefs);
1963         mBufDefs = NULL;
1964         for (uint32_t i = 0; i < mNumPlaneBufs; i++) {
1965             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, ops_tbl);
1966         }
1967         mStreamBufs->deallocate();
1968         delete mStreamBufs;
1969         mStreamBufs = NULL;
1970         free(regFlags);
1971         regFlags = NULL;
1972         rc = INVALID_OPERATION;
1973         goto err1;
1974     }
1975     memset(mPlaneBufDefs, 0,
1976              mNumPlaneBufs * (sizeof(mm_camera_buf_def_t)));
1977 
1978     for (uint32_t i = 0; i < mStreamInfo->num_bufs; i++) {
1979         mStreamBatchBufs->getUserBufDef(mStreamInfo->user_buf_info,
1980                 mBufDefs[i], i, mFrameLenOffset, mPlaneBufDefs,
1981                 mStreamBufs);
1982     }
1983 
1984     *num_bufs = mNumBufs;
1985     *initial_reg_flag = regFlags;
1986     *bufs = mBufDefs;
1987     LOGH("stream type: %d, numBufs: %d mNumPlaneBufs: %d",
1988              mStreamInfo->stream_type, mNumBufs, mNumPlaneBufs);
1989 
1990     return NO_ERROR;
1991 
1992 err1:
1993     mStreamBatchBufs->deallocate();
1994     delete mStreamBatchBufs;
1995     mStreamBatchBufs = NULL;
1996     return rc;
1997 }
1998 
1999 
2000 /*===========================================================================
2001  * FUNCTION   : releaseBuffs
2002  *
2003  * DESCRIPTION: method to deallocate stream buffers
2004  *
2005  * PARAMETERS :
2006  *
2007  * RETURN     : int32_t type of status
2008  *              NO_ERROR  -- success
2009  *              none-zero failure code
2010  *==========================================================================*/
releaseBuffs()2011 int32_t QCameraStream::releaseBuffs()
2012 {
2013     int rc = NO_ERROR;
2014 
2015     if (mBufAllocPid != 0) {
2016         cond_signal(true);
2017         LOGD("wait for buf allocation thread dead");
2018         pthread_join(mBufAllocPid, NULL);
2019         mBufAllocPid = 0;
2020         LOGD("return from buf allocation thread");
2021     }
2022 
2023     if (mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
2024         return releaseBatchBufs(NULL);
2025     }
2026 
2027     if ((NULL != mBufDefs) && (mStreamBufs != NULL)) {
2028         uint8_t numBufsToUnmap = mStreamBufs->getMappable();
2029         for (uint32_t i = 0; i < numBufsToUnmap; i++) {
2030             rc = unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, NULL);
2031             if (rc < 0) {
2032                 LOGE("map_stream_buf failed: %d", rc);
2033             }
2034         }
2035 
2036         // mBufDefs just keep a ptr to the buffer
2037         // mm-camera-interface own the buffer, so no need to free
2038         mBufDefs = NULL;
2039         memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
2040     }
2041     if (!mStreamBufsAcquired && (mStreamBufs != NULL)) {
2042         mStreamBufs->deallocate();
2043         delete mStreamBufs;
2044         mStreamBufs = NULL;
2045     }
2046     return rc;
2047 }
2048 
2049 /*===========================================================================
2050  * FUNCTION   : releaseBatchBufs
2051  *
2052  * DESCRIPTION: method to deallocate stream buffers and batch buffers
2053  *
2054  * PARAMETERS :
2055  *   @ops_tbl    : ptr to buf mapping/unmapping ops
2056  *
2057  * RETURN     : int32_t type of status
2058  *              NO_ERROR  -- success
2059  *              none-zero failure code
2060 
2061  *==========================================================================*/
releaseBatchBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)2062 int32_t QCameraStream::releaseBatchBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
2063 {
2064     int rc = NO_ERROR;
2065 
2066     if (NULL != mPlaneBufDefs) {
2067         for (uint32_t i = 0; i < mNumPlaneBufs; i++) {
2068             rc = unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_BUF, i, -1, ops_tbl);
2069             if (rc < 0) {
2070                 LOGE("map_stream_buf failed: %d", rc);
2071             }
2072         }
2073 
2074         // mBufDefs just keep a ptr to the buffer
2075         // mm-camera-interface own the buffer, so no need to free
2076         mPlaneBufDefs = NULL;
2077         memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
2078         mNumPlaneBufs = 0;
2079     }
2080 
2081     if (mStreamBufs != NULL) {
2082         mStreamBufs->deallocate();
2083         delete mStreamBufs;
2084     }
2085 
2086     mBufDefs = NULL;
2087 
2088     if (mStreamBatchBufs != NULL) {
2089         for (uint8_t i = 0; i < mStreamBatchBufs->getCnt(); i++) {
2090             unmapBuf(CAM_MAPPING_BUF_TYPE_STREAM_USER_BUF, i, -1, ops_tbl);
2091         }
2092         mStreamBatchBufs->deallocate();
2093         delete mStreamBatchBufs;
2094         mStreamBatchBufs = NULL;
2095     }
2096     return rc;
2097 
2098 }
2099 
2100 /*===========================================================================
2101  * FUNCTION   : BufAllocRoutine
2102  *
2103  * DESCRIPTION: function to allocate additional stream buffers
2104  *
2105  * PARAMETERS :
2106  *   @data    : user data ptr
2107  *
2108  * RETURN     : none
2109  *==========================================================================*/
BufAllocRoutine(void * data)2110 void *QCameraStream::BufAllocRoutine(void *data)
2111 {
2112     QCameraStream *pme = (QCameraStream *)data;
2113     int32_t rc = NO_ERROR;
2114 
2115     LOGH("E");
2116     pme->cond_wait();
2117     if (pme->mNumBufsNeedAlloc > 0) {
2118         uint8_t numBufAlloc = (uint8_t)(pme->mNumBufs - pme->mNumBufsNeedAlloc);
2119         rc = pme->mAllocator.allocateMoreStreamBuf(pme->mStreamBufs,
2120                                                    pme->mFrameLenOffset.frame_len,
2121                                                    pme->mNumBufsNeedAlloc);
2122         if (rc != NO_ERROR) {
2123             LOGE("Failed to allocate buffers");
2124             pme->mNumBufsNeedAlloc = 0;
2125             return NULL;
2126         }
2127 
2128         pme->mNumBufsNeedAlloc = 0;
2129         QCameraBufferMaps bufferMaps;
2130         for (uint32_t i = numBufAlloc; i < pme->mNumBufs; i++) {
2131             ssize_t bufSize = pme->mStreamBufs->getSize(i);
2132             if (BAD_INDEX == bufSize) {
2133                 LOGE("Failed to retrieve buffer size (bad index)");
2134                 return NULL;
2135             }
2136 
2137             rc = bufferMaps.enqueue(CAM_MAPPING_BUF_TYPE_STREAM_BUF,
2138                     pme->mHandle, i /*buf index*/, -1 /*plane index*/,
2139                     0 /*cookie*/, pme->mStreamBufs->getFd(i), bufSize,
2140                     pme->mStreamBufs->getPtr(i));
2141 
2142             if (rc < 0) {
2143                 LOGE("Failed to map buffers");
2144                 return NULL;
2145             }
2146         }
2147 
2148         cam_buf_map_type_list bufMapList;
2149         rc = bufferMaps.getCamBufMapList(bufMapList);
2150         if (rc == NO_ERROR) {
2151             rc = pme->m_MemOpsTbl.bundled_map_ops(&bufMapList, pme->m_MemOpsTbl.userdata);
2152         }
2153         if (rc != 0) {
2154             LOGE("Failed to map buffers with return code %d", rc);
2155             return NULL;
2156         }
2157 
2158         for (uint32_t i = numBufAlloc; i < pme->mNumBufs; i++) {
2159             pme->mStreamBufs->getBufDef(pme->mFrameLenOffset, pme->mBufDefs[i], i);
2160             pme->mCamOps->qbuf(pme->mCamHandle, pme->mChannelHandle,
2161                     &pme->mBufDefs[i]);
2162         }
2163     }
2164     LOGH("X");
2165     return NULL;
2166 }
2167 
2168 /*===========================================================================
2169  * FUNCTION   : cond_signal
2170  *
2171  * DESCRIPTION: signal if flag "wait_for_cond" is set
2172  *
2173  *==========================================================================*/
cond_signal(bool forceExit)2174 void QCameraStream::cond_signal(bool forceExit)
2175 {
2176     pthread_mutex_lock(&m_lock);
2177     if(wait_for_cond == TRUE){
2178         wait_for_cond = FALSE;
2179         if (forceExit) {
2180             mNumBufsNeedAlloc = 0;
2181         }
2182         pthread_cond_signal(&m_cond);
2183     }
2184     pthread_mutex_unlock(&m_lock);
2185 }
2186 
2187 
2188 /*===========================================================================
2189  * FUNCTION   : cond_wait
2190  *
2191  * DESCRIPTION: wait on if flag "wait_for_cond" is set
2192  *
2193  *==========================================================================*/
cond_wait()2194 void QCameraStream::cond_wait()
2195 {
2196     pthread_mutex_lock(&m_lock);
2197     while (wait_for_cond == TRUE) {
2198         pthread_cond_wait(&m_cond, &m_lock);
2199     }
2200     pthread_mutex_unlock(&m_lock);
2201 }
2202 
2203 /*===========================================================================
2204  * FUNCTION   : putBufs
2205  *
2206  * DESCRIPTION: deallocate stream buffers
2207  *
2208  * PARAMETERS :
2209  *   @ops_tbl    : ptr to buf mapping/unmapping ops
2210  *
2211  * RETURN     : int32_t type of status
2212  *              NO_ERROR  -- success
2213  *              none-zero failure code
2214  *==========================================================================*/
putBufs(mm_camera_map_unmap_ops_tbl_t * ops_tbl)2215 int32_t QCameraStream::putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl)
2216 {
2217     int rc = NO_ERROR;
2218 
2219     if (mBufAllocPid != 0) {
2220         cond_signal(true);
2221         LOGL("wait for buf allocation thread dead");
2222         pthread_join(mBufAllocPid, NULL);
2223         mBufAllocPid = 0;
2224         LOGL("return from buf allocation thread");
2225     }
2226 
2227     uint8_t numBufsToUnmap = mStreamBufs->getMappable();
2228     for (uint32_t i = 0; i < numBufsToUnmap; i++) {
2229         rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
2230         if (rc < 0) {
2231             LOGE("map_stream_buf failed: %d", rc);
2232         }
2233     }
2234     mBufDefs = NULL; // mBufDefs just keep a ptr to the buffer
2235                      // mm-camera-interface own the buffer, so no need to free
2236     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
2237     if ( !mStreamBufsAcquired ) {
2238         mStreamBufs->deallocate();
2239         delete mStreamBufs;
2240         mStreamBufs = NULL;
2241     }
2242 
2243     return rc;
2244 }
2245 
2246 /*===========================================================================
2247  * FUNCTION   : putBufsDeffered
2248  *
2249  * DESCRIPTION: function to deallocate deffered stream buffers
2250  *
2251  * PARAMETERS : none
2252  *
2253  * RETURN     : int32_t type of status
2254  *              NO_ERROR  -- success
2255  *              none-zero failure code
2256  *==========================================================================*/
putBufsDeffered()2257 int32_t QCameraStream::putBufsDeffered()
2258 {
2259     if (mBufAllocPid != 0) {
2260         cond_signal(true);
2261         LOGH("%s: wait for buf allocation thread dead", __func__);
2262         // Wait for the allocation of additional stream buffers
2263         pthread_join(mBufAllocPid, NULL);
2264         mBufAllocPid = 0;
2265         LOGH("%s: return from buf allocation thread", __func__);
2266     }
2267     // Deallocation of the deffered stream buffers handled separately
2268     return NO_ERROR;
2269 }
2270 
2271 /*===========================================================================
2272  * FUNCTION   : invalidateBuf
2273  *
2274  * DESCRIPTION: invalidate a specific stream buffer
2275  *
2276  * PARAMETERS :
2277  *   @index   : index of the buffer to invalidate
2278  *
2279  * RETURN     : int32_t type of status
2280  *              NO_ERROR  -- success
2281  *              none-zero failure code
2282  *==========================================================================*/
invalidateBuf(uint32_t index)2283 int32_t QCameraStream::invalidateBuf(uint32_t index)
2284 {
2285     if (mStreamBufs == NULL) {
2286         LOGE("Invalid Operation");
2287         return INVALID_OPERATION;
2288     }
2289     return mStreamBufs->invalidateCache(index);
2290 }
2291 
2292 /*===========================================================================
2293  * FUNCTION   : cleanInvalidateBuf
2294  *
2295  * DESCRIPTION: clean invalidate a specific stream buffer
2296  *
2297  * PARAMETERS :
2298  *   @index   : index of the buffer to clean invalidate
2299  *
2300  * RETURN     : int32_t type of status
2301  *              NO_ERROR  -- success
2302  *              none-zero failure code
2303  *==========================================================================*/
cleanInvalidateBuf(uint32_t index)2304 int32_t QCameraStream::cleanInvalidateBuf(uint32_t index)
2305 {
2306     if (mStreamBufs == NULL) {
2307         LOGE("Invalid Operation");
2308         return INVALID_OPERATION;
2309     }
2310     return mStreamBufs->cleanInvalidateCache(index);
2311 }
2312 
2313 /*===========================================================================
2314  * FUNCTION   : cleanBuf
2315  *
2316  * DESCRIPTION: clean a specific stream buffer
2317  *
2318  * PARAMETERS :
2319  *   @index   : index of the buffer to clean
2320  *
2321  * RETURN     : int32_t type of status
2322  *              NO_ERROR  -- success
2323  *              none-zero failure code
2324  *==========================================================================*/
cleanBuf(uint32_t index)2325 int32_t QCameraStream::cleanBuf(uint32_t index)
2326 {
2327     if (mStreamBufs == NULL) {
2328         LOGE("Invalid Operation");
2329         return INVALID_OPERATION;
2330     }
2331     return mStreamBufs->cleanCache(index);
2332 }
2333 
2334 /*===========================================================================
2335  * FUNCTION   : isTypeOf
2336  *
2337  * DESCRIPTION: helper function to determine if the stream is of the queried type
2338  *
2339  * PARAMETERS :
2340  *   @type    : stream type as of queried
2341  *
2342  * RETURN     : true/false
2343  *==========================================================================*/
isTypeOf(cam_stream_type_t type)2344 bool QCameraStream::isTypeOf(cam_stream_type_t type)
2345 {
2346     if (mStreamInfo != NULL && (mStreamInfo->stream_type == type)) {
2347         return true;
2348     } else {
2349         return false;
2350     }
2351 }
2352 
2353 /*===========================================================================
2354  * FUNCTION   : isOrignalTypeOf
2355  *
2356  * DESCRIPTION: helper function to determine if the original stream is of the
2357  *              queried type if it's reproc stream
2358  *
2359  * PARAMETERS :
2360  *   @type    : stream type as of queried
2361  *
2362  * RETURN     : true/false
2363  *==========================================================================*/
isOrignalTypeOf(cam_stream_type_t type)2364 bool QCameraStream::isOrignalTypeOf(cam_stream_type_t type)
2365 {
2366     if (mStreamInfo != NULL &&
2367         mStreamInfo->stream_type == CAM_STREAM_TYPE_OFFLINE_PROC &&
2368         mStreamInfo->reprocess_config.pp_type == CAM_ONLINE_REPROCESS_TYPE &&
2369         mStreamInfo->reprocess_config.online.input_stream_type == type) {
2370         return true;
2371     } else if (
2372         mStreamInfo != NULL &&
2373         mStreamInfo->stream_type == CAM_STREAM_TYPE_OFFLINE_PROC &&
2374         mStreamInfo->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE &&
2375         mStreamInfo->reprocess_config.offline.input_type == type) {
2376         return true;
2377     } else {
2378         return false;
2379     }
2380 }
2381 
2382 /*===========================================================================
2383  * FUNCTION   : getMyType
2384  *
2385  * DESCRIPTION: return stream type
2386  *
2387  * PARAMETERS : none
2388  *
2389  * RETURN     : stream type
2390  *==========================================================================*/
getMyType()2391 cam_stream_type_t QCameraStream::getMyType()
2392 {
2393     if (mStreamInfo != NULL) {
2394         return mStreamInfo->stream_type;
2395     } else {
2396         return CAM_STREAM_TYPE_DEFAULT;
2397     }
2398 }
2399 
2400 /*===========================================================================
2401  * FUNCTION   : getMyOriginalType
2402  *
2403  * DESCRIPTION: return stream type
2404  *
2405  * PARAMETERS : none
2406  *
2407  * RETURN     : stream type
2408  *==========================================================================*/
getMyOriginalType()2409 cam_stream_type_t QCameraStream::getMyOriginalType()
2410 {
2411     if (mStreamInfo != NULL) {
2412         if (mStreamInfo->stream_type == CAM_STREAM_TYPE_OFFLINE_PROC &&
2413                 mStreamInfo->reprocess_config.pp_type == CAM_ONLINE_REPROCESS_TYPE) {
2414             return mStreamInfo->reprocess_config.online.input_stream_type;
2415         } else if (mStreamInfo->stream_type == CAM_STREAM_TYPE_OFFLINE_PROC &&
2416                 mStreamInfo->reprocess_config.pp_type == CAM_OFFLINE_REPROCESS_TYPE) {
2417             return mStreamInfo->reprocess_config.offline.input_type;
2418         } else {
2419             return mStreamInfo->stream_type;
2420         }
2421     } else {
2422         return CAM_STREAM_TYPE_DEFAULT;
2423     }
2424 }
2425 
2426 /*===========================================================================
2427  * FUNCTION   : getFrameOffset
2428  *
2429  * DESCRIPTION: query stream buffer frame offset info
2430  *
2431  * PARAMETERS :
2432  *   @offset  : reference to struct to store the queried frame offset info
2433  *
2434  * RETURN     : int32_t type of status
2435  *              NO_ERROR  -- success
2436  *              none-zero failure code
2437  *==========================================================================*/
getFrameOffset(cam_frame_len_offset_t & offset)2438 int32_t QCameraStream::getFrameOffset(cam_frame_len_offset_t &offset)
2439 {
2440     if (NULL == mStreamInfo) {
2441         return NO_INIT;
2442     }
2443 
2444     offset = mFrameLenOffset;
2445     if ((ROTATE_90 == mOnlineRotation) || (ROTATE_270 == mOnlineRotation)
2446             || (offset.frame_len == 0) || (offset.num_planes == 0)) {
2447         // Re-calculate frame offset in case of online rotation
2448         cam_stream_info_t streamInfo = *mStreamInfo;
2449         getFrameDimension(streamInfo.dim);
2450         calcOffset(&streamInfo);
2451         offset = streamInfo.buf_planes.plane_info;
2452     }
2453 
2454     return 0;
2455 }
2456 
2457 /*===========================================================================
2458  * FUNCTION   : getCropInfo
2459  *
2460  * DESCRIPTION: query crop info of the stream
2461  *
2462  * PARAMETERS :
2463  *   @crop    : reference to struct to store the queried crop info
2464  *
2465  * RETURN     : int32_t type of status
2466  *              NO_ERROR  -- success
2467  *              none-zero failure code
2468  *==========================================================================*/
getCropInfo(cam_rect_t & crop)2469 int32_t QCameraStream::getCropInfo(cam_rect_t &crop)
2470 {
2471     pthread_mutex_lock(&mCropLock);
2472     crop = mCropInfo;
2473     pthread_mutex_unlock(&mCropLock);
2474     return NO_ERROR;
2475 }
2476 
2477 /*===========================================================================
2478  * FUNCTION   : setCropInfo
2479  *
2480  * DESCRIPTION: set crop info of the stream
2481  *
2482  * PARAMETERS :
2483  *   @crop    : struct to store new crop info
2484  *
2485  * RETURN     : int32_t type of status
2486  *              NO_ERROR  -- success
2487  *              none-zero failure code
2488  *==========================================================================*/
setCropInfo(cam_rect_t crop)2489 int32_t QCameraStream::setCropInfo(cam_rect_t crop)
2490 {
2491     pthread_mutex_lock(&mCropLock);
2492     mCropInfo = crop;
2493     pthread_mutex_unlock(&mCropLock);
2494     return NO_ERROR;
2495 }
2496 
2497 /*===========================================================================
2498  * FUNCTION   : getFrameDimension
2499  *
2500  * DESCRIPTION: query stream frame dimension info
2501  *
2502  * PARAMETERS :
2503  *   @dim     : reference to struct to store the queried frame dimension
2504  *
2505  * RETURN     : int32_t type of status
2506  *              NO_ERROR  -- success
2507  *              none-zero failure code
2508  *==========================================================================*/
getFrameDimension(cam_dimension_t & dim)2509 int32_t QCameraStream::getFrameDimension(cam_dimension_t &dim)
2510 {
2511     if (mStreamInfo != NULL) {
2512         if ((ROTATE_90 == mOnlineRotation) || (ROTATE_270 == mOnlineRotation)) {
2513             dim.width = mStreamInfo->dim.height;
2514             dim.height = mStreamInfo->dim.width;
2515         } else {
2516             dim = mStreamInfo->dim;
2517         }
2518         return 0;
2519     }
2520     return -1;
2521 }
2522 
2523 /*===========================================================================
2524  * FUNCTION   : getFormat
2525  *
2526  * DESCRIPTION: query stream format
2527  *
2528  * PARAMETERS :
2529  *   @fmt     : reference to stream format
2530  *
2531  * RETURN     : int32_t type of status
2532  *              NO_ERROR  -- success
2533  *              none-zero failure code
2534  *==========================================================================*/
getFormat(cam_format_t & fmt)2535 int32_t QCameraStream::getFormat(cam_format_t &fmt)
2536 {
2537     if (mStreamInfo != NULL) {
2538         fmt = mStreamInfo->fmt;
2539         return 0;
2540     }
2541     return -1;
2542 }
2543 
2544 /*===========================================================================
2545  * FUNCTION   : getMyServerID
2546  *
2547  * DESCRIPTION: query server stream ID
2548  *
2549  * PARAMETERS : None
2550  *
2551  * RETURN     : stream ID from server
2552  *==========================================================================*/
getMyServerID()2553 uint32_t QCameraStream::getMyServerID() {
2554     if (mStreamInfo != NULL) {
2555         return mStreamInfo->stream_svr_id;
2556     } else {
2557         return 0;
2558     }
2559 }
2560 
2561 /*===========================================================================
2562  * FUNCTION   : acquireStreamBufs
2563  *
2564  * DESCRIPTION: acquire stream buffers and postpone their release.
2565  *
2566  * PARAMETERS : None
2567  *
2568  * RETURN     : int32_t type of status
2569  *              NO_ERROR  -- success
2570  *              none-zero failure code
2571  *==========================================================================*/
acquireStreamBufs()2572 int32_t QCameraStream::acquireStreamBufs()
2573 {
2574     mStreamBufsAcquired = true;
2575 
2576     return NO_ERROR;
2577 }
2578 
2579 /*===========================================================================
2580  * FUNCTION   : mapBuf
2581  *
2582  * DESCRIPTION: map stream related buffer to backend server
2583  *
2584  * PARAMETERS :
2585  *   @buf_type : mapping type of buffer
2586  *   @buf_idx  : index of buffer
2587  *   @plane_idx: plane index
2588  *   @fd       : fd of the buffer
2589  *   @buffer   : buffer address
2590  *   @size     : lenght of the buffer
2591  *   @ops_tbl  : ptr to buf mapping/unmapping ops
2592  *
2593  * RETURN     : int32_t type of status
2594  *              NO_ERROR  -- success
2595  *              none-zero failure code
2596  *==========================================================================*/
mapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,void * buffer,size_t size,mm_camera_map_unmap_ops_tbl_t * ops_tbl)2597 int32_t QCameraStream::mapBuf(uint8_t buf_type, uint32_t buf_idx,
2598         int32_t plane_idx, int fd, void *buffer, size_t size,
2599         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
2600 {
2601     cam_buf_map_type_list bufMapList;
2602     int32_t rc = QCameraBufferMaps::makeSingletonBufMapList(
2603            (cam_mapping_buf_type)buf_type, mHandle, buf_idx, plane_idx,
2604            0 /*cookie*/, fd, size, bufMapList, buffer);
2605 
2606     if (rc != NO_ERROR) {
2607         return rc;
2608     }
2609 
2610     return mapBufs(bufMapList, ops_tbl);
2611 }
2612 
2613 /*===========================================================================
2614  * FUNCTION   : mapBufs
2615  *
2616  * DESCRIPTION: map stream related buffers to backend server
2617  *
2618  * PARAMETERS :
2619  *   @bufMapList : buffer mapping information
2620  *   @ops_tbl    : ptr to buf mapping/unmapping ops
2621  *
2622  * RETURN     : int32_t type of status
2623  *              NO_ERROR  -- success
2624  *              none-zero failure code
2625  *==========================================================================*/
2626 
mapBufs(cam_buf_map_type_list bufMapList,__unused mm_camera_map_unmap_ops_tbl_t * ops_tbl)2627 int32_t QCameraStream::mapBufs(cam_buf_map_type_list bufMapList,
2628         __unused mm_camera_map_unmap_ops_tbl_t *ops_tbl)
2629 {
2630     if (m_MemOpsTbl.bundled_map_ops != NULL) {
2631         return m_MemOpsTbl.bundled_map_ops(&bufMapList, m_MemOpsTbl.userdata);
2632     } else {
2633         return mCamOps->map_stream_bufs(mCamHandle, mChannelHandle,
2634                 &bufMapList);
2635     }
2636 
2637 }
2638 
2639 /*===========================================================================
2640  * FUNCTION   : unmapBuf
2641  *
2642  * DESCRIPTION: unmap stream related buffer to backend server
2643  *
2644  * PARAMETERS :
2645  *   @buf_type : mapping type of buffer
2646  *   @buf_idx  : index of buffer
2647  *   @plane_idx: plane index
2648  *   @ops_tbl    : ptr to buf mapping/unmapping ops
2649  *
2650  * RETURN     : int32_t type of status
2651  *              NO_ERROR  -- success
2652  *              none-zero failure code
2653  *==========================================================================*/
unmapBuf(uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,mm_camera_map_unmap_ops_tbl_t * ops_tbl)2654 int32_t QCameraStream::unmapBuf(uint8_t buf_type, uint32_t buf_idx, int32_t plane_idx,
2655         mm_camera_map_unmap_ops_tbl_t *ops_tbl)
2656 {
2657     if (ops_tbl != NULL) {
2658         return ops_tbl->unmap_ops(buf_idx, plane_idx,
2659                 (cam_mapping_buf_type)buf_type, ops_tbl->userdata);
2660     } else {
2661         return mCamOps->unmap_stream_buf(mCamHandle, mChannelHandle,
2662                 mHandle, buf_type, buf_idx, plane_idx);
2663     }
2664 }
2665 
2666 /*===========================================================================
2667  * FUNCTION   : setParameter
2668  *
2669  * DESCRIPTION: set stream based parameters
2670  *
2671  * PARAMETERS :
2672  *   @param   : ptr to parameters to be set
2673  *
2674  * RETURN     : int32_t type of status
2675  *              NO_ERROR  -- success
2676  *              none-zero failure code
2677  *==========================================================================*/
setParameter(cam_stream_parm_buffer_t & param)2678 int32_t QCameraStream::setParameter(cam_stream_parm_buffer_t &param)
2679 {
2680     int32_t rc = NO_ERROR;
2681     pthread_mutex_lock(&mParameterLock);
2682     mStreamInfo->parm_buf = param;
2683     rc = mCamOps->set_stream_parms(mCamHandle,
2684                                    mChannelHandle,
2685                                    mHandle,
2686                                    &mStreamInfo->parm_buf);
2687     if (rc == NO_ERROR) {
2688         param = mStreamInfo->parm_buf;
2689     }
2690     pthread_mutex_unlock(&mParameterLock);
2691     return rc;
2692 }
2693 
2694 /*===========================================================================
2695  * FUNCTION   : getParameter
2696  *
2697  * DESCRIPTION: get stream based parameters
2698  *
2699  * PARAMETERS :
2700  *   @param   : ptr to parameters to be red
2701  *
2702  * RETURN     : int32_t type of status
2703  *              NO_ERROR  -- success
2704  *              none-zero failure code
2705  *==========================================================================*/
getParameter(cam_stream_parm_buffer_t & param)2706 int32_t QCameraStream::getParameter(cam_stream_parm_buffer_t &param)
2707 {
2708     int32_t rc = NO_ERROR;
2709     pthread_mutex_lock(&mParameterLock);
2710     mStreamInfo->parm_buf = param;
2711     rc = mCamOps->get_stream_parms(mCamHandle,
2712                                    mChannelHandle,
2713                                    mHandle,
2714                                    &mStreamInfo->parm_buf);
2715     if (rc == NO_ERROR) {
2716         param = mStreamInfo->parm_buf;
2717     }
2718     pthread_mutex_unlock(&mParameterLock);
2719     return rc;
2720 }
2721 
2722 /*===========================================================================
2723  * FUNCTION   : releaseFrameData
2724  *
2725  * DESCRIPTION: callback function to release frame data node
2726  *
2727  * PARAMETERS :
2728  *   @data      : ptr to post process input data
2729  *   @user_data : user data ptr (QCameraReprocessor)
2730  *
2731  * RETURN     : None
2732  *==========================================================================*/
releaseFrameData(void * data,void * user_data)2733 void QCameraStream::releaseFrameData(void *data, void *user_data)
2734 {
2735     QCameraStream *pme = (QCameraStream *)user_data;
2736     mm_camera_super_buf_t *frame = (mm_camera_super_buf_t *)data;
2737     if (NULL != pme) {
2738         pme->bufDone(frame->bufs[0]->buf_idx);
2739     }
2740 }
2741 
2742 /*===========================================================================
2743  * FUNCTION   : configStream
2744  *
2745  * DESCRIPTION: send stream configuration to back end
2746  *
2747  * PARAMETERS :
2748  *
2749  * RETURN     : int32_t type of status
2750  *              NO_ERROR  -- success
2751  *              none-zero failure code
2752  *==========================================================================*/
configStream()2753 int32_t QCameraStream::configStream()
2754 {
2755     int rc = NO_ERROR;
2756 
2757     // Configure the stream
2758     mm_camera_stream_config_t stream_config;
2759     stream_config.stream_info = mStreamInfo;
2760     stream_config.mem_vtbl = mMemVtbl;
2761     stream_config.stream_cb_sync = NULL;
2762     stream_config.stream_cb = dataNotifyCB;
2763     stream_config.padding_info = mPaddingInfo;
2764     stream_config.userdata = this;
2765     rc = mCamOps->config_stream(mCamHandle,
2766                 mChannelHandle, mHandle, &stream_config);
2767     if (rc < 0) {
2768         LOGE("Failed to config stream, rc = %d", rc);
2769         mCamOps->unmap_stream_buf(mCamHandle,
2770                 mChannelHandle,
2771                 mHandle,
2772                 CAM_MAPPING_BUF_TYPE_STREAM_INFO,
2773                 0,
2774                 -1);
2775         return UNKNOWN_ERROR;
2776     }
2777 
2778     return rc;
2779 }
2780 
2781 /*===========================================================================
2782  * FUNCTION   : setSyncDataCB
2783  *
2784  * DESCRIPTION: register callback with mm-interface for this stream
2785  *
2786  * PARAMETERS :
2787        @stream_cb   : Callback function
2788  *
2789  * RETURN     : int32_t type of status
2790  *              NO_ERROR  -- success
2791  *              non-zero failure code
2792  *==========================================================================*/
setSyncDataCB(stream_cb_routine data_cb)2793 int32_t QCameraStream::setSyncDataCB(stream_cb_routine data_cb)
2794 {
2795     int32_t rc = NO_ERROR;
2796 
2797     if (mCamOps != NULL) {
2798         mSYNCDataCB = data_cb;
2799         rc = mCamOps->register_stream_buf_cb(mCamHandle,
2800                 mChannelHandle, mHandle, dataNotifySYNCCB, MM_CAMERA_STREAM_CB_TYPE_SYNC,
2801                 this);
2802         if (rc == NO_ERROR) {
2803             mSyncCBEnabled = TRUE;
2804             return rc;
2805         }
2806     }
2807     LOGE("Interface handle is NULL");
2808     return UNKNOWN_ERROR;
2809 }
2810 
2811 /*===========================================================================
2812  * FUNCTION   : processCameraControl
2813  *
2814  * DESCRIPTION: Suspend and resume camera
2815  *
2816  * PARAMETERS :
2817  *
2818  * RETURN     : int32_t type of status
2819  *              NO_ERROR  -- success
2820  *              none-zero failure code
2821  *==========================================================================*/
processCameraControl(uint32_t camState)2822 int32_t QCameraStream::processCameraControl(uint32_t camState)
2823 {
2824     mActiveCameras = camState;
2825     return NO_ERROR;
2826 }
2827 
2828 /*===========================================================================
2829  * FUNCTION   : switchStreamCb
2830  *
2831  * DESCRIPTION: switch stream's in case of dual camera
2832  *
2833  * PARAMETERS :
2834  * @camMaster : Master camera
2835  *
2836  * RETURN     : int32_t type of status
2837  *              NO_ERROR  -- success
2838  *              none-zero failure code
2839  *==========================================================================*/
switchStreamCb(uint32_t camMaster)2840 int32_t QCameraStream::switchStreamCb(uint32_t camMaster)
2841 {
2842     int32_t ret = NO_ERROR;
2843     if (needCbSwitch() && (camMaster != mMasterCamera)) {
2844         ret = mCamOps->handle_frame_sync_cb(mCamHandle, mChannelHandle,
2845                 mHandle, MM_CAMERA_CB_REQ_TYPE_SWITCH);
2846     }
2847     // Update master camera
2848     mMasterCamera = camMaster;
2849     return ret;
2850 }
2851 
2852 /*===========================================================================
2853  * FUNCTION   : needCbSwitch
2854  *
2855  * DESCRIPTION: Function to enable callback switch based on availability of
2856  *              spatial alignment
2857  *
2858  * PARAMETERS :
2859  *
2860  * RETURN     : int32_t type of status
2861  *              NO_ERROR  -- success
2862  *              none-zero failure code
2863  *==========================================================================*/
needCbSwitch()2864 bool QCameraStream::needCbSwitch()
2865 {
2866     if (!isDualStream()) {
2867         return false;
2868     }
2869 
2870     if ((mStreamInfo->pp_config.feature_mask & CAM_QTI_FEATURE_SAT)
2871             || (mStreamInfo->pp_config.feature_mask & CAM_QTI_FEATURE_SAC)
2872             || (needFrameSync())
2873             || (getMyType() == CAM_STREAM_TYPE_SNAPSHOT)
2874             || (getMyType() == CAM_STREAM_TYPE_METADATA)) {
2875         return false;
2876     } else {
2877         return true;
2878     }
2879 }
2880 
2881 /*===========================================================================
2882  * FUNCTION   : needFrameSync
2883  *
2884  * DESCRIPTION: Function to enable stream frame buffer sync
2885  *
2886  * PARAMETERS :
2887  *
2888  * RETURN     : int32_t type of status
2889  *              NO_ERROR  -- success
2890  *              none-zero failure code
2891  *==========================================================================*/
needFrameSync()2892 bool QCameraStream::needFrameSync()
2893 {
2894     if (!isDualStream()) {
2895         return false;
2896     }
2897 
2898     switch (getMyType()) {
2899     default:
2900         return false;
2901         break;
2902     }
2903 }
2904 
2905 /*===========================================================================
2906  * FUNCTION   : setBundleInfo
2907  *
2908  * DESCRIPTION: set bundle for this stream to MCT
2909  *
2910  * PARAMETERS :
2911  *
2912  * RETURN     : int32_t type of status
2913  *              NO_ERROR  -- success
2914  *              none-zero failure code
2915  *==========================================================================*/
setBundleInfo()2916 int32_t QCameraStream::setBundleInfo()
2917 {
2918     int32_t ret = NO_ERROR;
2919     cam_bundle_config_t bundleInfo;
2920 
2921     if ((isTypeOf(CAM_STREAM_TYPE_METADATA))
2922             || (isTypeOf(CAM_STREAM_TYPE_OFFLINE_PROC))) {
2923         // Skip metadata for reprocess now because PP module cannot handle meta data
2924         // May need furthur discussion if Imaginglib need meta data
2925         return ret;
2926     }
2927 
2928     cam_stream_parm_buffer_t param, aux_param;
2929     uint32_t active_handle = get_main_camera_handle(mChannelHandle);
2930     memset(&bundleInfo, 0, sizeof(bundleInfo));
2931     if (active_handle) {
2932         ret = mCamOps->get_bundle_info(mCamHandle, active_handle,
2933                 &bundleInfo);
2934         memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
2935         param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
2936         param.bundleInfo = bundleInfo;
2937     }
2938 
2939     memset(&aux_param, 0, sizeof(cam_stream_parm_buffer_t));
2940     if (isDualStream()) {
2941         active_handle = get_aux_camera_handle(mChannelHandle);
2942         memset(&bundleInfo, 0, sizeof(bundleInfo));
2943         ret = mCamOps->get_bundle_info(mCamHandle, active_handle,
2944                 &bundleInfo);
2945         aux_param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
2946         aux_param.bundleInfo = bundleInfo;
2947     }
2948     pthread_mutex_lock(&mParameterLock);
2949     mStreamInfo->parm_buf = param;
2950     if ((aux_param.bundleInfo.num_of_streams > 1)
2951             && (mStreamInfo->aux_str_info != NULL)) {
2952         mStreamInfo->aux_str_info->parm_buf = aux_param;
2953     }
2954 
2955     if ((mStreamInfo->parm_buf.bundleInfo.num_of_streams > 1)
2956             || (((mStreamInfo->aux_str_info != NULL) &&
2957             (mStreamInfo->aux_str_info->parm_buf.bundleInfo.num_of_streams > 1)))) {
2958         ret = mCamOps->set_stream_parms(mCamHandle,
2959                 mChannelHandle, mHandle,
2960                 &mStreamInfo->parm_buf);
2961     }
2962     pthread_mutex_unlock(&mParameterLock);
2963     if (ret != NO_ERROR) {
2964         LOGE("stream setParameter for set bundle failed");
2965         return ret;
2966     }
2967     return ret;
2968 }
2969 
2970 /*===========================================================================
2971  * FUNCTION   : handleCacheOps
2972  *
2973  * DESCRIPTION: handle cache ops for this stream buffer
2974  *
2975  * PARAMETERS :
2976        @buf   : stream buffer
2977  *
2978  * RETURN     : int32_t type of status
2979  *              NO_ERROR  -- success
2980  *              non-zero failure code
2981  *==========================================================================*/
handleCacheOps(mm_camera_buf_def_t * buf)2982 int32_t QCameraStream::handleCacheOps(mm_camera_buf_def_t* buf)
2983 {
2984     int32_t rc = 0;
2985     if( !buf) {
2986         LOGE("Error!! buf_info: %p", buf);
2987         rc = -1;
2988         return rc;
2989     }
2990     if ((mMemVtbl.clean_invalidate_buf  == NULL) ||
2991             (mMemVtbl.invalidate_buf  == NULL) ||
2992             (mMemVtbl.clean_buf  == NULL)) {
2993         LOGI("Clean/Invalidate cache ops not supported");
2994         rc = -1;
2995         return rc;
2996     }
2997 
2998     LOGH("[CACHE_OPS] Stream type: %d buf index: %d cache ops flags: 0x%x",
2999             buf->stream_type, buf->buf_idx, buf->cache_flags);
3000 
3001     if ((buf->cache_flags & CPU_HAS_READ_WRITTEN) ==
3002         CPU_HAS_READ_WRITTEN) {
3003         rc = mMemVtbl.clean_invalidate_buf(
3004                 buf->buf_idx, mMemVtbl.user_data);
3005     } else if ((buf->cache_flags & CPU_HAS_READ) ==
3006         CPU_HAS_READ) {
3007         rc = mMemVtbl.invalidate_buf(
3008                 buf->buf_idx, mMemVtbl.user_data);
3009     } else if ((buf->cache_flags & CPU_HAS_WRITTEN) ==
3010         CPU_HAS_WRITTEN) {
3011         rc = mMemVtbl.clean_buf(
3012                 buf->buf_idx, mMemVtbl.user_data);
3013     }
3014     if (rc != 0) {
3015         LOGW("Warning!! Clean/Invalidate cache failed on buffer index: %d",
3016                 buf->buf_idx);
3017     }
3018     // Reset buffer cache flags after cache ops
3019     buf->cache_flags = 0;
3020     return rc;
3021 }
3022 
3023 
3024 }; // namespace qcamera
3025