From 121969b7e0d958092fae76226dc55fe8547a1da6 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Tue, 21 Oct 2014 14:12:25 -0700 Subject: release camera without holding CameraSource mutex Bug: 17997578 Change-Id: Iba93848ad10ba84d2d836573da7ce242c761582f --- media/libstagefright/CameraSource.cpp | 99 ++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 41 deletions(-) (limited to 'media/libstagefright/CameraSource.cpp') diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 2b50763..f76aed6 100644 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -677,63 +677,80 @@ void CameraSource::stopCameraRecording() { void CameraSource::releaseCamera() { ALOGV("releaseCamera"); - if (mCamera != 0) { + sp camera; + bool coldCamera = false; + { + Mutex::Autolock autoLock(mLock); + // get a local ref and clear ref to mCamera now + camera = mCamera; + mCamera.clear(); + coldCamera = (mCameraFlags & FLAGS_HOT_CAMERA) == 0; + } + + if (camera != 0) { int64_t token = IPCThreadState::self()->clearCallingIdentity(); - if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) { + if (coldCamera) { ALOGV("Camera was cold when we started, stopping preview"); - mCamera->stopPreview(); - mCamera->disconnect(); + camera->stopPreview(); + camera->disconnect(); } - mCamera->unlock(); - mCamera.clear(); - mCamera = 0; + camera->unlock(); IPCThreadState::self()->restoreCallingIdentity(token); } - if (mCameraRecordingProxy != 0) { - mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier); - mCameraRecordingProxy.clear(); + + { + Mutex::Autolock autoLock(mLock); + if (mCameraRecordingProxy != 0) { + mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier); + mCameraRecordingProxy.clear(); + } + mCameraFlags = 0; } - mCameraFlags = 0; } status_t CameraSource::reset() { ALOGD("reset: E"); - Mutex::Autolock autoLock(mLock); - mStarted = false; - mFrameAvailableCondition.signal(); - int64_t token; - bool isTokenValid = false; - if (mCamera != 0) { - token = IPCThreadState::self()->clearCallingIdentity(); - isTokenValid = true; - } - releaseQueuedFrames(); - while (!mFramesBeingEncoded.empty()) { - if (NO_ERROR != - mFrameCompleteCondition.waitRelative(mLock, - mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) { - ALOGW("Timed out waiting for outstanding frames being encoded: %zu", - mFramesBeingEncoded.size()); + { + Mutex::Autolock autoLock(mLock); + mStarted = false; + mFrameAvailableCondition.signal(); + + int64_t token; + bool isTokenValid = false; + if (mCamera != 0) { + token = IPCThreadState::self()->clearCallingIdentity(); + isTokenValid = true; + } + releaseQueuedFrames(); + while (!mFramesBeingEncoded.empty()) { + if (NO_ERROR != + mFrameCompleteCondition.waitRelative(mLock, + mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) { + ALOGW("Timed out waiting for outstanding frames being encoded: %zu", + mFramesBeingEncoded.size()); + } + } + stopCameraRecording(); + if (isTokenValid) { + IPCThreadState::self()->restoreCallingIdentity(token); } - } - stopCameraRecording(); - releaseCamera(); - if (isTokenValid) { - IPCThreadState::self()->restoreCallingIdentity(token); - } - if (mCollectStats) { - ALOGI("Frames received/encoded/dropped: %d/%d/%d in %" PRId64 " us", - mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, - mLastFrameTimestampUs - mFirstFrameTimeUs); - } + if (mCollectStats) { + ALOGI("Frames received/encoded/dropped: %d/%d/%d in %" PRId64 " us", + mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped, + mLastFrameTimestampUs - mFirstFrameTimeUs); + } - if (mNumGlitches > 0) { - ALOGW("%d long delays between neighboring video frames", mNumGlitches); + if (mNumGlitches > 0) { + ALOGW("%d long delays between neighboring video frames", mNumGlitches); + } + + CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); } - CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped); + releaseCamera(); + ALOGD("reset: X"); return OK; } -- cgit v1.1