Merge "audioflinger: fix pre processing effect leak" into lmp-dev
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index d8ed836..511871d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1176,12 +1176,14 @@
void NuPlayer::GenericSource::readBuffer(
media_track_type trackType, int64_t seekTimeUs, int64_t *actualTimeUs, bool formatChange) {
Track *track;
+ size_t maxBuffers = 1;
switch (trackType) {
case MEDIA_TRACK_TYPE_VIDEO:
track = &mVideoTrack;
break;
case MEDIA_TRACK_TYPE_AUDIO:
track = &mAudioTrack;
+ maxBuffers = 64;
break;
case MEDIA_TRACK_TYPE_SUBTITLE:
track = &mSubtitleTrack;
@@ -1214,7 +1216,7 @@
options.setNonBlocking();
}
- for (;;) {
+ for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
MediaBuffer *mbuf;
status_t err = track->mSource->read(&mbuf, &options);
@@ -1245,7 +1247,7 @@
sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType, actualTimeUs);
track->mPackets->queueAccessUnit(buffer);
- break;
+ ++numBuffers;
} else if (err == WOULD_BLOCK) {
break;
} else if (err == INFO_FORMAT_CHANGED) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index df3e992..9020a8d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -50,6 +50,10 @@
namespace android {
+// TODO optimize buffer size for power consumption
+// The offload read buffer size is 32 KB but 24 KB uses less power.
+const size_t NuPlayer::kAggregateBufferSizeBytes = 24 * 1024;
+
struct NuPlayer::Action : public RefBase {
Action() {}
@@ -730,7 +734,7 @@
if (err == -EWOULDBLOCK) {
if (mSource->feedMoreTSData() == OK) {
- msg->post(10000ll);
+ msg->post(10 * 1000ll);
}
}
} else if (what == Decoder::kWhatEOS) {
@@ -995,6 +999,7 @@
ALOGV("both audio and video are flushed now.");
mPendingAudioAccessUnit.clear();
+ mAggregateBuffer.clear();
if (mTimeDiscontinuityPending) {
mRenderer->signalTimeDiscontinuity();
@@ -1256,14 +1261,8 @@
// Aggregate smaller buffers into a larger buffer.
// The goal is to reduce power consumption.
// Unfortunately this does not work with the software AAC decoder.
- // TODO optimize buffer size for power consumption
- // The offload read buffer size is 32 KB but 24 KB uses less power.
- const int kAudioBigBufferSizeBytes = 24 * 1024;
- bool doBufferAggregation = (audio && mOffloadAudio);
- sp<ABuffer> biggerBuffer;
+ bool doBufferAggregation = (audio && mOffloadAudio);;
bool needMoreData = false;
- int numSmallBuffers = 0;
- bool gotTime = false;
bool dropAccessUnit;
do {
@@ -1279,14 +1278,10 @@
}
if (err == -EWOULDBLOCK) {
- if (biggerBuffer == NULL) {
- return err;
- } else {
- break; // Reply with data that we already have.
- }
+ return err;
} else if (err != OK) {
if (err == INFO_DISCONTINUITY) {
- if (biggerBuffer != NULL) {
+ if (mAggregateBuffer != NULL) {
// We already have some data so save this for later.
mPendingAudioErr = err;
mPendingAudioAccessUnit = accessUnit;
@@ -1401,46 +1396,45 @@
size_t smallSize = accessUnit->size();
needMoreData = false;
- if (doBufferAggregation && (biggerBuffer == NULL)
+ if (doBufferAggregation && (mAggregateBuffer == NULL)
// Don't bother if only room for a few small buffers.
- && (smallSize < (kAudioBigBufferSizeBytes / 3))) {
+ && (smallSize < (kAggregateBufferSizeBytes / 3))) {
// Create a larger buffer for combining smaller buffers from the extractor.
- biggerBuffer = new ABuffer(kAudioBigBufferSizeBytes);
- biggerBuffer->setRange(0, 0); // start empty
+ mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
+ mAggregateBuffer->setRange(0, 0); // start empty
}
- if (biggerBuffer != NULL) {
+ if (mAggregateBuffer != NULL) {
int64_t timeUs;
+ int64_t dummy;
bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs);
+ bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy);
// Will the smaller buffer fit?
- size_t bigSize = biggerBuffer->size();
- size_t roomLeft = biggerBuffer->capacity() - bigSize;
+ size_t bigSize = mAggregateBuffer->size();
+ size_t roomLeft = mAggregateBuffer->capacity() - bigSize;
// Should we save this small buffer for the next big buffer?
// If the first small buffer did not have a timestamp then save
// any buffer that does have a timestamp until the next big buffer.
if ((smallSize > roomLeft)
- || (!gotTime && (numSmallBuffers > 0) && smallTimestampValid)) {
+ || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) {
mPendingAudioErr = err;
mPendingAudioAccessUnit = accessUnit;
accessUnit.clear();
} else {
+ // Grab time from first small buffer if available.
+ if ((bigSize == 0) && smallTimestampValid) {
+ mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
+ }
// Append small buffer to the bigger buffer.
- memcpy(biggerBuffer->base() + bigSize, accessUnit->data(), smallSize);
+ memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
bigSize += smallSize;
- biggerBuffer->setRange(0, bigSize);
+ mAggregateBuffer->setRange(0, bigSize);
- // Keep looping until we run out of room in the biggerBuffer.
+ // Keep looping until we run out of room in the mAggregateBuffer.
needMoreData = true;
- // Grab time from first small buffer if available.
- if ((numSmallBuffers == 0) && smallTimestampValid) {
- biggerBuffer->meta()->setInt64("timeUs", timeUs);
- gotTime = true;
- }
-
- ALOGV("feedDecoderInputData() #%d, smallSize = %zu, bigSize = %zu, capacity = %zu",
- numSmallBuffers, smallSize, bigSize, biggerBuffer->capacity());
- numSmallBuffers++;
+ ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu",
+ smallSize, bigSize, mAggregateBuffer->capacity());
}
}
} while (dropAccessUnit || needMoreData);
@@ -1459,9 +1453,11 @@
mCCDecoder->decode(accessUnit);
}
- if (biggerBuffer != NULL) {
- ALOGV("feedDecoderInputData() reply with aggregated buffer, %d", numSmallBuffers);
- reply->setBuffer("buffer", biggerBuffer);
+ if (mAggregateBuffer != NULL) {
+ ALOGV("feedDecoderInputData() reply with aggregated buffer, %zu",
+ mAggregateBuffer->size());
+ reply->setBuffer("buffer", mAggregateBuffer);
+ mAggregateBuffer.clear();
} else {
reply->setBuffer("buffer", accessUnit);
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 89ae11c..2e951bd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -67,6 +67,8 @@
status_t getSelectedTrack(int32_t type, Parcel* reply) const;
status_t selectTrack(size_t trackIndex, bool select);
+ static const size_t kAggregateBufferSizeBytes;
+
protected:
virtual ~NuPlayer();
@@ -158,8 +160,11 @@
// notion of time has changed.
bool mTimeDiscontinuityPending;
+ // Used by feedDecoderInputData to aggregate small buffers into
+ // one large buffer.
sp<ABuffer> mPendingAudioAccessUnit;
status_t mPendingAudioErr;
+ sp<ABuffer> mAggregateBuffer;
FlushStatus mFlushingAudio;
FlushStatus mFlushingVideo;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index ab7906a..f7aacdd 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -30,8 +30,10 @@
namespace android {
-static const int kMaxPendingBuffers = 10;
-static const int kMaxCachedBytes = 200000;
+static const size_t kMaxCachedBytes = 200000;
+// The buffers will contain a bit less than kAggregateBufferSizeBytes.
+// So we can start off with just enough buffers to keep the cache full.
+static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes);
NuPlayer::DecoderPassThrough::DecoderPassThrough(
const sp<AMessage> ¬ify)
@@ -39,7 +41,8 @@
mNotify(notify),
mBufferGeneration(0),
mReachedEOS(true),
- mPendingBuffers(0),
+ mPendingBuffersToFill(0),
+ mPendingBuffersToDrain(0),
mCachedBytes(0),
mComponentName("pass through decoder") {
mDecoderLooper = new ALooper;
@@ -79,12 +82,13 @@
void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
ALOGV("[%s] onConfigure", mComponentName.c_str());
- mPendingBuffers = 0;
mCachedBytes = 0;
+ mPendingBuffersToFill = 0;
+ mPendingBuffersToDrain = 0;
mReachedEOS = false;
++mBufferGeneration;
- requestABuffer();
+ requestMaxBuffers();
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatOutputFormatChanged);
@@ -98,12 +102,15 @@
return generation != mBufferGeneration;
}
-void NuPlayer::DecoderPassThrough::requestABuffer() {
- if (mCachedBytes >= kMaxCachedBytes || mReachedEOS) {
- ALOGV("[%s] mReachedEOS=%d, max pending buffers(%d:%d)",
- mComponentName.c_str(), (mReachedEOS ? 1 : 0),
- mPendingBuffers, kMaxPendingBuffers);
- return;
+bool NuPlayer::DecoderPassThrough::requestABuffer() {
+ if (mCachedBytes >= kMaxCachedBytes) {
+ ALOGV("[%s] mCachedBytes = %zu",
+ mComponentName.c_str(), mCachedBytes);
+ return false;
+ }
+ if (mReachedEOS) {
+ ALOGV("[%s] reached EOS", mComponentName.c_str());
+ return false;
}
sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
@@ -113,19 +120,16 @@
notify->setInt32("what", kWhatFillThisBuffer);
notify->setMessage("reply", reply);
notify->post();
- mPendingBuffers++;
+ mPendingBuffersToFill++;
+ ALOGV("requestABuffer: #ToFill = %zu, #ToDrain = %zu", mPendingBuffersToFill,
+ mPendingBuffersToDrain);
- // pending buffers will already result in requestABuffer
- if (mPendingBuffers < kMaxPendingBuffers) {
- sp<AMessage> message = new AMessage(kWhatRequestABuffer, id());
- message->setInt32("generation", mBufferGeneration);
- message->post();
- }
- return;
+ return true;
}
void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
const sp<AMessage> &msg) {
+ --mPendingBuffersToFill;
if (mReachedEOS) {
return;
}
@@ -153,11 +157,16 @@
notify->setBuffer("buffer", buffer);
notify->setMessage("reply", reply);
notify->post();
+ ++mPendingBuffersToDrain;
+ ALOGV("onInputBufferFilled: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
+ mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
}
void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
- mPendingBuffers--;
+ --mPendingBuffersToDrain;
mCachedBytes -= size;
+ ALOGV("onBufferConsumed: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
+ mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
requestABuffer();
}
@@ -167,11 +176,20 @@
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatFlushCompleted);
notify->post();
- mPendingBuffers = 0;
+ mPendingBuffersToFill = 0;
+ mPendingBuffersToDrain = 0;
mCachedBytes = 0;
mReachedEOS = false;
}
+void NuPlayer::DecoderPassThrough::requestMaxBuffers() {
+ for (size_t i = 0; i < kMaxPendingBuffers; i++) {
+ if (!requestABuffer()) {
+ break;
+ }
+ }
+}
+
void NuPlayer::DecoderPassThrough::onShutdown() {
++mBufferGeneration;
@@ -229,7 +247,7 @@
case kWhatResume:
{
- requestABuffer();
+ requestMaxBuffers();
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index 8590856..fb20257 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -55,19 +55,26 @@
sp<AMessage> mNotify;
sp<ALooper> mDecoderLooper;
- void requestABuffer();
+ /** Returns true if a buffer was requested.
+ * Returns false if at EOS or cache already full.
+ */
+ bool requestABuffer();
bool isStaleReply(const sp<AMessage> &msg);
void onConfigure(const sp<AMessage> &format);
void onFlush();
void onInputBufferFilled(const sp<AMessage> &msg);
void onBufferConsumed(int32_t size);
+ void requestMaxBuffers();
void onShutdown();
int32_t mBufferGeneration;
- bool mReachedEOS;
- int32_t mPendingBuffers;
- int32_t mCachedBytes;
+ bool mReachedEOS;
+ // TODO mPendingBuffersToFill and mPendingBuffersToDrain are only for
+ // debugging. They can be removed when the power investigation is done.
+ size_t mPendingBuffersToFill;
+ size_t mPendingBuffersToDrain;
+ size_t mCachedBytes;
AString mComponentName;
DISALLOW_EVIL_CONSTRUCTORS(DecoderPassThrough);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9cfbe6a..e200857 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -803,9 +803,14 @@
}
AutoMutex lock(mHardwareLock);
- audio_hw_device_t *dev = mPrimaryHardwareDev->hwDevice();
mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
- ret = dev->set_mic_mute(dev, state);
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ status_t result = dev->set_mic_mute(dev, state);
+ if (result != NO_ERROR) {
+ ret = result;
+ }
+ }
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
}
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index abdbc5c..d5f6c1e 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -3670,8 +3670,11 @@
void AudioPolicyManager::checkOutputForAllStrategies()
{
- checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
+ if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+ checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
checkOutputForStrategy(STRATEGY_PHONE);
+ if (mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] != AUDIO_POLICY_FORCE_SYSTEM_ENFORCED)
+ checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);
checkOutputForStrategy(STRATEGY_SONIFICATION);
checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);
checkOutputForStrategy(STRATEGY_MEDIA);
@@ -3752,23 +3755,28 @@
}
// check the following by order of priority to request a routing change if necessary:
- // 1: the strategy enforced audible is active on the output:
+ // 1: the strategy enforced audible is active and enforced on the output:
// use device for strategy enforced audible
// 2: we are in call or the strategy phone is active on the output:
// use device for strategy phone
- // 3: the strategy sonification is active on the output:
+ // 3: the strategy for enforced audible is active but not enforced on the output:
+ // use the device for strategy enforced audible
+ // 4: the strategy sonification is active on the output:
// use device for strategy sonification
- // 4: the strategy "respectful" sonification is active on the output:
+ // 5: the strategy "respectful" sonification is active on the output:
// use device for strategy "respectful" sonification
- // 5: the strategy media is active on the output:
+ // 6: the strategy media is active on the output:
// use device for strategy media
- // 6: the strategy DTMF is active on the output:
+ // 7: the strategy DTMF is active on the output:
// use device for strategy DTMF
- if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) {
+ if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE) &&
+ mForceUse[AUDIO_POLICY_FORCE_FOR_SYSTEM] == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
} else if (isInCall() ||
outputDesc->isStrategyActive(STRATEGY_PHONE)) {
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
+ } else if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) {
+ device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
} else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
} else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index ed9137f..aa9d746 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -983,6 +983,13 @@
bool fixedLens = minFocusDistance.count == 0 ||
minFocusDistance.data.f[0] == 0;
+ camera_metadata_ro_entry_t focusDistanceCalibration =
+ staticInfo(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, 0, 0,
+ false);
+ bool canFocusInfinity = (focusDistanceCalibration.count &&
+ focusDistanceCalibration.data.u8[0] !=
+ ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED);
+
camera_metadata_ro_entry_t availableFocalLengths =
staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
if (!availableFocalLengths.count) return NO_INIT;
@@ -1033,6 +1040,13 @@
sceneModeOverrides.data.u8[i * kModesPerSceneMode + 2];
switch(afMode) {
case ANDROID_CONTROL_AF_MODE_OFF:
+ if (!fixedLens && !canFocusInfinity) {
+ ALOGE("%s: Camera %d: Scene mode override lists asks for"
+ " fixed focus on a device with focuser but not"
+ " calibrated for infinity focus", __FUNCTION__,
+ cameraId);
+ return NO_INIT;
+ }
modes.focusMode = fixedLens ?
FOCUS_MODE_FIXED : FOCUS_MODE_INFINITY;
break;
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
index fa65b74..de31e23 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.cpp
@@ -244,6 +244,46 @@
return mZslStreamId;
}
+status_t ZslProcessor3::updateRequestWithDefaultStillRequest(CameraMetadata &request) const {
+ sp<Camera2Client> client = mClient.promote();
+ if (client == 0) {
+ ALOGE("%s: Camera %d: Client does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+ sp<Camera3Device> device =
+ static_cast<Camera3Device*>(client->getCameraDevice().get());
+ if (device == 0) {
+ ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
+ return INVALID_OPERATION;
+ }
+
+ CameraMetadata stillTemplate;
+ device->createDefaultRequest(CAMERA3_TEMPLATE_STILL_CAPTURE, &stillTemplate);
+
+ // Find some of the post-processing tags, and assign the value from template to the request.
+ // Only check the aberration mode and noise reduction mode for now, as they are very important
+ // for image quality.
+ uint32_t postProcessingTags[] = {
+ ANDROID_NOISE_REDUCTION_MODE,
+ ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+ ANDROID_COLOR_CORRECTION_MODE,
+ ANDROID_TONEMAP_MODE,
+ ANDROID_SHADING_MODE,
+ ANDROID_HOT_PIXEL_MODE,
+ ANDROID_EDGE_MODE
+ };
+
+ camera_metadata_entry_t entry;
+ for (size_t i = 0; i < sizeof(postProcessingTags) / sizeof(uint32_t); i++) {
+ entry = stillTemplate.find(postProcessingTags[i]);
+ if (entry.count > 0) {
+ request.update(postProcessingTags[i], entry.data.u8, 1);
+ }
+ }
+
+ return OK;
+}
+
status_t ZslProcessor3::pushToReprocess(int32_t requestId) {
ALOGV("%s: Send in reprocess request with id %d",
__FUNCTION__, requestId);
@@ -369,6 +409,13 @@
}
}
+ // Update post-processing settings
+ res = updateRequestWithDefaultStillRequest(request);
+ if (res != OK) {
+ ALOGW("%s: Unable to update post-processing tags, the reprocessed image quality "
+ "may be compromised", __FUNCTION__);
+ }
+
mLatestCapturedRequest = request;
res = client->getCameraDevice()->capture(request);
if (res != OK ) {
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
index 2975f7c..fc9f70c 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor3.h
@@ -135,6 +135,9 @@
nsecs_t getCandidateTimestampLocked(size_t* metadataIdx) const;
bool isFixedFocusMode(uint8_t afMode) const;
+
+ // Update the post-processing metadata with the default still capture request template
+ status_t updateRequestWithDefaultStillRequest(CameraMetadata &request) const;
};
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index fafe349..6a7f9e7 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1044,6 +1044,11 @@
return INVALID_OPERATION;
}
+ if (!mRequestTemplateCache[templateId].isEmpty()) {
+ *request = mRequestTemplateCache[templateId];
+ return OK;
+ }
+
const camera_metadata_t *rawRequest;
ATRACE_BEGIN("camera3->construct_default_request_settings");
rawRequest = mHal3Device->ops->construct_default_request_settings(
@@ -1055,6 +1060,7 @@
return DEAD_OBJECT;
}
*request = rawRequest;
+ mRequestTemplateCache[templateId] = rawRequest;
return OK;
}
@@ -1086,6 +1092,10 @@
ALOGV("%s: Camera %d: Waiting until idle", __FUNCTION__, mId);
status_t res = waitUntilStateThenRelock(/*active*/ false, kShutdownTimeout);
+ if (res != OK) {
+ SET_ERR_L("Error waiting for HAL to drain: %s (%d)", strerror(-res),
+ res);
+ }
return res;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index b99ed7e..ec6bba1 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -174,6 +174,8 @@
CameraMetadata mDeviceInfo;
+ CameraMetadata mRequestTemplateCache[CAMERA3_TEMPLATE_COUNT];
+
uint32_t mDeviceVersion;
enum Status {