blob: b23f9b39715080d088436c2a3ad5e88bb19762b3 [file] [log] [blame]
/*
Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 <pthread.h>
#include "mm_camera_dbg.h"
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
#include "mm_qcamera_app.h"
#define BUFF_SIZE_128 128
static int num_run = 0;
static int mm_app_dump_video_frame(struct msm_frame *frame,
uint32_t len)
{
static int v_cnt = 0;
char bufp[BUFF_SIZE_128];
int file_fdp;
int rc = 0;
return rc; /* disable dump */
v_cnt++;
if(0 == (v_cnt % 10))
snprintf(bufp, BUFF_SIZE_128, "/data/v_%d.yuv", v_cnt);
else
return 0;
file_fdp = open(bufp, O_RDWR | O_CREAT, 0777);
if (file_fdp < 0) {
CDBG("cannot open file %s\n", bufp);
rc = -1;
goto end;
}
CDBG("%s:dump frame to '%s'\n", __func__, bufp);
write(file_fdp,
(const void *)frame->buffer, len);
close(file_fdp);
end:
return rc;
}
static int mm_app_set_video_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
fmt->fmt = pme->dim.enc_format;
fmt->width = pme->dim.video_width;
fmt->height = pme->dim.video_height;
return rc;
}
#if 0
int mm_stream_deinit_video_buf(uint32_t camera_handle,
uint32_t ch_id, uint32_t stream_id,
void *user_data, uint8_t num_bufs,
mm_camera_buf_def_t *bufs)
{
int i, rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
for(i = 0; i < num_bufs; i++) {
rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &(pme->video_buf.frame[i].fd_data),
(void *)pme->video_buf.frame[i].buffer, pme->video_buf.frame_len);
if(rc != MM_CAMERA_OK) {
CDBG_ERROR("%s: mm_camera_do_munmap err, pmem_fd = %d, rc = %d",
__func__, bufs[i].fd, rc);
}
}
return rc;
}
int mm_stream_init_video_buf(uint32_t camera_handle,
uint32_t ch_id, uint32_t stream_id,
void *user_data,
mm_camera_frame_len_offset *frame_offset_info,
uint8_t num_bufs,
uint8_t *initial_reg_flag,
mm_camera_buf_def_t *bufs)
{
int i,j,num_planes, frame_len, y_off, cbcr_off;
uint32_t planes[VIDEO_MAX_PLANES];
uint32_t pmem_addr = 0;
mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
num_planes = frame_offset_info->num_planes;
for ( i = 0; i < num_planes; i++) {
planes[i] = frame_offset_info->mp[i].len;
}
frame_len = frame_offset_info->frame_len;
y_off = frame_offset_info->mp[0].offset;
cbcr_off = frame_offset_info->mp[1].offset;
CDBG("Allocating video Memory for %d buffers frame_len = %d",num_bufs,frame_offset_info->frame_len);
for (i = 0; i < num_bufs ; i++) {
int j;
pme->video_buf.reg[i] = 1;
initial_reg_flag[i] = 1;
pme->video_buf.frame_len = frame_len;
pme->video_buf.frame[i].ion_alloc.len = pme->video_buf.frame_len;
pme->video_buf.frame[i].ion_alloc.flags =
(0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
pme->video_buf.frame[i].ion_alloc.align = 4096;
pmem_addr = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
&(pme->video_buf.frame[i].ion_alloc), &(pme->video_buf.frame[i].fd_data),
&pme->video_buf.frame[i].fd);
pme->video_buf.frame[i].buffer = pmem_addr;
pme->video_buf.frame[i].path = OUTPUT_TYPE_V;
pme->video_buf.frame[i].y_off = 0;
pme->video_buf.frame[i].cbcr_off = planes[0];
pme->video_buf.frame[i].phy_offset = 0;
CDBG("Buffer allocated Successfully fd = %d",pme->video_buf.frame[i].fd);
bufs[i].fd = pme->video_buf.frame[i].fd;
//bufs[i].buffer = pmem_addr;
bufs[i].frame_len = pme->video_buf.frame[i].ion_alloc.len;
bufs[i].num_planes = num_planes;
bufs[i].frame = &pme->video_buf.frame[i];
/* Plane 0 needs to be set seperately. Set other planes
* in a loop. */
bufs[i].planes[0].length = planes[0];
bufs[i].planes[0].m.userptr = bufs[i].fd;
bufs[i].planes[0].data_offset = y_off;
bufs[i].planes[0].reserved[0] = 0;
//buf_def->buf.mp[i].frame_offset;
for (j = 1; j < num_planes; j++) {
bufs[i].planes[j].length = planes[j];
bufs[i].planes[j].m.userptr = bufs[i].fd;
bufs[i].planes[j].data_offset = cbcr_off;
bufs[i].planes[j].reserved[0] =
bufs[i].planes[j-1].reserved[0] +
bufs[i].planes[j-1].length;
}
}
return MM_CAMERA_OK;
}
#endif
void video_cb_signal(mm_camera_app_obj_t *pme)
{
if(pme->cam_state == CAMERA_STATE_RECORD) {
mm_camera_app_done();
}
}
static void mm_app_video_notify_cb(mm_camera_super_buf_t *bufs,
void *user_data)
{
int rc;
mm_camera_buf_def_t *frame = NULL;
mm_camera_app_obj_t *pme = NULL;
CDBG("%s: BEGIN\n", __func__);
frame = bufs->bufs[MM_CAMERA_PREVIEW] ;
pme = (mm_camera_app_obj_t *)user_data;
CDBG("%s: BEGIN - length=%d, frame idx = %d\n", __func__, frame->frame_len, frame->frame_idx);
//Need to code to Send to Encoder .. Simulat
CDBG("In CB function i/p = %p o/p = %p",bufs->bufs[MM_CAMERA_PREVIEW],frame);
dumpFrameToFile(frame,pme->dim.orig_video_width,pme->dim.orig_video_height,"video", 1);
if(MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,frame))
{
CDBG_ERROR("%s: Failed in Snapshot Qbuf\n", __func__);
return;
}
video_cb_signal(pme);
CDBG("%s: END\n", __func__);
}
int mm_app_config_video(int cam_id)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
mm_app_set_video_fmt(cam_id,&pme->stream[MM_CAMERA_VIDEO].str_config.fmt);
pme->stream[MM_CAMERA_VIDEO].str_config.need_stream_on = 1;
pme->stream[MM_CAMERA_VIDEO].str_config.num_of_bufs = VIDEO_BUF_NUM;
if(MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_VIDEO].id,
&pme->stream[MM_CAMERA_VIDEO].str_config))) {
CDBG_ERROR("%s:MM_CAMERA_VIDEO config streaming err=%d\n", __func__, rc);
goto end;
}
CDBG("config_stream stream is successfull");
pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.need_stream_on = pme->fullSizeSnapshot;
pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.num_of_bufs = 1;
mm_app_set_live_snapshot_fmt(cam_id,&pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.fmt);
if(MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id,
&pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config))) {
CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
goto end;
}
end:
return rc;
}
int mm_app_prepare_video(int cam_id)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
pme->stream[MM_CAMERA_VIDEO].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
mm_app_video_notify_cb,pme,
MM_CAMERA_VIDEO, 0);
if(!pme->stream[MM_CAMERA_VIDEO].id) {
CDBG("%s:MM_CAMERA_VIDEO streaming err = %d\n", __func__, rc);
rc = -1;
goto end;
}
CDBG("Add stream is successfull stream ID = %d",pme->stream[MM_CAMERA_PREVIEW].id);
/* Code to add live snapshot*/
pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
NULL,pme,
MM_CAMERA_SNAPSHOT_MAIN, 0);
CDBG("Add Snapshot main is successfull stream ID = %d",pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id);
if(!pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id) {
CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
rc = -1;
goto end;
}
/*if(mm_app_config_video(cam_id) != MM_CAMERA_OK)
{
CDBG_ERROR("%s:Video config err=%d\n", __func__, rc);
}*/
end:
return rc;
}
int mm_app_unprepare_video(int cam_id)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
if(MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_VIDEO].id))){
CDBG_ERROR("%s : Delete Stream Video error",__func__);
goto end;
}
if(MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id))){
CDBG_ERROR("%s : Delete Stream Video error",__func__);
goto end;
}
end:
CDBG("del_stream successfull");
return rc;
}
static int mm_app_streamon_video(int cam_id)
{
int stream[2];
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
if(mm_app_config_video(cam_id) != MM_CAMERA_OK)
{
CDBG_ERROR("%s:Video config err=%d\n", __func__, rc);
}
stream[MM_CAMERA_VIDEO] = pme->stream[MM_CAMERA_VIDEO].id;
if(MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,1,&stream[1])))
{
CDBG_ERROR("%s : Start Stream video Error",__func__);
return -1;
}
CDBG("Start video stream is successfull");
pme->cam_state = CAMERA_STATE_RECORD;
return rc;
}
static int mm_app_streamoff_video(int cam_id)
{
int stream[2];
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
stream[0] = pme->stream[MM_CAMERA_VIDEO].id;
if(MM_CAMERA_OK != (rc =pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,1,&stream)))
{
CDBG_ERROR("%s : stop Stream video Error",__func__);
goto end;
}
CDBG("stop video stream is successfull");
pme->cam_state = CAMERA_STATE_PREVIEW;
end:
return rc;
}
int mm_app_stop_video(int cam_id)
{
int stream[2];
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
stream[0] = pme->stream[MM_CAMERA_VIDEO].id;
if(MM_CAMERA_OK != (rc = mm_app_streamoff_video(cam_id))){
CDBG_ERROR("%s : Video Stream off error",__func__);
goto end;
}
end:
return rc;
}
static int mm_app_start_video(int cam_id)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
CDBG("pme = %p, pme->cam =%p, pme->ch = %d pme->cam->camera_handle = %d",
pme,pme->cam,pme->ch_id,pme->cam->camera_handle);
if(MM_CAMERA_OK != (rc = mm_app_prepare_video(cam_id))){
CDBG_ERROR("%s:MM_CAMERA_VIDEO streaming err = %d\n", __func__, rc);
goto end;
}
if(MM_CAMERA_OK != (rc = mm_app_streamon_video(cam_id))){
CDBG_ERROR("%s:MM_CAMERA_VIDEO streaming err = %d\n", __func__, rc);
goto end;
}
end:
CDBG("%s: END, rc=%d\n", __func__, rc);
return rc;
}
int mm_app_open_recorder(int cam_id)
{
int rc = MM_CAMERA_OK;
int value = 1;
int powermode = 1;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
CDBG("%s: mm_app_open_recorder",__func__);
if(pme->cam_mode == RECORDER_MODE) {
CDBG("%s : Already in record mode",__func__);
return rc;
}
if(MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))){
CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
goto end;
}
if(MM_CAMERA_OK != initDisplay())
{
CDBG_ERROR("%s : Could not initalize display",__func__);
goto end;
}
pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_RECORDING_HINT, &value);
pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_LOW_POWER_MODE, &powermode);
if(MM_CAMERA_OK != (rc = mm_app_prepare_preview(cam_id))){
CDBG_ERROR("%s:stream on preview err=%d\n", __func__, rc);
goto end;
}
if(MM_CAMERA_OK != (rc = mm_app_prepare_video(cam_id))){
CDBG_ERROR("%s:stream on video err=%d\n", __func__, rc);
goto end;
}
if(MM_CAMERA_OK != (rc = mm_app_streamon_preview(cam_id))){
CDBG_ERROR("%s:start preview err=%d\n", __func__, rc);
goto end;
}
pme->cam_mode = RECORDER_MODE;
end:
CDBG("%s: END, rc=%d\n", __func__, rc);
return rc;
}
int startRecording(int cam_id)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
CDBG("%s: Start Recording mode = %d state = %d",__func__,pme->cam_mode,pme->cam_state);
if(pme->cam_mode == CAMERA_MODE || pme->cam_mode == ZSL_MODE) {
switch(pme->cam_state) {
case CAMERA_STATE_PREVIEW:
if(MM_CAMERA_OK != mm_app_open_recorder(cam_id)){
CDBG_ERROR("%s: Open Record Failed \n", __func__);
return -1;
}
break;
case CAMERA_STATE_RECORD:
case CAMERA_STATE_SNAPSHOT:
default:
break;
}
}/*else{
mm_app_prepare_video(cam_id);
}*/
CDBG("%s : startRecording : mode = %d state = %d",__func__,pme->cam_mode,pme->cam_state);
if(pme->cam_mode == RECORDER_MODE && pme->cam_state == CAMERA_STATE_PREVIEW){
if(MM_CAMERA_OK != mm_app_streamon_video(cam_id)){
CDBG_ERROR("%s:start video err=%d\n", __func__, rc);
return -1;
}
}
CDBG("%s: END, rc=%d\n", __func__, rc);
return rc;
}
int stopRecording(int cam_id)
{
int rc = MM_CAMERA_OK;
mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
if(pme->cam_mode != RECORDER_MODE || pme->cam_state != CAMERA_STATE_RECORD) {
return rc;
}
if(MM_CAMERA_OK != mm_app_stop_video(cam_id)){
CDBG_ERROR("%s:stop video err=%d\n", __func__, rc);
return -1;
}
return rc;
}