summaryrefslogtreecommitdiffstats
path: root/libcamera
diff options
context:
space:
mode:
authorMike J. Chen <mjchen@sta.samsung.com>2011-01-21 17:33:39 -0800
committerAndroid Git Automerger <android-git-automerger@android.com>2011-01-21 17:33:39 -0800
commit75b9e15c39d07133c5033008209478ff1c811376 (patch)
tree7cd58edf0ef1c3f76e5febd23d20f7928a1535dd /libcamera
parent917d76478ff06c1e7767202f6ddb9e70116ef442 (diff)
parent395193b9992fa3ebed47700446d9d2ccf4428a45 (diff)
downloaddevice_samsung_crespo-75b9e15c39d07133c5033008209478ff1c811376.zip
device_samsung_crespo-75b9e15c39d07133c5033008209478ff1c811376.tar.gz
device_samsung_crespo-75b9e15c39d07133c5033008209478ff1c811376.tar.bz2
am 395193b9: am 050e57e0: S5PC11X: libcamera: buffer cleanup
* commit '395193b9992fa3ebed47700446d9d2ccf4428a45': S5PC11X: libcamera: buffer cleanup
Diffstat (limited to 'libcamera')
-rwxr-xr-xlibcamera/SecCamera.cpp254
-rw-r--r--libcamera/SecCamera.h9
-rw-r--r--libcamera/SecCameraHWInterface.cpp241
-rw-r--r--libcamera/SecCameraHWInterface.h23
4 files changed, 283 insertions, 244 deletions
diff --git a/libcamera/SecCamera.cpp b/libcamera/SecCamera.cpp
index 38f675c..6998a5d 100755
--- a/libcamera/SecCamera.cpp
+++ b/libcamera/SecCamera.cpp
@@ -81,21 +81,6 @@ unsigned long measure_time(struct timeval *start, struct timeval *stop)
return time;
}
-static int close_buffers(struct fimc_buffer *buffers)
-{
- int i;
-
- for (i = 0; i < MAX_BUFFERS; i++) {
- if (buffers[i].start) {
- munmap(buffers[i].start, buffers[i].length);
- //LOGV("munmap():virt. addr[%d]: 0x%x size = %d\n", i, (unsigned int) buffers[i].start, buffers[i].length);
- buffers[i].start = NULL;
- }
- }
-
- return 0;
-}
-
static int get_pixel_depth(unsigned int fmt)
{
int depth = 0;
@@ -137,21 +122,19 @@ static int get_pixel_depth(unsigned int fmt)
#define ALIGN_H(x) (((x) + 0x1F) & (~0x1F)) // Set as multiple of 32
#define ALIGN_BUF(x) (((x) + 0x1FFF)& (~0x1FFF)) // Set as multiple of 8K
-static int init_yuv_buffers(struct fimc_buffer *buffers, int width, int height, unsigned int fmt)
+static int init_preview_buffers(struct fimc_buffer *buffers, int width, int height, unsigned int fmt)
{
int i, len;
- len = (width * height * get_pixel_depth(fmt)) / 8;
+ if (fmt==V4L2_PIX_FMT_NV12T) {
+ len = ALIGN_BUF(ALIGN_W(width) * ALIGN_H(height)) +
+ ALIGN_BUF(ALIGN_W(width) * ALIGN_H(height / 2));
+ } else {
+ len = (width * height * get_pixel_depth(fmt)) / 8;
+ }
for (i = 0; i < MAX_BUFFERS; i++) {
- if (fmt==V4L2_PIX_FMT_NV12T) {
- buffers[i].start = NULL;
- buffers[i].length = ALIGN_BUF(ALIGN_W(width) * ALIGN_H(height)) +
- ALIGN_BUF(ALIGN_W(width) * ALIGN_H(height / 2));
- } else {
- buffers[i].start = NULL;
- buffers[i].length = len;
- }
+ buffers[i].length = len;
}
return 0;
@@ -178,11 +161,28 @@ static int fimc_poll(struct pollfd *events)
return ret;
}
-static int fimc_esd_poll(struct pollfd *events)
+int SecCamera::previewPoll(bool preview)
{
int ret;
- ret = poll(events, 1, 1000);
+ if (preview) {
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int status = 0;
+
+ if (!(++m_esd_check_count % 60)) {
+ status = getCameraSensorESDStatus();
+ m_esd_check_count = 0;
+ if (status) {
+ LOGE("ERR(%s) ESD status(%d)", __func__, status);
+ return status;
+ }
+ }
+#endif
+
+ ret = poll(&m_events_c, 1, 1000);
+ } else {
+ ret = poll(&m_events_c2, 1, 1000);
+ }
if (ret < 0) {
LOGE("ERR(%s):poll error\n", __func__);
@@ -355,34 +355,34 @@ static int fimc_v4l2_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs)
return req.count;
}
-static int fimc_v4l2_querybuf(int fp, struct fimc_buffer *buffers, enum v4l2_buf_type type, int nr_frames)
+static int fimc_v4l2_querybuf(int fp, struct fimc_buffer *buffer, enum v4l2_buf_type type)
{
struct v4l2_buffer v4l2_buf;
- int i, ret;
+ int ret;
- for (i = 0; i < nr_frames; i++) {
- v4l2_buf.type = type;
- v4l2_buf.memory = V4L2_MEMORY_MMAP;
- v4l2_buf.index = i;
+ LOGI("%s :", __func__);
- ret = ioctl(fp , VIDIOC_QUERYBUF, &v4l2_buf);
- if (ret < 0) {
- LOGE("ERR(%s):VIDIOC_QUERYBUF failed\n", __func__);
- return -1;
- }
+ v4l2_buf.type = type;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buf.index = 0;
- if (nr_frames == 1) {
- buffers[i].length = v4l2_buf.length;
- if ((buffers[i].start = (char *)mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
- fp, v4l2_buf.m.offset)) < 0) {
- LOGE("%s %d] mmap() failed\n",__func__, __LINE__);
- return -1;
- }
+ ret = ioctl(fp , VIDIOC_QUERYBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYBUF failed\n", __func__);
+ return -1;
+ }
- //LOGV("buffers[%d].start = %p v4l2_buf.length = %d", i, buffers[i].start, v4l2_buf.length);
- }
+ buffer->length = v4l2_buf.length;
+ if ((buffer->start = (char *)mmap(0, v4l2_buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fp, v4l2_buf.m.offset)) < 0) {
+ LOGE("%s %d] mmap() failed\n",__func__, __LINE__);
+ return -1;
}
+ LOGI("%s: buffer->start = %p v4l2_buf.length = %d",
+ __func__, buffer->start, v4l2_buf.length);
+
return 0;
}
@@ -443,7 +443,7 @@ static int fimc_v4l2_dqbuf(int fp)
ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf);
if (ret < 0) {
- LOGE("ERR(%s):VIDIOC_DQBUF failed\n", __func__);
+ LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame\n", __func__);
return ret;
}
@@ -604,6 +604,8 @@ SecCamera::SecCamera() :
m_params->sharpness = -1;
m_params->white_balance = -1;
+ memset(&m_capture_buf, 0, sizeof(m_capture_buf));
+
LOGV("%s :", __func__);
}
@@ -756,9 +758,9 @@ void SecCamera::DeinitCamera()
stopRecord();
- /* close m_cam_fd after stopRecord() because stopRecord()
- * uses m_cam_fd to change frame rate
- */
+ /* close m_cam_fd after stopRecord() because stopRecord()
+ * uses m_cam_fd to change frame rate
+ */
LOGI("DeinitCamera: m_cam_fd(%d)", m_cam_fd);
if (m_cam_fd > -1) {
close(m_cam_fd);
@@ -822,11 +824,8 @@ int SecCamera::startPreview(void)
ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_width,m_preview_height,m_preview_v4lformat, 0);
CHECK(ret);
- init_yuv_buffers(m_buffers_c, m_preview_width, m_preview_height, m_preview_v4lformat);
ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
CHECK(ret);
- ret = fimc_v4l2_querybuf(m_cam_fd, m_buffers_c, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
- CHECK(ret);
LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d\n",
__func__, m_preview_width, m_preview_height, m_angle);
@@ -880,10 +879,8 @@ int SecCamera::stopPreview(void)
LOGV("%s :", __func__);
- close_buffers(m_buffers_c);
-
if (m_flag_camera_start == 0) {
- LOGV("%s: doing nothing because m_flag_camera_start is zero", __func__);
+ LOGW("%s: doing nothing because m_flag_camera_start is zero", __func__);
return 0;
}
@@ -896,9 +893,9 @@ int SecCamera::stopPreview(void)
}
ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK(ret);
m_flag_camera_start = 0;
- CHECK(ret);
return ret;
}
@@ -906,6 +903,8 @@ int SecCamera::stopPreview(void)
//Recording
int SecCamera::startRecord(void)
{
+ int ret, i;
+
LOGV("%s :", __func__);
// aleady started
@@ -919,30 +918,22 @@ int SecCamera::startRecord(void)
return -1;
}
- memset(&m_events_c2, 0, sizeof(m_events_c2));
- m_events_c2.fd = m_cam_fd2;
- m_events_c2.events = POLLIN | POLLERR;
-
- int m_record_v4lformat = V4L2_PIX_FMT_NV12T;
/* enum_fmt, s_fmt sample */
- int ret = fimc_v4l2_enum_fmt(m_cam_fd2,m_record_v4lformat);
+ ret = fimc_v4l2_enum_fmt(m_cam_fd2, V4L2_PIX_FMT_NV12T);
CHECK(ret);
- LOGE("%s: m_recording_width = %d, m_recording_height = %d\n", __func__, m_recording_width, m_recording_height);
-
- ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_width, m_recording_height, m_record_v4lformat, 0);
+ LOGI("%s: m_recording_width = %d, m_recording_height = %d\n",
+ __func__, m_recording_width, m_recording_height);
+ ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_width,
+ m_recording_height, V4L2_PIX_FMT_NV12T, 0);
CHECK(ret);
- init_yuv_buffers(m_buffers_c2, m_recording_width, m_recording_height, m_record_v4lformat);
-
ret = fimc_v4l2_reqbufs(m_cam_fd2, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
CHECK(ret);
- ret = fimc_v4l2_querybuf(m_cam_fd2, m_buffers_c2, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
- CHECK(ret);
/* start with all buffers in queue */
- for (int i = 0; i < MAX_BUFFERS; i++) {
+ for (i = 0; i < MAX_BUFFERS; i++) {
ret = fimc_v4l2_qbuf(m_cam_fd2, i);
CHECK(ret);
}
@@ -950,7 +941,10 @@ int SecCamera::startRecord(void)
ret = fimc_v4l2_streamon(m_cam_fd2);
CHECK(ret);
- // It is a delay for a new frame, not to show the previous bigger ugly picture frame.
+ // Get and throw away the first frame since it is often garbled.
+ memset(&m_events_c2, 0, sizeof(m_events_c2));
+ m_events_c2.fd = m_cam_fd2;
+ m_events_c2.events = POLLIN | POLLERR;
ret = fimc_poll(&m_events_c2);
CHECK(ret);
@@ -963,21 +957,21 @@ int SecCamera::stopRecord(void)
{
int ret;
- if (m_flag_record_start == 0)
- return 0;
-
LOGV("%s :", __func__);
- close_buffers(m_buffers_c2);
+ if (m_flag_record_start == 0) {
+ LOGW("%s: doing nothing because m_flag_record_start is zero", __func__);
+ return 0;
+ }
if (m_cam_fd2 <= 0) {
LOGE("ERR(%s):Camera was closed\n", __func__);
return -1;
}
- ret = fimc_v4l2_streamoff(m_cam_fd2);
-
m_flag_record_start = 0;
+
+ ret = fimc_v4l2_streamoff(m_cam_fd2);
CHECK(ret);
return 0;
@@ -1029,20 +1023,7 @@ int SecCamera::getPreview()
int index;
int ret;
-#ifdef ENABLE_ESD_PREVIEW_CHECK
- int status = 0;
-
- if (!(++m_esd_check_count % 60)) {
- status = getCameraSensorESDStatus();
- m_esd_check_count = 0;
- }
-#endif // ENABLE_ESD_PREVIEW_CHECK
-
-#ifdef ENABLE_ESD_PREVIEW_CHECK
- if (m_flag_camera_start == 0 || fimc_esd_poll(&m_events_c) == 0 || status) {
-#else
- if (m_flag_camera_start == 0 || fimc_esd_poll(&m_events_c) == 0) {
-#endif
+ if (m_flag_camera_start == 0 || previewPoll(true) == 0) {
LOGE("ERR(%s):Start Camera Device Reset \n", __func__);
/* GAUDI Project([arun.c@samsung.com]) 2010.05.20. [Implemented ESD code] */
/*
@@ -1060,12 +1041,12 @@ int SecCamera::getPreview()
ret = fimc_v4l2_s_input(m_cam_fd, 1000);
CHECK(ret);
ret = startPreview();
-
if (ret < 0) {
LOGE("ERR(%s): startPreview() return %d\n", __func__, ret);
return 0;
}
}
+
index = fimc_v4l2_dqbuf(m_cam_fd);
if (!(0 <= index && index < MAX_BUFFERS)) {
LOGE("ERR(%s):wrong index = %d\n", __func__, index);
@@ -1078,25 +1059,31 @@ int SecCamera::getPreview()
return index;
}
-int SecCamera::getRecord()
+int SecCamera::getRecordFrame()
{
- int index;
-
if (m_flag_record_start == 0) {
LOGE("%s: m_flag_record_start is 0", __func__);
- startRecord();
- }
- fimc_poll(&m_events_c2);
- index = fimc_v4l2_dqbuf(m_cam_fd2);
- if (!(0 <= index && index < MAX_BUFFERS)) {
- LOGE("ERR(%s):wrong index = %d\n", __func__, index);
return -1;
}
- int ret = fimc_v4l2_qbuf(m_cam_fd2, index);
- CHECK(ret);
+ previewPoll(false);
+ return fimc_v4l2_dqbuf(m_cam_fd2);
+}
- return index;
+int SecCamera::releaseRecordFrame(int index)
+{
+ if (!m_flag_record_start) {
+ /* this can happen when recording frames are returned after
+ * the recording is stopped at the driver level. we don't
+ * need to return the buffers in this case and we've seen
+ * cases where fimc could crash if we called qbuf and it
+ * wasn't expecting it.
+ */
+ LOGI("%s: recording not in progress, ignoring", __func__);
+ return 0;
+ }
+
+ return fimc_v4l2_qbuf(m_cam_fd2, index);
}
int SecCamera::setPreviewSize(int width, int height, int pixel_format)
@@ -1175,6 +1162,7 @@ int SecCamera::setSnapshotCmd(void)
if (m_flag_camera_start > 0) {
LOG_TIME_START(0)
+ LOGW("WARN(%s):Camera was in preview, should have been stopped\n", __func__);
stopPreview();
LOG_TIME_END(0)
}
@@ -1190,11 +1178,9 @@ int SecCamera::setSnapshotCmd(void)
CHECK(ret);
ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, V4L2_PIX_FMT_JPEG);
CHECK(ret);
- init_yuv_buffers(m_buffers_c, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat);
-
ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
CHECK(ret);
- ret = fimc_v4l2_querybuf(m_cam_fd, m_buffers_c, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
+ ret = fimc_v4l2_querybuf(m_cam_fd, &m_capture_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
CHECK(ret);
ret = fimc_v4l2_qbuf(m_cam_fd, 0);
@@ -1207,6 +1193,21 @@ int SecCamera::setSnapshotCmd(void)
return 0;
}
+int SecCamera::endSnapshot(void)
+{
+ int ret;
+
+ LOGI("%s :", __func__);
+ if (m_capture_buf.start) {
+ munmap(m_capture_buf.start, m_capture_buf.length);
+ LOGI("munmap():virt. addr %p size = %d\n",
+ m_capture_buf.start, m_capture_buf.length);
+ m_capture_buf.start = NULL;
+ m_capture_buf.length = 0;
+ }
+ return 0;
+}
+
/*
* Set Jpeg quality & exif info and get JPEG data from camera ISP
*/
@@ -1223,7 +1224,7 @@ unsigned char* SecCamera::getJpeg(int *jpeg_size, unsigned int *phyaddr)
ret = fimc_poll(&m_events_c);
CHECK_PTR(ret);
index = fimc_v4l2_dqbuf(m_cam_fd);
- if (!(0 <= index && index < MAX_BUFFERS)) {
+ if (index != 0) {
LOGE("ERR(%s):wrong index = %d\n", __func__, index);
return NULL;
}
@@ -1241,7 +1242,7 @@ unsigned char* SecCamera::getJpeg(int *jpeg_size, unsigned int *phyaddr)
LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d\n\n",
index, m_snapshot_width, m_snapshot_height, *jpeg_size);
- addr = (unsigned char*)(m_buffers_c[index].start) + main_offset;
+ addr = (unsigned char*)(m_capture_buf.start) + main_offset;
*phyaddr = getPhyAddrY(index) + m_postview_offset;
LOG_TIME_START(2) // post
@@ -1381,6 +1382,7 @@ int SecCamera::getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_bu
if (m_flag_camera_start > 0) {
LOG_TIME_START(0)
+ LOGW("WARN(%s):Camera was in preview, should have been stopped\n", __func__);
stopPreview();
LOG_TIME_END(0)
}
@@ -1417,11 +1419,9 @@ int SecCamera::getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_bu
CHECK(ret);
ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat);
CHECK(ret);
- init_yuv_buffers(m_buffers_c, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat);
-
ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
CHECK(ret);
- ret = fimc_v4l2_querybuf(m_cam_fd, m_buffers_c, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
+ ret = fimc_v4l2_querybuf(m_cam_fd, &m_capture_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
CHECK(ret);
ret = fimc_v4l2_qbuf(m_cam_fd, 0);
@@ -1440,7 +1440,8 @@ int SecCamera::getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_bu
LOG_TIME_END(2)
- memcpy(yuv_buf, (unsigned char*)m_buffers_c[index].start, m_snapshot_width * m_snapshot_height * 2);
+ LOGI("%s : calling memcpy from m_capture_buf", __func__);
+ memcpy(yuv_buf, (unsigned char*)m_capture_buf.start, m_snapshot_width * m_snapshot_height * 2);
LOG_TIME_START(5) // post
fimc_v4l2_streamoff(m_cam_fd);
LOG_TIME_END(5)
@@ -1579,21 +1580,21 @@ int SecCamera::setSnapshotPixelFormat(int pixel_format)
if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV420", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__);
else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
- LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__);
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__);
else
- LOGE("SnapshotFormat:UnknownFormat");
+ LOGD("SnapshotFormat:UnknownFormat");
#endif
return 0;
}
@@ -1603,11 +1604,6 @@ int SecCamera::getSnapshotPixelFormat(void)
return m_snapshot_v4lformat;
}
-int SecCamera::cancelPicture(void)
-{
- return close_buffers(m_buffers_c);
-}
-
// ======================================================================
// Settings
@@ -1752,6 +1748,7 @@ int SecCamera::SetRotate(int angle)
}
}
}
+
return 0;
}
@@ -1777,6 +1774,7 @@ int SecCamera::setFrameRate(int frame_rate)
}
}
}
+
return 0;
}
diff --git a/libcamera/SecCamera.h b/libcamera/SecCamera.h
index 7710ce4..0580373 100644
--- a/libcamera/SecCamera.h
+++ b/libcamera/SecCamera.h
@@ -292,11 +292,11 @@ public:
int startRecord(void);
int stopRecord(void);
- int getRecord(void);
+ int getRecordFrame(void);
+ int releaseRecordFrame(int index);
unsigned int getRecPhyAddrY(int);
unsigned int getRecPhyAddrC(int);
- int cancelPicture(void);
int getPreview(void);
int setPreviewSize(int width, int height, int pixel_format);
int getPreviewSize(int *width, int *height, int *frame_size);
@@ -410,6 +410,7 @@ public:
int setExifOrientationInfo(int orientationInfo);
int setBatchReflection(void);
int setSnapshotCmd(void);
+ int endSnapshot(void);
int setCameraSensorReset(void);
int setSensorMode(int sensor_mode); /* Camcorder fix fps */
int setShotMode(int shot_mode); /* Shot mode */
@@ -424,6 +425,7 @@ public:
int setDefultIMEI(int imei);
int getDefultIMEI(void);
const __u8* getCameraSensorName(void);
+ int previewPoll(bool preview);
#ifdef ENABLE_ESD_PREVIEW_CHECK
int getCameraSensorESDStatus(void);
#endif // ENABLE_ESD_PREVIEW_CHECK
@@ -495,7 +497,6 @@ private:
int m_cam_fd2;
struct pollfd m_events_c2;
int m_flag_record_start;
- struct fimc_buffer m_buffers_c2[MAX_BUFFERS];
int m_preview_v4lformat;
int m_preview_width;
@@ -553,7 +554,7 @@ private:
exif_attribute_t mExifInfo;
- struct fimc_buffer m_buffers_c[MAX_BUFFERS];
+ struct fimc_buffer m_capture_buf;
struct pollfd m_events_c;
inline int m_frameSize(int format, int width, int height);
diff --git a/libcamera/SecCameraHWInterface.cpp b/libcamera/SecCameraHWInterface.cpp
index ff708ce..85e0c01 100644
--- a/libcamera/SecCameraHWInterface.cpp
+++ b/libcamera/SecCameraHWInterface.cpp
@@ -64,7 +64,6 @@ static const int EFFECT_SKIP_FRAME = 1;
CameraHardwareSec::CameraHardwareSec(int cameraId)
:
- mPreviewRunning(false),
mCaptureInProgress(false),
mParameters(),
mPreviewHeap(0),
@@ -129,6 +128,11 @@ CameraHardwareSec::CameraHardwareSec(int cameraId)
initDefaultParameters(cameraId);
mExitAutoFocusThread = false;
+ mExitPreviewThread = false;
+ /* whether the PreviewThread is active in preview or stopped. we
+ * create the thread but it is initially in stopped state.
+ */
+ mPreviewRunning = false;
mPreviewThread = new PreviewThread(this);
mAutoFocusThread = new AutoFocusThread(this);
mPictureThread = new PictureThread(this);
@@ -419,9 +423,37 @@ void CameraHardwareSec::setSkipFrame(int frame)
mSkipFrame = frame;
}
+int CameraHardwareSec::previewThreadWrapper()
+{
+ LOGI("%s: starting", __func__);
+ while (1) {
+ mPreviewLock.lock();
+ while (!mPreviewRunning) {
+ LOGI("%s: calling mSecCamera->stopPreview() and waiting", __func__);
+ mSecCamera->stopPreview();
+ /* signal that we're stopping */
+ mPreviewStoppedCondition.signal();
+ mPreviewCondition.wait(mPreviewLock);
+ LOGI("%s: return from wait", __func__);
+ }
+ mPreviewLock.unlock();
+
+ if (mExitPreviewThread) {
+ LOGI("%s: exiting", __func__);
+ mSecCamera->stopPreview();
+ return 0;
+ }
+ previewThread();
+ }
+}
+
int CameraHardwareSec::previewThread()
{
int index;
+ nsecs_t timestamp;
+ unsigned int phyYAddr;
+ unsigned int phyCAddr;
+ struct addrs *addrs;
index = mSecCamera->getPreview();
if (index < 0) {
@@ -436,7 +468,15 @@ int CameraHardwareSec::previewThread()
}
mSkipFrameLock.unlock();
- nsecs_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ phyYAddr = mSecCamera->getPhyAddrY(index);
+ phyCAddr = mSecCamera->getPhyAddrC(index);
+
+ if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
+ LOGE("ERR(%s):Fail on SecCamera getPhyAddr Y addr = %0x C addr = %0x", __func__, phyYAddr, phyCAddr);
+ return UNKNOWN_ERROR;
+ }
int width, height, frame_size, offset;
@@ -445,45 +485,29 @@ int CameraHardwareSec::previewThread()
offset = (frame_size + 16) * index;
sp<MemoryBase> buffer = new MemoryBase(mPreviewHeap, offset, frame_size);
- unsigned int phyYAddr = mSecCamera->getPhyAddrY(index);
- unsigned int phyCAddr = mSecCamera->getPhyAddrC(index);
-
- if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
- LOGE("ERR(%s):Fail on SecCamera. Invalid PhyAddr, Y addr = %0x C addr = %0x",
- __func__, phyYAddr, phyCAddr);
- return UNKNOWN_ERROR;
- }
memcpy(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size ), &phyYAddr, 4);
memcpy(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size + 4), &phyCAddr, 4);
#if defined(BOARD_USES_OVERLAY)
if (mUseOverlay) {
int ret;
+ overlay_buffer_t overlay_buffer;
+
mOverlayBufferIdx ^= 1;
memcpy(static_cast<unsigned char*>(mPreviewHeap->base()) + offset + frame_size + sizeof(phyYAddr) + sizeof(phyCAddr),
- &mOverlayBufferIdx, sizeof(mOverlayBufferIdx));
+ &mOverlayBufferIdx, sizeof(mOverlayBufferIdx));
ret = mOverlay->queueBuffer((void*)(static_cast<unsigned char *>(mPreviewHeap->base()) + (offset + frame_size)));
- if (ret == ALL_BUFFERS_FLUSHED) {
- goto OverlayEnd;
- } else if (ret == -1) {
+ if (ret == -1 ) {
LOGE("ERR(%s):overlay queueBuffer fail", __func__);
- goto OverlayEnd;
- }
-
- overlay_buffer_t overlay_buffer;
- ret = mOverlay->dequeueBuffer(&overlay_buffer);
-
- if (ret == ALL_BUFFERS_FLUSHED) {
- goto OverlayEnd;
- } else if (ret == -1) {
- LOGE("ERR(%s):overlay dequeueBuffer fail", __func__);
- goto OverlayEnd;
- }
- }
-
-OverlayEnd:
+ } else if (ret != ALL_BUFFERS_FLUSHED) {
+ ret = mOverlay->dequeueBuffer(&overlay_buffer);
+ if (ret == -1) {
+ LOGE("ERR(%s):overlay dequeueBuffer fail", __func__);
+ }
+ }
+ }
#endif
// Notify the client of a new frame.
@@ -492,35 +516,32 @@ OverlayEnd:
}
if (mRecordRunning == true) {
- int index = mSecCamera->getRecord();
-
+ index = mSecCamera->getRecordFrame();
if (index < 0) {
LOGE("ERR(%s):Fail on SecCamera->getRecord()", __func__);
return UNKNOWN_ERROR;
}
- unsigned int phyYAddr = mSecCamera->getRecPhyAddrY(index);
- unsigned int phyCAddr = mSecCamera->getRecPhyAddrC(index);
+ phyYAddr = mSecCamera->getRecPhyAddrY(index);
+ phyCAddr = mSecCamera->getRecPhyAddrC(index);
if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__, phyYAddr, phyCAddr);
return UNKNOWN_ERROR;
}
- struct addrs *addrs = (struct addrs *)mRecordHeap->base();
+
+ addrs = (struct addrs *)mRecordHeap->base();
sp<MemoryBase> buffer = new MemoryBase(mRecordHeap, index * sizeof(struct addrs), sizeof(struct addrs));
addrs[index].addr_y = phyYAddr;
addrs[index].addr_cbcr = phyCAddr;
+ addrs[index].buf_index = index;
// Notify the client of a new frame.
if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
- //nsecs_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, buffer, mCallbackCookie);
- }
- } else if (mRecordRunning == false) {
- if (mSecCamera->stopRecord() < 0) {
- LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);
- return UNKNOWN_ERROR;
+ } else {
+ mSecCamera->releaseRecordFrame(index);
}
}
@@ -534,18 +555,18 @@ status_t CameraHardwareSec::startPreview()
LOGV("%s :", __func__);
Mutex::Autolock lock(mStateLock);
- if (mPreviewRunning) {
- // already running
- LOGE("%s : preview thread already running", __func__);
- return INVALID_OPERATION;
- }
-
if (mCaptureInProgress) {
LOGE("%s : capture in progress, not allowed", __func__);
return INVALID_OPERATION;
}
- mSecCamera->stopPreview();
+ mPreviewLock.lock();
+ if (mPreviewRunning) {
+ // already running
+ LOGE("%s : preview thread already running", __func__);
+ mPreviewLock.unlock();
+ return INVALID_OPERATION;
+ }
setSkipFrame(INITIAL_SKIP_FRAME);
@@ -573,7 +594,8 @@ status_t CameraHardwareSec::startPreview()
LOGV("CameraHardwareSec: mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",mPostViewWidth,mPostViewHeight,mPostViewSize);
mPreviewRunning = true;
- mPreviewThread->run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+ mPreviewCondition.signal();
+ mPreviewLock.unlock();
return NO_ERROR;
}
@@ -641,24 +663,22 @@ void CameraHardwareSec::stopPreview()
{
LOGV("%s :", __func__);
- if (!previewEnabled())
- return;
-
- /* request that the preview thread exit. we can wait because we're
- * called by CameraServices with a lock but it has disabled all preview
- * related callbacks so previewThread should not invoke any callbacks.
- */
- mPreviewThread->requestExitAndWait();
-
- if (mSecCamera->stopPreview() < 0)
- LOGE("ERR(%s):Fail on mSecCamera->stopPreview()", __func__);
-
- mPreviewRunning = false;
+ /* request that the preview thread stop. */
+ mPreviewLock.lock();
+ if (mPreviewRunning) {
+ mPreviewRunning = false;
+ mPreviewCondition.signal();
+ /* wait until preview thread is stopped */
+ mPreviewStoppedCondition.wait(mPreviewLock);
+ } else {
+ LOGI("%s : preview not running, doing nothing", __func__);
+ }
+ mPreviewLock.unlock();
}
bool CameraHardwareSec::previewEnabled()
{
- Mutex::Autolock lock(mStateLock);
+ Mutex::Autolock lock(mPreviewLock);
LOGV("%s : %d", __func__, mPreviewRunning);
return mPreviewRunning;
}
@@ -683,7 +703,13 @@ void CameraHardwareSec::stopRecording()
{
LOGV("%s :", __func__);
- mRecordRunning = false;
+ if (mRecordRunning == true) {
+ if (mSecCamera->stopRecord() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);
+ return;
+ }
+ mRecordRunning = false;
+ }
}
bool CameraHardwareSec::recordingEnabled()
@@ -695,15 +721,11 @@ bool CameraHardwareSec::recordingEnabled()
void CameraHardwareSec::releaseRecordingFrame(const sp<IMemory>& mem)
{
- LOG_CAMERA_PREVIEW("%s :", __func__);
+ ssize_t offset;
+ sp<IMemoryHeap> heap = mem->getMemory(&offset, NULL);
+ struct addrs *addrs = (struct addrs *)((uint8_t *)heap->base() + offset);
-// ssize_t offset; size_t size;
-// sp<MemoryBase> mem1 = mem;
-// sp<MemoryHeapBase> heap = mem->getMemory(&offset, &size);
-// sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
-// mem1.clear();
-// heap.clear();
+ mSecCamera->releaseRecordFrame(addrs->buf_index);
}
// ---------------------------------------------------------------------------
@@ -722,12 +744,20 @@ int CameraHardwareSec::autoFocusThread()
* in CameraServices layer.
*/
mFocusLock.lock();
- mCondition.wait(mFocusLock);
- mFocusLock.unlock();
-
/* check early exit request */
- if (mExitAutoFocusThread)
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request0", __func__);
+ return NO_ERROR;
+ }
+ mFocusCondition.wait(mFocusLock);
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request1", __func__);
return NO_ERROR;
+ }
+ mFocusLock.unlock();
LOGV("%s : calling setAutoFocus", __func__);
if (mSecCamera->setAutofocus() < 0) {
@@ -757,6 +787,7 @@ int CameraHardwareSec::autoFocusThread()
mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
}
+ LOGV("%s : exiting with no error", __func__);
return NO_ERROR;
}
@@ -764,7 +795,7 @@ status_t CameraHardwareSec::autoFocus()
{
LOGV("%s :", __func__);
/* signal autoFocusThread to run once */
- mCondition.signal();
+ mFocusCondition.signal();
return NO_ERROR;
}
@@ -988,14 +1019,6 @@ int CameraHardwareSec::pictureThread()
LOG_CAMERA("getSnapshotAndJpeg interval: %lu us", LOG_TIME(1));
}
- /* the capture is done at this point so we can allow sensor commands
- * again, we still need to do jpeg and thumbnail processing, but the
- * sensor is available for something else
- */
- mStateLock.lock();
- mCaptureInProgress = false;
- mStateLock.unlock();
-
int JpegImageSize, JpegExifSize;
bool isLSISensor = false;
@@ -1051,21 +1074,14 @@ int CameraHardwareSec::pictureThread()
ret = mOverlay->queueBuffer((void*)(static_cast<unsigned char *>(mPreviewHeap->base()) + offset +
(mPostViewWidth*mPostViewHeight * 3 / 2)));
- if (ret == ALL_BUFFERS_FLUSHED) {
- goto PostviewOverlayEnd;
- } else if (ret == -1) {
+ if (ret == -1) {
LOGE("ERR(%s):overlay queueBuffer fail", __func__);
- goto PostviewOverlayEnd;
- }
-
- overlay_buffer_t overlay_buffer;
- ret = mOverlay->dequeueBuffer(&overlay_buffer);
-
- if (ret == ALL_BUFFERS_FLUSHED) {
- goto PostviewOverlayEnd;
- } else if (ret == -1) {
- LOGE("ERR(%s):overlay dequeueBuffer fail", __func__);
- goto PostviewOverlayEnd;
+ } else if (ret != ALL_BUFFERS_FLUSHED) {
+ overlay_buffer_t overlay_buffer;
+ ret = mOverlay->dequeueBuffer(&overlay_buffer);
+ if (ret == -1) {
+ LOGE("ERR(%s):overlay dequeueBuffer fail", __func__);
+ }
}
PostviewOverlayEnd:
@@ -1081,7 +1097,8 @@ PostviewOverlayEnd:
LOGV("JpegExifSize=%d", JpegExifSize);
if (JpegExifSize < 0) {
- return UNKNOWN_ERROR;
+ ret = UNKNOWN_ERROR;
+ goto out;
}
unsigned char *ExifStart = (unsigned char *)JpegHeap->base() + 2;
@@ -1098,6 +1115,12 @@ PostviewOverlayEnd:
LOG_CAMERA("pictureThread interval: %lu us", LOG_TIME(0));
LOGV("%s : pictureThread end", __func__);
+
+out:
+ mStateLock.lock();
+ mCaptureInProgress = false;
+ mStateLock.unlock();
+
return ret;
}
@@ -1126,9 +1149,6 @@ status_t CameraHardwareSec::cancelPicture()
{
mPictureThread->requestExitAndWait();
- mSecCamera->cancelPicture();
-
- LOGW("%s : not supported, just returning NO_ERROR", __func__);
return NO_ERROR;
}
@@ -2043,6 +2063,14 @@ void CameraHardwareSec::release()
* for ourself to exit, which is a deadlock.
*/
if (mPreviewThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable or running. signal it so it wakes
+ * up and can exit.
+ */
+ mPreviewThread->requestExit();
+ mExitPreviewThread = true;
+ mPreviewRunning = true; /* let it run so it can exit */
+ mPreviewCondition.signal();
mPreviewThread->requestExitAndWait();
mPreviewThread.clear();
}
@@ -2050,9 +2078,11 @@ void CameraHardwareSec::release()
/* this thread is normally already in it's threadLoop but blocked
* on the condition variable. signal it so it wakes up and can exit.
*/
+ mFocusLock.lock();
mAutoFocusThread->requestExit();
mExitAutoFocusThread = true;
- mCondition.signal();
+ mFocusCondition.signal();
+ mFocusLock.unlock();
mAutoFocusThread->requestExitAndWait();
mAutoFocusThread.clear();
}
@@ -2066,8 +2096,11 @@ void CameraHardwareSec::release()
if (mJpegHeap != NULL)
mJpegHeap.clear();
- if (mPreviewHeap != NULL)
+ if (mPreviewHeap != NULL) {
+ LOGI("%s: calling mPreviewHeap.dispose()", __func__);
+ mPreviewHeap->dispose();
mPreviewHeap.clear();
+ }
if (mRecordHeap != NULL)
mRecordHeap.clear();
diff --git a/libcamera/SecCameraHWInterface.h b/libcamera/SecCameraHWInterface.h
index 5c1a78b..150de62 100644
--- a/libcamera/SecCameraHWInterface.h
+++ b/libcamera/SecCameraHWInterface.h
@@ -83,13 +83,12 @@ private:
PreviewThread(CameraHardwareSec *hw):
Thread(false),
mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+ }
virtual bool threadLoop() {
- int ret = mHardware->previewThread();
- // loop until we need to quit
- if(ret == NO_ERROR)
- return true;
- else
- return false;
+ mHardware->previewThreadWrapper();
+ return false;
}
};
@@ -101,6 +100,7 @@ private:
mHardware(hw) { }
virtual bool threadLoop() {
mHardware->pictureThread();
+ mHardware->mSecCamera->endSnapshot();
return false;
}
};
@@ -123,7 +123,7 @@ private:
sp<PreviewThread> mPreviewThread;
int previewThread();
- bool mPreviewRunning;
+ int previewThreadWrapper();
sp<AutoFocusThread> mAutoFocusThread;
int autoFocusThread();
@@ -159,9 +159,16 @@ private:
void setSkipFrame(int frame);
/* used by auto focus thread to block until it's told to run */
mutable Mutex mFocusLock;
- mutable Condition mCondition;
+ mutable Condition mFocusCondition;
bool mExitAutoFocusThread;
+ /* used by preview thread to block until it's told to run */
+ mutable Mutex mPreviewLock;
+ mutable Condition mPreviewCondition;
+ mutable Condition mPreviewStoppedCondition;
+ bool mPreviewRunning;
+ bool mExitPreviewThread;
+
/* used to guard threading state */
mutable Mutex mStateLock;