Home | History | Annotate | Download | only in camera
      1 /*
      2 ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
      3 **
      4 ** Licensed under the Apache License, Version 2.0 (the "License");
      5 ** you may not use this file except in compliance with the License.
      6 ** You may obtain a copy of the License at
      7 **
      8 **     http://www.apache.org/licenses/LICENSE-2.0
      9 **
     10 ** Unless required by applicable law or agreed to in writing, software
     11 ** distributed under the License is distributed on an "AS IS" BASIS,
     12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 ** See the License for the specific language governing permissions and
     14 ** limitations under the License.
     15 */
     16 
     17 /*#error uncomment this for compiler test!*/
     18 
     19 //#define ALOG_NDEBUG 0
     20 #define ALOG_NIDEBUG 0
     21 #define LOG_TAG "QCameraHWI_Mem"
     22 #include <utils/Log.h>
     23 
     24 #include <utils/Errors.h>
     25 #include <utils/threads.h>
     26 //#include <binder/MemoryHeapPmem.h>
     27 #include <utils/String16.h>
     28 #include <sys/types.h>
     29 #include <sys/stat.h>
     30 #include <unistd.h>
     31 #include <fcntl.h>
     32 #include <cutils/properties.h>
     33 #include <math.h>
     34 #if HAVE_ANDROID_OS
     35 #include <linux/android_pmem.h>
     36 #endif
     37 #include <linux/ioctl.h>
     38 #include "QCameraParameters.h"
     39 #include <media/mediarecorder.h>
     40 #include <gralloc_priv.h>
     41 
     42 #include "QCameraHWI_Mem.h"
     43 
     44 #define CAMERA_HAL_UNUSED(expr) do { (void)(expr); } while (0)
     45 
     46 /* QCameraHardwareInterface class implementation goes here*/
     47 /* following code implement the contol logic of this class*/
     48 
     49 namespace android {
     50 
     51 
     52 static bool register_buf(int size,
     53                          int frame_size,
     54                          int cbcr_offset,
     55                          int yoffset,
     56                          int pmempreviewfd,
     57                          uint32_t offset,
     58                          uint8_t *buf,
     59                          int pmem_type,
     60                          bool vfe_can_write,
     61                          bool register_buffer = true);
     62 
     63 #if 0
     64 MMCameraDL::MMCameraDL(){
     65     ALOGV("MMCameraDL: E");
     66     libmmcamera = NULL;
     67 #if DLOPEN_LIBMMCAMERA
     68     libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
     69 #endif
     70     ALOGV("Open MM camera DL libeomcamera loaded at %p ", libmmcamera);
     71     ALOGV("MMCameraDL: X");
     72 }
     73 
     74 void * MMCameraDL::pointer(){
     75     return libmmcamera;
     76 }
     77 
     78 MMCameraDL::~MMCameraDL(){
     79     ALOGV("~MMCameraDL: E");
     80     LINK_mm_camera_destroy();
     81     if (libmmcamera != NULL) {
     82         ::dlclose(libmmcamera);
     83         ALOGV("closed MM Camera DL ");
     84     }
     85     libmmcamera = NULL;
     86     ALOGV("~MMCameraDL: X");
     87 }
     88 
     89 
     90 wp<MMCameraDL> MMCameraDL::instance;
     91 Mutex MMCameraDL::singletonLock;
     92 
     93 
     94 sp<MMCameraDL> MMCameraDL::getInstance(){
     95     Mutex::Autolock instanceLock(singletonLock);
     96     sp<MMCameraDL> mmCamera = instance.promote();
     97     if(mmCamera == NULL){
     98         mmCamera = new MMCameraDL();
     99         instance = mmCamera;
    100     }
    101     return mmCamera;
    102 }
    103 #endif
    104 
    105 MemPool::MemPool(int buffer_size, int num_buffers,
    106                                          int frame_size,
    107                                          const char *name) :
    108     mBufferSize(buffer_size),
    109     mNumBuffers(num_buffers),
    110     mFrameSize(frame_size),
    111     mBuffers(NULL), mName(name)
    112 {
    113     int page_size_minus_1 = getpagesize() - 1;
    114     mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
    115 }
    116 
    117 void MemPool::completeInitialization()
    118 {
    119     // If we do not know how big the frame will be, we wait to allocate
    120     // the buffers describing the individual frames until we do know their
    121     // size.
    122 
    123     if (mFrameSize > 0) {
    124         mBuffers = new sp<MemoryBase>[mNumBuffers];
    125         for (int i = 0; i < mNumBuffers; i++) {
    126             mBuffers[i] = new
    127                 MemoryBase(mHeap,
    128                            i * mAlignedBufferSize,
    129                            mFrameSize);
    130         }
    131     }
    132 }
    133 
    134 AshmemPool::AshmemPool(int buffer_size, int num_buffers,
    135                                                int frame_size,
    136                                                const char *name) :
    137     MemPool(buffer_size,
    138                                     num_buffers,
    139                                     frame_size,
    140                                     name)
    141 {
    142     ALOGV("constructing MemPool %s backed by ashmem: "
    143          "%d frames @ %d uint8_ts, "
    144          "buffer size %d",
    145          mName,
    146          num_buffers, frame_size, buffer_size);
    147 
    148     int page_mask = getpagesize() - 1;
    149     int ashmem_size = buffer_size * num_buffers;
    150     ashmem_size += page_mask;
    151     ashmem_size &= ~page_mask;
    152 
    153     mHeap = new MemoryHeapBase(ashmem_size);
    154 
    155     completeInitialization();
    156 }
    157 
    158 static bool register_buf(int size,
    159                          int frame_size,
    160                          int cbcr_offset,
    161                          int yoffset,
    162                          int pmempreviewfd,
    163                          uint32_t offset,
    164                          uint8_t *buf,
    165                          int pmem_type,
    166                          bool vfe_can_write,
    167                          bool register_buffer)
    168 {
    169     /*TODO*/
    170     /*
    171     struct msm_pmem_info pmemBuf;
    172     CAMERA_HAL_UNUSED(frame_size);
    173 
    174     pmemBuf.type     = pmem_type;
    175     pmemBuf.fd       = pmempreviewfd;
    176     pmemBuf.offset   = offset;
    177     pmemBuf.len      = size;
    178     pmemBuf.vaddr    = buf;
    179     pmemBuf.y_off    = yoffset;
    180     pmemBuf.cbcr_off = cbcr_offset;
    181 
    182     pmemBuf.active   = vfe_can_write;
    183 
    184     ALOGV("register_buf:  reg = %d buffer = %p",
    185          !register_buffer, buf);
    186     if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER :
    187         CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) {
    188          ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM  error %s",
    189                strerror(errno));
    190          return false;
    191          }*/
    192 
    193     return true;
    194 
    195 }
    196 
    197 #if 0
    198 bool register_record_buffers(bool register_buffer) {
    199     ALOGI("%s: (%d) E", __FUNCTION__, register_buffer);
    200     struct msm_pmem_info pmemBuf;
    201 
    202     for (int cnt = 0; cnt < VIDEO_BUFFER_COUNT; ++cnt) {
    203         pmemBuf.type     = MSM_PMEM_VIDEO;
    204         pmemBuf.fd       = mRecordHeap->mHeap->getHeapID();
    205         pmemBuf.offset   = mRecordHeap->mAlignedBufferSize * cnt;
    206         pmemBuf.len      = mRecordHeap->mBufferSize;
    207         pmemBuf.vaddr    = (uint8_t *)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
    208         pmemBuf.y_off    = 0;
    209         pmemBuf.cbcr_off = recordframes[0].cbcr_off;
    210         if(register_buffer == true) {
    211             pmemBuf.active   = (cnt<ACTIVE_VIDEO_BUFFERS);
    212             if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
    213                 pmemBuf.type = MSM_PMEM_VIDEO_VPE;
    214                 pmemBuf.active = 1;
    215             }
    216         } else {
    217             pmemBuf.active   = false;
    218         }
    219 
    220         ALOGV("register_buf:  reg = %d buffer = %p", !register_buffer,
    221           (void *)pmemBuf.vaddr);
    222         if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER :
    223                 CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) {
    224             ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM  error %s",
    225                 strerror(errno));
    226             return false;
    227         }
    228     }
    229     return true;
    230 }
    231 #endif
    232 #if 0
    233 PmemPool::PmemPool(const char *pmem_pool,
    234                                            int flags,
    235                                            int pmem_type,
    236                                            int buffer_size, int num_buffers,
    237                                            int frame_size, int cbcr_offset,
    238                                            int yOffset, const char *name) :
    239     MemPool(buffer_size,num_buffers,frame_size,name),
    240     mPmemType(pmem_type),
    241     mCbCrOffset(cbcr_offset),
    242     myOffset(yOffset)
    243 {
    244     ALOGI("constructing MemPool %s backed by pmem pool %s: "
    245          "%d frames @ %d bytes, buffer size %d",
    246          mName,
    247          pmem_pool, num_buffers, frame_size,
    248          buffer_size);
    249 
    250     //mMMCameraDLRef = MMCameraDL::getInstance();
    251 
    252 
    253     // Make a new mmap'ed heap that can be shared across processes.
    254     // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
    255     mAlignedSize = mAlignedBufferSize * num_buffers;
    256 
    257     sp<MemoryHeapBase> masterHeap =
    258         new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
    259 
    260     if (masterHeap->getHeapID() < 0) {
    261         ALOGE("failed to construct master heap for pmem pool %s", pmem_pool);
    262         masterHeap.clear();
    263         return;
    264     }
    265 
    266     sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
    267     if (pmemHeap->getHeapID() >= 0) {
    268         pmemHeap->slap();
    269         masterHeap.clear();
    270         mHeap = pmemHeap;
    271         pmemHeap.clear();
    272 
    273         mFd = mHeap->getHeapID();
    274         if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
    275             ALOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
    276                  pmem_pool,
    277                  ::strerror(errno), errno);
    278             mHeap.clear();
    279             return;
    280         }
    281 
    282         ALOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
    283              pmem_pool,
    284              mFd,
    285              mSize.len);
    286         ALOGE("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
    287 
    288 #if 0
    289         // Unregister preview buffers with the camera drivers.  Allow the VFE to write
    290         // to all preview buffers except for the last one.
    291         // Only Register the preview, snapshot and thumbnail buffers with the kernel.
    292         if( (strcmp("postview", mName) != 0) ){
    293             int num_buf = num_buffers;
    294             if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
    295             ALOGD("num_buffers = %d", num_buf);
    296             for (int cnt = 0; cnt < num_buf; ++cnt) {
    297                 int active = 1;
    298                 if(pmem_type == MSM_PMEM_VIDEO){
    299                      active = (cnt<ACTIVE_VIDEO_BUFFERS);
    300                      //When VPE is enabled, set the last record
    301                      //buffer as active and pmem type as PMEM_VIDEO_VPE
    302                      //as this is a requirement from VPE operation.
    303                      //No need to set this pmem type to VIDEO_VPE while unregistering,
    304                      //because as per camera stack design: "the VPE AXI is also configured
    305                      //when VFE is configured for VIDEO, which is as part of preview
    306                      //initialization/start. So during this VPE AXI config camera stack
    307                      //will lookup the PMEM_VIDEO_VPE buffer and give it as o/p of VPE and
    308                      //change it's type to PMEM_VIDEO".
    309                      if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
    310                          active = 1;
    311                          pmem_type = MSM_PMEM_VIDEO_VPE;
    312                      }
    313                      ALOGV(" pmempool creating video buffers : active %d ", active);
    314                 }
    315                 else if (pmem_type == MSM_PMEM_PREVIEW){
    316                     active = (cnt < ACTIVE_PREVIEW_BUFFERS);
    317                 }
    318                 else if ((pmem_type == MSM_PMEM_MAINIMG)
    319                      || (pmem_type == MSM_PMEM_THUMBNAIL)){
    320                     active = (cnt < ACTIVE_ZSL_BUFFERS);
    321                 }
    322                 register_buf(mBufferSize,
    323                          mFrameSize, mCbCrOffset, myOffset,
    324                          mHeap->getHeapID(),
    325                          mAlignedBufferSize * cnt,
    326                          (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
    327                          pmem_type,
    328                          active);
    329             }
    330         }
    331 #endif
    332         completeInitialization();
    333     }
    334     else ALOGE("pmem pool %s error: could not create master heap!",
    335               pmem_pool);
    336     ALOGI("%s: (%s) X ", __FUNCTION__, mName);
    337 }
    338 #endif
    339 
    340 PmemPool::~PmemPool()
    341 {
    342     ALOGV("%s: %s E", __FUNCTION__, mName);
    343 #if 0
    344     if (mHeap != NULL) {
    345         // Unregister preview buffers with the camera drivers.
    346         //  Only Unregister the preview, snapshot and thumbnail
    347         //  buffers with the kernel.
    348         if( (strcmp("postview", mName) != 0) ){
    349             int num_buffers = mNumBuffers;
    350             if(!strcmp("preview", mName)) num_buffers = PREVIEW_BUFFER_COUNT;
    351             for (int cnt = 0; cnt < num_buffers; ++cnt) {
    352                 register_buf(mBufferSize,
    353                          mFrameSize,
    354                          mCbCrOffset,
    355                          myOffset,
    356                          mHeap->getHeapID(),
    357                          mAlignedBufferSize * cnt,
    358                          (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
    359                          mPmemType,
    360                          false,
    361                          false /* unregister */);
    362             }
    363         }
    364     }
    365     mMMCameraDLRef.clear();
    366 #endif
    367     ALOGV("%s: %s X", __FUNCTION__, mName);
    368 }
    369 MemPool::~MemPool()
    370 {
    371     ALOGV("destroying MemPool %s", mName);
    372     if (mFrameSize > 0)
    373         delete [] mBuffers;
    374     mHeap.clear();
    375     ALOGV("destroying MemPool %s completed", mName);
    376 }
    377 
    378 
    379 status_t MemPool::dump(int fd, const Vector<String16>& args) const
    380 {
    381     const size_t SIZE = 256;
    382     char buffer[SIZE];
    383     String8 result;
    384     CAMERA_HAL_UNUSED(args);
    385     snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
    386     result.append(buffer);
    387     if (mName) {
    388         snprintf(buffer, 255, "mem pool name (%s)\n", mName);
    389         result.append(buffer);
    390     }
    391     if (mHeap != 0) {
    392         snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
    393                  mHeap->getBase(), mHeap->getSize(),
    394                  mHeap->getFlags(), mHeap->getDevice());
    395         result.append(buffer);
    396     }
    397     snprintf(buffer, 255,
    398              "buffer size (%d), number of buffers (%d), frame size(%d)",
    399              mBufferSize, mNumBuffers, mFrameSize);
    400     result.append(buffer);
    401     write(fd, result.string(), result.size());
    402     return NO_ERROR;
    403 }
    404 
    405 };
    406