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