Merge "audioflinger: pause HW A/V sync output when AudioTrack underruns" into lmp-mr1-dev
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index d9646d9..ca3832d 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -167,10 +167,6 @@
return INVALID_OPERATION;
}
- // handle default values first.
- if (inputSource == AUDIO_SOURCE_DEFAULT) {
- inputSource = AUDIO_SOURCE_MIC;
- }
if (pAttributes == NULL) {
memset(&mAttributes, 0, sizeof(audio_attributes_t));
mAttributes.source = inputSource;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index d050c78..e7e1759 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -380,13 +380,22 @@
status_t NuPlayerDriver::getCurrentPosition(int *msec) {
int64_t tempUs = 0;
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (mSeekInProgress || mState == STATE_PAUSED) {
+ tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
+ *msec = (int)divRound(tempUs, (int64_t)(1000));
+ return OK;
+ }
+ }
+
status_t ret = mPlayer->getCurrentPosition(&tempUs);
Mutex::Autolock autoLock(mLock);
// We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
// means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
// position value that's different the seek to position.
- if (ret != OK || mSeekInProgress) {
+ if (ret != OK) {
tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
} else {
mPositionUs = tempUs;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 21b74ee..57fcfe5 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -39,6 +39,15 @@
static const int64_t kOffloadPauseMaxUs = 10000000ll;
// static
+const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {
+ AUDIO_CHANNEL_NONE,
+ AUDIO_OUTPUT_FLAG_NONE,
+ AUDIO_FORMAT_INVALID,
+ 0, // mNumChannels
+ 0 // mSampleRate
+};
+
+// static
const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
NuPlayer::Renderer::Renderer(
@@ -68,6 +77,7 @@
mNotifyCompleteVideo(false),
mSyncQueues(false),
mPaused(false),
+ mPausePositionMediaTimeUs(0),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
@@ -75,6 +85,7 @@
mAudioOffloadPauseTimeoutGeneration(0),
mAudioOffloadTornDown(false),
mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
+ mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0) {
}
@@ -166,11 +177,48 @@
msg->post();
}
+// Called on any threads, except renderer's thread.
status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
- return getCurrentPosition(mediaUs, ALooper::GetNowUs());
+ {
+ Mutex::Autolock autoLock(mLock);
+ int64_t currentPositionUs;
+ if (getCurrentPositionIfPaused_l(¤tPositionUs)) {
+ *mediaUs = currentPositionUs;
+ return OK;
+ }
+ }
+ return getCurrentPositionFromAnchor(mediaUs, ALooper::GetNowUs());
}
-status_t NuPlayer::Renderer::getCurrentPosition(
+// Called on only renderer's thread.
+status_t NuPlayer::Renderer::getCurrentPositionOnLooper(int64_t *mediaUs) {
+ return getCurrentPositionOnLooper(mediaUs, ALooper::GetNowUs());
+}
+
+// Called on only renderer's thread.
+// Since mPaused and mPausePositionMediaTimeUs are changed only on renderer's
+// thread, no need to acquire mLock.
+status_t NuPlayer::Renderer::getCurrentPositionOnLooper(
+ int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
+ int64_t currentPositionUs;
+ if (getCurrentPositionIfPaused_l(¤tPositionUs)) {
+ *mediaUs = currentPositionUs;
+ return OK;
+ }
+ return getCurrentPositionFromAnchor(mediaUs, nowUs, allowPastQueuedVideo);
+}
+
+// Called either with mLock acquired or on renderer's thread.
+bool NuPlayer::Renderer::getCurrentPositionIfPaused_l(int64_t *mediaUs) {
+ if (!mPaused) {
+ return false;
+ }
+ *mediaUs = mPausePositionMediaTimeUs;
+ return true;
+}
+
+// Called on any threads.
+status_t NuPlayer::Renderer::getCurrentPositionFromAnchor(
int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
Mutex::Autolock autoLock(mTimeLock);
if (!mHasAudio && !mHasVideo) {
@@ -638,10 +686,13 @@
mAudioQueue.erase(mAudioQueue.begin());
entry = NULL;
- // Need to stop the track here, because that will play out the last
- // little bit at the end of the file. Otherwise short files won't play.
- mAudioSink->stop();
- mNumFramesWritten = 0;
+ if (mAudioSink->needsTrailingPadding()) {
+ // If we're not in gapless playback (i.e. through setNextPlayer), we
+ // need to stop the track here, because that will play out the last
+ // little bit at the end of the file. Otherwise short files won't play.
+ mAudioSink->stop();
+ mNumFramesWritten = 0;
+ }
return false;
}
@@ -715,7 +766,8 @@
int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
int64_t currentPositionUs;
- if (getCurrentPosition(¤tPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
+ if (getCurrentPositionOnLooper(
+ ¤tPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
// If failed to get current position, e.g. due to audio clock is not ready, then just
// play out video immediately without delay.
return nowUs;
@@ -1176,6 +1228,11 @@
ALOGW("Renderer::onPause() called while already paused!");
return;
}
+ int64_t currentPositionUs;
+ if (getCurrentPositionFromAnchor(
+ ¤tPositionUs, ALooper::GetNowUs()) == OK) {
+ mPausePositionMediaTimeUs = currentPositionUs;
+ }
{
Mutex::Autolock autoLock(mLock);
++mAudioQueueGeneration;
@@ -1303,7 +1360,7 @@
mAudioOffloadTornDown = true;
int64_t currentPositionUs;
- if (getCurrentPosition(¤tPositionUs) != OK) {
+ if (getCurrentPositionOnLooper(¤tPositionUs) != OK) {
currentPositionUs = 0;
}
@@ -1395,6 +1452,8 @@
// no change from previous configuration, everything ok.
return OK;
}
+ mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
+
ALOGV("openAudioSink: try to open AudioSink in offload mode");
uint32_t offloadFlags = flags;
offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
@@ -1436,6 +1495,20 @@
ALOGV("openAudioSink: open AudioSink in NON-offload mode");
uint32_t pcmFlags = flags;
pcmFlags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+
+ const PcmInfo info = {
+ (audio_channel_mask_t)channelMask,
+ (audio_output_flags_t)pcmFlags,
+ AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
+ numChannels,
+ sampleRate
+ };
+ if (memcmp(&mCurrentPcmInfo, &info, sizeof(info)) == 0) {
+ ALOGV("openAudioSink: no change in pcm mode");
+ // no change from previous configuration, everything ok.
+ return OK;
+ }
+
audioSinkChanged = true;
mAudioSink->close();
mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
@@ -1450,8 +1523,10 @@
(audio_output_flags_t)pcmFlags);
if (err != OK) {
ALOGW("openAudioSink: non offloaded open failed status: %d", err);
+ mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
return err;
}
+ mCurrentPcmInfo = info;
mAudioSink->start();
}
if (audioSinkChanged) {
@@ -1466,6 +1541,7 @@
void NuPlayer::Renderer::onCloseAudioSink() {
mAudioSink->close();
mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER;
+ mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
}
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 406c64c..23907c8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -62,8 +62,6 @@
// Following setters and getters are protected by mTimeLock.
status_t getCurrentPosition(int64_t *mediaUs);
- status_t getCurrentPosition(
- int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
void setHasMedia(bool audio);
void setAudioFirstAnchorTime(int64_t mediaUs);
void setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs);
@@ -168,7 +166,10 @@
bool mSyncQueues;
+ // modified on only renderer's thread.
bool mPaused;
+ int64_t mPausePositionMediaTimeUs;
+
bool mVideoSampleReceived;
bool mVideoRenderingStarted;
int32_t mVideoRenderingStartGeneration;
@@ -180,9 +181,25 @@
bool mAudioOffloadTornDown;
audio_offload_info_t mCurrentOffloadInfo;
+ struct PcmInfo {
+ audio_channel_mask_t mChannelMask;
+ audio_output_flags_t mFlags;
+ audio_format_t mFormat;
+ int32_t mNumChannels;
+ int32_t mSampleRate;
+ };
+ PcmInfo mCurrentPcmInfo;
+ static const PcmInfo AUDIO_PCMINFO_INITIALIZER;
+
int32_t mTotalBuffersQueued;
int32_t mLastAudioBufferDrained;
+ status_t getCurrentPositionOnLooper(int64_t *mediaUs);
+ status_t getCurrentPositionOnLooper(
+ int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
+ bool getCurrentPositionIfPaused_l(int64_t *mediaUs);
+ status_t getCurrentPositionFromAnchor(
+ int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
size_t fillAudioBuffer(void *buffer, size_t size);
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 32291c8..0c2ff15 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -36,7 +36,8 @@
mTotalTransferBytes(0),
mPrevBandwidthMeasureTimeUs(0),
mPrevEstimatedBandWidthKbps(0),
- mBandWidthCollectFreqMs(5000) {
+ mBandWidthCollectFreqMs(5000),
+ mMaxBandwidthHistoryItems(100) {
}
void HTTPBase::addBandwidthMeasurement(
@@ -50,7 +51,7 @@
mTotalTransferBytes += numBytes;
mBandwidthHistory.push_back(entry);
- if (++mNumBandwidthHistoryItems > 100) {
+ if (++mNumBandwidthHistoryItems > mMaxBandwidthHistoryItems) {
BandwidthEntry *entry = &*mBandwidthHistory.begin();
mTotalTransferTimeUs -= entry->mDelayUs;
mTotalTransferBytes -= entry->mNumBytes;
@@ -104,6 +105,10 @@
return OK;
}
+void HTTPBase::setBandwidthHistorySize(size_t numHistoryItems) {
+ mMaxBandwidthHistoryItems = numHistoryItems;
+}
+
// static
void HTTPBase::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
int res = qtaguid_tagSocket(sockfd, kTag, uid);
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index d922dc0..2eb7e5c 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -999,6 +999,9 @@
int64_t duration;
int32_t samplerate;
+ if (!mLastTrack) {
+ return ERROR_MALFORMED;
+ }
if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e1c8a41..c2381b4 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1014,11 +1014,13 @@
// Notify mCrypto of video resolution changes
if (mCrypto != NULL) {
- int32_t height, width;
- if (mOutputFormat->findInt32("height", &height) &&
- mOutputFormat->findInt32("width", &width)) {
- mCrypto->notifyResolution(width, height);
- }
+ int32_t left, top, right, bottom, width, height;
+ if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
+ mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
+ } else if (mOutputFormat->findInt32("width", &width)
+ && mOutputFormat->findInt32("height", &height)) {
+ mCrypto->notifyResolution(width, height);
+ }
}
break;
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 6219053..b8868aa 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -76,7 +76,7 @@
status_t seekToTime(int64_t timeUs);
status_t seekToOffset(off64_t offset);
- status_t readNextPacket(MediaBuffer **buffer);
+ status_t readNextPacket(MediaBuffer **buffer, bool conf);
status_t init();
@@ -185,7 +185,7 @@
}
MediaBuffer *packet;
- status_t err = mExtractor->mImpl->readNextPacket(&packet);
+ status_t err = mExtractor->mImpl->readNextPacket(&packet, /* conf = */ false);
if (err != OK) {
return err;
@@ -457,7 +457,7 @@
return sizeof(header) + page->mNumSegments + totalSize;
}
-status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
+status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out, bool conf) {
*out = NULL;
MediaBuffer *buffer = NULL;
@@ -523,10 +523,8 @@
mFirstPacketInPage = false;
}
- if (mVi.rate) {
- // Rate may not have been initialized yet if we're currently
- // reading the configuration packets...
- // Fortunately, the timestamp doesn't matter for those.
+ // ignore timestamp for configuration packets
+ if (!conf) {
int32_t curBlockSize = packetBlockSize(buffer);
if (mCurrentPage.mPrevPacketSize < 0) {
mCurrentPage.mPrevPacketSize = curBlockSize;
@@ -605,7 +603,7 @@
MediaBuffer *packet;
status_t err;
- if ((err = readNextPacket(&packet)) != OK) {
+ if ((err = readNextPacket(&packet, /* conf = */ true)) != OK) {
return err;
}
ALOGV("read packet of size %zu\n", packet->range_length());
@@ -616,7 +614,7 @@
return err;
}
- if ((err = readNextPacket(&packet)) != OK) {
+ if ((err = readNextPacket(&packet, /* conf = */ true)) != OK) {
return err;
}
ALOGV("read packet of size %zu\n", packet->range_length());
@@ -627,7 +625,7 @@
return err;
}
- if ((err = readNextPacket(&packet)) != OK) {
+ if ((err = readNextPacket(&packet, /* conf = */ true)) != OK) {
return err;
}
ALOGV("read packet of size %zu\n", packet->range_length());
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 0b18666..9daab3b 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -49,6 +49,9 @@
namespace android {
+// Number of recently-read bytes to use for bandwidth estimation
+const size_t LiveSession::kBandwidthHistoryBytes = 200 * 1024;
+
LiveSession::LiveSession(
const sp<AMessage> ¬ify, uint32_t flags,
const sp<IMediaHTTPService> &httpService)
@@ -84,6 +87,13 @@
mPacketSources2.add(indexToType(i), new AnotherPacketSource(NULL /* meta */));
mBuffering[i] = false;
}
+
+ size_t numHistoryItems = kBandwidthHistoryBytes /
+ PlaylistFetcher::kDownloadBlockSize + 1;
+ if (numHistoryItems < 5) {
+ numHistoryItems = 5;
+ }
+ mHTTPDataSource->setBandwidthHistorySize(numHistoryItems);
}
LiveSession::~LiveSession() {
@@ -145,10 +155,24 @@
}
}
+ int32_t targetDuration = 0;
+ sp<AMessage> meta = packetSource->getLatestEnqueuedMeta();
+ if (meta != NULL) {
+ meta->findInt32("targetDuration", &targetDuration);
+ }
+
+ int64_t targetDurationUs = targetDuration * 1000000ll;
+ if (targetDurationUs == 0 ||
+ targetDurationUs > PlaylistFetcher::kMinBufferedDurationUs) {
+ // Fetchers limit buffering to
+ // min(3 * targetDuration, kMinBufferedDurationUs)
+ targetDurationUs = PlaylistFetcher::kMinBufferedDurationUs;
+ }
+
if (mBuffering[idx]) {
if (mSwitchInProgress
|| packetSource->isFinished(0)
- || packetSource->getEstimatedDurationUs() > 10000000ll) {
+ || packetSource->getEstimatedDurationUs() > targetDurationUs) {
mBuffering[idx] = false;
}
}
@@ -859,7 +883,11 @@
// Only resize when we don't know the size.
size_t bufferRemaining = buffer->capacity() - buffer->size();
if (bufferRemaining == 0 && getSizeErr != OK) {
- bufferRemaining = 32768;
+ size_t bufferIncrement = buffer->size() / 2;
+ if (bufferIncrement < 32768) {
+ bufferIncrement = 32768;
+ }
+ bufferRemaining = bufferIncrement;
ALOGV("increasing download buffer to %zu bytes",
buffer->size() + bufferRemaining);
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 896a8fc..dfb5e59 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -114,6 +114,8 @@
kWhatSwitchDown = 'sDwn',
};
+ static const size_t kBandwidthHistoryBytes;
+
struct BandwidthItem {
size_t mPlaylistIndex;
unsigned long mBandwidth;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index d8eed5b..4a97803 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -49,8 +49,9 @@
// static
const int64_t PlaylistFetcher::kMinBufferedDurationUs = 10000000ll;
const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
-const int32_t PlaylistFetcher::kDownloadBlockSize = 2048;
-const int32_t PlaylistFetcher::kNumSkipFrames = 10;
+// LCM of 188 (size of a TS packet) & 1k works well
+const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
+const int32_t PlaylistFetcher::kNumSkipFrames = 5;
PlaylistFetcher::PlaylistFetcher(
const sp<AMessage> ¬ify,
@@ -561,7 +562,7 @@
// Don't resume if we would stop within a resume threshold.
int32_t discontinuitySeq;
int64_t latestTimeUs = 0, stopTimeUs = 0;
- sp<AMessage> latestMeta = packetSource->getLatestDequeuedMeta();
+ sp<AMessage> latestMeta = packetSource->getLatestEnqueuedMeta();
if (latestMeta != NULL
&& latestMeta->findInt32("discontinuitySeq", &discontinuitySeq)
&& discontinuitySeq == mDiscontinuitySeq
@@ -610,7 +611,12 @@
int32_t targetDurationSecs;
int64_t targetDurationUs = kMinBufferedDurationUs;
if (mPlaylist != NULL) {
- CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+ if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
+ "target-duration", &targetDurationSecs)) {
+ ALOGE("Playlist is missing required EXT-X-TARGETDURATION tag");
+ notifyError(ERROR_MALFORMED);
+ return;
+ }
targetDurationUs = targetDurationSecs * 1000000ll;
}
@@ -1159,6 +1165,11 @@
accessUnit->meta()->setInt32("discard", discard);
}
+ int32_t targetDurationSecs;
+ if (mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs)) {
+ accessUnit->meta()->setInt32("targetDuration", targetDurationSecs);
+ }
+
accessUnit->meta()->setInt32("discontinuitySeq", mDiscontinuitySeq);
accessUnit->meta()->setInt64("segmentStartTimeUs", getSegmentStartTimeUs(mSeqNumber));
return accessUnit;
@@ -1668,7 +1679,7 @@
int64_t PlaylistFetcher::resumeThreshold(const sp<AMessage> &msg) {
int64_t durationUs, threshold;
- if (msg->findInt64("durationUs", &durationUs)) {
+ if (msg->findInt64("durationUs", &durationUs) && durationUs > 0) {
return kNumSkipFrames * durationUs;
}
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index 78c358f..67161a9 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -34,6 +34,9 @@
struct String8;
struct PlaylistFetcher : public AHandler {
+ static const int64_t kMinBufferedDurationUs;
+ static const int32_t kDownloadBlockSize;
+
enum {
kWhatStarted,
kWhatPaused,
@@ -92,9 +95,7 @@
kWhatDownloadNext = 'dlnx',
};
- static const int64_t kMinBufferedDurationUs;
static const int64_t kMaxMonitorDelayUs;
- static const int32_t kDownloadBlockSize;
static const int32_t kNumSkipFrames;
static bool bufferStartsWithTsSyncByte(const sp<ABuffer>& buffer);
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index 1c3cd5e..0c66e27 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -48,6 +48,8 @@
virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
+ virtual void setBandwidthHistorySize(size_t numHistoryItems);
+
static void RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag);
static void UnRegisterSocketUserTag(int sockfd);
@@ -55,7 +57,7 @@
static void UnRegisterSocketUserMark(int sockfd);
protected:
- void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+ virtual void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
private:
struct BandwidthEntry {
@@ -69,6 +71,7 @@
size_t mNumBandwidthHistoryItems;
int64_t mTotalTransferTimeUs;
size_t mTotalTransferBytes;
+ size_t mMaxBandwidthHistoryItems;
enum {
kMinBandwidthCollectFreqMs = 1000, // 1 second
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index c579d4c..f266fe7 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -218,12 +218,19 @@
}
if (mLatestEnqueuedMeta == NULL) {
- mLatestEnqueuedMeta = buffer->meta();
+ mLatestEnqueuedMeta = buffer->meta()->dup();
} else {
int64_t latestTimeUs = 0;
+ int64_t frameDeltaUs = 0;
CHECK(mLatestEnqueuedMeta->findInt64("timeUs", &latestTimeUs));
if (lastQueuedTimeUs > latestTimeUs) {
- mLatestEnqueuedMeta = buffer->meta();
+ mLatestEnqueuedMeta = buffer->meta()->dup();
+ frameDeltaUs = lastQueuedTimeUs - latestTimeUs;
+ mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
+ } else if (!mLatestEnqueuedMeta->findInt64("durationUs", &frameDeltaUs)) {
+ // For B frames
+ frameDeltaUs = latestTimeUs - lastQueuedTimeUs;
+ mLatestEnqueuedMeta->setInt64("durationUs", frameDeltaUs);
}
}
}
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 7544052..4f0c6b1 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -166,7 +166,9 @@
if (*handle == mPatches[index]->mHandle) {
ALOGV("createAudioPatch() removing patch handle %d", *handle);
halHandle = mPatches[index]->mHalHandle;
+ Patch *removedPatch = mPatches[index];
mPatches.removeAt(index);
+ delete removedPatch;
break;
}
}
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index 4bc3c7f..b8846c6 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -241,14 +241,21 @@
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
+
+ audio_source_t inputSource = attr->source;
+
// already checked by client, but double-check in case the client wrapper is bypassed
- if (attr->source >= AUDIO_SOURCE_CNT && attr->source != AUDIO_SOURCE_HOTWORD &&
- attr->source != AUDIO_SOURCE_FM_TUNER) {
+ if (inputSource >= AUDIO_SOURCE_CNT && inputSource != AUDIO_SOURCE_HOTWORD &&
+ inputSource != AUDIO_SOURCE_FM_TUNER) {
return BAD_VALUE;
}
- if (((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
- ((attr->source == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
+ if (inputSource == AUDIO_SOURCE_DEFAULT) {
+ inputSource = AUDIO_SOURCE_MIC;
+ }
+
+ if (((inputSource == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
+ ((inputSource == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
return BAD_VALUE;
}
@@ -256,7 +263,7 @@
{
Mutex::Autolock _l(mLock);
// the audio_in_acoustics_t parameter is ignored by get_input()
- *input = mpAudioPolicy->get_input(mpAudioPolicy, attr->source, samplingRate,
+ *input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
format, channelMask, (audio_in_acoustics_t) 0);
audioPolicyEffects = mAudioPolicyEffects;
}
@@ -266,7 +273,7 @@
if (audioPolicyEffects != 0) {
// create audio pre processors according to input source
- status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session);
+ status_t status = audioPolicyEffects->addInputEffects(*input, inputSource, session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGW("Failed to add effects on input %d", input);
}
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index a3389e0..0349327 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -596,6 +596,9 @@
}
handleIncallSonification((audio_stream_type_t)stream, false, true);
}
+
+ // force reevaluating accessibility routing when call starts
+ mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
}
// store previous phone state for management of sonification strategy below
@@ -1290,6 +1293,11 @@
outputDesc->mPolicyMix->mRegistrationId);
}
+ // force reevaluating accessibility routing when ringtone or alarm starts
+ if (strategy == STRATEGY_SONIFICATION) {
+ mpClientInterface->invalidateStream(AUDIO_STREAM_ACCESSIBILITY);
+ }
+
if (waitMs > muteWaitMs) {
usleep((waitMs - muteWaitMs) * 2 * 1000);
}
@@ -1432,10 +1440,16 @@
// handle legacy remote submix case where the address was not always specified
String8 address = String8("");
bool isSoundTrigger = false;
- audio_source_t halInputSource = attr->source;
+ audio_source_t inputSource = attr->source;
+ audio_source_t halInputSource;
AudioMix *policyMix = NULL;
- if (attr->source == AUDIO_SOURCE_REMOTE_SUBMIX &&
+ if (inputSource == AUDIO_SOURCE_DEFAULT) {
+ inputSource = AUDIO_SOURCE_MIC;
+ }
+ halInputSource = inputSource;
+
+ if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
address = String8(attr->tags + strlen("addr="));
@@ -1451,9 +1465,9 @@
policyMix = &mPolicyMixes[index]->mMix;
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
} else {
- device = getDeviceAndMixForInputSource(attr->source, &policyMix);
+ device = getDeviceAndMixForInputSource(inputSource, &policyMix);
if (device == AUDIO_DEVICE_NONE) {
- ALOGW("getInputForAttr() could not find device for source %d", attr->source);
+ ALOGW("getInputForAttr() could not find device for source %d", inputSource);
return BAD_VALUE;
}
if (policyMix != NULL) {
@@ -1475,7 +1489,7 @@
*inputType = API_INPUT_LEGACY;
}
// adapt channel selection to input source
- switch (attr->source) {
+ switch (inputSource) {
case AUDIO_SOURCE_VOICE_UPLINK:
channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
break;
@@ -1488,7 +1502,7 @@
default:
break;
}
- if (attr->source == AUDIO_SOURCE_HOTWORD) {
+ if (inputSource == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
*input = mSoundTriggerSessions.valueFor(session);
@@ -1551,7 +1565,7 @@
}
sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile);
- inputDesc->mInputSource = attr->source;
+ inputDesc->mInputSource = inputSource;
inputDesc->mRefCount = 0;
inputDesc->mOpenRefCount = 1;
inputDesc->mSamplingRate = samplingRate;
@@ -2047,12 +2061,23 @@
{
for (size_t i = 0; i < mInputs.size(); i++) {
const sp<AudioInputDescriptor> inputDescriptor = mInputs.valueAt(i);
- if ((inputDescriptor->mInputSource == (int)source ||
- (source == AUDIO_SOURCE_VOICE_RECOGNITION &&
- inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD))
- && (inputDescriptor->mRefCount > 0)) {
+ if (inputDescriptor->mRefCount == 0) {
+ continue;
+ }
+ if (inputDescriptor->mInputSource == (int)source) {
return true;
}
+ // AUDIO_SOURCE_HOTWORD is equivalent to AUDIO_SOURCE_VOICE_RECOGNITION only if it
+ // corresponds to an active capture triggered by a hardware hotword recognition
+ if ((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
+ (inputDescriptor->mInputSource == AUDIO_SOURCE_HOTWORD)) {
+ // FIXME: we should not assume that the first session is the active one and keep
+ // activity count per session. Same in startInput().
+ ssize_t index = mSoundTriggerSessions.indexOfKey(inputDescriptor->mSessions.itemAt(0));
+ if (index >= 0) {
+ return true;
+ }
+ }
}
return false;
}
@@ -3423,29 +3448,15 @@
}
void AudioPolicyManager::findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
+ const audio_devices_t device /*in*/,
const String8 address /*in*/,
SortedVector<audio_io_handle_t>& outputs /*out*/) {
- // look for a match on the given address on the addresses of the outputs:
- // find the address by finding the patch that maps to this output
- ssize_t patchIdx = mAudioPatches.indexOfKey(desc->mPatchHandle);
- //ALOGV(" inspecting output %d (patch %d) for supported device=0x%x",
- // outputIdx, patchIdx, desc->mProfile->mSupportedDevices.types());
- if (patchIdx >= 0) {
- const sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patchIdx);
- const int numSinks = patchDesc->mPatch.num_sinks;
- for (ssize_t j=0; j < numSinks; j++) {
- if (patchDesc->mPatch.sinks[j].type == AUDIO_PORT_TYPE_DEVICE) {
- const char* patchAddr =
- patchDesc->mPatch.sinks[j].ext.device.address;
- if (strncmp(patchAddr,
- address.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
- ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
- desc->mIoHandle, patchDesc->mPatch.sinks[j].ext.device.address);
- outputs.add(desc->mIoHandle);
- break;
- }
- }
- }
+ sp<DeviceDescriptor> devDesc =
+ desc->mProfile->mSupportedDevices.getDevice(device, address);
+ if (devDesc != 0) {
+ ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
+ desc->mIoHandle, address.string());
+ outputs.add(desc->mIoHandle);
}
}
@@ -3469,7 +3480,7 @@
outputs.add(mOutputs.keyAt(i));
} else {
ALOGV(" checking address match due to device 0x%x", device);
- findIoHandlesByAddress(desc, address, outputs);
+ findIoHandlesByAddress(desc, device, address, outputs);
}
}
}
@@ -3697,7 +3708,7 @@
// exact match on device
if (deviceDistinguishesOnAddress(device) &&
(desc->mProfile->mSupportedDevices.types() == device)) {
- findIoHandlesByAddress(desc, address, outputs);
+ findIoHandlesByAddress(desc, device, address, outputs);
} else if (!(desc->mProfile->mSupportedDevices.types()
& mAvailableOutputDevices.types())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
@@ -5288,7 +5299,7 @@
for (size_t i = 0; i < mInputs.size(); i++) {
const sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
if (desc->mRefCount > 0) {
- return count++;
+ count++;
}
}
return count;
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index 2059f58..633888f 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -889,6 +889,7 @@
// see deviceDistinguishesOnAddress(audio_devices_t) for whether the device type is one
// where addresses are used to distinguish between one connected device and another.
void findIoHandlesByAddress(sp<AudioOutputDescriptor> desc /*in*/,
+ const audio_devices_t device /*in*/,
const String8 address /*in*/,
SortedVector<audio_io_handle_t>& outputs /*out*/);
uint32_t nextUniqueId();