mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1171330: P11. Add eviction support. r=cajbir.
We evict data in two steps. Up to playback time, or tail data. --HG-- extra : rebase_source : 052273e92d3b3704f513a55aac3e5d75c0d900fa
This commit is contained in:
parent
a998798778
commit
5d7588e70d
@ -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->mSize;
|
||||
}
|
||||
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->mSize;
|
||||
}
|
||||
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->mSize;
|
||||
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->mSize;
|
||||
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__);
|
||||
}
|
||||
|
||||
@ -891,6 +972,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
|
||||
@ -1046,6 +1130,7 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
|
||||
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
|
||||
TimeUnit::FromMicroseconds(sample->mTime + sample->mDuration)));
|
||||
}
|
||||
trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->mSize;
|
||||
data.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
@ -1064,6 +1149,7 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
|
||||
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
|
||||
TimeUnit::FromMicroseconds(sample->mTime + sample->mDuration)));
|
||||
}
|
||||
trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->mSize;
|
||||
data.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
@ -1080,6 +1166,7 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
|
||||
removedInterval = removedInterval.Span(
|
||||
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
|
||||
TimeUnit::FromMicroseconds(sample->mTime + sample->mDuration)));
|
||||
trackBuffer.mSizeBuffer -= sizeof(*aSample) + sample->mSize;
|
||||
data.RemoveElementAt(i);
|
||||
}
|
||||
// Update our buffered range to exclude the range just removed.
|
||||
@ -1094,6 +1181,8 @@ TrackBuffersManager::ProcessFrame(MediaRawData* aSample,
|
||||
} else {
|
||||
data.AppendElement(aSample);
|
||||
}
|
||||
trackBuffer.mSizeBuffer += sizeof(*aSample) + aSample->mSize;
|
||||
|
||||
// 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 multipple threads.
|
||||
mutable Monitor mMonitor;
|
||||
// Set by the main thread, but only when all our tasks are completes
|
||||
|
Loading…
Reference in New Issue
Block a user