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 
46 namespace android {
47 
48 
49 static 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
61 MMCameraDL::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 
71 void * MMCameraDL::pointer(){
72     return libmmcamera;
73 }
74 
75 MMCameraDL::~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 
87 wp<MMCameraDL> MMCameraDL::instance;
88 Mutex MMCameraDL::singletonLock;
89 
90 
91 sp<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 
MemPool(int buffer_size,int num_buffers,int frame_size,const char * name)102 MemPool::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 
completeInitialization()114 void 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 
AshmemPool(int buffer_size,int num_buffers,int frame_size,const char * name)131 AshmemPool::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 
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)155 static 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
195 bool 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
230 PmemPool::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 
~PmemPool()337 PmemPool::~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 }
~MemPool()366 MemPool::~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 
dump(int fd,const Vector<String16> & args) const376 status_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