• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MemPool(int buffer_size,int num_buffers,int frame_size,const char * name)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 
completeInitialization()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 
AshmemPool(int buffer_size,int num_buffers,int frame_size,const char * name)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 
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)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 
~PmemPool()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 }
~MemPool()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 
dump(int fd,const Vector<String16> & args) const379 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