Add eviction support to TrackBuffersManager

We evict data in two steps. Up to playback time, or tail data.
This commit is contained in:
trav90
2017-05-04 02:29:08 -05:00
committed by roytam1
parent cead5d3907
commit 4708ca920e
2 changed files with 99 additions and 3 deletions
+92 -3
View File
@@ -129,7 +129,20 @@ TrackBuffersManager::EvictData(TimeUnit aPlaybackTime,
uint32_t aThreshold,
TimeUnit* aBufferStartTime)
{
// TODO.
MOZ_ASSERT(NS_IsMainThread());
int64_t toEvict = GetSize() - aThreshold;
if (toEvict <= 0) {
return EvictDataResult::NO_DATA_EVICTED;
}
MSE_DEBUG("Reaching our size limit, schedule eviction of %lld bytes", toEvict);
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableMethodWithArgs<TimeUnit, uint32_t>(
this, &TrackBuffersManager::DoEvictData,
aPlaybackTime, toEvict);
GetTaskQueue()->Dispatch(task.forget());
return EvictDataResult::NO_DATA_EVICTED;
}
@@ -182,8 +195,7 @@ TrackBuffersManager::Buffered()
int64_t
TrackBuffersManager::GetSize()
{
// TODO
return 0;
return mSizeSourceBuffer;
}
void
@@ -280,6 +292,70 @@ TrackBuffersManager::CompleteResetParserState()
mAbort = false;
}
void
TrackBuffersManager::DoEvictData(const TimeUnit& aPlaybackTime,
uint32_t aSizeToEvict)
{
MOZ_ASSERT(OnTaskQueue());
// Remove any data we've already played, up to 5s behind.
TimeUnit lowerLimit = aPlaybackTime - TimeUnit::FromSeconds(5);
TimeUnit to;
// Video is what takes the most space, only evict there if we have video.
const auto& track = HasVideo() ? mVideoTracks : mAudioTracks;
const auto& buffer = track.mBuffers.LastElement();
uint32_t lastKeyFrameIndex = 0;
int64_t toEvict = aSizeToEvict;
uint32_t partialEvict = 0;
for (uint32_t i = 0; i < buffer.Length(); i++) {
const auto& frame = buffer[i];
if (frame->mKeyframe) {
lastKeyFrameIndex = i;
toEvict -= partialEvict;
if (toEvict < 0) {
break;
}
partialEvict = 0;
}
if (frame->mTime >= lowerLimit.ToMicroseconds()) {
break;
}
partialEvict += sizeof(*frame) + frame->Size();
}
if (lastKeyFrameIndex > 0) {
CodedFrameRemoval(
TimeInterval(TimeUnit::FromMicroseconds(0),
TimeUnit::FromMicroseconds(buffer[lastKeyFrameIndex-1]->mTime)));
}
if (toEvict <= 0) {
return;
}
// Still some to remove. Remove data starting from the end, up to 5s ahead
// of our playtime.
TimeUnit upperLimit = aPlaybackTime + TimeUnit::FromSeconds(5);
for (int32_t i = buffer.Length() - 1; i >= 0; i--) {
const auto& frame = buffer[i];
if (frame->mKeyframe) {
lastKeyFrameIndex = i;
toEvict -= partialEvict;
if (toEvict < 0) {
break;
}
partialEvict = 0;
}
if (frame->mTime <= upperLimit.ToMicroseconds()) {
break;
}
partialEvict += sizeof(*frame) + frame->Size();
}
if (lastKeyFrameIndex < buffer.Length()) {
CodedFrameRemoval(
TimeInterval(TimeUnit::FromMicroseconds(buffer[lastKeyFrameIndex+1]->mTime),
TimeUnit::FromInfinity()));
}
}
void
TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
{
@@ -332,6 +408,7 @@ TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
TimeInterval(TimeUnit::FromMicroseconds(frame->mTime),
TimeUnit::FromMicroseconds(frame->mTime + frame->mDuration)));
}
track->mSizeBuffer -= sizeof(*frame) + frame->Size();
data.RemoveElementAt(i);
}
}
@@ -346,6 +423,7 @@ TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
removedInterval = removedInterval.Span(
TimeInterval(TimeUnit::FromMicroseconds(frame->mTime),
TimeUnit::FromMicroseconds(frame->mTime + frame->mDuration)));
track->mSizeBuffer -= sizeof(*frame) + frame->Size();
data.RemoveElementAt(i);
}
}
@@ -369,6 +447,9 @@ TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
MSE_DEBUG("after video ranges=%s", DumpTimeRanges(mVideoTracks.mBufferedRanges).get());
MSE_DEBUG("after audio ranges=%s", DumpTimeRanges(mAudioTracks.mBufferedRanges).get());
// Update our reported total size.
mSizeSourceBuffer = mVideoTracks.mSizeBuffer + mAudioTracks.mSizeBuffer;
mRangeRemovalPromise.ResolveIfExists(true, __func__);
}
@@ -884,6 +965,9 @@ TrackBuffersManager::CompleteCodedFrameProcessing()
mAudioBufferedRanges = mAudioTracks.mBufferedRanges;
}
// Update our reported total size.
mSizeSourceBuffer = mVideoTracks.mSizeBuffer + mAudioTracks.mSizeBuffer;
// Return to step 6.4 of Segment Parser Loop algorithm
// 4. If this SourceBuffer is full and cannot accept more media data, then set the buffer full flag to true.
// TODO
@@ -1039,6 +1123,7 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
TimeUnit::FromMicroseconds(sample->mTime + sample->mDuration)));
}
trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->Size();
data.RemoveElementAt(i);
}
}
@@ -1057,6 +1142,7 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
TimeUnit::FromMicroseconds(sample->mTime + sample->mDuration)));
}
trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->Size();
data.RemoveElementAt(i);
}
}
@@ -1073,6 +1159,7 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
removedInterval = removedInterval.Span(
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
TimeUnit::FromMicroseconds(sample->mTime + sample->mDuration)));
trackBuffer.mSizeBuffer -= sizeof(*aSample) + sample->Size();
data.RemoveElementAt(i);
}
// Update our buffered range to exclude the range just removed.
@@ -1087,6 +1174,8 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
} else {
data.AppendElement(aSample);
}
trackBuffer.mSizeBuffer += sizeof(*aSample) + aSample->Size();
// 17. Set last decode timestamp for track buffer to decode timestamp.
trackBuffer.mLastDecodeTimestamp = Some(decodeTimestamp);
// 18. Set last frame duration for track buffer to frame duration.
@@ -159,10 +159,13 @@ private:
OnDemuxFailed(TrackType::kAudioTrack, aFailure);
}
void DoEvictData(const TimeUnit& aPlaybackTime, uint32_t aThreshold);
struct TrackData {
TrackData()
: mNumTracks(0)
, mNeedRandomAccessPoint(true)
, mSizeBuffer(0)
{}
uint32_t mNumTracks;
Maybe<TimeUnit> mLastDecodeTimestamp;
@@ -176,6 +179,7 @@ private:
// We only manage a single track of each type at this time.
nsTArray<TrackBuffer> mBuffers;
TimeIntervals mBufferedRanges;
uint32_t mSizeBuffer;
};
bool ProcessFrame(MediaRawData* aSample, TrackData& aTrackData);
MediaPromiseRequestHolder<CodedFrameProcessingPromise> mProcessingRequest;
@@ -223,6 +227,9 @@ private:
// Set to true if mediasource state changed to ended.
Atomic<bool> mEnded;
// Global size of this source buffer content.
Atomic<int64_t> mSizeSourceBuffer;
// Monitor to protect following objects accessed across multiple threads.
mutable Monitor mMonitor;
// Set by the main thread, but only when all our tasks are completes