Fix build breakage caused by commit 940829f69b52d6038db66a9c727534636ecc456d. am: baa9146401 am: 0aaa2c606c am: 784c8ac91a am: b65f47d30a am: 1cdd3c4262 am: 0954180087 am: be50e42a6c am: d82d9f0b1f am: dd6fc9a192
am: 941e41588f
Change-Id: I51686def5d8134b6120634f35d575be51aa7c98e
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 75515ac..a419e17 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -313,7 +313,7 @@
short mA1_Q14; // Q14 coefficient
// delay line of full amplitude generator
- short mS1, mS2; // delay line S2 oldest
+ long mS1, mS2; // delay line S2 oldest
short mS2_0; // saved value for reinitialisation
short mAmplitude_Q15; // Q15 amplitude
};
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index cc62786..00b2c71 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -50,6 +50,7 @@
bool isVideo() const { return mIsVideo; }
sp<IGraphicBufferProducer> getGraphicBufferProducer();
void setInputBufferTimeOffset(int64_t timeOffsetUs);
+ int64_t getFirstSampleSystemTimeUs();
// MediaSource
virtual status_t start(MetaData *params = NULL);
@@ -79,6 +80,7 @@
kWhatStop,
kWhatPause,
kWhatSetInputBufferTimeOffset,
+ kWhatGetFirstSampleSystemTimeUs,
kWhatStopStalled,
};
@@ -90,6 +92,7 @@
uint32_t flags = 0);
status_t onStart(MetaData *params);
+ void onPause();
status_t init();
status_t initEncoder();
void releaseEncoder();
@@ -123,6 +126,8 @@
List<size_t> mAvailEncoderInputIndices;
List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
int64_t mInputBufferTimeOffsetUs;
+ int64_t mFirstSampleSystemTimeUs;
+ bool mPausePending;
// audio drift time
int64_t mFirstSampleTimeUs;
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 2f53637..9a087ff 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -1612,8 +1612,8 @@
lS1 = (long)0;
lS2 = (long)mS2_0;
} else {
- lS1 = (long)mS1;
- lS2 = (long)mS2;
+ lS1 = mS1;
+ lS2 = mS2;
}
lA1 = (long)mA1_Q14;
lAmplitude = (long)mAmplitude_Q15;
@@ -1649,8 +1649,8 @@
}
// save status
- mS1 = (short)lS1;
- mS2 = (short)lS2;
+ mS1 = lS1;
+ mS2 = lS2;
}
} // end namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 24ca582..bd1fd7c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1807,19 +1807,38 @@
return OK;
}
- // 30 ms buffer to avoid timestamp overlap
- mTotalPausedDurationUs += (systemTime() / 1000) - mPauseStartTimeUs - 30000;
+ int64_t bufferStartTimeUs = 0;
+ bool allSourcesStarted = true;
+ for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
+ if (source == nullptr) {
+ continue;
+ }
+ int64_t timeUs = source->getFirstSampleSystemTimeUs();
+ if (timeUs < 0) {
+ allSourcesStarted = false;
+ }
+ if (bufferStartTimeUs < timeUs) {
+ bufferStartTimeUs = timeUs;
+ }
+ }
+
+ if (allSourcesStarted) {
+ if (mPauseStartTimeUs < bufferStartTimeUs) {
+ mPauseStartTimeUs = bufferStartTimeUs;
+ }
+ // 30 ms buffer to avoid timestamp overlap
+ mTotalPausedDurationUs += (systemTime() / 1000) - mPauseStartTimeUs - 30000;
+ }
double timeOffset = -mTotalPausedDurationUs;
if (mCaptureFpsEnable) {
timeOffset *= mCaptureFps / mFrameRate;
}
- if (mAudioEncoderSource != NULL) {
- mAudioEncoderSource->setInputBufferTimeOffset((int64_t)timeOffset);
- mAudioEncoderSource->start();
- }
- if (mVideoEncoderSource != NULL) {
- mVideoEncoderSource->setInputBufferTimeOffset((int64_t)timeOffset);
- mVideoEncoderSource->start();
+ for (const auto &source : { mAudioEncoderSource, mVideoEncoderSource }) {
+ if (source == nullptr) {
+ continue;
+ }
+ source->setInputBufferTimeOffset((int64_t)timeOffset);
+ source->start();
}
mPauseStartTimeUs = 0;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 5039922..311c745 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -342,6 +342,17 @@
postSynchronouslyAndReturnError(msg);
}
+int64_t MediaCodecSource::getFirstSampleSystemTimeUs() {
+ sp<AMessage> msg = new AMessage(kWhatGetFirstSampleSystemTimeUs, mReflector);
+ sp<AMessage> response;
+ msg->postAndAwaitResponse(&response);
+ int64_t timeUs;
+ if (!response->findInt64("time-us", &timeUs)) {
+ timeUs = -1ll;
+ }
+ return timeUs;
+}
+
status_t MediaCodecSource::start(MetaData* params) {
sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
msg->setObject("meta", params);
@@ -408,6 +419,8 @@
mEncoderDataSpace(0),
mGraphicBufferConsumer(consumer),
mInputBufferTimeOffsetUs(0),
+ mFirstSampleSystemTimeUs(-1ll),
+ mPausePending(false),
mFirstSampleTimeUs(-1ll),
mGeneration(0) {
CHECK(mLooper != NULL);
@@ -646,17 +659,19 @@
if (mbuf != NULL) {
CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
- timeUs += mInputBufferTimeOffsetUs;
-
- // Due to the extra delay adjustment at the beginning of start/resume,
- // the adjusted timeUs may be negative if MediaCodecSource goes into pause
- // state before feeding any buffers to the encoder. Drop the buffer in this
- // case.
- if (timeUs < 0) {
- mbuf->release();
- return OK;
+ if (mFirstSampleSystemTimeUs < 0ll) {
+ mFirstSampleSystemTimeUs = systemTime() / 1000;
+ if (mPausePending) {
+ mPausePending = false;
+ onPause();
+ mbuf->release();
+ mAvailEncoderInputIndices.push_back(bufferIndex);
+ return OK;
+ }
}
+ timeUs += mInputBufferTimeOffsetUs;
+
// push decoding time for video, or drift time for audio
if (mIsVideo) {
mDecodingTimeQueue.push_back(timeUs);
@@ -665,7 +680,6 @@
if (mFirstSampleTimeUs < 0ll) {
mFirstSampleTimeUs = timeUs;
}
-
int64_t driftTimeUs = 0;
if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
&& driftTimeUs) {
@@ -717,6 +731,10 @@
if (mStarted) {
ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
+ if (mPausePending) {
+ mPausePending = false;
+ return OK;
+ }
if (mIsVideo) {
mEncoder->requestIDRFrame();
}
@@ -763,6 +781,15 @@
return OK;
}
+void MediaCodecSource::onPause() {
+ if (mFlags & FLAG_USE_SURFACE_INPUT) {
+ suspend();
+ } else {
+ CHECK(mPuller != NULL);
+ mPuller->pause();
+ }
+}
+
void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatPullerNotify:
@@ -832,25 +859,27 @@
}
MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
- memcpy(mbuf->data(), outbuf->data(), outbuf->size());
+ mbuf->add_ref();
if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
if (mIsVideo) {
int64_t decodingTimeUs;
if (mFlags & FLAG_USE_SURFACE_INPUT) {
+ if (mFirstSampleSystemTimeUs < 0ll) {
+ mFirstSampleSystemTimeUs = systemTime() / 1000;
+ if (mPausePending) {
+ mPausePending = false;
+ onPause();
+ mbuf->release();
+ break;
+ }
+ }
// Time offset is not applied at
// feedEncoderInputBuffer() in surface input case.
timeUs += mInputBufferTimeOffsetUs;
-
- // Due to the extra delay adjustment at the beginning of
- // start/resume, the adjusted timeUs may be negative if
- // MediaCodecSource goes into pause state before feeding
- // any buffers to the encoder. Drop the buffer in this case.
- if (timeUs < 0) {
- mEncoder->releaseOutputBuffer(index);
- break;
- }
-
+ // GraphicBufferSource is supposed to discard samples
+ // queued before start, and offset timeUs by start time
+ CHECK_GE(timeUs, 0ll);
// TODO:
// Decoding time for surface source is unavailable,
// use presentation time for now. May need to move
@@ -883,8 +912,8 @@
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
}
+ memcpy(mbuf->data(), outbuf->data(), outbuf->size());
mbuf->setObserver(this);
- mbuf->add_ref();
{
Mutexed<Output>::Locked output(mOutput);
@@ -975,11 +1004,10 @@
case kWhatPause:
{
- if (mFlags & FLAG_USE_SURFACE_INPUT) {
- suspend();
+ if (mFirstSampleSystemTimeUs < 0) {
+ mPausePending = true;
} else {
- CHECK(mPuller != NULL);
- mPuller->pause();
+ onPause();
}
break;
}
@@ -994,6 +1022,16 @@
response->postReply(replyID);
break;
}
+ case kWhatGetFirstSampleSystemTimeUs:
+ {
+ sp<AReplyToken> replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt64("time-us", mFirstSampleSystemTimeUs);
+ response->postReply(replyID);
+ break;
+ }
default:
TRESPASS();
}
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 8b831f0..05dacac 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -3,7 +3,8 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
- ServiceUtilities.cpp
+ ServiceUtilities.cpp \
+ LockWatch.cpp
# FIXME Move this library to frameworks/native
LOCAL_MODULE := libserviceutility
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 79f4a66..c32eadd 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -246,7 +246,9 @@
}
mPatchPanel = new PatchPanel(this);
-
+ // FIXME: bug 30737845: trigger audioserver restart if main audioflinger lock
+ // is held continuously for more than 3 seconds
+ mLockWatch = new LockWatch(mLock, String8("AudioFlinger"));
mMode = AUDIO_MODE_NORMAL;
}
@@ -279,6 +281,7 @@
}
}
}
+ mLockWatch->requestExitAndWait();
}
static const char * const audio_interfaces[] = {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c56dcc1..e334d80 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -58,6 +58,7 @@
#include "SpdifStreamOut.h"
#include "AudioHwDevice.h"
#include "LinearMap.h"
+#include "LockWatch.h"
#include <powermanager/IPowerManager.h>
@@ -630,6 +631,7 @@
};
mutable Mutex mLock;
+ sp<LockWatch> mLockWatch;
// protects mClients and mNotificationClients.
// must be locked after mLock and ThreadBase::mLock if both must be locked
// avoids acquiring AudioFlinger::mLock from inside thread loop.
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index 2ca2cac..7b6dfcb 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -474,18 +474,18 @@
ALOGV("processFrames(%zu %zu) remaining(%zu)", *dstFrames, *srcFrames, mRemaining);
// Note dstFrames is the required number of frames.
- // Ensure consumption from src is as expected.
- //TODO: add logic to track "very accurate" consumption related to speed, original sampling
- //rate, actual frames processed.
- const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
- if (*srcFrames < targetSrc) { // limit dst frames to that possible
- *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
- } else if (*srcFrames > targetSrc + 1) {
- *srcFrames = targetSrc + 1;
- }
-
if (!mAudioPlaybackRateValid) {
//fallback mode
+ // Ensure consumption from src is as expected.
+ // TODO: add logic to track "very accurate" consumption related to speed, original sampling
+ // rate, actual frames processed.
+
+ const size_t targetSrc = *dstFrames * mPlaybackRate.mSpeed;
+ if (*srcFrames < targetSrc) { // limit dst frames to that possible
+ *dstFrames = *srcFrames / mPlaybackRate.mSpeed;
+ } else if (*srcFrames > targetSrc + 1) {
+ *srcFrames = targetSrc + 1;
+ }
if (*dstFrames > 0) {
switch(mPlaybackRate.mFallbackMode) {
case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
diff --git a/services/audioflinger/LockWatch.cpp b/services/audioflinger/LockWatch.cpp
new file mode 100644
index 0000000..21eed6e
--- /dev/null
+++ b/services/audioflinger/LockWatch.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LockWatch"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include "LockWatch.h"
+
+namespace android {
+
+void LockWatch::onFirstRef()
+{
+ run("lock watch", ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+bool LockWatch::threadLoop()
+{
+ while (!exitPending()) {
+ // we neglect previous lock time effect on period
+ usleep(mPeriodMs * 1000);
+ if (mLock.timedLock(milliseconds(mTimeOutMs)) != NO_ERROR) {
+ LOG_ALWAYS_FATAL("LockWatch timeout for: %s", mTag.string());
+ }
+ mLock.unlock();
+ }
+ return false;
+}
+
+} // namespace android
+
diff --git a/services/audioflinger/LockWatch.h b/services/audioflinger/LockWatch.h
new file mode 100644
index 0000000..2d30217
--- /dev/null
+++ b/services/audioflinger/LockWatch.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef LOCK_WATCH_H
+#define LOCK_WATCH_H
+
+#include <utils/String8.h>
+#include <utils/Thread.h>
+
+namespace android {
+
+// periodically checks if a mutex can be acquired and kill process otherwise
+class LockWatch : public Thread {
+
+public:
+ static const uint32_t DEFAULT_PERIOD_MS = 10000; // 10 seconds default check period
+ static const uint32_t DEFAULT_TIMEOUT_MS = 3000; // 3 seconds default lock timeout
+
+ LockWatch(Mutex& lock, const String8& tag = String8(""),
+ uint32_t periodMs = DEFAULT_PERIOD_MS, uint32_t timeoutMs = DEFAULT_TIMEOUT_MS)
+ : Thread(false /*canCallJava*/),
+ mLock(lock), mTag(tag), mPeriodMs(periodMs), mTimeOutMs(timeoutMs) {}
+
+ virtual ~LockWatch() { }
+
+ // RefBase
+ virtual void onFirstRef();
+
+private:
+ // Thread
+ virtual bool threadLoop();
+
+ Mutex& mLock; // monitored mutex
+ String8 mTag; // tag
+ uint32_t mPeriodMs; // check period in milliseconds
+ uint32_t mTimeOutMs; // mutex lock timeout in milliseconds
+};
+
+} // namespace android
+
+#endif // LOCK_WATCH_H
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index aeab451..48a2a99 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -170,6 +170,9 @@
return res;
}
+ /** Register in-flight map to the status tracker */
+ mInFlightStatusId = mStatusTracker->addComponent();
+
/** Create buffer manager */
mBufferManager = new Camera3BufferManager();
@@ -2196,6 +2199,10 @@
aeTriggerCancelOverride));
if (res < 0) return res;
+ if (mInFlightMap.size() == 1) {
+ mStatusTracker->markComponentActive(mInFlightStatusId);
+ }
+
return OK;
}
@@ -2252,6 +2259,11 @@
mInFlightMap.removeItemsAt(idx, 1);
+ // Indicate idle inFlightMap to the status tracker
+ if (mInFlightMap.size() == 0) {
+ mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
+ }
+
ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3244258..17893a9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -725,6 +725,7 @@
Mutex mInFlightLock; // Protects mInFlightMap
InFlightMap mInFlightMap;
+ int mInFlightStatusId;
status_t registerInFlight(uint32_t frameNumber,
int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,