[WVDRM] Fix for stuttering on low bandwidth
Reintroduces the play/pause rebuffering logic we eliminated in JB zero day to fix double spins and slow startup - but activates that logic only based on a comparison of the current bandwidth measurement and the lowest bitrate track in the movie. Needs to be submitted with related changes in /frameworks/av bug: 7230071 Change-Id: Ib3859a961bd3901a9c4df01eeab2b8b75f49aefe
This commit is contained in:
@@ -524,19 +524,26 @@ int64_t WVMExtractorImpl::getCachedDurationUs(status_t *finalStatus) {
|
|||||||
const size_t kMaxEncodedRates = 32;
|
const size_t kMaxEncodedRates = 32;
|
||||||
unsigned long encodedRates[kMaxEncodedRates];
|
unsigned long encodedRates[kMaxEncodedRates];
|
||||||
size_t ratesReturned, currentTrack;
|
size_t ratesReturned, currentTrack;
|
||||||
|
unsigned long minRate = ULONG_MAX;
|
||||||
|
unsigned long bandwidth = ULONG_MAX;
|
||||||
|
|
||||||
WVStatus status = WV_Info_GetAdaptiveBitrates(mSession, encodedRates, kMaxEncodedRates,
|
WVStatus status = WV_Info_GetAdaptiveBitrates(mSession, encodedRates, kMaxEncodedRates,
|
||||||
&ratesReturned, ¤tTrack);
|
&ratesReturned, ¤tTrack);
|
||||||
if (status == WV_Status_OK) {
|
if (status == WV_Status_OK) {
|
||||||
if (currentTrack != kMaxEncodedRates && ratesReturned != 0) {
|
if (currentTrack != kMaxEncodedRates && ratesReturned != 0) {
|
||||||
|
for (size_t i = 0; i < ratesReturned; i++) {
|
||||||
|
if (encodedRates[i] < minRate) {
|
||||||
|
minRate = encodedRates[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WV_Info_CurrentBandwidth(mSession, &bandwidth);
|
||||||
|
|
||||||
// Log the current adaptive rate every 5 seconds
|
// Log the current adaptive rate every 5 seconds
|
||||||
time_t now = time(0);
|
time_t now = time(0);
|
||||||
static time_t lastLogTime = now;
|
static time_t lastLogTime = now;
|
||||||
if (now > lastLogTime + 5) {
|
if (now > lastLogTime + 5) {
|
||||||
lastLogTime = now;
|
lastLogTime = now;
|
||||||
unsigned long bandwidth = -1;
|
|
||||||
WV_Info_CurrentBandwidth(mSession, &bandwidth);
|
|
||||||
|
|
||||||
ALOGI("using adaptive track #%d, rate=%ld, bandwidth=%ld\n",
|
ALOGI("using adaptive track #%d, rate=%ld, bandwidth=%ld\n",
|
||||||
currentTrack, encodedRates[currentTrack], bandwidth);
|
currentTrack, encodedRates[currentTrack], bandwidth);
|
||||||
}
|
}
|
||||||
@@ -544,12 +551,22 @@ int64_t WVMExtractorImpl::getCachedDurationUs(status_t *finalStatus) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t durationUs = 0;
|
uint64_t durationUs = 0;
|
||||||
|
float secondsBuffered;
|
||||||
|
status = WV_Info_TimeBuffered(mSession, &secondsBuffered);
|
||||||
|
|
||||||
if (!mVideoSource->isStalled() && !mAudioSource->isStalled()) {
|
//
|
||||||
// Data is buffered as long as the pull isn't stalled.
|
// As long as the bandwidth is greater than the min bitrate, don't
|
||||||
// The amount indicated doesn't matter as long as it
|
// need to consider rebuffering so return a buffered time greater
|
||||||
// is more than the high water mark.
|
// than the low water mark. This provides fast startup when the
|
||||||
|
// network speed is good and rebuffering when it is not.
|
||||||
|
//
|
||||||
|
if (bandwidth != ULONG_MAX && minRate != ULONG_MAX && bandwidth >= minRate) {
|
||||||
|
//ALOGD("Bandwidth %ld is sufficient for lowest rate %ld, override buffered time", bandwidth, minRate);
|
||||||
durationUs = 10000000LL;
|
durationUs = 10000000LL;
|
||||||
|
} else {
|
||||||
|
unsigned long kScaleFactor = 2; // scale to cached duration to tune watermark levels
|
||||||
|
durationUs = (uint64_t)(secondsBuffered * 1000000LL * kScaleFactor);
|
||||||
|
//ALOGD("Bandwidth %ld is too low for lowest rate %ld, use buffered time %lld", bandwidth, minRate, durationUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == WV_Status_End_Of_Media) {
|
if (status == WV_Status_End_Of_Media) {
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ WVMMediaSource::WVMMediaSource(WVSession *session, WVEsSelector esSelector,
|
|||||||
mIsLiveStream(isLive),
|
mIsLiveStream(isLive),
|
||||||
mNewSegment(false),
|
mNewSegment(false),
|
||||||
mCryptoInitialized(false),
|
mCryptoInitialized(false),
|
||||||
mIsStalled(false),
|
|
||||||
mStripADTS(false),
|
mStripADTS(false),
|
||||||
mGroup(NULL),
|
mGroup(NULL),
|
||||||
mKeyTime(0),
|
mKeyTime(0),
|
||||||
@@ -214,8 +213,6 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
{
|
{
|
||||||
Mutex::Autolock autoLock(mLock);
|
Mutex::Autolock autoLock(mLock);
|
||||||
|
|
||||||
mIsStalled = false;
|
|
||||||
|
|
||||||
CHECK(mStarted);
|
CHECK(mStarted);
|
||||||
|
|
||||||
*buffer = NULL;
|
*buffer = NULL;
|
||||||
@@ -351,8 +348,6 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
return ERROR_IO;
|
return ERROR_IO;
|
||||||
} else {
|
} else {
|
||||||
// Didn't get anything, sleep a bit so we don't hog the CPU then try again
|
// Didn't get anything, sleep a bit so we don't hog the CPU then try again
|
||||||
if (retryCount > 10)
|
|
||||||
mIsStalled = true;
|
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -364,15 +359,12 @@ status_t WVMMediaSource::read(MediaBuffer **buffer, const ReadOptions *options)
|
|||||||
|
|
||||||
if (seekNextSync && ((mKeyTime < seekTimeUs) || !syncFrame)) {
|
if (seekNextSync && ((mKeyTime < seekTimeUs) || !syncFrame)) {
|
||||||
// drop frames up to next sync if requested
|
// drop frames up to next sync if requested
|
||||||
mIsStalled = true;
|
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
mDecryptContext.Initialize(mediaBuf);
|
mDecryptContext.Initialize(mediaBuf);
|
||||||
mEncryptedSizes.clear();
|
mEncryptedSizes.clear();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsStalled = false;
|
|
||||||
|
|
||||||
if (offset + bytesRead < mediaBuf->size())
|
if (offset + bytesRead < mediaBuf->size())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ public:
|
|||||||
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
|
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
|
||||||
|
|
||||||
void addEncryptedSize(size_t size) { mEncryptedSizes.push_back(size); }
|
void addEncryptedSize(size_t size) { mEncryptedSizes.push_back(size); }
|
||||||
bool isStalled() const { return mIsStalled; }
|
|
||||||
|
|
||||||
static int sLastError;
|
static int sLastError;
|
||||||
|
|
||||||
@@ -87,7 +86,6 @@ private:
|
|||||||
bool mIsLiveStream;
|
bool mIsLiveStream;
|
||||||
bool mNewSegment;
|
bool mNewSegment;
|
||||||
bool mCryptoInitialized;
|
bool mCryptoInitialized;
|
||||||
bool mIsStalled;
|
|
||||||
bool mStripADTS;
|
bool mStripADTS;
|
||||||
|
|
||||||
MediaBufferGroup *mGroup;
|
MediaBufferGroup *mGroup;
|
||||||
|
|||||||
Reference in New Issue
Block a user