Bug 1160695 - Track demuxer-estimated duration separately. r=jww

This commit is contained in:
Bobby Holley 2015-06-02 15:29:50 -07:00
parent 6db2f8e38f
commit 8d973d850d
4 changed files with 49 additions and 29 deletions

View File

@ -49,6 +49,12 @@ namespace mozilla {
// fluctuating bitrates.
static const int64_t CAN_PLAY_THROUGH_MARGIN = 1;
// The amount of instability we tollerate in calls to
// MediaDecoder::UpdateEstimatedMediaDuration(); changes of duration
// less than this are ignored, as they're assumed to be the result of
// instability in the duration estimation.
static const uint64_t ESTIMATED_DURATION_FUZZ_FACTOR_USECS = USECS_PER_S / 2;
// avoid redefined macro in unified build
#undef DECODER_LOG
@ -346,6 +352,8 @@ MediaDecoder::MediaDecoder() :
mReentrantMonitor("media.decoder"),
mNetworkDuration(AbstractThread::MainThread(), NullableTimeUnit(),
"MediaDecoder::mNetworkDuration (Canonical)"),
mEstimatedDuration(AbstractThread::MainThread(), NullableTimeUnit(),
"MediaDecoder::mEstimatedDuration (Canonical)"),
mExplicitDuration(AbstractThread::MainThread(), Maybe<double>(),
"MediaDecoder::mExplicitDuration (Canonical)"),
mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING,
@ -1113,8 +1121,17 @@ void MediaDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
if (mPlayState <= PLAY_STATE_LOADING) {
return;
}
NS_ENSURE_TRUE_VOID(GetStateMachine());
GetStateMachine()->UpdateEstimatedDuration(aDuration);
// The duration is only changed if its significantly different than the
// the current estimate, as the incoming duration is an estimate and so
// often is unstable as more data is read and the estimate is updated.
// Can result in a durationchangeevent. aDuration is in microseconds.
if (mEstimatedDuration.Ref().isSome() &&
mozilla::Abs(mEstimatedDuration.Ref().ref().ToMicroseconds() - aDuration) < ESTIMATED_DURATION_FUZZ_FACTOR_USECS) {
return;
}
mEstimatedDuration = Some(TimeUnit::FromMicroseconds(aDuration));
}
void MediaDecoder::SetMediaSeekable(bool aMediaSeekable) {

View File

@ -995,6 +995,17 @@ public:
AbstractCanonical<media::NullableTimeUnit>* CanonicalNetworkDuration() { return &mNetworkDuration; }
protected:
// Media duration according to the demuxer's current estimate.
//
// Note that it's quite bizarre for this to live on the main thread - it would
// make much more sense for this to be owned by the demuxer's task queue. But
// currently this is only every changed in NotifyDataArrived, which runs on
// the main thread. That will need to be cleaned up at some point.
Canonical<media::NullableTimeUnit> mEstimatedDuration;
public:
AbstractCanonical<media::NullableTimeUnit>* CanonicalEstimatedDuration() { return &mEstimatedDuration; }
protected:
// Media duration set explicitly by JS. At present, this is only ever present
// for MSE.
Canonical<Maybe<double>> mExplicitDuration;

View File

@ -163,12 +163,6 @@ static_assert(QUICK_BUFFERING_LOW_DATA_USECS <= AMPLE_AUDIO_USECS,
} // namespace detail
// The amount of instability we tollerate in calls to
// MediaDecoderStateMachine::UpdateEstimatedDuration(); changes of duration
// less than this are ignored, as they're assumed to be the result of
// instability in the duration estimation.
static const uint64_t ESTIMATED_DURATION_FUZZ_FACTOR_USECS = USECS_PER_S / 2;
static TimeDuration UsecsToDuration(int64_t aUsecs) {
return TimeDuration::FromMicroseconds(aUsecs);
}
@ -200,6 +194,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mDurationSet(false),
mNetworkDuration(mTaskQueue, NullableTimeUnit(),
"MediaDecoderStateMachine::mNetworkDuration (Mirror)"),
mEstimatedDuration(mTaskQueue, NullableTimeUnit(),
"MediaDecoderStateMachine::EstimatedDuration (Mirror)"),
mExplicitDuration(mTaskQueue, Maybe<double>(),
"MediaDecoderStateMachine::mExplicitDuration (Mirror)"),
mPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING,
@ -300,6 +296,7 @@ MediaDecoderStateMachine::InitializationTask()
// Connect mirrors.
mNetworkDuration.Connect(mDecoder->CanonicalNetworkDuration());
mEstimatedDuration.Connect(mDecoder->CanonicalEstimatedDuration());
mExplicitDuration.Connect(mDecoder->CanonicalExplicitDuration());
mPlayState.Connect(mDecoder->CanonicalPlayState());
mNextPlayState.Connect(mDecoder->CanonicalNextPlayState());
@ -315,6 +312,7 @@ MediaDecoderStateMachine::InitializationTask()
mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged);
mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
mWatchManager.Watch(mNetworkDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mEstimatedDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mExplicitDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged);
@ -1474,6 +1472,17 @@ void MediaDecoderStateMachine::RecomputeDuration()
}
TimeUnit duration = TimeUnit::FromSeconds(d);
SetDuration(duration.ToMicroseconds());
} else if (mEstimatedDuration.Ref().isSome()) {
if (mEstimatedDuration.Ref()->ToMicroseconds() != GetDuration()) {
SetDuration(mEstimatedDuration.Ref()->ToMicroseconds());
// XXXbholley - Firing the event here is historical, and not necessarily
// sensical.
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethodWithArg<TimeUnit>(mDecoder, &MediaDecoder::DurationChanged,
TimeUnit::FromMicroseconds(GetDuration()));
AbstractThread::MainThread()->Dispatch(event.forget());
}
} else if (mInfo.mMetadataDuration.isSome()) {
SetDuration(mInfo.mMetadataDuration.ref().ToMicroseconds());
} else if (mInfo.mMetadataEndTime.isSome() && mStartTime >= 0) {
@ -1523,20 +1532,6 @@ void MediaDecoderStateMachine::SetDuration(int64_t aDuration)
}
}
void MediaDecoderStateMachine::UpdateEstimatedDuration(int64_t aDuration)
{
AssertCurrentThreadInMonitor();
int64_t duration = GetDuration();
if (aDuration != duration &&
mozilla::Abs(aDuration - duration) > ESTIMATED_DURATION_FUZZ_FACTOR_USECS) {
SetDuration(aDuration);
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethodWithArg<TimeUnit>(mDecoder, &MediaDecoder::DurationChanged,
TimeUnit::FromMicroseconds(GetDuration()));
AbstractThread::MainThread()->Dispatch(event.forget());
}
}
void MediaDecoderStateMachine::SetFragmentEndTime(int64_t aEndTime)
{
AssertCurrentThreadInMonitor();
@ -2586,6 +2581,7 @@ MediaDecoderStateMachine::FinishShutdown()
// Disconnect canonicals and mirrors before shutting down our task queue.
mNetworkDuration.DisconnectIfConnected();
mEstimatedDuration.DisconnectIfConnected();
mExplicitDuration.DisconnectIfConnected();
mPlayState.DisconnectIfConnected();
mNextPlayState.DisconnectIfConnected();

View File

@ -206,13 +206,6 @@ public:
// A value of INT64_MAX will be treated as infinity.
void SetDuration(int64_t aDuration);
// Called from main thread to update the duration with an estimated value.
// The duration is only changed if its significantly different than the
// the current duration, as the incoming duration is an estimate and so
// often is unstable as more data is read and the estimate is updated.
// Can result in a durationchangeevent. aDuration is in microseconds.
void UpdateEstimatedDuration(int64_t aDuration);
// Functions used by assertions to ensure we're calling things
// on the appropriate threads.
bool OnDecodeTaskQueue() const;
@ -906,6 +899,9 @@ public:
// The duration according to HTTP headers etc, mirrored from the main thread.
Mirror<media::NullableTimeUnit> mNetworkDuration;
// The duration according to the demuxer's current estimate, mirrored from the main thread.
Mirror<media::NullableTimeUnit> mEstimatedDuration;
// The duration explicitly set by JS, mirrored from the main thread.
Mirror<Maybe<double>> mExplicitDuration;