"stop preview: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
}
+ {
+ // Ideally we should recover the override after recording stopped, but
+ // right now recording stream will live until here, so we are forced to
+ // recover here. TODO: find a better way to handle that (b/17495165)
+ SharedParameters::Lock l(mParameters);
+ l.mParameters.recoverOverriddenJpegSize();
+ }
// no break
case Parameters::WAITING_FOR_PREVIEW_WINDOW: {
SharedParameters::Lock l(mParameters);
// and we can't fail record start without stagefright asserting.
params.previewCallbackFlags = 0;
- res = updateProcessorStream<
- StreamingProcessor,
- &StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
- params);
+ bool recordingStreamNeedsUpdate;
+ res = mStreamingProcessor->recordingStreamNeedsUpdate(params, &recordingStreamNeedsUpdate);
if (res != OK) {
- ALOGE("%s: Camera %d: Unable to update recording stream: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
+ ALOGE("%s: Camera %d: Can't query recording stream",
+ __FUNCTION__, mCameraId);
return res;
}
+ if (recordingStreamNeedsUpdate) {
+ // Need to stop stream here in case updateRecordingStream fails
+ // Right now camera device cannot handle configureStream failure gracefully
+ // when device is streaming
+ res = mStreamingProcessor->stopStream();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't stop streaming to update record stream",
+ __FUNCTION__, mCameraId);
+ return res;
+ }
+ res = mDevice->waitUntilDrained();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
+ res = updateProcessorStream<
+ StreamingProcessor,
+ &StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
+ params);
+
+ // updateRecordingStream might trigger a configureStream call and device might fail
+ // configureStream due to jpeg size > video size. Try again with jpeg size overridden
+ // to video size.
+ // TODO: This may not be needed after we add stop streaming above. Remove that if
+ // it's the case.
+ if (res == BAD_VALUE) {
+ overrideVideoSnapshotSize(params);
+ res = updateProcessorStream<
+ StreamingProcessor,
+ &StreamingProcessor::updateRecordingStream>(mStreamingProcessor,
+ params);
+ }
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to update recording stream: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ return res;
+ }
+ }
+
Vector<int32_t> outputStreams;
outputStreams.push(getPreviewStreamId());
outputStreams.push(getRecordingStreamId());
res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,
outputStreams);
- // try to reconfigure jpeg to video size if configureStreams failed
- if (res == BAD_VALUE) {
- ALOGV("%s: Camera %d: configure still size to video size before recording"
- , __FUNCTION__, mCameraId);
- params.overrideJpegSizeByVideoSize();
- res = updateProcessorStream(mJpegProcessor, params);
- if (res != OK) {
- ALOGE("%s: Camera %d: Can't configure still image size to video size: %s (%d)",
- __FUNCTION__, mCameraId, strerror(-res), res);
- return res;
- }
+ // startStream might trigger a configureStream call and device might fail
+ // configureStream due to jpeg size > video size. Try again with jpeg size overridden
+ // to video size.
+ if (res == BAD_VALUE) {
+ overrideVideoSnapshotSize(params);
res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,
outputStreams);
}
mCameraService->playSound(CameraService::SOUND_RECORDING);
- l.mParameters.recoverOverriddenJpegSize();
res = startPreviewL(l.mParameters, true);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to return to preview",
return res;
}
+status_t Camera2Client::overrideVideoSnapshotSize(Parameters ¶ms) {
+ ALOGV("%s: Camera %d: configure still size to video size before recording"
+ , __FUNCTION__, mCameraId);
+ params.overrideJpegSizeByVideoSize();
+ status_t res = updateProcessorStream(mJpegProcessor, params);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Can't override video snapshot size to video size: %s (%d)",
+ __FUNCTION__, mCameraId, strerror(-res), res);
+ }
+ return res;
+}
+
const char* Camera2Client::kAutofocusLabel = "autofocus";
const char* Camera2Client::kTakepictureLabel = "take_picture";
return OK;
}
+status_t StreamingProcessor::recordingStreamNeedsUpdate(
+ const Parameters ¶ms, bool *needsUpdate) {
+ status_t res;
+
+ if (needsUpdate == 0) {
+ ALOGE("%s: Camera %d: invalid argument", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+
+ if (mRecordingStreamId == NO_STREAM) {
+ *needsUpdate = true;
+ return OK;
+ }
+
+ sp<CameraDeviceBase> device = mDevice.promote();
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+
+ uint32_t currentWidth, currentHeight;
+ res = device->getStreamInfo(mRecordingStreamId,
+ ¤tWidth, ¤tHeight, 0);
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Error querying recording output stream info: "
+ "%s (%d)", __FUNCTION__, mId,
+ strerror(-res), res);
+ return res;
+ }
+
+ if (mRecordingConsumer == 0 || currentWidth != (uint32_t)params.videoWidth ||
+ currentHeight != (uint32_t)params.videoHeight) {
+ *needsUpdate = true;
+ }
+ *needsUpdate = false;
+ return res;
+}
+
status_t StreamingProcessor::updateRecordingStream(const Parameters ¶ms) {
ATRACE_CALL();
status_t res;