1 /* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #define LOG_TAG "QCameraHWI_Mem"
31
32 #include <string.h>
33 #include <fcntl.h>
34 #include <sys/mman.h>
35 #include <utils/Errors.h>
36 #include <gralloc_priv.h>
37 #include <QComOMXMetadata.h>
38 #include "QCamera2HWI.h"
39 #include "QCameraMem.h"
40
41 extern "C" {
42 #include <mm_camera_interface.h>
43 }
44
45 using namespace android;
46
47 namespace qcamera {
48
49 // QCaemra2Memory base class
50
51 /*===========================================================================
52 * FUNCTION : QCameraMemory
53 *
54 * DESCRIPTION: default constructor of QCameraMemory
55 *
56 * PARAMETERS :
57 * @cached : flag indicates if using cached memory
58 *
59 * RETURN : None
60 *==========================================================================*/
QCameraMemory(bool cached)61 QCameraMemory::QCameraMemory(bool cached)
62 :m_bCached(cached)
63 {
64 mBufferCount = 0;
65 for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
66 mMemInfo[i].fd = 0;
67 mMemInfo[i].main_ion_fd = 0;
68 mMemInfo[i].handle = NULL;
69 mMemInfo[i].size = 0;
70 }
71 }
72
73 /*===========================================================================
74 * FUNCTION : ~QCameraMemory
75 *
76 * DESCRIPTION: deconstructor of QCameraMemory
77 *
78 * PARAMETERS : none
79 *
80 * RETURN : None
81 *==========================================================================*/
~QCameraMemory()82 QCameraMemory::~QCameraMemory()
83 {
84 }
85
86 /*===========================================================================
87 * FUNCTION : cacheOpsInternal
88 *
89 * DESCRIPTION: ion related memory cache operations
90 *
91 * PARAMETERS :
92 * @index : index of the buffer
93 * @cmd : cache ops command
94 * @vaddr : ptr to the virtual address
95 *
96 * RETURN : int32_t type of status
97 * NO_ERROR -- success
98 * none-zero failure code
99 *==========================================================================*/
cacheOpsInternal(int index,unsigned int cmd,void * vaddr)100 int QCameraMemory::cacheOpsInternal(int index, unsigned int cmd, void *vaddr)
101 {
102 if (!m_bCached) {
103 // Memory is not cached, no need for cache ops
104 ALOGV("%s: No cache ops here for uncached memory", __func__);
105 return OK;
106 }
107
108 struct ion_flush_data cache_inv_data;
109 struct ion_custom_data custom_data;
110 int ret = OK;
111
112 if (index >= mBufferCount) {
113 ALOGE("%s: index %d out of bound [0, %d)", __func__, index, mBufferCount);
114 return BAD_INDEX;
115 }
116
117 memset(&cache_inv_data, 0, sizeof(cache_inv_data));
118 memset(&custom_data, 0, sizeof(custom_data));
119 cache_inv_data.vaddr = vaddr;
120 cache_inv_data.fd = mMemInfo[index].fd;
121 cache_inv_data.handle = mMemInfo[index].handle;
122 cache_inv_data.length = mMemInfo[index].size;
123 custom_data.cmd = cmd;
124 custom_data.arg = (unsigned long)&cache_inv_data;
125
126 ALOGD("%s: addr = %p, fd = %d, handle = %p length = %d, ION Fd = %d",
127 __func__, cache_inv_data.vaddr, cache_inv_data.fd,
128 cache_inv_data.handle, cache_inv_data.length,
129 mMemInfo[index].main_ion_fd);
130 ret = ioctl(mMemInfo[index].main_ion_fd, ION_IOC_CUSTOM, &custom_data);
131 if (ret < 0)
132 ALOGE("%s: Cache Invalidate failed: %s\n", __func__, strerror(errno));
133
134 return ret;
135 }
136
137 /*===========================================================================
138 * FUNCTION : getFd
139 *
140 * DESCRIPTION: return file descriptor of the indexed buffer
141 *
142 * PARAMETERS :
143 * @index : index of the buffer
144 *
145 * RETURN : file descriptor
146 *==========================================================================*/
getFd(int index) const147 int QCameraMemory::getFd(int index) const
148 {
149 if (index >= mBufferCount)
150 return BAD_INDEX;
151
152 return mMemInfo[index].fd;
153 }
154
155 /*===========================================================================
156 * FUNCTION : getSize
157 *
158 * DESCRIPTION: return buffer size of the indexed buffer
159 *
160 * PARAMETERS :
161 * @index : index of the buffer
162 *
163 * RETURN : buffer size
164 *==========================================================================*/
getSize(int index) const165 int QCameraMemory::getSize(int index) const
166 {
167 if (index >= mBufferCount)
168 return BAD_INDEX;
169
170 return (int)mMemInfo[index].size;
171 }
172
173 /*===========================================================================
174 * FUNCTION : getCnt
175 *
176 * DESCRIPTION: query number of buffers allocated
177 *
178 * PARAMETERS : none
179 *
180 * RETURN : number of buffers allocated
181 *==========================================================================*/
getCnt() const182 int QCameraMemory::getCnt() const
183 {
184 return mBufferCount;
185 }
186
187 /*===========================================================================
188 * FUNCTION : getBufDef
189 *
190 * DESCRIPTION: query detailed buffer information
191 *
192 * PARAMETERS :
193 * @offset : [input] frame buffer offset
194 * @bufDef : [output] reference to struct to store buffer definition
195 * @index : [input] index of the buffer
196 *
197 * RETURN : none
198 *==========================================================================*/
getBufDef(const cam_frame_len_offset_t & offset,mm_camera_buf_def_t & bufDef,int index) const199 void QCameraMemory::getBufDef(const cam_frame_len_offset_t &offset,
200 mm_camera_buf_def_t &bufDef, int index) const
201 {
202 if (!mBufferCount) {
203 ALOGE("Memory not allocated");
204 return;
205 }
206 bufDef.fd = mMemInfo[index].fd;
207 bufDef.frame_len = offset.frame_len;
208 bufDef.mem_info = (void *)this;
209 bufDef.num_planes = offset.num_planes;
210 bufDef.buffer = getPtr(index);
211 bufDef.buf_idx = index;
212
213 /* Plane 0 needs to be set separately. Set other planes in a loop */
214 bufDef.planes[0].length = offset.mp[0].len;
215 bufDef.planes[0].m.userptr = mMemInfo[index].fd;
216 bufDef.planes[0].data_offset = offset.mp[0].offset;
217 bufDef.planes[0].reserved[0] = 0;
218 for (int i = 1; i < bufDef.num_planes; i++) {
219 bufDef.planes[i].length = offset.mp[i].len;
220 bufDef.planes[i].m.userptr = mMemInfo[i].fd;
221 bufDef.planes[i].data_offset = offset.mp[i].offset;
222 bufDef.planes[i].reserved[0] =
223 bufDef.planes[i-1].reserved[0] +
224 bufDef.planes[i-1].length;
225 }
226 }
227
228 /*===========================================================================
229 * FUNCTION : alloc
230 *
231 * DESCRIPTION: allocate requested number of buffers of certain size
232 *
233 * PARAMETERS :
234 * @count : number of buffers to be allocated
235 * @size : lenght of the buffer to be allocated
236 * @heap_id : heap id to indicate where the buffers will be allocated from
237 *
238 * RETURN : int32_t type of status
239 * NO_ERROR -- success
240 * none-zero failure code
241 *==========================================================================*/
alloc(int count,int size,int heap_id)242 int QCameraMemory::alloc(int count, int size, int heap_id)
243 {
244 int rc = OK;
245 if (count > MM_CAMERA_MAX_NUM_FRAMES) {
246 ALOGE("Buffer count %d out of bound. Max is %d", count, MM_CAMERA_MAX_NUM_FRAMES);
247 return BAD_INDEX;
248 }
249 if (mBufferCount) {
250 ALOGE("Allocating a already allocated heap memory");
251 return INVALID_OPERATION;
252 }
253
254 for (int i = 0; i < count; i ++) {
255 rc = allocOneBuffer(mMemInfo[i], heap_id, size);
256 if (rc < 0) {
257 ALOGE("AllocateIonMemory failed");
258 for (int j = i-1; j >= 0; j--)
259 deallocOneBuffer(mMemInfo[j]);
260 break;
261 }
262 }
263 return rc;
264 }
265
266 /*===========================================================================
267 * FUNCTION : dealloc
268 *
269 * DESCRIPTION: deallocate buffers
270 *
271 * PARAMETERS : none
272 *
273 * RETURN : none
274 *==========================================================================*/
dealloc()275 void QCameraMemory::dealloc()
276 {
277 for (int i = 0; i < mBufferCount; i++)
278 deallocOneBuffer(mMemInfo[i]);
279 }
280
281 /*===========================================================================
282 * FUNCTION : allocOneBuffer
283 *
284 * DESCRIPTION: impl of allocating one buffers of certain size
285 *
286 * PARAMETERS :
287 * @memInfo : [output] reference to struct to store additional memory allocation info
288 * @heap : [input] heap id to indicate where the buffers will be allocated from
289 * @size : [input] lenght of the buffer to be allocated
290 *
291 * RETURN : int32_t type of status
292 * NO_ERROR -- success
293 * none-zero failure code
294 *==========================================================================*/
allocOneBuffer(QCameraMemInfo & memInfo,int heap_id,int size)295 int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo, int heap_id, int size)
296 {
297 int rc = OK;
298 struct ion_handle_data handle_data;
299 struct ion_allocation_data alloc;
300 struct ion_fd_data ion_info_fd;
301 int main_ion_fd = 0;
302
303 main_ion_fd = open("/dev/ion", O_RDONLY);
304 if (main_ion_fd < 0) {
305 ALOGE("Ion dev open failed: %s\n", strerror(errno));
306 goto ION_OPEN_FAILED;
307 }
308
309 memset(&alloc, 0, sizeof(alloc));
310 alloc.len = size;
311 /* to make it page size aligned */
312 alloc.len = (alloc.len + 4095) & (~4095);
313 alloc.align = 4096;
314 if (m_bCached) {
315 alloc.flags = ION_FLAG_CACHED;
316 }
317 alloc.heap_mask = heap_id;
318 rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
319 if (rc < 0) {
320 ALOGE("ION allocation failed: %s\n", strerror(errno));
321 goto ION_ALLOC_FAILED;
322 }
323
324 memset(&ion_info_fd, 0, sizeof(ion_info_fd));
325 ion_info_fd.handle = alloc.handle;
326 rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
327 if (rc < 0) {
328 ALOGE("ION map failed %s\n", strerror(errno));
329 goto ION_MAP_FAILED;
330 }
331
332 memInfo.main_ion_fd = main_ion_fd;
333 memInfo.fd = ion_info_fd.fd;
334 memInfo.handle = ion_info_fd.handle;
335 memInfo.size = alloc.len;
336 return OK;
337
338 ION_MAP_FAILED:
339 memset(&handle_data, 0, sizeof(handle_data));
340 handle_data.handle = ion_info_fd.handle;
341 ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
342 ION_ALLOC_FAILED:
343 close(main_ion_fd);
344 ION_OPEN_FAILED:
345 return NO_MEMORY;
346 }
347
348 /*===========================================================================
349 * FUNCTION : deallocOneBuffer
350 *
351 * DESCRIPTION: impl of deallocating one buffers
352 *
353 * PARAMETERS :
354 * @memInfo : reference to struct that stores additional memory allocation info
355 *
356 * RETURN : none
357 *==========================================================================*/
deallocOneBuffer(QCameraMemInfo & memInfo)358 void QCameraMemory::deallocOneBuffer(QCameraMemInfo &memInfo)
359 {
360 struct ion_handle_data handle_data;
361
362 if (memInfo.fd > 0) {
363 close(memInfo.fd);
364 memInfo.fd = 0;
365 }
366
367 if (memInfo.main_ion_fd > 0) {
368 memset(&handle_data, 0, sizeof(handle_data));
369 handle_data.handle = memInfo.handle;
370 ioctl(memInfo.main_ion_fd, ION_IOC_FREE, &handle_data);
371 close(memInfo.main_ion_fd);
372 memInfo.main_ion_fd = 0;
373 }
374 memInfo.handle = NULL;
375 memInfo.size = 0;
376 }
377
378 /*===========================================================================
379 * FUNCTION : QCameraHeapMemory
380 *
381 * DESCRIPTION: constructor of QCameraHeapMemory for ion memory used internally in HAL
382 *
383 * PARAMETERS :
384 * @cached : flag indicates if using cached memory
385 *
386 * RETURN : none
387 *==========================================================================*/
QCameraHeapMemory(bool cached)388 QCameraHeapMemory::QCameraHeapMemory(bool cached)
389 : QCameraMemory(cached)
390 {
391 for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
392 mPtr[i] = NULL;
393 }
394
395 /*===========================================================================
396 * FUNCTION : ~QCameraHeapMemory
397 *
398 * DESCRIPTION: deconstructor of QCameraHeapMemory
399 *
400 * PARAMETERS : none
401 *
402 * RETURN : none
403 *==========================================================================*/
~QCameraHeapMemory()404 QCameraHeapMemory::~QCameraHeapMemory()
405 {
406 }
407
408 /*===========================================================================
409 * FUNCTION : getPtr
410 *
411 * DESCRIPTION: return buffer pointer
412 *
413 * PARAMETERS :
414 * @index : index of the buffer
415 *
416 * RETURN : buffer ptr
417 *==========================================================================*/
getPtr(int index) const418 void *QCameraHeapMemory::getPtr(int index) const
419 {
420 if (index >= mBufferCount) {
421 ALOGE("index out of bound");
422 return (void *)BAD_INDEX;
423 }
424 return mPtr[index];
425 }
426
427 /*===========================================================================
428 * FUNCTION : allocate
429 *
430 * DESCRIPTION: allocate requested number of buffers of certain size
431 *
432 * PARAMETERS :
433 * @count : number of buffers to be allocated
434 * @size : lenght of the buffer to be allocated
435 *
436 * RETURN : int32_t type of status
437 * NO_ERROR -- success
438 * none-zero failure code
439 *==========================================================================*/
allocate(int count,int size)440 int QCameraHeapMemory::allocate(int count, int size)
441 {
442 int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
443 int rc = alloc(count, size, heap_mask);
444 if (rc < 0)
445 return rc;
446
447 for (int i = 0; i < count; i ++) {
448 void *vaddr = mmap(NULL,
449 mMemInfo[i].size,
450 PROT_READ | PROT_WRITE,
451 MAP_SHARED,
452 mMemInfo[i].fd, 0);
453 if (vaddr == MAP_FAILED) {
454 for (int j = i-1; j >= 0; j --) {
455 munmap(mPtr[i], mMemInfo[i].size);
456 rc = NO_MEMORY;
457 break;
458 }
459 } else
460 mPtr[i] = vaddr;
461 }
462 if (rc == 0)
463 mBufferCount = count;
464 return OK;
465 }
466
467 /*===========================================================================
468 * FUNCTION : deallocate
469 *
470 * DESCRIPTION: deallocate buffers
471 *
472 * PARAMETERS : none
473 *
474 * RETURN : none
475 *==========================================================================*/
deallocate()476 void QCameraHeapMemory::deallocate()
477 {
478 for (int i = 0; i < mBufferCount; i++) {
479 munmap(mPtr[i], mMemInfo[i].size);
480 mPtr[i] = NULL;
481 }
482 dealloc();
483 mBufferCount = 0;
484 }
485
486 /*===========================================================================
487 * FUNCTION : cacheOps
488 *
489 * DESCRIPTION: ion related memory cache operations
490 *
491 * PARAMETERS :
492 * @index : index of the buffer
493 * @cmd : cache ops command
494 *
495 * RETURN : int32_t type of status
496 * NO_ERROR -- success
497 * none-zero failure code
498 *==========================================================================*/
cacheOps(int index,unsigned int cmd)499 int QCameraHeapMemory::cacheOps(int index, unsigned int cmd)
500 {
501 if (index >= mBufferCount)
502 return BAD_INDEX;
503 return cacheOpsInternal(index, cmd, mPtr[index]);
504 }
505
506 /*===========================================================================
507 * FUNCTION : getRegFlags
508 *
509 * DESCRIPTION: query initial reg flags
510 *
511 * PARAMETERS :
512 * @regFlags: initial reg flags of the allocated buffers
513 *
514 * RETURN : int32_t type of status
515 * NO_ERROR -- success
516 * none-zero failure code
517 *==========================================================================*/
getRegFlags(uint8_t *) const518 int QCameraHeapMemory::getRegFlags(uint8_t * /*regFlags*/) const
519 {
520 return INVALID_OPERATION;
521 }
522
523 /*===========================================================================
524 * FUNCTION : getMemory
525 *
526 * DESCRIPTION: get camera memory
527 *
528 * PARAMETERS :
529 * @index : buffer index
530 * @metadata: flag if it's metadata
531 *
532 * RETURN : camera memory ptr
533 * NULL if not supported or failed
534 *==========================================================================*/
getMemory(int,bool) const535 camera_memory_t *QCameraHeapMemory::getMemory(
536 int /*index*/, bool /*metadata*/) const
537 {
538 return NULL;
539 }
540
541 /*===========================================================================
542 * FUNCTION : getMatchBufIndex
543 *
544 * DESCRIPTION: query buffer index by opaque ptr
545 *
546 * PARAMETERS :
547 * @opaque : opaque ptr
548 * @metadata: flag if it's metadata
549 *
550 * RETURN : buffer index if match found,
551 * -1 if failed
552 *==========================================================================*/
getMatchBufIndex(const void * opaque,bool metadata) const553 int QCameraHeapMemory::getMatchBufIndex(const void *opaque,
554 bool metadata) const
555 {
556 int index = -1;
557 if (metadata) {
558 return -1;
559 }
560 for (int i = 0; i < mBufferCount; i++) {
561 if (mPtr[i] == opaque) {
562 index = i;
563 break;
564 }
565 }
566 return index;
567 }
568
569 /*===========================================================================
570 * FUNCTION : QCameraStreamMemory
571 *
572 * DESCRIPTION: constructor of QCameraStreamMemory
573 * ION memory allocated directly from /dev/ion and shared with framework
574 *
575 * PARAMETERS :
576 * @getMemory : camera memory request ops table
577 * @cached : flag indicates if using cached memory
578 *
579 * RETURN : none
580 *==========================================================================*/
QCameraStreamMemory(camera_request_memory getMemory,bool cached)581 QCameraStreamMemory::QCameraStreamMemory(camera_request_memory getMemory,
582 bool cached)
583 :QCameraMemory(cached),
584 mGetMemory(getMemory)
585 {
586 for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
587 mCameraMemory[i] = NULL;
588 }
589
590 /*===========================================================================
591 * FUNCTION : ~QCameraStreamMemory
592 *
593 * DESCRIPTION: deconstructor of QCameraStreamMemory
594 *
595 * PARAMETERS : none
596 *
597 * RETURN : none
598 *==========================================================================*/
~QCameraStreamMemory()599 QCameraStreamMemory::~QCameraStreamMemory()
600 {
601 }
602
603 /*===========================================================================
604 * FUNCTION : allocate
605 *
606 * DESCRIPTION: allocate requested number of buffers of certain size
607 *
608 * PARAMETERS :
609 * @count : number of buffers to be allocated
610 * @size : lenght of the buffer to be allocated
611 *
612 * RETURN : int32_t type of status
613 * NO_ERROR -- success
614 * none-zero failure code
615 *==========================================================================*/
allocate(int count,int size)616 int QCameraStreamMemory::allocate(int count, int size)
617 {
618 int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
619 int rc = alloc(count, size, heap_mask);
620 if (rc < 0)
621 return rc;
622
623 for (int i = 0; i < count; i ++) {
624 mCameraMemory[i] = mGetMemory(mMemInfo[i].fd, mMemInfo[i].size, 1, this);
625 }
626 mBufferCount = count;
627 return NO_ERROR;
628 }
629
630 /*===========================================================================
631 * FUNCTION : deallocate
632 *
633 * DESCRIPTION: deallocate buffers
634 *
635 * PARAMETERS : none
636 *
637 * RETURN : none
638 *==========================================================================*/
deallocate()639 void QCameraStreamMemory::deallocate()
640 {
641 for (int i = 0; i < mBufferCount; i ++) {
642 mCameraMemory[i]->release(mCameraMemory[i]);
643 mCameraMemory[i] = NULL;
644 }
645 dealloc();
646 mBufferCount = 0;
647 }
648
649 /*===========================================================================
650 * FUNCTION : cacheOps
651 *
652 * DESCRIPTION: ion related memory cache operations
653 *
654 * PARAMETERS :
655 * @index : index of the buffer
656 * @cmd : cache ops command
657 *
658 * RETURN : int32_t type of status
659 * NO_ERROR -- success
660 * none-zero failure code
661 *==========================================================================*/
cacheOps(int index,unsigned int cmd)662 int QCameraStreamMemory::cacheOps(int index, unsigned int cmd)
663 {
664 if (index >= mBufferCount)
665 return BAD_INDEX;
666 return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
667 }
668
669 /*===========================================================================
670 * FUNCTION : getRegFlags
671 *
672 * DESCRIPTION: query initial reg flags
673 *
674 * PARAMETERS :
675 * @regFlags: initial reg flags of the allocated buffers
676 *
677 * RETURN : int32_t type of status
678 * NO_ERROR -- success
679 * none-zero failure code
680 *==========================================================================*/
getRegFlags(uint8_t * regFlags) const681 int QCameraStreamMemory::getRegFlags(uint8_t *regFlags) const
682 {
683 for (int i = 0; i < mBufferCount; i ++)
684 regFlags[i] = 1;
685 return NO_ERROR;
686 }
687
688 /*===========================================================================
689 * FUNCTION : getMemory
690 *
691 * DESCRIPTION: get camera memory
692 *
693 * PARAMETERS :
694 * @index : buffer index
695 * @metadata: flag if it's metadata
696 *
697 * RETURN : camera memory ptr
698 * NULL if not supported or failed
699 *==========================================================================*/
getMemory(int index,bool metadata) const700 camera_memory_t *QCameraStreamMemory::getMemory(int index, bool metadata) const
701 {
702 if (index >= mBufferCount || metadata)
703 return NULL;
704 return mCameraMemory[index];
705 }
706
707 /*===========================================================================
708 * FUNCTION : getMatchBufIndex
709 *
710 * DESCRIPTION: query buffer index by opaque ptr
711 *
712 * PARAMETERS :
713 * @opaque : opaque ptr
714 * @metadata: flag if it's metadata
715 *
716 * RETURN : buffer index if match found,
717 * -1 if failed
718 *==========================================================================*/
getMatchBufIndex(const void * opaque,bool metadata) const719 int QCameraStreamMemory::getMatchBufIndex(const void *opaque,
720 bool metadata) const
721 {
722 int index = -1;
723 if (metadata) {
724 return -1;
725 }
726 for (int i = 0; i < mBufferCount; i++) {
727 if (mCameraMemory[i]->data == opaque) {
728 index = i;
729 break;
730 }
731 }
732 return index;
733 }
734
735 /*===========================================================================
736 * FUNCTION : getPtr
737 *
738 * DESCRIPTION: return buffer pointer
739 *
740 * PARAMETERS :
741 * @index : index of the buffer
742 *
743 * RETURN : buffer ptr
744 *==========================================================================*/
getPtr(int index) const745 void *QCameraStreamMemory::getPtr(int index) const
746 {
747 if (index >= mBufferCount) {
748 ALOGE("index out of bound");
749 return (void *)BAD_INDEX;
750 }
751 return mCameraMemory[index]->data;
752 }
753
754 /*===========================================================================
755 * FUNCTION : QCameraVideoMemory
756 *
757 * DESCRIPTION: constructor of QCameraVideoMemory
758 * VideoStream buffers also include metadata buffers
759 *
760 * PARAMETERS :
761 * @getMemory : camera memory request ops table
762 * @cached : flag indicates if using cached ION memory
763 *
764 * RETURN : none
765 *==========================================================================*/
QCameraVideoMemory(camera_request_memory getMemory,bool cached)766 QCameraVideoMemory::QCameraVideoMemory(camera_request_memory getMemory,
767 bool cached)
768 : QCameraStreamMemory(getMemory, cached)
769 {
770 memset(mMetadata, 0, sizeof(mMetadata));
771 }
772
773 /*===========================================================================
774 * FUNCTION : ~QCameraVideoMemory
775 *
776 * DESCRIPTION: deconstructor of QCameraVideoMemory
777 *
778 * PARAMETERS : none
779 *
780 * RETURN : none
781 *==========================================================================*/
~QCameraVideoMemory()782 QCameraVideoMemory::~QCameraVideoMemory()
783 {
784 }
785
786 /*===========================================================================
787 * FUNCTION : allocate
788 *
789 * DESCRIPTION: allocate requested number of buffers of certain size
790 *
791 * PARAMETERS :
792 * @count : number of buffers to be allocated
793 * @size : lenght of the buffer to be allocated
794 *
795 * RETURN : int32_t type of status
796 * NO_ERROR -- success
797 * none-zero failure code
798 *==========================================================================*/
allocate(int count,int size)799 int QCameraVideoMemory::allocate(int count, int size)
800 {
801 int rc = QCameraStreamMemory::allocate(count, size);
802 if (rc < 0)
803 return rc;
804
805 for (int i = 0; i < count; i ++) {
806 mMetadata[i] = mGetMemory(-1,
807 sizeof(struct encoder_media_buffer_type), 1, this);
808 if (!mMetadata[i]) {
809 ALOGE("allocation of video metadata failed.");
810 for (int j = 0; j < i-1; j ++)
811 mMetadata[j]->release(mMetadata[j]);
812 QCameraStreamMemory::deallocate();
813 return NO_MEMORY;
814 }
815 struct encoder_media_buffer_type * packet =
816 (struct encoder_media_buffer_type *)mMetadata[i]->data;
817 packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size
818 packet->buffer_type = kMetadataBufferTypeCameraSource;
819 native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle);
820 nh->data[0] = mMemInfo[i].fd;
821 nh->data[1] = 0;
822 nh->data[2] = mMemInfo[i].size;
823 }
824 mBufferCount = count;
825 return NO_ERROR;
826 }
827
828 /*===========================================================================
829 * FUNCTION : deallocate
830 *
831 * DESCRIPTION: deallocate buffers
832 *
833 * PARAMETERS : none
834 *
835 * RETURN : none
836 *==========================================================================*/
deallocate()837 void QCameraVideoMemory::deallocate()
838 {
839 for (int i = 0; i < mBufferCount; i ++) {
840 mMetadata[i]->release(mMetadata[i]);
841 mMetadata[i] = NULL;
842 }
843 QCameraStreamMemory::deallocate();
844 mBufferCount = 0;
845 }
846
847 /*===========================================================================
848 * FUNCTION : getMemory
849 *
850 * DESCRIPTION: get camera memory
851 *
852 * PARAMETERS :
853 * @index : buffer index
854 * @metadata: flag if it's metadata
855 *
856 * RETURN : camera memory ptr
857 * NULL if not supported or failed
858 *==========================================================================*/
getMemory(int index,bool metadata) const859 camera_memory_t *QCameraVideoMemory::getMemory(int index, bool metadata) const
860 {
861 if (index >= mBufferCount)
862 return NULL;
863 if (metadata)
864 return mMetadata[index];
865 else
866 return mCameraMemory[index];
867 }
868
869 /*===========================================================================
870 * FUNCTION : getMatchBufIndex
871 *
872 * DESCRIPTION: query buffer index by opaque ptr
873 *
874 * PARAMETERS :
875 * @opaque : opaque ptr
876 * @metadata: flag if it's metadata
877 *
878 * RETURN : buffer index if match found,
879 * -1 if failed
880 *==========================================================================*/
getMatchBufIndex(const void * opaque,bool metadata) const881 int QCameraVideoMemory::getMatchBufIndex(const void *opaque,
882 bool metadata) const
883 {
884 int index = -1;
885 for (int i = 0; i < mBufferCount; i++) {
886 if (metadata) {
887 if (mMetadata[i]->data == opaque) {
888 index = i;
889 break;
890 }
891 } else {
892 if (mCameraMemory[i]->data == opaque) {
893 index = i;
894 break;
895 }
896 }
897 }
898 return index;
899 }
900
901 /*===========================================================================
902 * FUNCTION : QCameraGrallocMemory
903 *
904 * DESCRIPTION: constructor of QCameraGrallocMemory
905 * preview stream buffers are allocated from gralloc native_windoe
906 *
907 * PARAMETERS :
908 * @getMemory : camera memory request ops table
909 *
910 * RETURN : none
911 *==========================================================================*/
QCameraGrallocMemory(camera_request_memory getMemory)912 QCameraGrallocMemory::QCameraGrallocMemory(camera_request_memory getMemory)
913 : QCameraMemory(true)
914 {
915 mMinUndequeuedBuffers = 0;
916 mWindow = NULL;
917 mWidth = mHeight = 0;
918 mFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
919 mGetMemory = getMemory;
920 for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++) {
921 mBufferHandle[i] = NULL;
922 mLocalFlag[i] = BUFFER_NOT_OWNED;
923 mPrivateHandle[i] = NULL;
924 }
925 }
926
927 /*===========================================================================
928 * FUNCTION : ~QCameraGrallocMemory
929 *
930 * DESCRIPTION: deconstructor of QCameraGrallocMemory
931 *
932 * PARAMETERS : none
933 *
934 * RETURN : none
935 *==========================================================================*/
~QCameraGrallocMemory()936 QCameraGrallocMemory::~QCameraGrallocMemory()
937 {
938 }
939
940 /*===========================================================================
941 * FUNCTION : setWindowInfo
942 *
943 * DESCRIPTION: set native window gralloc ops table
944 *
945 * PARAMETERS :
946 * @window : gralloc ops table ptr
947 * @width : width of preview frame
948 * @height : height of preview frame
949 * @foramt : format of preview image
950 *
951 * RETURN : none
952 *==========================================================================*/
setWindowInfo(preview_stream_ops_t * window,int width,int height,int format)953 void QCameraGrallocMemory::setWindowInfo(preview_stream_ops_t *window,
954 int width, int height, int format)
955 {
956 mWindow = window;
957 mWidth = width;
958 mHeight = height;
959 mFormat = format;
960 }
961
962 /*===========================================================================
963 * FUNCTION : displayBuffer
964 *
965 * DESCRIPTION: send received frame to display
966 *
967 * PARAMETERS :
968 * @index : index of preview frame
969 *
970 * RETURN : int32_t type of status
971 * NO_ERROR -- success
972 * none-zero failure code
973 *==========================================================================*/
displayBuffer(int index)974 int QCameraGrallocMemory::displayBuffer(int index)
975 {
976 int err = NO_ERROR;
977 int dequeuedIdx = BAD_INDEX;
978
979 if (BUFFER_NOT_OWNED == mLocalFlag[index]) {
980 ALOGE("%s: buffer to be enqueued is not owned", __func__);
981 return INVALID_OPERATION;
982 }
983
984 err = mWindow->enqueue_buffer(mWindow, (buffer_handle_t *)mBufferHandle[index]);
985 if(err != 0) {
986 ALOGE("%s: enqueue_buffer failed, err = %d", __func__, err);
987 } else {
988 ALOGV("%s: enqueue_buffer hdl=%p", __func__, *mBufferHandle[index]);
989 mLocalFlag[index] = BUFFER_NOT_OWNED;
990 }
991
992 buffer_handle_t *buffer_handle = NULL;
993 int stride = 0;
994 err = mWindow->dequeue_buffer(mWindow, &buffer_handle, &stride);
995 if (err == NO_ERROR && buffer_handle != NULL) {
996 int i;
997 ALOGV("%s: dequed buf hdl =%p", __func__, *buffer_handle);
998 for(i = 0; i < mBufferCount; i++) {
999 if(mBufferHandle[i] == buffer_handle) {
1000 ALOGV("%s: Found buffer in idx:%d", __func__, i);
1001 mLocalFlag[i] = BUFFER_OWNED;
1002 dequeuedIdx = i;
1003 break;
1004 }
1005 }
1006 } else {
1007 ALOGD("%s: dequeue_buffer, no free buffer from display now", __func__);
1008 }
1009 return dequeuedIdx;
1010 }
1011
1012 /*===========================================================================
1013 * FUNCTION : allocate
1014 *
1015 * DESCRIPTION: allocate requested number of buffers of certain size
1016 *
1017 * PARAMETERS :
1018 * @count : number of buffers to be allocated
1019 * @size : lenght of the buffer to be allocated
1020 *
1021 * RETURN : int32_t type of status
1022 * NO_ERROR -- success
1023 * none-zero failure code
1024 *==========================================================================*/
allocate(int count,int)1025 int QCameraGrallocMemory::allocate(int count, int /*size*/)
1026 {
1027 int err = 0;
1028 status_t ret = NO_ERROR;
1029 int gralloc_usage = 0;
1030 struct ion_fd_data ion_info_fd;
1031 memset(&ion_info_fd, 0, sizeof(ion_info_fd));
1032
1033 ALOGI(" %s : E ", __FUNCTION__);
1034
1035 if (!mWindow) {
1036 ALOGE("Invalid native window");
1037 return INVALID_OPERATION;
1038 }
1039
1040 // Increment buffer count by min undequeued buffer.
1041 err = mWindow->get_min_undequeued_buffer_count(mWindow,&mMinUndequeuedBuffers);
1042 if (err != 0) {
1043 ALOGE("get_min_undequeued_buffer_count failed: %s (%d)",
1044 strerror(-err), -err);
1045 ret = UNKNOWN_ERROR;
1046 goto end;
1047 }
1048 count += mMinUndequeuedBuffers;
1049
1050 err = mWindow->set_buffer_count(mWindow, count);
1051 if (err != 0) {
1052 ALOGE("set_buffer_count failed: %s (%d)",
1053 strerror(-err), -err);
1054 ret = UNKNOWN_ERROR;
1055 goto end;
1056 }
1057
1058 err = mWindow->set_buffers_geometry(mWindow, mWidth, mHeight, mFormat);
1059 if (err != 0) {
1060 ALOGE("%s: set_buffers_geometry failed: %s (%d)",
1061 __func__, strerror(-err), -err);
1062 ret = UNKNOWN_ERROR;
1063 goto end;
1064 }
1065
1066 gralloc_usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
1067 err = mWindow->set_usage(mWindow, gralloc_usage);
1068 if(err != 0) {
1069 /* set_usage error out */
1070 ALOGE("%s: set_usage rc = %d", __func__, err);
1071 ret = UNKNOWN_ERROR;
1072 goto end;
1073 }
1074 ALOGD("%s: usage = %d, geometry: %p, %d, %d, %d",
1075 __func__, gralloc_usage, mWindow, mWidth, mHeight, mFormat);
1076
1077 //Allocate cnt number of buffers from native window
1078 for (int cnt = 0; cnt < count; cnt++) {
1079 int stride;
1080 err = mWindow->dequeue_buffer(mWindow, &mBufferHandle[cnt], &stride);
1081 if(!err) {
1082 ALOGV("dequeue buf hdl =%p", mBufferHandle[cnt]);
1083 mLocalFlag[cnt] = BUFFER_OWNED;
1084 } else {
1085 mLocalFlag[cnt] = BUFFER_NOT_OWNED;
1086 ALOGE("%s: dequeue_buffer idx = %d err = %d", __func__, cnt, err);
1087 }
1088
1089 ALOGV("%s: dequeue buf: %p\n", __func__, mBufferHandle[cnt]);
1090
1091 if(err != 0) {
1092 ALOGE("%s: dequeue_buffer failed: %s (%d)",
1093 __func__, strerror(-err), -err);
1094 ret = UNKNOWN_ERROR;
1095 for(int i = 0; i < cnt; i++) {
1096 if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
1097 err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1098 ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
1099 }
1100 mLocalFlag[i] = BUFFER_NOT_OWNED;
1101 mBufferHandle[i] = NULL;
1102 }
1103 memset(&mMemInfo, 0, sizeof(mMemInfo));
1104 goto end;
1105 }
1106
1107 mPrivateHandle[cnt] =
1108 (struct private_handle_t *)(*mBufferHandle[cnt]);
1109 mMemInfo[cnt].main_ion_fd = open("/dev/ion", O_RDONLY);
1110 if (mMemInfo[cnt].main_ion_fd < 0) {
1111 ALOGE("%s: failed: could not open ion device", __func__);
1112 for(int i = 0; i < cnt; i++) {
1113 struct ion_handle_data ion_handle;
1114 memset(&ion_handle, 0, sizeof(ion_handle));
1115 ion_handle.handle = mMemInfo[i].handle;
1116 if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
1117 ALOGE("%s: ion free failed", __func__);
1118 }
1119 close(mMemInfo[i].main_ion_fd);
1120 if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
1121 err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1122 ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
1123 }
1124 mLocalFlag[i] = BUFFER_NOT_OWNED;
1125 mBufferHandle[i] = NULL;
1126 }
1127 memset(&mMemInfo, 0, sizeof(mMemInfo));
1128 ret = UNKNOWN_ERROR;
1129 goto end;
1130 } else {
1131 ion_info_fd.fd = mPrivateHandle[cnt]->fd;
1132 if (ioctl(mMemInfo[cnt].main_ion_fd,
1133 ION_IOC_IMPORT, &ion_info_fd) < 0) {
1134 ALOGE("%s: ION import failed\n", __func__);
1135 for(int i = 0; i < cnt; i++) {
1136 struct ion_handle_data ion_handle;
1137 memset(&ion_handle, 0, sizeof(ion_handle));
1138 ion_handle.handle = mMemInfo[i].handle;
1139 if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
1140 ALOGE("ion free failed");
1141 }
1142 close(mMemInfo[i].main_ion_fd);
1143
1144 if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
1145 err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1146 ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
1147 }
1148 mLocalFlag[i] = BUFFER_NOT_OWNED;
1149 mBufferHandle[i] = NULL;
1150 }
1151 close(mMemInfo[cnt].main_ion_fd);
1152 memset(&mMemInfo, 0, sizeof(mMemInfo));
1153 ret = UNKNOWN_ERROR;
1154 goto end;
1155 }
1156 }
1157 mCameraMemory[cnt] =
1158 mGetMemory(mPrivateHandle[cnt]->fd,
1159 mPrivateHandle[cnt]->size,
1160 1,
1161 (void *)this);
1162 ALOGD("%s: idx = %d, fd = %d, size = %d, offset = %d",
1163 __func__, cnt, mPrivateHandle[cnt]->fd,
1164 mPrivateHandle[cnt]->size,
1165 mPrivateHandle[cnt]->offset);
1166 mMemInfo[cnt].fd =
1167 mPrivateHandle[cnt]->fd;
1168 mMemInfo[cnt].size =
1169 mPrivateHandle[cnt]->size;
1170 mMemInfo[cnt].handle = ion_info_fd.handle;
1171 }
1172 mBufferCount = count;
1173
1174 //Cancel min_undequeued_buffer buffers back to the window
1175 for (int i = 0; i < mMinUndequeuedBuffers; i ++) {
1176 err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1177 mLocalFlag[i] = BUFFER_NOT_OWNED;
1178 }
1179
1180 end:
1181 ALOGI(" %s : X ",__func__);
1182 return ret;
1183 }
1184
1185 /*===========================================================================
1186 * FUNCTION : deallocate
1187 *
1188 * DESCRIPTION: deallocate buffers
1189 *
1190 * PARAMETERS : none
1191 *
1192 * RETURN : none
1193 *==========================================================================*/
deallocate()1194 void QCameraGrallocMemory::deallocate()
1195 {
1196 ALOGI("%s: E ", __FUNCTION__);
1197
1198 for (int cnt = 0; cnt < mBufferCount; cnt++) {
1199 mCameraMemory[cnt]->release(mCameraMemory[cnt]);
1200 struct ion_handle_data ion_handle;
1201 memset(&ion_handle, 0, sizeof(ion_handle));
1202 ion_handle.handle = mMemInfo[cnt].handle;
1203 if (ioctl(mMemInfo[cnt].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
1204 ALOGE("ion free failed");
1205 }
1206 close(mMemInfo[cnt].main_ion_fd);
1207 if(mLocalFlag[cnt] != BUFFER_NOT_OWNED) {
1208 if (mWindow) {
1209 mWindow->cancel_buffer(mWindow, mBufferHandle[cnt]);
1210 ALOGD("cancel_buffer: hdl =%p", (*mBufferHandle[cnt]));
1211 } else {
1212 ALOGE("Preview window is NULL, cannot cancel_buffer: hdl =%p",
1213 (*mBufferHandle[cnt]));
1214 }
1215 }
1216 mLocalFlag[cnt] = BUFFER_NOT_OWNED;
1217 ALOGD("put buffer %d successfully", cnt);
1218 }
1219 mBufferCount = 0;
1220 ALOGI(" %s : X ",__FUNCTION__);
1221 }
1222
1223 /*===========================================================================
1224 * FUNCTION : cacheOps
1225 *
1226 * DESCRIPTION: ion related memory cache operations
1227 *
1228 * PARAMETERS :
1229 * @index : index of the buffer
1230 * @cmd : cache ops command
1231 *
1232 * RETURN : int32_t type of status
1233 * NO_ERROR -- success
1234 * none-zero failure code
1235 *==========================================================================*/
cacheOps(int index,unsigned int cmd)1236 int QCameraGrallocMemory::cacheOps(int index, unsigned int cmd)
1237 {
1238 if (index >= mBufferCount)
1239 return BAD_INDEX;
1240 return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
1241 }
1242
1243 /*===========================================================================
1244 * FUNCTION : getRegFlags
1245 *
1246 * DESCRIPTION: query initial reg flags
1247 *
1248 * PARAMETERS :
1249 * @regFlags: initial reg flags of the allocated buffers
1250 *
1251 * RETURN : int32_t type of status
1252 * NO_ERROR -- success
1253 * none-zero failure code
1254 *==========================================================================*/
getRegFlags(uint8_t * regFlags) const1255 int QCameraGrallocMemory::getRegFlags(uint8_t *regFlags) const
1256 {
1257 int i = 0;
1258 for (i = 0; i < mMinUndequeuedBuffers; i ++)
1259 regFlags[i] = 0;
1260 for (; i < mBufferCount; i ++)
1261 regFlags[i] = 1;
1262 return NO_ERROR;
1263 }
1264
1265 /*===========================================================================
1266 * FUNCTION : getMemory
1267 *
1268 * DESCRIPTION: get camera memory
1269 *
1270 * PARAMETERS :
1271 * @index : buffer index
1272 * @metadata: flag if it's metadata
1273 *
1274 * RETURN : camera memory ptr
1275 * NULL if not supported or failed
1276 *==========================================================================*/
getMemory(int index,bool metadata) const1277 camera_memory_t *QCameraGrallocMemory::getMemory(int index, bool metadata) const
1278 {
1279 if (index >= mBufferCount || metadata)
1280 return NULL;
1281 return mCameraMemory[index];
1282 }
1283
1284 /*===========================================================================
1285 * FUNCTION : getMatchBufIndex
1286 *
1287 * DESCRIPTION: query buffer index by opaque ptr
1288 *
1289 * PARAMETERS :
1290 * @opaque : opaque ptr
1291 * @metadata: flag if it's metadata
1292 *
1293 * RETURN : buffer index if match found,
1294 * -1 if failed
1295 *==========================================================================*/
getMatchBufIndex(const void * opaque,bool metadata) const1296 int QCameraGrallocMemory::getMatchBufIndex(const void *opaque,
1297 bool metadata) const
1298 {
1299 int index = -1;
1300 if (metadata) {
1301 return -1;
1302 }
1303 for (int i = 0; i < mBufferCount; i++) {
1304 if (mCameraMemory[i]->data == opaque) {
1305 index = i;
1306 break;
1307 }
1308 }
1309 return index;
1310 }
1311
1312 /*===========================================================================
1313 * FUNCTION : getPtr
1314 *
1315 * DESCRIPTION: return buffer pointer
1316 *
1317 * PARAMETERS :
1318 * @index : index of the buffer
1319 *
1320 * RETURN : buffer ptr
1321 *==========================================================================*/
getPtr(int index) const1322 void *QCameraGrallocMemory::getPtr(int index) const
1323 {
1324 if (index >= mBufferCount) {
1325 ALOGE("index out of bound");
1326 return (void *)BAD_INDEX;
1327 }
1328 return mCameraMemory[index]->data;
1329 }
1330
1331 }; //namespace qcamera
1332