/* ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ /*#error uncomment this for compiler test!*/ //#define ALOG_NDEBUG 0 #define ALOG_NIDEBUG 0 #define LOG_TAG "QCameraHWI_Mem" #include #include #include //#include #include #include #include #include #include #include #include #include #include "QCameraParameters.h" #include #include #include "QCameraHWI_Mem.h" #define CAMERA_HAL_UNUSED(expr) do { (void)(expr); } while (0) /* QCameraHardwareInterface class implementation goes here*/ /* following code implement the contol logic of this class*/ namespace android { static bool register_buf(int size, int frame_size, int cbcr_offset, int yoffset, int pmempreviewfd, uint32_t offset, uint8_t *buf, int pmem_type, bool vfe_can_write, bool register_buffer = true); #if 0 MMCameraDL::MMCameraDL(){ ALOGV("MMCameraDL: E"); libmmcamera = NULL; #if DLOPEN_LIBMMCAMERA libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW); #endif ALOGV("Open MM camera DL libeomcamera loaded at %p ", libmmcamera); ALOGV("MMCameraDL: X"); } void * MMCameraDL::pointer(){ return libmmcamera; } MMCameraDL::~MMCameraDL(){ ALOGV("~MMCameraDL: E"); LINK_mm_camera_destroy(); if (libmmcamera != NULL) { ::dlclose(libmmcamera); ALOGV("closed MM Camera DL "); } libmmcamera = NULL; ALOGV("~MMCameraDL: X"); } wp MMCameraDL::instance; Mutex MMCameraDL::singletonLock; sp MMCameraDL::getInstance(){ Mutex::Autolock instanceLock(singletonLock); sp mmCamera = instance.promote(); if(mmCamera == NULL){ mmCamera = new MMCameraDL(); instance = mmCamera; } return mmCamera; } #endif MemPool::MemPool(int buffer_size, int num_buffers, int frame_size, const char *name) : mBufferSize(buffer_size), mNumBuffers(num_buffers), mFrameSize(frame_size), mBuffers(NULL), mName(name) { int page_size_minus_1 = getpagesize() - 1; mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1); } void MemPool::completeInitialization() { // If we do not know how big the frame will be, we wait to allocate // the buffers describing the individual frames until we do know their // size. if (mFrameSize > 0) { mBuffers = new sp[mNumBuffers]; for (int i = 0; i < mNumBuffers; i++) { mBuffers[i] = new MemoryBase(mHeap, i * mAlignedBufferSize, mFrameSize); } } } AshmemPool::AshmemPool(int buffer_size, int num_buffers, int frame_size, const char *name) : MemPool(buffer_size, num_buffers, frame_size, name) { ALOGV("constructing MemPool %s backed by ashmem: " "%d frames @ %d uint8_ts, " "buffer size %d", mName, num_buffers, frame_size, buffer_size); int page_mask = getpagesize() - 1; int ashmem_size = buffer_size * num_buffers; ashmem_size += page_mask; ashmem_size &= ~page_mask; mHeap = new MemoryHeapBase(ashmem_size); completeInitialization(); } static bool register_buf(int size, int frame_size, int cbcr_offset, int yoffset, int pmempreviewfd, uint32_t offset, uint8_t *buf, int pmem_type, bool vfe_can_write, bool register_buffer) { /*TODO*/ /* struct msm_pmem_info pmemBuf; CAMERA_HAL_UNUSED(frame_size); pmemBuf.type = pmem_type; pmemBuf.fd = pmempreviewfd; pmemBuf.offset = offset; pmemBuf.len = size; pmemBuf.vaddr = buf; pmemBuf.y_off = yoffset; pmemBuf.cbcr_off = cbcr_offset; pmemBuf.active = vfe_can_write; ALOGV("register_buf: reg = %d buffer = %p", !register_buffer, buf); if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER : CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) { ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM error %s", strerror(errno)); return false; }*/ return true; } #if 0 bool register_record_buffers(bool register_buffer) { ALOGI("%s: (%d) E", __FUNCTION__, register_buffer); struct msm_pmem_info pmemBuf; for (int cnt = 0; cnt < VIDEO_BUFFER_COUNT; ++cnt) { pmemBuf.type = MSM_PMEM_VIDEO; pmemBuf.fd = mRecordHeap->mHeap->getHeapID(); pmemBuf.offset = mRecordHeap->mAlignedBufferSize * cnt; pmemBuf.len = mRecordHeap->mBufferSize; pmemBuf.vaddr = (uint8_t *)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt; pmemBuf.y_off = 0; pmemBuf.cbcr_off = recordframes[0].cbcr_off; if(register_buffer == true) { pmemBuf.active = (cnt masterHeap = new MemoryHeapBase(pmem_pool, mAlignedSize, flags); if (masterHeap->getHeapID() < 0) { ALOGE("failed to construct master heap for pmem pool %s", pmem_pool); masterHeap.clear(); return; } sp pmemHeap = new MemoryHeapPmem(masterHeap, flags); if (pmemHeap->getHeapID() >= 0) { pmemHeap->slap(); masterHeap.clear(); mHeap = pmemHeap; pmemHeap.clear(); mFd = mHeap->getHeapID(); if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) { ALOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)", pmem_pool, ::strerror(errno), errno); mHeap.clear(); return; } ALOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", pmem_pool, mFd, mSize.len); ALOGE("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize); #if 0 // Unregister preview buffers with the camera drivers. Allow the VFE to write // to all preview buffers except for the last one. // Only Register the preview, snapshot and thumbnail buffers with the kernel. if( (strcmp("postview", mName) != 0) ){ int num_buf = num_buffers; if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount; ALOGD("num_buffers = %d", num_buf); for (int cnt = 0; cnt < num_buf; ++cnt) { int active = 1; if(pmem_type == MSM_PMEM_VIDEO){ active = (cntgetHeapID(), mAlignedBufferSize * cnt, (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt, pmem_type, active); } } #endif completeInitialization(); } else ALOGE("pmem pool %s error: could not create master heap!", pmem_pool); ALOGI("%s: (%s) X ", __FUNCTION__, mName); } #endif PmemPool::~PmemPool() { ALOGV("%s: %s E", __FUNCTION__, mName); #if 0 if (mHeap != NULL) { // Unregister preview buffers with the camera drivers. // Only Unregister the preview, snapshot and thumbnail // buffers with the kernel. if( (strcmp("postview", mName) != 0) ){ int num_buffers = mNumBuffers; if(!strcmp("preview", mName)) num_buffers = PREVIEW_BUFFER_COUNT; for (int cnt = 0; cnt < num_buffers; ++cnt) { register_buf(mBufferSize, mFrameSize, mCbCrOffset, myOffset, mHeap->getHeapID(), mAlignedBufferSize * cnt, (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt, mPmemType, false, false /* unregister */); } } } mMMCameraDLRef.clear(); #endif ALOGV("%s: %s X", __FUNCTION__, mName); } MemPool::~MemPool() { ALOGV("destroying MemPool %s", mName); if (mFrameSize > 0) delete [] mBuffers; mHeap.clear(); ALOGV("destroying MemPool %s completed", mName); } status_t MemPool::dump(int fd, const Vector& args) const { const size_t SIZE = 256; char buffer[SIZE]; String8 result; CAMERA_HAL_UNUSED(args); snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n"); result.append(buffer); if (mName) { snprintf(buffer, 255, "mem pool name (%s)\n", mName); result.append(buffer); } if (mHeap != 0) { snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n", mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice()); result.append(buffer); } snprintf(buffer, 255, "buffer size (%d), number of buffers (%d), frame size(%d)", mBufferSize, mNumBuffers, mFrameSize); result.append(buffer); write(fd, result.string(), result.size()); return NO_ERROR; } };