summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/ACodec.h2
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp4
-rw-r--r--media/libmedia/mediaplayer.cpp2
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp4
-rw-r--r--media/libstagefright/ACodec.cpp31
-rw-r--r--media/libstagefright/MetaData.cpp1
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp2
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.cpp3
-rw-r--r--services/audioflinger/AudioPolicyService.cpp14
-rw-r--r--services/audioflinger/Effects.cpp2
-rw-r--r--services/audioflinger/Threads.cpp8
-rw-r--r--services/audioflinger/test-resample.cpp4
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp120
-rw-r--r--services/camera/libcameraservice/Camera3Device.cpp40
-rw-r--r--services/camera/libcameraservice/Camera3Device.h1
-rw-r--r--services/camera/libcameraservice/camera2/CallbackProcessor.cpp27
-rw-r--r--services/camera/libcameraservice/camera2/CaptureSequencer.cpp6
-rw-r--r--services/camera/libcameraservice/camera2/ZslProcessor3.cpp5
18 files changed, 189 insertions, 87 deletions
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 34bae29..df25d7b 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -278,7 +278,7 @@ private:
void deferMessage(const sp<AMessage> &msg);
void processDeferredMessages();
- void sendFormatChange();
+ void sendFormatChange(const sp<AMessage> &reply);
void signalError(
OMX_ERRORTYPE error = OMX_ErrorUndefined,
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 54f8d9e..85232e7 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -82,7 +82,7 @@ const effect_descriptor_t gBassBoostDescriptor = {
{0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
{0x8631f300, 0x72e2, 0x11df, 0xb57e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
EFFECT_CONTROL_API_VERSION,
- (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_DEVICE_IND
| EFFECT_FLAG_VOLUME_CTRL),
BASS_BOOST_CUP_LOAD_ARM9E,
BUNDLE_MEM_USAGE,
@@ -108,7 +108,7 @@ const effect_descriptor_t gEqualizerDescriptor = {
{0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
{0xce772f20, 0x847d, 0x11df, 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid Eq NXP
EFFECT_CONTROL_API_VERSION,
- (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL),
EQUALIZER_CUP_LOAD_ARM9E,
BUNDLE_MEM_USAGE,
"Equalizer",
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 68cbdf5..963b04f 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -124,7 +124,7 @@ status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
mCurrentState = MEDIA_PLAYER_INITIALIZED;
err = NO_ERROR;
} else {
- ALOGE("Unable to to create media player");
+ ALOGE("Unable to create media player");
}
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index acff958..57ec7ea 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -321,7 +321,7 @@ status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& ar
mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
result.append(buffer);
}
- snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
+ snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n",
mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
result.append(buffer);
snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
@@ -535,8 +535,8 @@ void MediaPlayerService::Client::disconnect()
{
Mutex::Autolock l(mLock);
p = mPlayer;
+ mClient.clear();
}
- mClient.clear();
mPlayer.clear();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 64e3885..cf41cf2 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2229,7 +2229,7 @@ void ACodec::processDeferredMessages() {
}
}
-void ACodec::sendFormatChange() {
+void ACodec::sendFormatChange(const sp<AMessage> &reply) {
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatOutputFormatChanged);
@@ -2294,14 +2294,12 @@ void ACodec::sendFormatChange() {
rect.nTop + rect.nHeight - 1);
if (mNativeWindow != NULL) {
- android_native_rect_t crop;
- crop.left = rect.nLeft;
- crop.top = rect.nTop;
- crop.right = rect.nLeft + rect.nWidth;
- crop.bottom = rect.nTop + rect.nHeight;
-
- CHECK_EQ(0, native_window_set_crop(
- mNativeWindow.get(), &crop));
+ reply->setRect(
+ "crop",
+ rect.nLeft,
+ rect.nTop,
+ rect.nLeft + rect.nWidth,
+ rect.nTop + rect.nHeight);
}
}
break;
@@ -3057,8 +3055,11 @@ bool ACodec::BaseState::onOMXFillBufferDone(
break;
}
+ sp<AMessage> reply =
+ new AMessage(kWhatOutputBufferDrained, mCodec->id());
+
if (!mCodec->mSentFormat) {
- mCodec->sendFormatChange();
+ mCodec->sendFormatChange(reply);
}
info->mData->setRange(rangeOffset, rangeLength);
@@ -3081,9 +3082,6 @@ bool ACodec::BaseState::onOMXFillBufferDone(
notify->setBuffer("buffer", info->mData);
notify->setInt32("flags", flags);
- sp<AMessage> reply =
- new AMessage(kWhatOutputBufferDrained, mCodec->id());
-
reply->setPointer("buffer-id", info->mBufferID);
notify->setMessage("reply", reply);
@@ -3127,6 +3125,13 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
+ android_native_rect_t crop;
+ if (msg->findRect("crop",
+ &crop.left, &crop.top, &crop.right, &crop.bottom)) {
+ CHECK_EQ(0, native_window_set_crop(
+ mCodec->mNativeWindow.get(), &crop));
+ }
+
int32_t render;
if (mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
index a01ec97..ae6ae2d 100644
--- a/media/libstagefright/MetaData.cpp
+++ b/media/libstagefright/MetaData.cpp
@@ -282,6 +282,7 @@ void MetaData::typed_data::freeStorage() {
if (!usesReservoir()) {
if (u.ext_data) {
free(u.ext_data);
+ u.ext_data = NULL;
}
}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 8bc0275..e02af90 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -748,10 +748,10 @@ void SoftMPEG4Encoder::onQueueFilled(OMX_U32 portIndex) {
outQueue.erase(outQueue.begin());
CHECK(!mInputBufferInfoVec.empty());
InputBufferInfo *inputBufInfo = mInputBufferInfoVec.begin();
- mInputBufferInfoVec.erase(mInputBufferInfoVec.begin());
outHeader->nTimeStamp = inputBufInfo->mTimeUs;
outHeader->nFlags |= (inputBufInfo->mFlags | OMX_BUFFERFLAG_ENDOFFRAME);
outHeader->nFilledLen = dataLength;
+ mInputBufferInfoVec.erase(mInputBufferInfoVec.begin());
outInfo->mOwnedByUs = false;
notifyFillBufferDone(outHeader);
}
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 501a970..af369b5 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -117,7 +117,8 @@ void ARTPConnection::MakePortPair(
bumpSocketBufferSize(*rtcpSocket);
- unsigned start = (rand() * 1000)/ RAND_MAX + 15550;
+ /* rand() * 1000 may overflow int type, use long long */
+ unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
start &= ~1;
for (unsigned port = start; port < 65536; port += 2) {
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 4256fc4..2706880 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -49,6 +49,8 @@ static const char kCmdDeadlockedString[] = "AudioPolicyService command thread ma
static const int kDumpLockRetries = 50;
static const int kDumpLockSleepUs = 20000;
+static const nsecs_t kAudioCommandTimeout = 3000000000; // 3 seconds
+
namespace {
extern struct audio_policy_service_ops aps_ops;
};
@@ -707,7 +709,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
data->mIO);
if (command->mWaitStatus) {
command->mCond.signal();
- mWaitWorkCV.wait(mLock);
+ command->mCond.waitRelative(mLock, kAudioCommandTimeout);
}
delete data;
}break;
@@ -718,7 +720,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
if (command->mWaitStatus) {
command->mCond.signal();
- mWaitWorkCV.wait(mLock);
+ command->mCond.waitRelative(mLock, kAudioCommandTimeout);
}
delete data;
}break;
@@ -729,7 +731,7 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
if (command->mWaitStatus) {
command->mCond.signal();
- mWaitWorkCV.wait(mLock);
+ command->mCond.waitRelative(mLock, kAudioCommandTimeout);
}
delete data;
}break;
@@ -837,7 +839,7 @@ status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type
if (command->mWaitStatus) {
command->mCond.wait(mLock);
status = command->mStatus;
- mWaitWorkCV.signal();
+ command->mCond.signal();
}
return status;
}
@@ -862,7 +864,7 @@ status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_hand
if (command->mWaitStatus) {
command->mCond.wait(mLock);
status = command->mStatus;
- mWaitWorkCV.signal();
+ command->mCond.signal();
}
return status;
}
@@ -883,7 +885,7 @@ status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume
if (command->mWaitStatus) {
command->mCond.wait(mLock);
status = command->mStatus;
- mWaitWorkCV.signal();
+ command->mCond.signal();
}
return status;
}
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index d66294c..942ea35 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -680,7 +680,7 @@ status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
return mStatus;
}
status_t status = NO_ERROR;
- if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+ if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
status_t cmdStatus;
uint32_t size = sizeof(status_t);
uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6b3ded9..97f66f4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2990,9 +2990,11 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l()
// forward device change to effects that have requested to be
// aware of attached audio device.
- mOutDevice = value;
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mOutDevice);
+ if (value != AUDIO_DEVICE_NONE) {
+ mOutDevice = value;
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ mEffectChains[i]->setDevice_l(mOutDevice);
+ }
}
}
diff --git a/services/audioflinger/test-resample.cpp b/services/audioflinger/test-resample.cpp
index b082e8c..7a314cf 100644
--- a/services/audioflinger/test-resample.cpp
+++ b/services/audioflinger/test-resample.cpp
@@ -219,12 +219,12 @@ int main(int argc, char* argv[]) {
memset(output_vaddr, 0, output_size);
timespec start, end;
- clock_gettime(CLOCK_MONOTONIC_HR, &start);
+ clock_gettime(CLOCK_MONOTONIC, &start);
resampler->resample((int*) output_vaddr, out_frames, &provider);
resampler->resample((int*) output_vaddr, out_frames, &provider);
resampler->resample((int*) output_vaddr, out_frames, &provider);
resampler->resample((int*) output_vaddr, out_frames, &provider);
- clock_gettime(CLOCK_MONOTONIC_HR, &end);
+ clock_gettime(CLOCK_MONOTONIC, &end);
int64_t start_ns = start.tv_sec * 1000000000LL + start.tv_nsec;
int64_t end_ns = end.tv_sec * 1000000000LL + end.tv_nsec;
int64_t time = (end_ns - start_ns)/4;
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 081fdec..16688cf 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -611,27 +611,35 @@ void Camera2Client::setPreviewCallbackFlag(int flag) {
void Camera2Client::setPreviewCallbackFlagL(Parameters &params, int flag) {
status_t res = OK;
+
+ switch(params.state) {
+ case Parameters::STOPPED:
+ case Parameters::WAITING_FOR_PREVIEW_WINDOW:
+ case Parameters::PREVIEW:
+ // OK
+ break;
+ default:
+ if (flag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+ ALOGE("%s: Camera %d: Can't use preview callbacks "
+ "in state %d", __FUNCTION__, mCameraId, params.state);
+ return;
+ }
+ }
+
if (flag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
ALOGV("%s: setting oneshot", __FUNCTION__);
params.previewCallbackOneShot = true;
}
if (params.previewCallbackFlags != (uint32_t)flag) {
params.previewCallbackFlags = flag;
- switch(params.state) {
- case Parameters::PREVIEW:
+
+ if (params.state == Parameters::PREVIEW) {
res = startPreviewL(params, true);
- break;
- case Parameters::RECORD:
- case Parameters::VIDEO_SNAPSHOT:
- res = startRecordingL(params, true);
- break;
- default:
- break;
- }
- if (res != OK) {
- ALOGE("%s: Camera %d: Unable to refresh request in state %s",
- __FUNCTION__, mCameraId,
- Parameters::getStateName(params.state));
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to refresh request in state %s",
+ __FUNCTION__, mCameraId,
+ Parameters::getStateName(params.state));
+ }
}
}
@@ -682,10 +690,46 @@ status_t Camera2Client::startPreviewL(Parameters &params, bool restart) {
return res;
}
+ // We could wait to create the JPEG output stream until first actual use
+ // (first takePicture call). However, this would substantially increase the
+ // first capture latency on HAL3 devices, and potentially on some HAL2
+ // devices. So create it unconditionally at preview start. As a drawback,
+ // this increases gralloc memory consumption for applications that don't
+ // ever take a picture.
+ // TODO: Find a better compromise, though this likely would involve HAL
+ // changes.
+ res = updateProcessorStream(mJpegProcessor, params);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't pre-configure still image "
+ "stream: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ return res;
+ }
+
Vector<uint8_t> outputStreams;
bool callbacksEnabled = params.previewCallbackFlags &
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
if (callbacksEnabled) {
+ // Can't have recording stream hanging around when enabling callbacks,
+ // since it exceeds the max stream count on some devices.
+ if (mStreamingProcessor->getRecordingStreamId() != NO_STREAM) {
+ ALOGV("%s: Camera %d: Clearing out recording stream before "
+ "creating callback stream", __FUNCTION__, mCameraId);
+ res = mStreamingProcessor->stopStream();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't stop streaming to delete "
+ "recording stream", __FUNCTION__, mCameraId);
+ return res;
+ }
+ res = mStreamingProcessor->deleteRecordingStream();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to delete recording stream before "
+ "enabling callbacks: %s (%d)", __FUNCTION__, mCameraId,
+ strerror(-res), res);
+ return res;
+ }
+ }
+
res = mCallbackProcessor->updateStream(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
@@ -719,18 +763,6 @@ status_t Camera2Client::startPreviewL(Parameters &params, bool restart) {
res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,
outputStreams);
} else {
- // With recording hint set, we're going to be operating under the
- // assumption that the user will record video. To optimize recording
- // startup time, create the necessary output streams for recording and
- // video snapshot now if they don't already exist.
- res = updateProcessorStream(mJpegProcessor, params);
- if (res != OK) {
- ALOGE("%s: Camera %d: Can't pre-configure still image "
- "stream: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
-
if (!restart) {
res = mStreamingProcessor->updateRecordingRequest(params);
if (res != OK) {
@@ -894,6 +926,29 @@ status_t Camera2Client::startRecordingL(Parameters &params, bool restart) {
}
}
+ // Not all devices can support a preview callback stream and a recording
+ // stream at the same time, so assume none of them can.
+ if (mCallbackProcessor->getStreamId() != NO_STREAM) {
+ ALOGV("%s: Camera %d: Clearing out callback stream before "
+ "creating recording stream", __FUNCTION__, mCameraId);
+ res = mStreamingProcessor->stopStream();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't stop streaming to delete callback stream",
+ __FUNCTION__, mCameraId);
+ return res;
+ }
+ res = mCallbackProcessor->deleteStream();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to delete callback stream before "
+ "record: %s (%d)", __FUNCTION__, mCameraId,
+ strerror(-res), res);
+ return res;
+ }
+ }
+ // Disable callbacks if they're enabled; can't record and use callbacks,
+ // and we can't fail record start without stagefright asserting.
+ params.previewCallbackFlags = 0;
+
res = updateProcessorStream<
StreamingProcessor,
&StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
@@ -905,17 +960,6 @@ status_t Camera2Client::startRecordingL(Parameters &params, bool restart) {
}
Vector<uint8_t> outputStreams;
- bool callbacksEnabled = params.previewCallbackFlags &
- CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK;
- if (callbacksEnabled) {
- res = mCallbackProcessor->updateStream(params);
- if (res != OK) {
- ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
- outputStreams.push(getCallbackStreamId());
- }
outputStreams.push(getPreviewStreamId());
outputStreams.push(getRecordingStreamId());
@@ -1647,6 +1691,8 @@ status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,
* queue) and then try again. Resume streaming once we're done.
*/
if (res == -EBUSY) {
+ ALOGV("%s: Camera %d: Pausing to update stream", __FUNCTION__,
+ mCameraId);
res = mStreamingProcessor->togglePauseStream(/*pause*/true);
if (res != OK) {
ALOGE("%s: Camera %d: Can't pause streaming: %s (%d)",
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index c7edb76..cc7802b 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -170,6 +170,7 @@ status_t Camera3Device::initialize(camera_module_t *module)
mHal3Device = device;
mStatus = STATUS_IDLE;
mNextStreamId = 0;
+ mNeedConfig = true;
return OK;
}
@@ -180,24 +181,29 @@ status_t Camera3Device::disconnect() {
ALOGV("%s: E", __FUNCTION__);
- status_t res;
- if (mStatus == STATUS_UNINITIALIZED) return OK;
+ status_t res = OK;
+ if (mStatus == STATUS_UNINITIALIZED) return res;
if (mStatus == STATUS_ACTIVE ||
(mStatus == STATUS_ERROR && mRequestThread != NULL)) {
res = mRequestThread->clearRepeatingRequests();
if (res != OK) {
SET_ERR_L("Can't stop streaming");
- return res;
- }
- res = waitUntilDrainedLocked();
- if (res != OK) {
- SET_ERR_L("Timeout waiting for HAL to drain");
- return res;
+ // Continue to close device even in case of error
+ } else {
+ res = waitUntilDrainedLocked();
+ if (res != OK) {
+ SET_ERR_L("Timeout waiting for HAL to drain");
+ // Continue to close device even in case of error
+ }
}
}
assert(mStatus == STATUS_IDLE || mStatus == STATUS_ERROR);
+ if (mStatus == STATUS_ERROR) {
+ CLOGE("Shutting down in an error state");
+ }
+
if (mRequestThread != NULL) {
mRequestThread->requestExit();
}
@@ -206,7 +212,12 @@ status_t Camera3Device::disconnect() {
mInputStream.clear();
if (mRequestThread != NULL) {
- mRequestThread->join();
+ if (mStatus != STATUS_ERROR) {
+ // HAL may be in a bad state, so waiting for request thread
+ // (which may be stuck in the HAL processCaptureRequest call)
+ // could be dangerous.
+ mRequestThread->join();
+ }
mRequestThread.clear();
}
@@ -218,7 +229,7 @@ status_t Camera3Device::disconnect() {
mStatus = STATUS_UNINITIALIZED;
ALOGV("%s: X", __FUNCTION__);
- return OK;
+ return res;
}
status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
@@ -582,6 +593,7 @@ status_t Camera3Device::createStream(sp<ANativeWindow> consumer,
}
*id = mNextStreamId++;
+ mNeedConfig = true;
// Continue captures if active at start
if (wasActive) {
@@ -707,6 +719,7 @@ status_t Camera3Device::deleteStream(int id) {
// fall through since we want to still list the stream as deleted.
}
mDeletedStreams.add(deletedStream);
+ mNeedConfig = true;
return res;
}
@@ -1007,6 +1020,12 @@ status_t Camera3Device::configureStreamsLocked() {
return INVALID_OPERATION;
}
+ if (!mNeedConfig) {
+ ALOGV("%s: Skipping config, no stream changes", __FUNCTION__);
+ mStatus = STATUS_ACTIVE;
+ return OK;
+ }
+
// Start configuring the streams
camera3_stream_configuration config;
@@ -1091,6 +1110,7 @@ status_t Camera3Device::configureStreamsLocked() {
// Finish configuring the streams lazily on first reference
mStatus = STATUS_ACTIVE;
+ mNeedConfig = false;
return OK;
}
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 7a8c22a..faa42b9 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -149,6 +149,7 @@ class Camera3Device :
StreamSet mOutputStreams;
sp<camera3::Camera3Stream> mInputStream;
int mNextStreamId;
+ bool mNeedConfig;
// Need to hold on to stream references until configure completes.
Vector<sp<camera3::Camera3StreamInterface> > mDeletedStreams;
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index 4987ab6..522f49a 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -74,8 +74,10 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
}
if (mCallbackConsumer == 0) {
- // Create CPU buffer queue endpoint
- mCallbackConsumer = new CpuConsumer(kCallbackHeapCount);
+ // Create CPU buffer queue endpoint. Make it async to avoid disconnect
+ // deadlocks.
+ mCallbackConsumer = new CpuConsumer(kCallbackHeapCount,
+ /*synchronized*/ false);
mCallbackConsumer->setFrameAvailableListener(this);
mCallbackConsumer->setName(String8("Camera2Client::CallbackConsumer"));
mCallbackWindow = new Surface(
@@ -133,7 +135,7 @@ status_t CallbackProcessor::updateStream(const Parameters &params) {
status_t CallbackProcessor::deleteStream() {
ATRACE_CALL();
sp<CameraDeviceBase> device;
-
+ status_t res;
{
Mutex::Autolock l(mInputMutex);
@@ -146,7 +148,19 @@ status_t CallbackProcessor::deleteStream() {
return INVALID_OPERATION;
}
}
- device->deleteStream(mCallbackStreamId);
+ res = device->waitUntilDrained();
+ if (res != OK) {
+ ALOGE("%s: Error waiting for HAL to drain: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+
+ res = device->deleteStream(mCallbackStreamId);
+ if (res != OK) {
+ ALOGE("%s: Unable to delete callback stream: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
{
Mutex::Autolock l(mInputMutex);
@@ -365,6 +379,9 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
ALOGV("%s: Freeing buffer", __FUNCTION__);
mCallbackConsumer->unlockBuffer(imgBuffer);
+
+ // mCallbackHeap may get freed up once input mutex is released
+ callbackHeap = mCallbackHeap;
}
// Call outside parameter lock to allow re-entrancy from notification
@@ -375,7 +392,7 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) {
ALOGV("%s: Camera %d: Invoking client data callback",
__FUNCTION__, mId);
l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME,
- mCallbackHeap->mBuffers[heapIdx], NULL);
+ callbackHeap->mBuffers[heapIdx], NULL);
}
}
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index 266e516..e5a011c 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -253,6 +253,12 @@ CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &c
res = INVALID_OPERATION;
break;
case Parameters::STILL_CAPTURE:
+ res = client->getCameraDevice()->waitUntilDrained();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't idle after still capture: "
+ "%s (%d)", __FUNCTION__, client->getCameraId(),
+ strerror(-res), res);
+ }
l.mParameters.state = Parameters::STOPPED;
break;
case Parameters::VIDEO_SNAPSHOT:
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
index 2e06691..40c77df 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor3.cpp
@@ -329,8 +329,9 @@ void ZslProcessor3::dump(int fd, const Vector<String16>& /*args*/) const {
}
bool ZslProcessor3::threadLoop() {
- // TODO: remove dependency on thread
- return true;
+ // TODO: remove dependency on thread. For now, shut thread down right
+ // away.
+ return false;
}
void ZslProcessor3::dumpZslQueue(int fd) const {