summaryrefslogtreecommitdiffstats
path: root/libcamera/SecCameraHWInterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libcamera/SecCameraHWInterface.cpp')
-rw-r--r--libcamera/SecCameraHWInterface.cpp241
1 files changed, 137 insertions, 104 deletions
diff --git a/libcamera/SecCameraHWInterface.cpp b/libcamera/SecCameraHWInterface.cpp
index bbbb48c..7e36a9d 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);
@@ -414,9 +418,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) {
@@ -431,7 +463,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;
@@ -440,45 +480,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.
@@ -487,35 +511,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);
}
}
@@ -529,18 +550,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);
@@ -568,7 +589,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;
}
@@ -636,24 +658,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;
}
@@ -678,7 +698,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()
@@ -690,15 +716,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);
}
// ---------------------------------------------------------------------------
@@ -717,12 +739,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) {
@@ -752,6 +782,7 @@ int CameraHardwareSec::autoFocusThread()
mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
}
+ LOGV("%s : exiting with no error", __func__);
return NO_ERROR;
}
@@ -759,7 +790,7 @@ status_t CameraHardwareSec::autoFocus()
{
LOGV("%s :", __func__);
/* signal autoFocusThread to run once */
- mCondition.signal();
+ mFocusCondition.signal();
return NO_ERROR;
}
@@ -983,14 +1014,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;
@@ -1046,21 +1069,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:
@@ -1076,7 +1092,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;
@@ -1093,6 +1110,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;
}
@@ -1121,9 +1144,6 @@ status_t CameraHardwareSec::cancelPicture()
{
mPictureThread->requestExitAndWait();
- mSecCamera->cancelPicture();
-
- LOGW("%s : not supported, just returning NO_ERROR", __func__);
return NO_ERROR;
}
@@ -2038,6 +2058,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();
}
@@ -2045,9 +2073,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();
}
@@ -2061,8 +2091,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();