blob: 250ab9c1e5ee53a43feef6b2d62be4cb799114c2 [file] [log] [blame]
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <cutils/properties.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <linux/msm_ion.h>
#include <sys/mman.h>
#include "mm_qcamera_dbg.h"
#include "mm_qcamera_app.h"
static pthread_mutex_t app_mutex;
static int thread_status = 0;
static pthread_cond_t app_cond_v;
#define MM_QCAMERA_APP_NANOSEC_SCALE 1000000000
int mm_camera_app_timedwait(uint8_t seconds)
{
int rc = 0;
pthread_mutex_lock(&app_mutex);
if(FALSE == thread_status) {
struct timespec tw;
memset(&tw, 0, sizeof tw);
tw.tv_sec = 0;
tw.tv_nsec = time(0) + seconds * MM_QCAMERA_APP_NANOSEC_SCALE;
rc = pthread_cond_timedwait(&app_cond_v, &app_mutex,&tw);
thread_status = FALSE;
}
pthread_mutex_unlock(&app_mutex);
return rc;
}
int mm_camera_app_wait()
{
int rc = 0;
pthread_mutex_lock(&app_mutex);
if(FALSE == thread_status){
pthread_cond_wait(&app_cond_v, &app_mutex);
thread_status = FALSE;
}
pthread_mutex_unlock(&app_mutex);
return rc;
}
void mm_camera_app_done()
{
pthread_mutex_lock(&app_mutex);
thread_status = TRUE;
pthread_cond_signal(&app_cond_v);
pthread_mutex_unlock(&app_mutex);
}
int mm_app_load_hal(mm_camera_app_t *my_cam_app)
{
memset(&my_cam_app->hal_lib, 0, sizeof(hal_interface_lib_t));
my_cam_app->hal_lib.ptr = dlopen("libmmcamera_interface.so", RTLD_NOW);
my_cam_app->hal_lib.ptr_jpeg = dlopen("libmmjpeg_interface.so", RTLD_NOW);
if (!my_cam_app->hal_lib.ptr || !my_cam_app->hal_lib.ptr_jpeg) {
CDBG_ERROR("%s Error opening HAL library %s\n", __func__, dlerror());
return -MM_CAMERA_E_GENERAL;
}
*(void **)&(my_cam_app->hal_lib.get_num_of_cameras) =
dlsym(my_cam_app->hal_lib.ptr, "get_num_of_cameras");
*(void **)&(my_cam_app->hal_lib.mm_camera_open) =
dlsym(my_cam_app->hal_lib.ptr, "camera_open");
*(void **)&(my_cam_app->hal_lib.jpeg_open) =
dlsym(my_cam_app->hal_lib.ptr_jpeg, "jpeg_open");
if (my_cam_app->hal_lib.get_num_of_cameras == NULL ||
my_cam_app->hal_lib.mm_camera_open == NULL ||
my_cam_app->hal_lib.jpeg_open == NULL) {
CDBG_ERROR("%s Error loading HAL sym %s\n", __func__, dlerror());
return -MM_CAMERA_E_GENERAL;
}
my_cam_app->num_cameras = my_cam_app->hal_lib.get_num_of_cameras();
CDBG("%s: num_cameras = %d\n", __func__, my_cam_app->num_cameras);
return MM_CAMERA_OK;
}
int mm_app_allocate_ion_memory(mm_camera_app_buf_t *buf, int ion_type)
{
int rc = MM_CAMERA_OK;
struct ion_handle_data handle_data;
struct ion_allocation_data alloc;
struct ion_fd_data ion_info_fd;
int main_ion_fd = 0;
void *data = NULL;
main_ion_fd = open("/dev/ion", O_RDONLY);
if (main_ion_fd <= 0) {
CDBG_ERROR("Ion dev open failed %s\n", strerror(errno));
goto ION_OPEN_FAILED;
}
memset(&alloc, 0, sizeof(alloc));
alloc.len = buf->mem_info.size;
/* to make it page size aligned */
alloc.len = (alloc.len + 4095) & (~4095);
alloc.align = 4096;
alloc.flags = ION_FLAG_CACHED;
alloc.heap_mask = ion_type;
rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
if (rc < 0) {
CDBG_ERROR("ION allocation failed\n");
goto ION_ALLOC_FAILED;
}
memset(&ion_info_fd, 0, sizeof(ion_info_fd));
ion_info_fd.handle = alloc.handle;
rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
if (rc < 0) {
CDBG_ERROR("ION map failed %s\n", strerror(errno));
goto ION_MAP_FAILED;
}
data = mmap(NULL,
alloc.len,
PROT_READ | PROT_WRITE,
MAP_SHARED,
ion_info_fd.fd,
0);
if (data == MAP_FAILED) {
CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
goto ION_MAP_FAILED;
}
buf->mem_info.main_ion_fd = main_ion_fd;
buf->mem_info.fd = ion_info_fd.fd;
buf->mem_info.handle = ion_info_fd.handle;
buf->mem_info.size = alloc.len;
buf->mem_info.data = data;
return MM_CAMERA_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 -MM_CAMERA_E_GENERAL;
}
int mm_app_deallocate_ion_memory(mm_camera_app_buf_t *buf)
{
struct ion_handle_data handle_data;
int rc = 0;
rc = munmap(buf->mem_info.data, buf->mem_info.size);
if (buf->mem_info.fd > 0) {
close(buf->mem_info.fd);
buf->mem_info.fd = 0;
}
if (buf->mem_info.main_ion_fd > 0) {
memset(&handle_data, 0, sizeof(handle_data));
handle_data.handle = buf->mem_info.handle;
ioctl(buf->mem_info.main_ion_fd, ION_IOC_FREE, &handle_data);
close(buf->mem_info.main_ion_fd);
buf->mem_info.main_ion_fd = 0;
}
return rc;
}
/* cmd = ION_IOC_CLEAN_CACHES, ION_IOC_INV_CACHES, ION_IOC_CLEAN_INV_CACHES */
int mm_app_cache_ops(mm_camera_app_meminfo_t *mem_info,
unsigned int cmd)
{
struct ion_flush_data cache_inv_data;
struct ion_custom_data custom_data;
int ret = MM_CAMERA_OK;
#ifdef USE_ION
if (NULL == mem_info) {
CDBG_ERROR("%s: mem_info is NULL, return here", __func__);
return -MM_CAMERA_E_GENERAL;
}
memset(&cache_inv_data, 0, sizeof(cache_inv_data));
memset(&custom_data, 0, sizeof(custom_data));
cache_inv_data.vaddr = mem_info->data;
cache_inv_data.fd = mem_info->fd;
cache_inv_data.handle = mem_info->handle;
cache_inv_data.length = mem_info->size;
custom_data.cmd = cmd;
custom_data.arg = (unsigned long)&cache_inv_data;
CDBG("addr = %p, fd = %d, handle = %p length = %d, ION Fd = %d",
cache_inv_data.vaddr, cache_inv_data.fd,
cache_inv_data.handle, cache_inv_data.length,
mem_info->main_ion_fd);
if(mem_info->main_ion_fd > 0) {
if(ioctl(mem_info->main_ion_fd, ION_IOC_CUSTOM, &custom_data) < 0) {
ALOGE("%s: Cache Invalidate failed\n", __func__);
ret = -MM_CAMERA_E_GENERAL;
}
}
#endif
return ret;
}
void mm_app_dump_frame(mm_camera_buf_def_t *frame,
char *name,
char *ext,
int frame_idx)
{
char file_name[64];
int file_fd;
int i;
if ( frame != NULL) {
snprintf(file_name, sizeof(file_name), "/data/%s_%d.%s", name, frame_idx, ext);
file_fd = open(file_name, O_RDWR | O_CREAT, 0777);
if (file_fd < 0) {
CDBG_ERROR("%s: cannot open file %s \n", __func__, file_name);
} else {
for (i = 0; i < frame->num_planes; i++) {
write(file_fd,
(uint8_t *)frame->buffer + frame->planes[i].data_offset,
frame->planes[i].length);
}
close(file_fd);
CDBG("dump %s", file_name);
}
}
}
void mm_app_dump_jpeg_frame(const void * data, uint32_t size, char* name, char* ext, int index)
{
char buf[32];
int file_fd;
if ( data != NULL) {
snprintf(buf, sizeof(buf), "/data/%s_%d.%s", name, index, ext);
CDBG("%s: %s size =%d, jobId=%d", __func__, buf, size, index);
file_fd = open(buf, O_RDWR | O_CREAT, 0777);
write(file_fd, data, size);
close(file_fd);
}
}
int mm_app_alloc_bufs(mm_camera_app_buf_t* app_bufs,
cam_frame_len_offset_t *frame_offset_info,
uint8_t num_bufs,
uint8_t is_streambuf)
{
int i, j;
int ion_type = 0x1 << CAMERA_ION_FALLBACK_HEAP_ID;
if (is_streambuf) {
ion_type |= 0x1 << CAMERA_ION_HEAP_ID;
}
for (i = 0; i < num_bufs ; i++) {
app_bufs[i].mem_info.size = frame_offset_info->frame_len;
mm_app_allocate_ion_memory(&app_bufs[i], ion_type);
app_bufs[i].buf.buf_idx = i;
app_bufs[i].buf.num_planes = frame_offset_info->num_planes;
app_bufs[i].buf.fd = app_bufs[i].mem_info.fd;
app_bufs[i].buf.frame_len = app_bufs[i].mem_info.size;
app_bufs[i].buf.buffer = app_bufs[i].mem_info.data;
app_bufs[i].buf.mem_info = (void *)&app_bufs[i].mem_info;
/* Plane 0 needs to be set seperately. Set other planes
* in a loop. */
app_bufs[i].buf.planes[0].length = frame_offset_info->mp[0].len;
app_bufs[i].buf.planes[0].m.userptr = app_bufs[i].buf.fd;
app_bufs[i].buf.planes[0].data_offset = frame_offset_info->mp[0].offset;
app_bufs[i].buf.planes[0].reserved[0] = 0;
for (j = 1; j < frame_offset_info->num_planes; j++) {
app_bufs[i].buf.planes[j].length = frame_offset_info->mp[j].len;
app_bufs[i].buf.planes[j].m.userptr = app_bufs[i].buf.fd;
app_bufs[i].buf.planes[j].data_offset = frame_offset_info->mp[j].offset;
app_bufs[i].buf.planes[j].reserved[0] =
app_bufs[i].buf.planes[j-1].reserved[0] +
app_bufs[i].buf.planes[j-1].length;
}
}
CDBG("%s: X", __func__);
return MM_CAMERA_OK;
}
int mm_app_release_bufs(uint8_t num_bufs,
mm_camera_app_buf_t* app_bufs)
{
int i, rc = MM_CAMERA_OK;
CDBG("%s: E", __func__);
for (i = 0; i < num_bufs; i++) {
rc = mm_app_deallocate_ion_memory(&app_bufs[i]);
}
memset(app_bufs, 0, num_bufs * sizeof(mm_camera_app_buf_t));
CDBG("%s: X", __func__);
return rc;
}
int mm_app_stream_initbuf(cam_frame_len_offset_t *frame_offset_info,
uint8_t *num_bufs,
uint8_t **initial_reg_flag,
mm_camera_buf_def_t **bufs,
mm_camera_map_unmap_ops_tbl_t *ops_tbl,
void *user_data)
{
mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
mm_camera_buf_def_t *pBufs = NULL;
uint8_t *reg_flags = NULL;
int i, rc;
stream->offset = *frame_offset_info;
CDBG("%s: alloc buf for stream_id %d, len=%d",
__func__, stream->s_id, frame_offset_info->frame_len);
pBufs = (mm_camera_buf_def_t *)malloc(sizeof(mm_camera_buf_def_t) * stream->num_of_bufs);
reg_flags = (uint8_t *)malloc(sizeof(uint8_t) * stream->num_of_bufs);
if (pBufs == NULL || reg_flags == NULL) {
CDBG_ERROR("%s: No mem for bufs", __func__);
if (pBufs != NULL) {
free(pBufs);
}
if (reg_flags != NULL) {
free(reg_flags);
}
return -1;
}
rc = mm_app_alloc_bufs(&stream->s_bufs[0],
frame_offset_info,
stream->num_of_bufs,
1);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: mm_stream_alloc_bufs err = %d", __func__, rc);
free(pBufs);
free(reg_flags);
return rc;
}
for (i = 0; i < stream->num_of_bufs; i++) {
/* mapping stream bufs first */
pBufs[i] = stream->s_bufs[i].buf;
reg_flags[i] = 1;
rc = ops_tbl->map_ops(pBufs[i].buf_idx,
-1,
pBufs[i].fd,
pBufs[i].frame_len,
ops_tbl->userdata);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: mapping buf[%d] err = %d", __func__, i, rc);
break;
}
}
if (rc != MM_CAMERA_OK) {
int j;
for (j=0; j>i; j++) {
ops_tbl->unmap_ops(pBufs[j].buf_idx, -1, ops_tbl->userdata);
}
mm_app_release_bufs(stream->num_of_bufs, &stream->s_bufs[0]);
free(pBufs);
free(reg_flags);
return rc;
}
*num_bufs = stream->num_of_bufs;
*bufs = pBufs;
*initial_reg_flag = reg_flags;
CDBG("%s: X",__func__);
return rc;
}
int32_t mm_app_stream_deinitbuf(mm_camera_map_unmap_ops_tbl_t *ops_tbl,
void *user_data)
{
mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
int i;
for (i = 0; i < stream->num_of_bufs ; i++) {
/* mapping stream bufs first */
ops_tbl->unmap_ops(stream->s_bufs[i].buf.buf_idx, -1, ops_tbl->userdata);
}
mm_app_release_bufs(stream->num_of_bufs, &stream->s_bufs[0]);
CDBG("%s: X",__func__);
return 0;
}
int32_t mm_app_stream_clean_invalidate_buf(int index, void *user_data)
{
mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
return mm_app_cache_ops(&stream->s_bufs[index].mem_info,
ION_IOC_CLEAN_INV_CACHES);
}
static void notify_evt_cb(uint32_t camera_handle,
mm_camera_event_t *evt,
void *user_data)
{
mm_camera_test_obj_t *test_obj =
(mm_camera_test_obj_t *)user_data;
if (test_obj == NULL || test_obj->cam->camera_handle != camera_handle) {
CDBG_ERROR("%s: Not a valid test obj", __func__);
return;
}
CDBG("%s:E evt = %d", __func__, evt->server_event_type);
switch (evt->server_event_type) {
case CAM_EVENT_TYPE_AUTO_FOCUS_DONE:
CDBG("%s: rcvd auto focus done evt", __func__);
break;
case CAM_EVENT_TYPE_ZOOM_DONE:
CDBG("%s: rcvd zoom done evt", __func__);
break;
default:
break;
}
CDBG("%s:X", __func__);
}
int mm_app_open(mm_camera_app_t *cam_app,
uint8_t cam_id,
mm_camera_test_obj_t *test_obj)
{
int32_t rc;
cam_frame_len_offset_t offset_info;
CDBG("%s:BEGIN\n", __func__);
test_obj->cam = cam_app->hal_lib.mm_camera_open(cam_id);
if(test_obj->cam == NULL) {
CDBG_ERROR("%s:dev open error\n", __func__);
return -MM_CAMERA_E_GENERAL;
}
CDBG("Open Camera id = %d handle = %d", cam_id, test_obj->cam->camera_handle);
/* alloc ion mem for capability buf */
memset(&offset_info, 0, sizeof(offset_info));
offset_info.frame_len = sizeof(cam_capability_t);
rc = mm_app_alloc_bufs(&test_obj->cap_buf,
&offset_info,
1,
0);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s:alloc buf for capability error\n", __func__);
goto error_after_cam_open;
}
/* mapping capability buf */
rc = test_obj->cam->ops->map_buf(test_obj->cam->camera_handle,
CAM_MAPPING_BUF_TYPE_CAPABILITY,
test_obj->cap_buf.mem_info.fd,
test_obj->cap_buf.mem_info.size);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s:map for capability error\n", __func__);
goto error_after_cap_buf_alloc;
}
/* alloc ion mem for getparm buf */
memset(&offset_info, 0, sizeof(offset_info));
offset_info.frame_len = sizeof(parm_buffer_t);
rc = mm_app_alloc_bufs(&test_obj->parm_buf,
&offset_info,
1,
0);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s:alloc buf for getparm_buf error\n", __func__);
goto error_after_cap_buf_map;
}
/* mapping getparm buf */
rc = test_obj->cam->ops->map_buf(test_obj->cam->camera_handle,
CAM_MAPPING_BUF_TYPE_PARM_BUF,
test_obj->parm_buf.mem_info.fd,
test_obj->parm_buf.mem_info.size);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s:map getparm_buf error\n", __func__);
goto error_after_getparm_buf_alloc;
}
rc = test_obj->cam->ops->register_event_notify(test_obj->cam->camera_handle,
notify_evt_cb,
test_obj);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: failed register_event_notify", __func__);
rc = -MM_CAMERA_E_GENERAL;
goto error_after_getparm_buf_map;
}
rc = test_obj->cam->ops->query_capability(test_obj->cam->camera_handle);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: failed query_capability", __func__);
rc = -MM_CAMERA_E_GENERAL;
goto error_after_getparm_buf_map;
}
memset(&test_obj->jpeg_ops, 0, sizeof(mm_jpeg_ops_t));
test_obj->jpeg_hdl = cam_app->hal_lib.jpeg_open(&test_obj->jpeg_ops);
if (test_obj->jpeg_hdl == 0) {
CDBG_ERROR("%s: jpeg lib open err", __func__);
rc = -MM_CAMERA_E_GENERAL;
goto error_after_getparm_buf_map;
}
return rc;
error_after_getparm_buf_map:
test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
CAM_MAPPING_BUF_TYPE_PARM_BUF);
error_after_getparm_buf_alloc:
mm_app_release_bufs(1, &test_obj->parm_buf);
error_after_cap_buf_map:
test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
CAM_MAPPING_BUF_TYPE_CAPABILITY);
error_after_cap_buf_alloc:
mm_app_release_bufs(1, &test_obj->cap_buf);
error_after_cam_open:
test_obj->cam->ops->close_camera(test_obj->cam->camera_handle);
test_obj->cam = NULL;
return rc;
}
int mm_app_close(mm_camera_test_obj_t *test_obj)
{
uint32_t rc = MM_CAMERA_OK;
if (test_obj == NULL || test_obj->cam ==NULL) {
CDBG_ERROR("%s: cam not opened", __func__);
return -MM_CAMERA_E_GENERAL;
}
/* unmap capability buf */
rc = test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
CAM_MAPPING_BUF_TYPE_CAPABILITY);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: unmap capability buf failed, rc=%d", __func__, rc);
}
/* unmap parm buf */
rc = test_obj->cam->ops->unmap_buf(test_obj->cam->camera_handle,
CAM_MAPPING_BUF_TYPE_PARM_BUF);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: unmap setparm buf failed, rc=%d", __func__, rc);
}
rc = test_obj->cam->ops->close_camera(test_obj->cam->camera_handle);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: close camera failed, rc=%d", __func__, rc);
}
test_obj->cam = NULL;
/* close jpeg client */
if (test_obj->jpeg_hdl && test_obj->jpeg_ops.close) {
rc = test_obj->jpeg_ops.close(test_obj->jpeg_hdl);
test_obj->jpeg_hdl = 0;
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: close jpeg failed, rc=%d", __func__, rc);
}
}
/* dealloc capability buf */
rc = mm_app_release_bufs(1, &test_obj->cap_buf);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: release capability buf failed, rc=%d", __func__, rc);
}
/* dealloc parm buf */
rc = mm_app_release_bufs(1, &test_obj->parm_buf);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: release setparm buf failed, rc=%d", __func__, rc);
}
return MM_CAMERA_OK;
}
mm_camera_channel_t * mm_app_add_channel(mm_camera_test_obj_t *test_obj,
mm_camera_channel_type_t ch_type,
mm_camera_channel_attr_t *attr,
mm_camera_buf_notify_t channel_cb,
void *userdata)
{
uint32_t ch_id = 0;
mm_camera_channel_t *channel = NULL;
ch_id = test_obj->cam->ops->add_channel(test_obj->cam->camera_handle,
attr,
channel_cb,
userdata);
if (ch_id == 0) {
CDBG_ERROR("%s: add channel failed", __func__);
return NULL;
}
channel = &test_obj->channels[ch_type];
channel->ch_id = ch_id;
return channel;
}
int mm_app_del_channel(mm_camera_test_obj_t *test_obj,
mm_camera_channel_t *channel)
{
test_obj->cam->ops->delete_channel(test_obj->cam->camera_handle,
channel->ch_id);
memset(channel, 0, sizeof(mm_camera_channel_t));
return MM_CAMERA_OK;
}
mm_camera_stream_t * mm_app_add_stream(mm_camera_test_obj_t *test_obj,
mm_camera_channel_t *channel)
{
mm_camera_stream_t *stream = NULL;
int rc = MM_CAMERA_OK;
cam_frame_len_offset_t offset_info;
stream = &(channel->streams[channel->num_streams++]);
stream->s_id = test_obj->cam->ops->add_stream(test_obj->cam->camera_handle,
channel->ch_id);
if (stream->s_id == 0) {
CDBG_ERROR("%s: add stream failed", __func__);
return NULL;
}
/* alloc ion mem for stream_info buf */
memset(&offset_info, 0, sizeof(offset_info));
offset_info.frame_len = sizeof(cam_stream_info_t);
rc = mm_app_alloc_bufs(&stream->s_info_buf,
&offset_info,
1,
0);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s:alloc buf for stream_info error\n", __func__);
test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle,
channel->ch_id,
stream->s_id);
stream->s_id = 0;
return NULL;
}
/* mapping streaminfo buf */
rc = test_obj->cam->ops->map_stream_buf(test_obj->cam->camera_handle,
channel->ch_id,
stream->s_id,
CAM_MAPPING_BUF_TYPE_STREAM_INFO,
0,
-1,
stream->s_info_buf.mem_info.fd,
stream->s_info_buf.mem_info.size);
if (rc != MM_CAMERA_OK) {
CDBG_ERROR("%s:map setparm_buf error\n", __func__);
mm_app_deallocate_ion_memory(&stream->s_info_buf);
test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle,
channel->ch_id,
stream->s_id);
stream->s_id = 0;
return NULL;
}
return stream;
}
int mm_app_del_stream(mm_camera_test_obj_t *test_obj,
mm_camera_channel_t *channel,
mm_camera_stream_t *stream)
{
test_obj->cam->ops->unmap_stream_buf(test_obj->cam->camera_handle,
channel->ch_id,
stream->s_id,
CAM_MAPPING_BUF_TYPE_STREAM_INFO,
0,
-1);
mm_app_deallocate_ion_memory(&stream->s_info_buf);
test_obj->cam->ops->delete_stream(test_obj->cam->camera_handle,
channel->ch_id,
stream->s_id);
memset(stream, 0, sizeof(mm_camera_stream_t));
return MM_CAMERA_OK;
}
mm_camera_channel_t *mm_app_get_channel_by_type(mm_camera_test_obj_t *test_obj,
mm_camera_channel_type_t ch_type)
{
return &test_obj->channels[ch_type];
}
int mm_app_config_stream(mm_camera_test_obj_t *test_obj,
mm_camera_channel_t *channel,
mm_camera_stream_t *stream,
mm_camera_stream_config_t *config)
{
return test_obj->cam->ops->config_stream(test_obj->cam->camera_handle,
channel->ch_id,
stream->s_id,
config);
}
int mm_app_start_channel(mm_camera_test_obj_t *test_obj,
mm_camera_channel_t *channel)
{
return test_obj->cam->ops->start_channel(test_obj->cam->camera_handle,
channel->ch_id);
}
int mm_app_stop_channel(mm_camera_test_obj_t *test_obj,
mm_camera_channel_t *channel)
{
return test_obj->cam->ops->stop_channel(test_obj->cam->camera_handle,
channel->ch_id);
}
int main(int argc, char **argv)
{
int c;
int rc;
int run_tc = 0;
int run_dual_tc = 0;
mm_camera_app_t my_cam_app;
CDBG("\nCamera Test Application\n");
while ((c = getopt(argc, argv, "tdh")) != -1) {
switch (c) {
case 't':
run_tc = 1;
break;
case 'd':
run_dual_tc = 1;
break;
case 'h':
default:
printf("usage: %s [-t] [-d] \n", argv[0]);
printf("-t: Unit test \n");
printf("-d: Dual camera test \n");
return 0;
}
}
memset(&my_cam_app, 0, sizeof(mm_camera_app_t));
if((mm_app_load_hal(&my_cam_app) != MM_CAMERA_OK)) {
CDBG_ERROR("%s:mm_app_init err\n", __func__);
return -1;
}
if(run_tc) {
printf("\tRunning unit test engine only\n");
rc = mm_app_unit_test_entry(&my_cam_app);
printf("\tUnit test engine. EXIT(%d)!!!\n", rc);
return rc;
}
#if 0
if(run_dual_tc) {
printf("\tRunning Dual camera test engine only\n");
rc = mm_app_dual_test_entry(&my_cam_app);
printf("\t Dual camera engine. EXIT(%d)!!!\n", rc);
exit(rc);
}
#endif
/* Clean up and exit. */
CDBG("Exiting test app\n");
return 0;
}