QCameraMem.cpp revision 6f83d735d8e3b918da42e6b559fcd0efb78133e5
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 : 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_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_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::deallocate();
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 = 0;
1014    struct ion_fd_data ion_info_fd;
1015    memset(&ion_info_fd, 0, sizeof(ion_info_fd));
1016
1017    ALOGI(" %s : E ", __FUNCTION__);
1018
1019    if (!mWindow) {
1020        ALOGE("Invalid native window");
1021        return INVALID_OPERATION;
1022    }
1023
1024    // Increment buffer count by min undequeued buffer.
1025    err = mWindow->get_min_undequeued_buffer_count(mWindow,&mMinUndequeuedBuffers);
1026    if (err != 0) {
1027        ALOGE("get_min_undequeued_buffer_count  failed: %s (%d)",
1028                strerror(-err), -err);
1029        ret = UNKNOWN_ERROR;
1030        goto end;
1031    }
1032    count += mMinUndequeuedBuffers;
1033
1034    err = mWindow->set_buffer_count(mWindow, count);
1035    if (err != 0) {
1036         ALOGE("set_buffer_count failed: %s (%d)",
1037                    strerror(-err), -err);
1038         ret = UNKNOWN_ERROR;
1039         goto end;
1040    }
1041
1042    err = mWindow->set_buffers_geometry(mWindow, mWidth, mHeight, mFormat);
1043    if (err != 0) {
1044         ALOGE("%s: set_buffers_geometry failed: %s (%d)",
1045               __func__, strerror(-err), -err);
1046         ret = UNKNOWN_ERROR;
1047         goto end;
1048    }
1049
1050    gralloc_usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
1051    err = mWindow->set_usage(mWindow, gralloc_usage);
1052    if(err != 0) {
1053        /* set_usage error out */
1054        ALOGE("%s: set_usage rc = %d", __func__, err);
1055        ret = UNKNOWN_ERROR;
1056        goto end;
1057    }
1058    ALOGD("%s: usage = %d, geometry: %p, %d, %d, %d",
1059          __func__, gralloc_usage, mWindow, mWidth, mHeight, mFormat);
1060
1061    //Allocate cnt number of buffers from native window
1062    for (int cnt = 0; cnt < count; cnt++) {
1063        int stride;
1064        err = mWindow->dequeue_buffer(mWindow, &mBufferHandle[cnt], &stride);
1065        if(!err) {
1066            ALOGV("dequeue buf hdl =%p", mBufferHandle[cnt]);
1067            mLocalFlag[cnt] = BUFFER_OWNED;
1068        } else {
1069            mLocalFlag[cnt] = BUFFER_NOT_OWNED;
1070            ALOGE("%s: dequeue_buffer idx = %d err = %d", __func__, cnt, err);
1071        }
1072
1073        ALOGV("%s: dequeue buf: %p\n", __func__, mBufferHandle[cnt]);
1074
1075        if(err != 0) {
1076            ALOGE("%s: dequeue_buffer failed: %s (%d)",
1077                  __func__, strerror(-err), -err);
1078            ret = UNKNOWN_ERROR;
1079            for(int i = 0; i < cnt; i++) {
1080                if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
1081                    err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1082                    ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
1083                }
1084                mLocalFlag[i] = BUFFER_NOT_OWNED;
1085                mBufferHandle[i] = NULL;
1086            }
1087            memset(&mMemInfo, 0, sizeof(mMemInfo));
1088            goto end;
1089        }
1090
1091        mPrivateHandle[cnt] =
1092            (struct private_handle_t *)(*mBufferHandle[cnt]);
1093        mMemInfo[cnt].main_ion_fd = open("/dev/ion", O_RDONLY);
1094        if (mMemInfo[cnt].main_ion_fd <= 0) {
1095            ALOGE("%s: failed: could not open ion device", __func__);
1096            for(int i = 0; i < cnt; i++) {
1097                struct ion_handle_data ion_handle;
1098                memset(&ion_handle, 0, sizeof(ion_handle));
1099                ion_handle.handle = mMemInfo[i].handle;
1100                if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
1101                    ALOGE("%s: ion free failed", __func__);
1102                }
1103                close(mMemInfo[i].main_ion_fd);
1104                if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
1105                    err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1106                    ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
1107                }
1108                mLocalFlag[i] = BUFFER_NOT_OWNED;
1109                mBufferHandle[i] = NULL;
1110            }
1111            memset(&mMemInfo, 0, sizeof(mMemInfo));
1112            ret = UNKNOWN_ERROR;
1113            goto end;
1114        } else {
1115            ion_info_fd.fd = mPrivateHandle[cnt]->fd;
1116            if (ioctl(mMemInfo[cnt].main_ion_fd,
1117                      ION_IOC_IMPORT, &ion_info_fd) < 0) {
1118                ALOGE("%s: ION import failed\n", __func__);
1119                for(int i = 0; i < cnt; i++) {
1120                    struct ion_handle_data ion_handle;
1121                    memset(&ion_handle, 0, sizeof(ion_handle));
1122                    ion_handle.handle = mMemInfo[i].handle;
1123                    if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
1124                        ALOGE("ion free failed");
1125                    }
1126                    close(mMemInfo[i].main_ion_fd);
1127
1128                    if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
1129                        err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1130                        ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
1131                    }
1132                    mLocalFlag[i] = BUFFER_NOT_OWNED;
1133                    mBufferHandle[i] = NULL;
1134                }
1135                close(mMemInfo[cnt].main_ion_fd);
1136                memset(&mMemInfo, 0, sizeof(mMemInfo));
1137                ret = UNKNOWN_ERROR;
1138                goto end;
1139            }
1140        }
1141        mCameraMemory[cnt] =
1142            mGetMemory(mPrivateHandle[cnt]->fd,
1143                    mPrivateHandle[cnt]->size,
1144                    1,
1145                    (void *)this);
1146        ALOGD("%s: idx = %d, fd = %d, size = %d, offset = %d",
1147              __func__, cnt, mPrivateHandle[cnt]->fd,
1148              mPrivateHandle[cnt]->size,
1149              mPrivateHandle[cnt]->offset);
1150        mMemInfo[cnt].fd =
1151            mPrivateHandle[cnt]->fd;
1152        mMemInfo[cnt].size =
1153            mPrivateHandle[cnt]->size;
1154        mMemInfo[cnt].handle = ion_info_fd.handle;
1155    }
1156    mBufferCount = count;
1157
1158    //Cancel min_undequeued_buffer buffers back to the window
1159    for (int i = 0; i < mMinUndequeuedBuffers; i ++) {
1160        err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
1161        mLocalFlag[i] = BUFFER_NOT_OWNED;
1162    }
1163
1164end:
1165    ALOGI(" %s : X ",__func__);
1166    return ret;
1167}
1168
1169/*===========================================================================
1170 * FUNCTION   : deallocate
1171 *
1172 * DESCRIPTION: deallocate buffers
1173 *
1174 * PARAMETERS : none
1175 *
1176 * RETURN     : none
1177 *==========================================================================*/
1178void QCameraGrallocMemory::deallocate()
1179{
1180    ALOGI("%s: E ", __FUNCTION__);
1181
1182    for (int cnt = 0; cnt < mBufferCount; cnt++) {
1183        mCameraMemory[cnt]->release(mCameraMemory[cnt]);
1184        struct ion_handle_data ion_handle;
1185        memset(&ion_handle, 0, sizeof(ion_handle));
1186        ion_handle.handle = mMemInfo[cnt].handle;
1187        if (ioctl(mMemInfo[cnt].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
1188            ALOGE("ion free failed");
1189        }
1190        close(mMemInfo[cnt].main_ion_fd);
1191        if(mLocalFlag[cnt] != BUFFER_NOT_OWNED) {
1192            if (mWindow) {
1193                mWindow->cancel_buffer(mWindow, mBufferHandle[cnt]);
1194                ALOGD("cancel_buffer: hdl =%p", (*mBufferHandle[cnt]));
1195            } else {
1196                ALOGE("Preview window is NULL, cannot cancel_buffer: hdl =%p",
1197                      (*mBufferHandle[cnt]));
1198            }
1199        }
1200        mLocalFlag[cnt] = BUFFER_NOT_OWNED;
1201        ALOGD("put buffer %d successfully", cnt);
1202    }
1203    mBufferCount = 0;
1204    ALOGI(" %s : X ",__FUNCTION__);
1205}
1206
1207/*===========================================================================
1208 * FUNCTION   : cacheOps
1209 *
1210 * DESCRIPTION: ion related memory cache operations
1211 *
1212 * PARAMETERS :
1213 *   @index   : index of the buffer
1214 *   @cmd     : cache ops command
1215 *
1216 * RETURN     : int32_t type of status
1217 *              NO_ERROR  -- success
1218 *              none-zero failure code
1219 *==========================================================================*/
1220int QCameraGrallocMemory::cacheOps(int index, unsigned int cmd)
1221{
1222    if (index >= mBufferCount)
1223        return BAD_INDEX;
1224    return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
1225}
1226
1227/*===========================================================================
1228 * FUNCTION   : getRegFlags
1229 *
1230 * DESCRIPTION: query initial reg flags
1231 *
1232 * PARAMETERS :
1233 *   @regFlags: initial reg flags of the allocated buffers
1234 *
1235 * RETURN     : int32_t type of status
1236 *              NO_ERROR  -- success
1237 *              none-zero failure code
1238 *==========================================================================*/
1239int QCameraGrallocMemory::getRegFlags(uint8_t *regFlags) const
1240{
1241    int i = 0;
1242    for (i = 0; i < mMinUndequeuedBuffers; i ++)
1243        regFlags[i] = 0;
1244    for (; i < mBufferCount; i ++)
1245        regFlags[i] = 1;
1246    return NO_ERROR;
1247}
1248
1249/*===========================================================================
1250 * FUNCTION   : getMemory
1251 *
1252 * DESCRIPTION: get camera memory
1253 *
1254 * PARAMETERS :
1255 *   @index   : buffer index
1256 *   @metadata: flag if it's metadata
1257 *
1258 * RETURN     : camera memory ptr
1259 *              NULL if not supported or failed
1260 *==========================================================================*/
1261camera_memory_t *QCameraGrallocMemory::getMemory(int index, bool metadata) const
1262{
1263    if (index >= mBufferCount || metadata)
1264        return NULL;
1265    return mCameraMemory[index];
1266}
1267
1268/*===========================================================================
1269 * FUNCTION   : getMatchBufIndex
1270 *
1271 * DESCRIPTION: query buffer index by opaque ptr
1272 *
1273 * PARAMETERS :
1274 *   @opaque  : opaque ptr
1275 *   @metadata: flag if it's metadata
1276 *
1277 * RETURN     : buffer index if match found,
1278 *              -1 if failed
1279 *==========================================================================*/
1280int QCameraGrallocMemory::getMatchBufIndex(const void *opaque,
1281                                           bool metadata) const
1282{
1283    int index = -1;
1284    if (metadata) {
1285        return -1;
1286    }
1287    for (int i = 0; i < mBufferCount; i++) {
1288        if (mCameraMemory[i]->data == opaque) {
1289            index = i;
1290            break;
1291        }
1292    }
1293    return index;
1294}
1295
1296/*===========================================================================
1297 * FUNCTION   : getPtr
1298 *
1299 * DESCRIPTION: return buffer pointer
1300 *
1301 * PARAMETERS :
1302 *   @index   : index of the buffer
1303 *
1304 * RETURN     : buffer ptr
1305 *==========================================================================*/
1306void *QCameraGrallocMemory::getPtr(int index) const
1307{
1308    if (index >= mBufferCount) {
1309        ALOGE("index out of bound");
1310        return (void *)BAD_INDEX;
1311    }
1312    return mCameraMemory[index]->data;
1313}
1314
1315}; //namespace qcamera
1316