blob: e8e469bea77907e7ad92db823f3f594867b71a5d [file] [log] [blame]
Iliyan Malchev6d016452013-03-27 16:27:56 -07001/*
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
49namespace android {
50
51
52static 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
64MMCameraDL::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
74void * MMCameraDL::pointer(){
75 return libmmcamera;
76}
77
78MMCameraDL::~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
90wp<MMCameraDL> MMCameraDL::instance;
91Mutex MMCameraDL::singletonLock;
92
93
94sp<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
105MemPool::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
117void 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
134AshmemPool::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
158static 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
198bool 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
233PmemPool::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
340PmemPool::~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}
369MemPool::~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
379status_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};