summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Shih <robertshih@google.com>2014-12-22 11:46:50 -0800
committerRobert Shih <robertshih@google.com>2014-12-22 11:50:26 -0800
commitf580806d893c4631f5324ff0af5c2db68a40ef42 (patch)
treebcb818e65e7702333bfb70103b63cf19ec90455f
parent5886252a7b08fb5c5d8829443e56a63956986148 (diff)
downloadframeworks_av-f580806d893c4631f5324ff0af5c2db68a40ef42.zip
frameworks_av-f580806d893c4631f5324ff0af5c2db68a40ef42.tar.gz
frameworks_av-f580806d893c4631f5324ff0af5c2db68a40ef42.tar.bz2
HLS: QCom enhancements
This commit consists of: http://go/pag/c/188753 Add NULL check for empty playlist http://go/pag/c/188754 Fix deadlock for low duration clips http://go/pag/c/188757 Create a copy of last enqueued metadata http://go/pag/c/188755 Propagate target duration to LiveSession http://go/pag/c/188762 Decouple block size from bandwidth estimate http://go/pag/c/188756 Reduce memcpy calls for chunked content http://go/pag/c/188758 Dont resume if we have almost fetched till stop time Bug: 18821145 Change-Id: I7fd650999c6c50bbadffd65adee9020e669dfe62
-rw-r--r--media/libstagefright/HTTPBase.cpp9
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp32
-rw-r--r--media/libstagefright/httplive/LiveSession.h2
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.cpp21
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.h5
-rw-r--r--media/libstagefright/include/HTTPBase.h5
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp11
7 files changed, 71 insertions, 14 deletions
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 @@ HTTPBase::HTTPBase()
mTotalTransferBytes(0),
mPrevBandwidthMeasureTimeUs(0),
mPrevEstimatedBandWidthKbps(0),
- mBandWidthCollectFreqMs(5000) {
+ mBandWidthCollectFreqMs(5000),
+ mMaxBandwidthHistoryItems(100) {
}
void HTTPBase::addBandwidthMeasurement(
@@ -50,7 +51,7 @@ void HTTPBase::addBandwidthMeasurement(
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 @@ status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
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/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> &notify, uint32_t flags,
const sp<IMediaHTTPService> &httpService)
@@ -84,6 +87,13 @@ LiveSession::LiveSession(
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 @@ status_t LiveSession::dequeueAccessUnit(
}
}
+ 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 @@ ssize_t LiveSession::fetchFile(
// 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 @@ private:
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 @@ namespace android {
// 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> &notify,
@@ -561,7 +562,7 @@ status_t PlaylistFetcher::onResumeUntil(const sp<AMessage> &msg) {
// 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 @@ void PlaylistFetcher::onMonitorQueue() {
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 @@ const sp<ABuffer> &PlaylistFetcher::setAccessUnitProperties(
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 @@ void PlaylistFetcher::updateDuration() {
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 M3UParser;
struct String8;
struct PlaylistFetcher : public AHandler {
+ static const int64_t kMinBufferedDurationUs;
+ static const int32_t kDownloadBlockSize;
+
enum {
kWhatStarted,
kWhatPaused,
@@ -92,9 +95,7 @@ private:
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 @@ struct HTTPBase : public DataSource {
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 @@ struct HTTPBase : public DataSource {
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 @@ private:
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 @@ void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
}
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);
}
}
}