summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libmedia/SoundPool.cpp4
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp5
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp9
-rw-r--r--services/audioflinger/Threads.cpp35
-rw-r--r--services/audioflinger/Tracks.cpp4
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.cpp2
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.cpp69
-rw-r--r--services/camera/libcameraservice/api1/client2/Parameters.h12
-rw-r--r--services/camera/libcameraservice/common/Camera2ClientBase.cpp2
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp47
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h4
11 files changed, 153 insertions, 40 deletions
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
index 7f10e05..0985164 100644
--- a/media/libmedia/SoundPool.cpp
+++ b/media/libmedia/SoundPool.cpp
@@ -18,7 +18,7 @@
#define LOG_TAG "SoundPool"
#include <utils/Log.h>
-//#define USE_SHARED_MEM_BUFFER
+#define USE_SHARED_MEM_BUFFER
#include <media/AudioTrack.h>
#include <media/mediaplayer.h>
@@ -602,7 +602,7 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV
// do not create a new audio track if current track is compatible with sample parameters
#ifdef USE_SHARED_MEM_BUFFER
newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
- channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_NONE, callback, userData);
+ channels, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
#else
newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
channels, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e1735fa..750287f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1396,6 +1396,11 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
uint32_t flags;
CHECK(msg->findInt32("flags", (int32_t *)&flags));
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyFlagsChanged(flags);
+ }
+
if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
&& (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
cancelPollDuration();
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 3385a19..18cf6d1 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -358,11 +358,10 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
uint32_t flags = 0;
if (mHandler->isSeekable()) {
- flags = FLAG_CAN_PAUSE | FLAG_CAN_SEEK;
-
- // Seeking 10secs forward or backward is a very expensive
- // operation for rtsp, so let's not enable that.
- // The user can always use the seek bar.
+ flags = FLAG_CAN_PAUSE
+ | FLAG_CAN_SEEK
+ | FLAG_CAN_SEEK_BACKWARD
+ | FLAG_CAN_SEEK_FORWARD;
}
notifyFlagsChanged(flags);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1b5a9a9..4234965 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -109,6 +109,9 @@ static const uint32_t kMinNormalMixBufferSizeMs = 20;
// maximum normal mix buffer size
static const uint32_t kMaxNormalMixBufferSizeMs = 24;
+// Offloaded output thread standby delay: allows track transition without going to standby
+static const nsecs_t kOffloadStandbyDelayNs = seconds(1);
+
// Whether to use fast mixer
static const enum {
FastMixer_Never, // never initialize or use: for debugging only
@@ -2137,13 +2140,11 @@ bool AudioFlinger::PlaybackThread::threadLoop()
mWaitWorkCV.wait(mLock);
ALOGV("async completion/wake");
acquireWakeLock_l();
+ standbyTime = systemTime() + standbyDelay;
+ sleepTime = 0;
if (exitPending()) {
break;
}
- if (!mActiveTracks.size() && (systemTime() > standbyTime)) {
- continue;
- }
- sleepTime = 0;
} else if ((!mActiveTracks.size() && systemTime() > standbyTime) ||
isSuspended()) {
// put audio hardware into standby after short delay
@@ -3509,7 +3510,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep
if (track->mFillingUpStatus == Track::FS_FILLED) {
track->mFillingUpStatus = Track::FS_ACTIVE;
- mLeftVolFloat = mRightVolFloat = 0;
+ // make sure processVolume_l() will apply new volume even if 0
+ mLeftVolFloat = mRightVolFloat = -1.0;
if (track->mState == TrackBase::RESUMING) {
track->mState = TrackBase::ACTIVE;
}
@@ -3701,7 +3703,11 @@ void AudioFlinger::DirectOutputThread::cacheParameters_l()
// use shorter standby delay as on normal output to release
// hardware resources as soon as possible
- standbyDelay = microseconds(activeSleepTime*2);
+ if (audio_is_linear_pcm(mFormat)) {
+ standbyDelay = microseconds(activeSleepTime*2);
+ } else {
+ standbyDelay = kOffloadStandbyDelayNs;
+ }
}
// ----------------------------------------------------------------------------
@@ -3837,6 +3843,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
size_t count = mActiveTracks.size();
mixer_state mixerStatus = MIXER_IDLE;
+ bool doHwPause = false;
+ bool doHwResume = false;
+
// find out which tracks need to be processed
for (size_t i = 0; i < count; i++) {
sp<Track> t = mActiveTracks[i].promote();
@@ -3868,7 +3877,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
track->setPaused();
if (last) {
if (!mHwPaused) {
- mOutput->stream->pause(mOutput->stream);
+ doHwPause = true;
mHwPaused = true;
}
// If we were part way through writing the mixbuffer to
@@ -3887,7 +3896,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
ALOGVV("OffloadThread: track %d s=%08x [OK]", track->name(), cblk->mServer);
if (track->mFillingUpStatus == Track::FS_FILLED) {
track->mFillingUpStatus = Track::FS_ACTIVE;
- mLeftVolFloat = mRightVolFloat = 0;
+ // make sure processVolume_l() will apply new volume even if 0
+ mLeftVolFloat = mRightVolFloat = -1.0;
if (track->mState == TrackBase::RESUMING) {
if (mPausedBytesRemaining) {
// Need to continue write that was interrupted
@@ -3901,7 +3911,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
if (last) {
if (mHwPaused) {
- mOutput->stream->resume(mOutput->stream);
+ doHwResume = true;
mHwPaused = false;
// threadLoop_mix() will handle the case that we need to
// resume an interrupted write
@@ -3963,10 +3973,17 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
processVolume_l(track, last);
}
+ // make sure the pause/flush/resume sequence is executed in the right order
+ if (doHwPause) {
+ mOutput->stream->pause(mOutput->stream);
+ }
if (mFlushPending) {
flushHw_l();
mFlushPending = false;
}
+ if (doHwResume) {
+ mOutput->stream->resume(mOutput->stream);
+ }
// remove all the tracks that need to be...
removeTracks_l(*tracksToRemove);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3a5dc35..3b1874e 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -402,7 +402,7 @@ void AudioFlinger::PlaybackThread::Track::destroy()
/*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
{
- result.append(" Name Client Type Fmt Chn mask Session fCount S F SRate "
+ result.append(" Name Client Type Fmt Chn mask Session fCount S F SRate "
"L dB R dB Server Main buf Aux Buf Flags UndFrmCnt\n");
}
@@ -467,7 +467,7 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
nowInUnderrun = '?';
break;
}
- snprintf(&buffer[7], size-7, " %6u %4u %3u %08X %7u %6u %1c %1d %5u %5.2g %5.2g "
+ snprintf(&buffer[7], size-7, " %6u %4u %08X %08X %7u %6u %1c %1d %5u %5.2g %5.2g "
"%08X %08X %08X 0x%03X %9u%c\n",
(mClient == 0) ? getpid_cached : mClient->pid(),
mStreamType,
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index bda2887..e7f6c53 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -604,7 +604,7 @@ void Camera2Client::setPreviewCallbackFlagL(Parameters &params, int flag) {
}
if (params.previewCallbackFlags != (uint32_t)flag) {
- if (flag != CAMERA_FRAME_CALLBACK_FLAG_NOOP) {
+ if (params.previewCallbackSurface && flag != CAMERA_FRAME_CALLBACK_FLAG_NOOP) {
// Disable any existing preview callback window when enabling
// preview callback flags
res = mCallbackProcessor->setCallbackWindow(NULL);
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 0459866..ad55feb 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -58,13 +58,13 @@ status_t Parameters::initialize(const CameraMetadata *info) {
res = buildQuirks();
if (res != OK) return res;
- camera_metadata_ro_entry_t availableProcessedSizes =
- staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, 2);
- if (!availableProcessedSizes.count) return NO_INIT;
+ const Size MAX_PREVIEW_SIZE = { MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT };
+ res = getFilteredPreviewSizes(MAX_PREVIEW_SIZE, &availablePreviewSizes);
+ if (res != OK) return res;
// TODO: Pick more intelligently
- previewWidth = availableProcessedSizes.data.i32[0];
- previewHeight = availableProcessedSizes.data.i32[1];
+ previewWidth = availablePreviewSizes[0].width;
+ previewHeight = availablePreviewSizes[0].height;
videoWidth = previewWidth;
videoHeight = previewHeight;
@@ -75,12 +75,13 @@ status_t Parameters::initialize(const CameraMetadata *info) {
previewWidth, previewHeight));
{
String8 supportedPreviewSizes;
- for (size_t i=0; i < availableProcessedSizes.count; i += 2) {
+ for (size_t i = 0; i < availablePreviewSizes.size(); i++) {
if (i != 0) supportedPreviewSizes += ",";
supportedPreviewSizes += String8::format("%dx%d",
- availableProcessedSizes.data.i32[i],
- availableProcessedSizes.data.i32[i+1]);
+ availablePreviewSizes[i].width,
+ availablePreviewSizes[i].height);
}
+ ALOGV("Supported preview sizes are: %s", supportedPreviewSizes.string());
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
supportedPreviewSizes);
params.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
@@ -1072,15 +1073,13 @@ status_t Parameters::set(const String8& paramString) {
validatedParams.previewWidth, validatedParams.previewHeight);
return BAD_VALUE;
}
- camera_metadata_ro_entry_t availablePreviewSizes =
- staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
- for (i = 0; i < availablePreviewSizes.count; i += 2 ) {
- if ((availablePreviewSizes.data.i32[i] ==
+ for (i = 0; i < availablePreviewSizes.size(); i++) {
+ if ((availablePreviewSizes[i].width ==
validatedParams.previewWidth) &&
- (availablePreviewSizes.data.i32[i+1] ==
+ (availablePreviewSizes[i].height ==
validatedParams.previewHeight)) break;
}
- if (i == availablePreviewSizes.count) {
+ if (i == availablePreviewSizes.size()) {
ALOGE("%s: Requested preview size %d x %d is not supported",
__FUNCTION__, validatedParams.previewWidth,
validatedParams.previewHeight);
@@ -1618,15 +1617,13 @@ status_t Parameters::set(const String8& paramString) {
__FUNCTION__);
return BAD_VALUE;
}
- camera_metadata_ro_entry_t availableVideoSizes =
- staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
- for (i = 0; i < availableVideoSizes.count; i += 2 ) {
- if ((availableVideoSizes.data.i32[i] ==
+ for (i = 0; i < availablePreviewSizes.size(); i++) {
+ if ((availablePreviewSizes[i].width ==
validatedParams.videoWidth) &&
- (availableVideoSizes.data.i32[i+1] ==
+ (availablePreviewSizes[i].height ==
validatedParams.videoHeight)) break;
}
- if (i == availableVideoSizes.count) {
+ if (i == availablePreviewSizes.size()) {
ALOGE("%s: Requested video size %d x %d is not supported",
__FUNCTION__, validatedParams.videoWidth,
validatedParams.videoHeight);
@@ -2447,6 +2444,38 @@ int Parameters::normalizedYToArray(int y) const {
return cropYToArray(normalizedYToCrop(y));
}
+status_t Parameters::getFilteredPreviewSizes(Size limit, Vector<Size> *sizes) {
+ if (info == NULL) {
+ ALOGE("%s: Static metadata is not initialized", __FUNCTION__);
+ return NO_INIT;
+ }
+ if (sizes == NULL) {
+ ALOGE("%s: Input size is null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ const size_t SIZE_COUNT = sizeof(Size) / sizeof(int);
+ camera_metadata_ro_entry_t availableProcessedSizes =
+ staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, SIZE_COUNT);
+ if (availableProcessedSizes.count < SIZE_COUNT) return BAD_VALUE;
+
+ Size previewSize;
+ for (size_t i = 0; i < availableProcessedSizes.count; i += SIZE_COUNT) {
+ previewSize.width = availableProcessedSizes.data.i32[i];
+ previewSize.height = availableProcessedSizes.data.i32[i+1];
+ // Need skip the preview sizes that are too large.
+ if (previewSize.width <= limit.width &&
+ previewSize.height <= limit.height) {
+ sizes->push(previewSize);
+ }
+ }
+ if (sizes->isEmpty()) {
+ ALOGE("generated preview size list is empty!!");
+ return BAD_VALUE;
+ }
+ return OK;
+}
+
Parameters::CropRegion Parameters::calculateCropRegion(
Parameters::CropRegion::Outputs outputs) const {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 464830c..a7111a3 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -105,6 +105,11 @@ struct Parameters {
};
Vector<Area> focusingAreas;
+ struct Size {
+ int32_t width;
+ int32_t height;
+ };
+
int32_t exposureCompensation;
bool autoExposureLock;
bool autoWhiteBalanceLock;
@@ -159,6 +164,9 @@ struct Parameters {
// Number of zoom steps to simulate
static const unsigned int NUM_ZOOM_STEPS = 100;
+ // Max preview size allowed
+ static const unsigned int MAX_PREVIEW_WIDTH = 1920;
+ static const unsigned int MAX_PREVIEW_HEIGHT = 1080;
// Full static camera info, object owned by someone else, such as
// Camera2Device.
@@ -317,6 +325,10 @@ private:
int cropYToNormalized(int y) const;
int normalizedXToCrop(int x) const;
int normalizedYToCrop(int y) const;
+
+ Vector<Size> availablePreviewSizes;
+ // Get size list (that are no larger than limit) from static metadata.
+ status_t getFilteredPreviewSizes(Size limit, Vector<Size> *sizes);
};
// This class encapsulates the Parameters class so that it can only be accessed
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 060e2a2..e808bf3 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -95,7 +95,7 @@ status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, TClientBase::mCameraId, strerror(-res), res);
- return NO_INIT;
+ return res;
}
res = mDevice->setNotifyCallback(this);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index b70a278..b468eb3 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1630,6 +1630,19 @@ bool Camera3Device::RequestThread::threadLoop() {
// If the request is the same as last, or we had triggers last time
if (mPrevRequest != nextRequest || triggersMixedIn) {
/**
+ * HAL workaround:
+ * Insert a dummy trigger ID if a trigger is set but no trigger ID is
+ */
+ res = addDummyTriggerIds(nextRequest);
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to insert dummy trigger IDs "
+ "(capture request %d, HAL device: %s (%d)",
+ (mFrameNumber+1), strerror(-res), res);
+ cleanUpFailedRequest(request, nextRequest, outputBuffers);
+ return false;
+ }
+
+ /**
* The request should be presorted so accesses in HAL
* are O(logn). Sidenote, sorting a sorted metadata is nop.
*/
@@ -2047,6 +2060,40 @@ status_t Camera3Device::RequestThread::removeTriggers(
return OK;
}
+status_t Camera3Device::RequestThread::addDummyTriggerIds(
+ const sp<CaptureRequest> &request) {
+ // Trigger ID 0 has special meaning in the HAL2 spec, so avoid it here
+ static const int32_t dummyTriggerId = 1;
+ status_t res;
+
+ CameraMetadata &metadata = request->mSettings;
+
+ // If AF trigger is active, insert a dummy AF trigger ID if none already
+ // exists
+ camera_metadata_entry afTrigger = metadata.find(ANDROID_CONTROL_AF_TRIGGER);
+ camera_metadata_entry afId = metadata.find(ANDROID_CONTROL_AF_TRIGGER_ID);
+ if (afTrigger.count > 0 &&
+ afTrigger.data.u8[0] != ANDROID_CONTROL_AF_TRIGGER_IDLE &&
+ afId.count == 0) {
+ res = metadata.update(ANDROID_CONTROL_AF_TRIGGER_ID, &dummyTriggerId, 1);
+ if (res != OK) return res;
+ }
+
+ // If AE precapture trigger is active, insert a dummy precapture trigger ID
+ // if none already exists
+ camera_metadata_entry pcTrigger =
+ metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
+ camera_metadata_entry pcId = metadata.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
+ if (pcTrigger.count > 0 &&
+ pcTrigger.data.u8[0] != ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE &&
+ pcId.count == 0) {
+ res = metadata.update(ANDROID_CONTROL_AE_PRECAPTURE_ID,
+ &dummyTriggerId, 1);
+ if (res != OK) return res;
+ }
+
+ return OK;
+}
/**
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 0b3ad6e..61caf13 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -314,6 +314,10 @@ class Camera3Device :
// restoring the old field values for those tags.
status_t removeTriggers(const sp<CaptureRequest> &request);
+ // HAL workaround: Make sure a trigger ID always exists if
+ // a trigger does
+ status_t addDummyTriggerIds(const sp<CaptureRequest> &request);
+
static const nsecs_t kRequestTimeout = 50e6; // 50 ms
// Waits for a request, or returns NULL if times out.