QCameraMem.cpp revision 744f5403bebb0e27140d16a5df7a341713c24a13
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
41extern "C" {
42#include <mm_camera_interface.h>
43}
44
45using namespace android;
46
47namespace 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 *==========================================================================*/
61QCameraMemory::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 *==========================================================================*/
82QCameraMemory::~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 *==========================================================================*/
100int 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 *==========================================================================*/
147int 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 *==========================================================================*/
165int 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 *==========================================================================*/
182int 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 *==========================================================================*/
199void 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 = mMemInfo[index].size;
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 *==========================================================================*/
242int 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 *==========================================================================*/
275void 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 *==========================================================================*/
295int 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
338ION_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);
342ION_ALLOC_FAILED:
343    close(main_ion_fd);
344ION_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 *==========================================================================*/
358void 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 *==========================================================================*/
388QCameraHeapMemory::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 *==========================================================================*/
404QCameraHeapMemory::~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 *==========================================================================*/
418void *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 *==========================================================================*/
440int 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 *==========================================================================*/
476void 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 *==========================================================================*/
499int 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 *==========================================================================*/
518int 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 *==========================================================================*/
535camera_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 *==========================================================================*/
553int 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 *==========================================================================*/
581QCameraStreamMemory::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 *==========================================================================*/
599QCameraStreamMemory::~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 *==========================================================================*/
616int 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 *==========================================================================*/
639void 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 *==========================================================================*/
662int 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 *==========================================================================*/
681int 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 *==========================================================================*/
700camera_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 *==========================================================================*/
719int 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 *==========================================================================*/
745void *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 *==========================================================================*/
766QCameraVideoMemory::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 *==========================================================================*/
782QCameraVideoMemory::~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 *==========================================================================*/
799int 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 *==========================================================================*/
837void 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 *==========================================================================*/
859camera_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 *==========================================================================*/
881int 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 *==========================================================================*/
912QCameraGrallocMemory::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 *==========================================================================*/
936QCameraGrallocMemory::~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 *==========================================================================*/
953void 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 *==========================================================================*/
974int 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 *==========================================================================*/
1025int 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
1180end:
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 *==========================================================================*/
1194void 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 *==========================================================================*/
1236int 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 *==========================================================================*/
1255int 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 *==========================================================================*/
1277camera_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 *==========================================================================*/
1296int 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 *==========================================================================*/
1322void *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