summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp65
-rw-r--r--media/libstagefright/httplive/LiveSession.h2
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.cpp85
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.h3
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.cpp26
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.h7
-rw-r--r--services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp38
-rw-r--r--services/camera/libcameraservice/api1/client2/StreamingProcessor.h3
8 files changed, 197 insertions, 32 deletions
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 5f566ca..3720085 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -1286,12 +1286,6 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
CHECK(msg->findInt32("streamMask", (int32_t *)&streamMask));
CHECK(msg->findInt32("resumeMask", (int32_t *)&resumeMask));
- for (size_t i = 0; i < kMaxStreams; ++i) {
- if (streamMask & indexToType(i)) {
- CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
- }
- }
-
int64_t timeUs;
int32_t pickTrack;
bool switching = false;
@@ -1307,7 +1301,20 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
}
+ for (size_t i = 0; i < kMaxStreams; ++i) {
+ if (streamMask & indexToType(i)) {
+ if (switching) {
+ CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mNewUri));
+ } else {
+ CHECK(msg->findString(mStreams[i].uriKey().c_str(), &mStreams[i].mUri));
+ }
+ }
+ }
+
mNewStreamMask = streamMask | resumeMask;
+ if (switching) {
+ mSwapMask = mStreamMask & ~resumeMask;
+ }
// Of all existing fetchers:
// * Resume fetchers that are still needed and assign them original packet sources.
@@ -1357,7 +1364,7 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
}
AString uri;
- uri = mStreams[i].mUri;
+ uri = switching ? mStreams[i].mNewUri : mStreams[i].mUri;
sp<PlaylistFetcher> fetcher = addFetcher(uri.c_str());
CHECK(fetcher != NULL);
@@ -1370,7 +1377,8 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
// TRICKY: looping from i as earlier streams are already removed from streamMask
for (size_t j = i; j < kMaxStreams; ++j) {
- if ((streamMask & indexToType(j)) && uri == mStreams[j].mUri) {
+ const AString &streamUri = switching ? mStreams[j].mNewUri : mStreams[j].mUri;
+ if ((streamMask & indexToType(j)) && uri == streamUri) {
sources[j] = mPacketSources.valueFor(indexToType(j));
if (timeUs >= 0) {
@@ -1459,7 +1467,6 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
mReconfigurationInProgress = false;
if (switching) {
mSwitchInProgress = true;
- mSwapMask = streamMask;
} else {
mStreamMask = mNewStreamMask;
}
@@ -1478,6 +1485,15 @@ void LiveSession::onSwapped(const sp<AMessage> &msg) {
int32_t stream;
CHECK(msg->findInt32("stream", &stream));
+
+ ssize_t idx = typeToIndex(stream);
+ CHECK(idx >= 0);
+ if ((mNewStreamMask & stream) && mStreams[idx].mNewUri.empty()) {
+ ALOGW("swapping stream type %d %s to empty stream", stream, mStreams[idx].mUri.c_str());
+ }
+ mStreams[idx].mUri = mStreams[idx].mNewUri;
+ mStreams[idx].mNewUri.clear();
+
mSwapMask &= ~stream;
if (mSwapMask != 0) {
return;
@@ -1489,6 +1505,15 @@ void LiveSession::onSwapped(const sp<AMessage> &msg) {
StreamType extraStream = (StreamType) (extraStreams & ~(extraStreams - 1));
swapPacketSource(extraStream);
extraStreams &= ~extraStream;
+
+ idx = typeToIndex(extraStream);
+ CHECK(idx >= 0);
+ if (mStreams[idx].mNewUri.empty()) {
+ ALOGW("swapping extra stream type %d %s to empty stream",
+ extraStream, mStreams[idx].mUri.c_str());
+ }
+ mStreams[idx].mUri = mStreams[idx].mNewUri;
+ mStreams[idx].mNewUri.clear();
}
tryToFinishBandwidthSwitch();
@@ -1569,6 +1594,28 @@ void LiveSession::cancelBandwidthSwitch() {
mSwitchGeneration++;
mSwitchInProgress = false;
mSwapMask = 0;
+
+ for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
+ FetcherInfo& info = mFetcherInfos.editValueAt(i);
+ if (info.mToBeRemoved) {
+ info.mToBeRemoved = false;
+ }
+ }
+
+ for (size_t i = 0; i < kMaxStreams; ++i) {
+ if (!mStreams[i].mNewUri.empty()) {
+ ssize_t j = mFetcherInfos.indexOfKey(mStreams[i].mNewUri);
+ if (j < 0) {
+ mStreams[i].mNewUri.clear();
+ continue;
+ }
+
+ const FetcherInfo &info = mFetcherInfos.valueAt(j);
+ info.mFetcher->stopAsync();
+ mFetcherInfos.removeItemsAt(j);
+ mStreams[i].mNewUri.clear();
+ }
+ }
}
bool LiveSession::canSwitchBandwidthTo(size_t bandwidthIndex) {
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 26df543..6be86cf 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -126,7 +126,7 @@ private:
struct StreamItem {
const char *mType;
- AString mUri;
+ AString mUri, mNewUri;
size_t mCurDiscontinuitySeq;
int64_t mLastDequeuedTimeUs;
int64_t mLastSampleDurationUs;
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 6f4a507..10038c5 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -921,6 +921,13 @@ void Camera2Client::stopPreviewL() {
"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);
@@ -1075,34 +1082,65 @@ status_t Camera2Client::startRecordingL(Parameters &params, bool restart) {
// 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);
}
@@ -1146,7 +1184,6 @@ void Camera2Client::stopRecording() {
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",
@@ -1923,6 +1960,18 @@ status_t Camera2Client::updateProcessorStream(sp<ProcessorT> processor,
return res;
}
+status_t Camera2Client::overrideVideoSnapshotSize(Parameters &params) {
+ 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";
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index f5c3a30..d68bb29 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -208,6 +208,9 @@ private:
// Wait until the camera device has received the latest control settings
status_t syncWithDevice();
+
+ // Video snapshot jpeg size overriding helper function
+ status_t overrideVideoSnapshotSize(Parameters &params);
};
}; // namespace android
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 8d00590..ed9137f 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -76,9 +76,29 @@ status_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) {
res = getFilteredSizes(MAX_VIDEO_SIZE, &availableVideoSizes);
if (res != OK) return res;
- // TODO: Pick more intelligently
- previewWidth = availablePreviewSizes[0].width;
- previewHeight = availablePreviewSizes[0].height;
+ // Select initial preview and video size that's under the initial bound and
+ // on the list of both preview and recording sizes
+ previewWidth = 0;
+ previewHeight = 0;
+ for (size_t i = 0 ; i < availablePreviewSizes.size(); i++) {
+ int newWidth = availablePreviewSizes[i].width;
+ int newHeight = availablePreviewSizes[i].height;
+ if (newWidth >= previewWidth && newHeight >= previewHeight &&
+ newWidth <= MAX_INITIAL_PREVIEW_WIDTH &&
+ newHeight <= MAX_INITIAL_PREVIEW_HEIGHT) {
+ for (size_t j = 0; j < availableVideoSizes.size(); j++) {
+ if (availableVideoSizes[j].width == newWidth &&
+ availableVideoSizes[j].height == newHeight) {
+ previewWidth = newWidth;
+ previewHeight = newHeight;
+ }
+ }
+ }
+ }
+ if (previewWidth == 0) {
+ ALOGE("%s: No initial preview size can be found!", __FUNCTION__);
+ return BAD_VALUE;
+ }
videoWidth = previewWidth;
videoHeight = previewHeight;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 5e6e6ab..815cc55 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -179,8 +179,13 @@ struct Parameters {
// Number of zoom steps to simulate
static const unsigned int NUM_ZOOM_STEPS = 100;
// Max preview size allowed
+ // This is set to a 1:1 value to allow for any aspect ratio that has
+ // a max long side of 1920 pixels
static const unsigned int MAX_PREVIEW_WIDTH = 1920;
- static const unsigned int MAX_PREVIEW_HEIGHT = 1080;
+ static const unsigned int MAX_PREVIEW_HEIGHT = 1920;
+ // Initial max preview/recording size bound
+ static const int MAX_INITIAL_PREVIEW_WIDTH = 1920;
+ static const int MAX_INITIAL_PREVIEW_HEIGHT = 1080;
// Aspect ratio tolerance
static const float ASPECT_RATIO_TOLERANCE = 0.001;
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index ab0af0d..9e7fff8 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -318,6 +318,44 @@ status_t StreamingProcessor::updateRecordingRequest(const Parameters &params) {
return OK;
}
+status_t StreamingProcessor::recordingStreamNeedsUpdate(
+ const Parameters &params, 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,
+ &currentWidth, &currentHeight, 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 &params) {
ATRACE_CALL();
status_t res;
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
index 833bb8f..8466af4 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.h
@@ -54,6 +54,9 @@ class StreamingProcessor:
status_t setRecordingBufferCount(size_t count);
status_t updateRecordingRequest(const Parameters &params);
+ // If needsUpdate is set to true, a updateRecordingStream call with params will recreate
+ // recording stream
+ status_t recordingStreamNeedsUpdate(const Parameters &params, bool *needsUpdate);
status_t updateRecordingStream(const Parameters &params);
status_t deleteRecordingStream();
int getRecordingStreamId() const;