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