int32_t QCameraStream::getBufs(cam_frame_len_offset_t *offset,
uint8_t *num_bufs,
uint8_t **initial_reg_flag,
mm_camera_buf_def_t **bufs,
mm_camera_map_unmap_ops_tbl_t *ops_tbl)
{
...
//Allocate stream buffer
mStreamBufs = mAllocator.allocateStreamBuf(mStreamInfo->stream_type,
mFrameLenOffset.frame_len, mFrameLenOffset.mp[0].stride,
mFrameLenOffset.mp[0].scanline, numBufAlloc, mStreamInfo->cam_type);//分配QCameraMemory对象,封装ion的分配管理过程。
if (!mStreamBufs) {
LOGE("Failed to allocate stream buffers");
return NO_MEMORY;
}
...
}
QCameraMemory *QCamera2HardwareInterface::allocateStreamBuf(
cam_stream_type_t stream_type, size_t size, int stride, int scanline,
uint8_t &bufferCnt, uint32_t cam_type)
{
...
case CAM_STREAM_TYPE_RAW:
if(isSecureMode()) {
...
} else {
mem = new QCameraStreamMemory(mGetMemory,
mCallbackCookie,
bCachedMem,
(bPoolMem) ? &m_memoryPool : NULL,
stream_type);//创建QCameraMemory子对象QCameraStreamMemory
}
break;
...
if (bufferCnt > 0) {
rc = mem->allocate(bufferCnt, size);//分配内存
if (rc < 0) {
delete mem;
return NULL;
}
bufferCnt = mem->getCnt();
}
...
}
int QCameraHeapMemory::allocate(uint8_t count, size_t size)
{
...
else{
rc = alloc(count, size, heap_id_mask);//调用alloc适配函数分配内存
if (rc < 0) {
ATRACE_END();
return rc;
}
for (int i = 0; i < count; i ++) {
void *vaddr = mmap(NULL,
mMemInfo[i].size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
mMemInfo[i].fd, 0);//通过fd,映射内核内存地址到用户空间,
if (vaddr == MAP_FAILED) {
for (int j = i-1; j >= 0; j --) {
munmap(mPtr[j], mMemInfo[j].size);
mPtr[j] = NULL;
deallocOneBuffer(mMemInfo[j]);
}
// Deallocate remaining buffers that have already been allocated
for (int j = i; j < count; j++) {
deallocOneBuffer(mMemInfo[j]);
}
ATRACE_END();
return NO_MEMORY;
} else
mPtr[i] = vaddr;//并将用户空间地址保存于mPtr数组中,供后续使用
}
}
...
}
int QCameraMemory::alloc(int count, size_t size, unsigned int heap_id)
{
...
for (int i = mBufferCount; i < new_bufCnt; i ++){
if ( NULL == mMemoryPool ) {
LOGH("No memory pool available, allocating now");
rc = allocOneBuffer(mMemInfo[i], heap_id, size, m_bCached,
secure_mode);//调用ion操作函数接口分配内存,fd等信息保存在mMemInfo中,后续再用ion通过fd操作内存。
if (rc < 0) {
LOGE("AllocateIonMemory failed");
for (int j = i-1; j >= 0; j--)
deallocOneBuffer(mMemInfo[j]);
break;
}
} else {//另一种分配方式,暂不研究
rc = mMemoryPool->allocateBuffer(mMemInfo[i],
heap_id,
size,
m_bCached,
mStreamType,
secure_mode);
if (rc < 0) {
LOGE("Memory pool allocation failed");
for (int j = i-1; j >= 0; j--)
mMemoryPool->releaseBuffer(mMemInfo[j],
mStreamType);
break;
}
}
}
...
}
int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo,
unsigned int heap_id, size_t size, bool cached, bool secure_mode)
{
int rc = OK;
struct ion_handle_data handle_data;
struct ion_allocation_data alloc;
struct ion_fd_data ion_info_fd;
int main_ion_fd = -1;
main_ion_fd = open("/dev/ion", O_RDONLY);//第一步:创建ion client
if (main_ion_fd < 0) {
LOGE("Ion dev open failed: %s\n", strerror(errno));
goto ION_OPEN_FAILED;
}
memset(&alloc, 0, sizeof(alloc));//第二步:设置struct ion_allocation_data alloc;进行内存分配,获取handle句柄
alloc.len = size;//1.分配的大小
/* to make it page size aligned */
alloc.len = (alloc.len + 4095U) & (~4095U);
alloc.align = 4096;//2.对齐字节
if (cached) {
alloc.flags = ION_FLAG_CACHED;
}
alloc.heap_id_mask = heap_id;//3.分配的内存类型camera,display等
if (secure_mode) {
LOGD("Allocate secure buffer\n");
if (QCameraCommon::is_target_SDM450())
alloc.heap_id_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
else
alloc.heap_id_mask = ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID);
alloc.flags = ION_FLAG_SECURE | ION_FLAG_CP_CAMERA;
alloc.align = 2097152; // 2 MiB alignment to be able to protect later
alloc.len = (alloc.len + 2097152U) & (~2097152U);
}
rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);//调用ioctl执行分配
if (rc < 0) {
LOGE("ION allocation failed: %s\n", strerror(errno));
goto ION_ALLOC_FAILED;
}
memset(&ion_info_fd, 0, sizeof(ion_info_fd));//第三步:设置struct ion_info_fd获取fd 为下一步作map用
ion_info_fd.handle = alloc.handle;//设置已分配内存的句柄
rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);//调用ioctl 用ION_IOC_SHARE命令获取fd
if (rc < 0) {
LOGE("ION map failed %s\n", strerror(errno));
goto ION_MAP_FAILED;
}
memInfo.main_ion_fd = main_ion_fd;//分配的内存信息保存于QCameraMemInfo,供后续使用。
memInfo.fd = ion_info_fd.fd;
memInfo.handle = ion_info_fd.handle;
memInfo.size = alloc.len;
memInfo.cached = cached;
memInfo.heap_id = heap_id;
LOGH("ION buffer %lx with size %d allocated memInfo.fd: %d main_ion_fd: %d",
(unsigned long)memInfo.handle, alloc.len, memInfo.fd, main_ion_fd);
return OK;
ION_MAP_FAILED:
memset(&handle_data, 0, sizeof(handle_data));
handle_data.handle = ion_info_fd.handle;
ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
ION_ALLOC_FAILED:
close(main_ion_fd);
ION_OPEN_FAILED:
return NO_MEMORY;
}