Track "network duration" separately and mirror it to the MDSM

This commit is contained in:
trav90
2017-07-02 03:54:07 -05:00
committed by Roy Tam
parent 58a9c5b569
commit 2fbf35f99a
7 changed files with 53 additions and 17 deletions
+3 -3
View File
@@ -2729,9 +2729,9 @@ nsresult HTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
double duration = aOriginal->GetDuration(); media::NullableTimeUnit duration = aOriginal->NetworkDuration();
if (duration >= 0) { if (duration.isSome()) {
decoder->SetDuration(duration); decoder->SetNetworkDuration(duration.ref());
decoder->SetMediaSeekable(aOriginal->IsMediaSeekable()); decoder->SetMediaSeekable(aOriginal->IsMediaSeekable());
} }
+11 -8
View File
@@ -32,8 +32,9 @@
#include "WMFDecoder.h" #include "WMFDecoder.h"
#endif #endif
using namespace mozilla::layers;
using namespace mozilla::dom; using namespace mozilla::dom;
using namespace mozilla::layers;
using namespace mozilla::media;
// Default timeout msecs until try to enter dormant state by heuristic. // Default timeout msecs until try to enter dormant state by heuristic.
static const int DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS = 60000; static const int DEFAULT_HEURISTIC_DORMANT_TIMEOUT_MSECS = 60000;
@@ -613,6 +614,8 @@ MediaDecoder::MediaDecoder() :
mMediaSeekable(true), mMediaSeekable(true),
mSameOriginMedia(false), mSameOriginMedia(false),
mReentrantMonitor("media.decoder"), mReentrantMonitor("media.decoder"),
mNetworkDuration(AbstractThread::MainThread(), NullableTimeUnit(),
"MediaDecoder::mNetworkDuration (Canonical)"),
mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING, mPlayState(AbstractThread::MainThread(), PLAY_STATE_LOADING,
"MediaDecoder::mPlayState (Canonical)"), "MediaDecoder::mPlayState (Canonical)"),
mNextState(AbstractThread::MainThread(), PLAY_STATE_PAUSED, mNextState(AbstractThread::MainThread(), PLAY_STATE_PAUSED,
@@ -764,7 +767,6 @@ nsresult MediaDecoder::InitializeStateMachine(MediaDecoder* aCloneDonor)
void MediaDecoder::SetStateMachineParameters() void MediaDecoder::SetStateMachineParameters()
{ {
ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mDecoderStateMachine->SetDuration(mDuration);
if (GetDecodedStream()) { if (GetDecodedStream()) {
mDecoderStateMachine->DispatchAudioCaptured(); mDecoderStateMachine->DispatchAudioCaptured();
} }
@@ -1365,9 +1367,14 @@ void MediaDecoder::DurationChanged()
} }
} }
void MediaDecoder::SetDuration(double aDuration) void MediaDecoder::SetNetworkDuration(TimeUnit aNetworkDuration)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
mNetworkDuration = Some(aNetworkDuration);
// 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)) { if (mozilla::IsInfinite(aDuration)) {
SetInfinite(true); SetInfinite(true);
} else if (IsNaN(aDuration)) { } else if (IsNaN(aDuration)) {
@@ -1377,12 +1384,8 @@ void MediaDecoder::SetDuration(double aDuration)
mDuration = static_cast<int64_t>(NS_round(aDuration * static_cast<double>(USECS_PER_S))); mDuration = static_cast<int64_t>(NS_round(aDuration * static_cast<double>(USECS_PER_S)));
} }
// Duration has changed so we should recompute playback rate.
ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
if (mDecoderStateMachine) {
mDecoderStateMachine->SetDuration(mDuration);
}
// Duration has changed so we should recompute playback rate
UpdatePlaybackRate(); UpdatePlaybackRate();
} }
+8 -1
View File
@@ -598,7 +598,8 @@ public:
// Set the duration of the media resource in units of seconds. // 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 // 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. // 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 // Sets the initial duration of the media. Called while the media metadata
// is being read and the decode is being setup. // is being read and the decode is being setup.
@@ -1126,6 +1127,12 @@ protected:
// without holding the monitor. // without holding the monitor.
nsAutoPtr<DecodedStreamData> mDecodedStream; nsAutoPtr<DecodedStreamData> mDecodedStream;
// 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. // Set to one of the valid play states.
// This can only be changed on the main thread while holding the decoder // 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 // monitor. Thus, it can be safely read while holding the decoder monitor
+20 -3
View File
@@ -43,9 +43,10 @@
namespace mozilla { namespace mozilla {
using namespace mozilla::layers;
using namespace mozilla::dom; using namespace mozilla::dom;
using namespace mozilla::gfx; using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::media;
#define NS_DispatchToMainThread(...) CompileError_UseAbstractThreadDispatchInstead #define NS_DispatchToMainThread(...) CompileError_UseAbstractThreadDispatchInstead
@@ -207,6 +208,8 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mStartTime(-1), mStartTime(-1),
mEndTime(-1), mEndTime(-1),
mDurationSet(false), mDurationSet(false),
mNetworkDuration(mTaskQueue, NullableTimeUnit(),
"MediaDecoderStateMachine::mNetworkDuration (Mirror)"),
mPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING, mPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_LOADING,
"MediaDecoderStateMachine::mPlayState (Mirror)"), "MediaDecoderStateMachine::mPlayState (Mirror)"),
mNextPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_PAUSED, mNextPlayState(mTaskQueue, MediaDecoder::PLAY_STATE_PAUSED,
@@ -304,6 +307,7 @@ MediaDecoderStateMachine::InitializationTask()
MOZ_ASSERT(OnTaskQueue()); MOZ_ASSERT(OnTaskQueue());
// Connect mirrors. // Connect mirrors.
mNetworkDuration.Connect(mDecoder->CanonicalNetworkDuration());
mPlayState.Connect(mDecoder->CanonicalPlayState()); mPlayState.Connect(mDecoder->CanonicalPlayState());
mNextPlayState.Connect(mDecoder->CanonicalNextPlayState()); mNextPlayState.Connect(mDecoder->CanonicalNextPlayState());
mLogicallySeeking.Connect(mDecoder->CanonicalLogicallySeeking()); mLogicallySeeking.Connect(mDecoder->CanonicalLogicallySeeking());
@@ -317,6 +321,7 @@ MediaDecoderStateMachine::InitializationTask()
mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged); mWatchManager.Watch(mVolume, &MediaDecoderStateMachine::VolumeChanged);
mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged); mWatchManager.Watch(mLogicalPlaybackRate, &MediaDecoderStateMachine::LogicalPlaybackRateChanged);
mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged); mWatchManager.Watch(mPreservesPitch, &MediaDecoderStateMachine::PreservesPitchChanged);
mWatchManager.Watch(mNetworkDuration, &MediaDecoderStateMachine::RecomputeDuration);
mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged); mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged); mWatchManager.Watch(mLogicallySeeking, &MediaDecoderStateMachine::LogicallySeekingChanged);
} }
@@ -1409,10 +1414,21 @@ private:
double mSeekTarget; double mSeekTarget;
}; };
void MediaDecoderStateMachine::RecomputeDuration()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// 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) void MediaDecoderStateMachine::SetDuration(int64_t aDuration)
{ {
MOZ_ASSERT(NS_IsMainThread() || OnDecodeTaskQueue()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
AssertCurrentThreadInMonitor();
if (aDuration < 0) { if (aDuration < 0) {
mDurationSet = false; mDurationSet = false;
@@ -2523,6 +2539,7 @@ MediaDecoderStateMachine::FinishShutdown()
mPendingWakeDecoder = nullptr; mPendingWakeDecoder = nullptr;
// Disconnect canonicals and mirrors before shutting down our task queue. // Disconnect canonicals and mirrors before shutting down our task queue.
mNetworkDuration.DisconnectIfConnected();
mPlayState.DisconnectIfConnected(); mPlayState.DisconnectIfConnected();
mNextPlayState.DisconnectIfConnected(); mNextPlayState.DisconnectIfConnected();
mLogicallySeeking.DisconnectIfConnected(); mLogicallySeeking.DisconnectIfConnected();
+6
View File
@@ -877,11 +877,17 @@ public:
// It will be set to -1 if the duration is infinite // It will be set to -1 if the duration is infinite
int64_t mEndTime; int64_t mEndTime;
// Recomputes the canonical duration from various sources.
void RecomputeDuration();
// Will be set when SetDuration has been called with a value != -1 // 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 // mDurationSet false doesn't indicate that we do not have a valid duration
// as mStartTime and mEndTime could have been set separately. // as mStartTime and mEndTime could have been set separately.
bool mDurationSet; 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. // The current play state and next play state, mirrored from the main thread.
Mirror<MediaDecoder::PlayState> mPlayState; Mirror<MediaDecoder::PlayState> mPlayState;
Mirror<MediaDecoder::PlayState> mNextPlayState; Mirror<MediaDecoder::PlayState> mNextPlayState;
+3 -1
View File
@@ -33,6 +33,8 @@
#include "nsProxyRelease.h" #include "nsProxyRelease.h"
#include "nsIContentPolicy.h" #include "nsIContentPolicy.h"
using mozilla::media::TimeUnit;
#ifdef PR_LOGGING #ifdef PR_LOGGING
PRLogModuleInfo* gMediaResourceLog; PRLogModuleInfo* gMediaResourceLog;
#define RESOURCE_LOG(msg, ...) PR_LOG(gMediaResourceLog, PR_LOG_DEBUG, \ #define RESOURCE_LOG(msg, ...) PR_LOG(gMediaResourceLog, PR_LOG_DEBUG, \
@@ -261,7 +263,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
double duration = durationText.ToDouble(&ec); double duration = durationText.ToDouble(&ec);
if (ec == NS_OK && duration >= 0) { if (ec == NS_OK && duration >= 0) {
mDecoder->SetDuration(duration); mDecoder->SetNetworkDuration(TimeUnit::FromSeconds(duration));
// We know the resource must be bounded. // We know the resource must be bounded.
dataIsBounded = true; dataIsBounded = true;
} }
+2 -1
View File
@@ -19,6 +19,7 @@
#include "mozilla/net/RtspChannelChild.h" #include "mozilla/net/RtspChannelChild.h"
#endif #endif
using namespace mozilla::net; using namespace mozilla::net;
using namespace mozilla::media;
#ifdef PR_LOGGING #ifdef PR_LOGGING
PRLogModuleInfo* gRtspMediaResourceLog; PRLogModuleInfo* gRtspMediaResourceLog;
@@ -727,7 +728,7 @@ RtspMediaResource::OnConnected(uint8_t aTrackIdx,
// Not live stream. // Not live stream.
mIsLiveStream = false; mIsLiveStream = false;
mDecoder->SetInfinite(false); mDecoder->SetInfinite(false);
mDecoder->SetDuration((double)(durationUs) / USECS_PER_S); mDecoder->SetNetworkDuration(TimeUnit::FromMicroseconds(durationUs));
} else { } else {
// Live stream. // Live stream.
// Check the preference "media.realtime_decoder.enabled". // Check the preference "media.realtime_decoder.enabled".