Bug 1160695 - Track "network duration" separately and mirror it to the MDSM. r=jww

This commit is contained in:
Bobby Holley 2015-05-28 12:13:56 -07:00
parent 83dfaddcec
commit 7fd942549a
7 changed files with 53 additions and 17 deletions

View File

@ -2720,9 +2720,9 @@ nsresult HTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
return NS_ERROR_FAILURE;
}
double duration = aOriginal->GetDuration();
if (duration >= 0) {
decoder->SetDuration(duration);
media::NullableTimeUnit duration = aOriginal->NetworkDuration();
if (duration.isSome()) {
decoder->SetNetworkDuration(duration.ref());
decoder->SetMediaSeekable(aOriginal->IsMediaSeekable());
}

View File

@ -32,8 +32,9 @@
#include "WMFDecoder.h"
#endif
using namespace mozilla::layers;
using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::media;
// Default timeout msecs until try to enter dormant state by heuristic.
static const int DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS = 60000;
@ -343,6 +344,8 @@ MediaDecoder::MediaDecoder() :
mMediaSeekable(true),
mSameOriginMedia(false),
mReentrantMonitor("media.decoder"),
mNetworkDuration(AbstractThread::MainThread(), NullableTimeUnit(),
"MediaDecoder::mNetworkDuration (Canonical)"),
mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING,
"MediaDecoder::mPlayState (Canonical)"),
mNextState(AbstractThread::MainThread(), PLAY_STATE_PAUSED,
@ -488,7 +491,6 @@ nsresult MediaDecoder::InitializeStateMachine(MediaDecoder* aCloneDonor)
void MediaDecoder::SetStateMachineParameters()
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mDecoderStateMachine->SetDuration(mDuration);
if (mMinimizePreroll) {
mDecoderStateMachine->DispatchMinimizePrerollUntilPlaybackStarts();
}
@ -1082,9 +1084,14 @@ void MediaDecoder::DurationChanged()
}
}
void MediaDecoder::SetDuration(double aDuration)
void MediaDecoder::SetNetworkDuration(TimeUnit aNetworkDuration)
{
MOZ_ASSERT(NS_IsMainThread());
mNetworkDuration = Some(aNetworkDuration);
// XXXbholley - it doesn't really make sense to change mDuration here, but
// we leave it for this patch. This will change in subsequent patches.
double aDuration = aNetworkDuration.ToSeconds();
if (mozilla::IsInfinite(aDuration)) {
SetInfinite(true);
} else if (IsNaN(aDuration)) {
@ -1094,12 +1101,8 @@ void MediaDecoder::SetDuration(double aDuration)
mDuration = static_cast<int64_t>(NS_round(aDuration * static_cast<double>(USECS_PER_S)));
}
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (mDecoderStateMachine) {
mDecoderStateMachine->SetDuration(mDuration);
}
// Duration has changed so we should recompute playback rate
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
UpdatePlaybackRate();
}

View File

@ -459,7 +459,8 @@ public:
// Set the duration of the media resource in units of seconds.
// This is called via a channel listener if it can pick up the duration
// from a content header. Must be called from the main thread only.
virtual void SetDuration(double aDuration);
void SetNetworkDuration(media::TimeUnit aDuration);
media::NullableTimeUnit NetworkDuration() { return mNetworkDuration; }
// Sets the initial duration of the media. Called while the media metadata
// is being read and the decode is being setup.
@ -994,6 +995,12 @@ private:
#endif
protected:
// Media duration according to HTTP headers.
Canonical<media::NullableTimeUnit> mNetworkDuration;
public:
AbstractCanonical<media::NullableTimeUnit>* CanonicalNetworkDuration() { return &mNetworkDuration; }
protected:
// Set to one of the valid play states.
// This can only be changed on the main thread while holding the decoder
// monitor. Thus, it can be safely read while holding the decoder monitor

View File

@ -44,9 +44,10 @@
namespace mozilla {
using namespace mozilla::layers;
using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::media;
#define NS_DispatchToMainThread(...) CompileError_UseAbstractThreadDispatchInstead
@ -197,6 +198,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mStartTime(-1),
mEndTime(-1),
mDurationSet(false),
mNetworkDuration(mTaskQueue, NullableTimeUnit(),
"MediaDecoderStateMachine::mNetworkDuration (Mirror)"),
mPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING,
"MediaDecoderStateMachine::mPlayState (Mirror)"),
mNextPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_PAUSED,
@ -294,6 +297,7 @@ MediaDecoderStateMachine::InitializationTask()
MOZ_ASSERT(OnTaskQueue());
// Connect mirrors.
mNetworkDuration.Connect(mDecoder->CanonicalNetworkDuration());
mPlayState.Connect(mDecoder->CanonicalPlayState());
mNextPlayState.Connect(mDecoder->CanonicalNextPlayState());
mLogicallySeeking.Connect(mDecoder->CanonicalLogicallySeeking());
@ -307,6 +311,7 @@ MediaDecoderStateMachine::InitializationTask()
mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged);
mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
mWatchManager.Watch(mNetworkDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged);
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::UpdateStreamBlockingForPlayState);
@ -1450,10 +1455,21 @@ private:
double mSeekTarget;
};
void MediaDecoderStateMachine::RecomputeDuration()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXXbholley - This will do something more sensible in upcoming patches. This
// would be incorrect if we ever sent spurious state mirroring updates.
if (mNetworkDuration.Ref().isSome()) {
SetDuration(mNetworkDuration.Ref().ref().ToMicroseconds());
}
}
void MediaDecoderStateMachine::SetDuration(int64_t aDuration)
{
MOZ_ASSERT(NS_IsMainThread() || OnDecodeTaskQueue());
AssertCurrentThreadInMonitor();
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (aDuration < 0) {
mDurationSet = false;
@ -2555,6 +2571,7 @@ MediaDecoderStateMachine::FinishShutdown()
mPendingWakeDecoder = nullptr;
// Disconnect canonicals and mirrors before shutting down our task queue.
mNetworkDuration.DisconnectIfConnected();
mPlayState.DisconnectIfConnected();
mNextPlayState.DisconnectIfConnected();
mLogicallySeeking.DisconnectIfConnected();

View File

@ -900,11 +900,17 @@ public:
// It will be set to -1 if the duration is infinite
int64_t mEndTime;
// Recomputes the canonical duration from various sources.
void RecomputeDuration();
// Will be set when SetDuration has been called with a value != -1
// mDurationSet false doesn't indicate that we do not have a valid duration
// as mStartTime and mEndTime could have been set separately.
bool mDurationSet;
// The duration according to HTTP headers etc, mirrored from the main thread.
Mirror<media::NullableTimeUnit> mNetworkDuration;
// The current play state and next play state, mirrored from the main thread.
Mirror<MediaDecoder::PlayState> mPlayState;
Mirror<MediaDecoder::PlayState> mNextPlayState;

View File

@ -33,6 +33,8 @@
#include "nsProxyRelease.h"
#include "nsIContentPolicy.h"
using mozilla::media::TimeUnit;
PRLogModuleInfo* gMediaResourceLog;
#define RESOURCE_LOG(msg, ...) MOZ_LOG(gMediaResourceLog, mozilla::LogLevel::Debug, \
(msg, ##__VA_ARGS__))
@ -260,7 +262,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
if (NS_SUCCEEDED(rv)) {
double duration = durationText.ToDouble(&ec);
if (ec == NS_OK && duration >= 0) {
mDecoder->SetDuration(duration);
mDecoder->SetNetworkDuration(TimeUnit::FromSeconds(duration));
// We know the resource must be bounded.
dataIsBounded = true;
}

View File

@ -19,6 +19,7 @@
#include "mozilla/net/RtspChannelChild.h"
#endif
using namespace mozilla::net;
using namespace mozilla::media;
PRLogModuleInfo* gRtspMediaResourceLog;
#define RTSP_LOG(msg, ...) MOZ_LOG(gRtspMediaResourceLog, mozilla::LogLevel::Debug, \
@ -725,7 +726,7 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx,
// Not live stream.
mIsLiveStream = false;
mDecoder->SetInfinite(false);
mDecoder->SetDuration((double)(durationUs) / USECS_PER_S);
mDecoder->SetNetworkDuration(TimeUnit::FromMicroseconds(durationUs));
} else {
// Live stream.
// Check the preference "media.realtime_decoder.enabled".