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