diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini
index 9a102c6b6f97..e8023134bc8c 100644
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -267,6 +267,8 @@ support-files =
skip-if = buildapp == 'mulet'
[test_audioNotificationStopOnNavigation.html]
skip-if = buildapp == 'mulet'
+[test_audioNotificationWithEarlyPlay.html]
+skip-if = buildapp == 'mulet'
[test_bug1091883.html]
[test_bug116083.html]
[test_bug793311.html]
diff --git a/dom/base/test/test_audioNotificationWithEarlyPlay.html b/dom/base/test/test_audioNotificationWithEarlyPlay.html
new file mode 100644
index 000000000000..66184ae03ab3
--- /dev/null
+++ b/dom/base/test/test_audioNotificationWithEarlyPlay.html
@@ -0,0 +1,73 @@
+
+
+
+ Test for audio controller in windows
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index 2e47c0946486..f76e600f4b69 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -3184,11 +3184,47 @@ void HTMLMediaElement::ProcessMediaFragmentURI()
}
}
+class MOZ_STACK_CLASS AutoNotifyAudioChannelAgent
+{
+ nsRefPtr mElement;
+ bool mShouldNotify;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
+public:
+ AutoNotifyAudioChannelAgent(HTMLMediaElement* aElement,
+ bool aNotify
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mElement(aElement)
+ , mShouldNotify(aNotify)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ if (mShouldNotify) {
+ mElement->NotifyAudioChannelAgent(false);
+ }
+ }
+ ~AutoNotifyAudioChannelAgent()
+ {
+ if (mShouldNotify) {
+ // The audio channel agent is destroyed at this point.
+ if (mElement->MaybeCreateAudioChannelAgent()) {
+ mElement->NotifyAudioChannelAgent(true);
+ }
+ }
+ }
+};
+
void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
nsAutoPtr aTags)
{
MOZ_ASSERT(NS_IsMainThread());
+ // If the element is gaining or losing an audio track, we need to notify
+ // the audio channel agent so that the correct audio-playback events will
+ // get dispatched.
+ bool audioTrackChanging = mMediaInfo.HasAudio() != aInfo->HasAudio();
+ AutoNotifyAudioChannelAgent autoNotify(this,
+ audioTrackChanging &&
+ mPlayingThroughTheAudioChannel);
+
mMediaInfo = *aInfo;
mIsEncrypted = aInfo->IsEncrypted()
#ifdef MOZ_EME
@@ -4488,7 +4524,25 @@ nsresult HTMLMediaElement::UpdateChannelMuteState(float aVolume, bool aMuted)
return NS_OK;
}
-void HTMLMediaElement::UpdateAudioChannelPlayingState()
+bool
+HTMLMediaElement::MaybeCreateAudioChannelAgent()
+{
+ if (!mAudioChannelAgent) {
+ nsresult rv;
+ mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return false;
+ }
+ MOZ_ASSERT(mAudioChannelAgent);
+ mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
+ static_cast(mAudioChannel),
+ this);
+ }
+ return true;
+}
+
+void
+HTMLMediaElement::UpdateAudioChannelPlayingState()
{
bool playingThroughTheAudioChannel =
(!mPaused &&
@@ -4506,18 +4560,9 @@ void HTMLMediaElement::UpdateAudioChannelPlayingState()
return;
}
- if (!mAudioChannelAgent) {
- nsresult rv;
- mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
- if (!mAudioChannelAgent) {
- return;
- }
- mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetInnerWindow(),
- static_cast(mAudioChannel),
- this);
+ if (MaybeCreateAudioChannelAgent()) {
+ NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel);
}
-
- NotifyAudioChannelAgent(mPlayingThroughTheAudioChannel);
}
}
diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h
index 664b508dc4bc..410168beaed1 100644
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -35,10 +35,6 @@
// Define to output information on decoding and painting framerate
/* #define DEBUG_FRAME_RATE 1 */
-class nsIChannel;
-class nsIHttpChannel;
-class nsILoadGroup;
-
typedef uint16_t nsMediaNetworkState;
typedef uint16_t nsMediaReadyState;
@@ -56,9 +52,13 @@ class MediaTrack;
} // namespace dom
} // namespace mozilla
+class AutoNotifyAudioChannelAgent;
+class nsIChannel;
+class nsIHttpChannel;
+class nsILoadGroup;
+class nsIRunnable;
class nsITimer;
class nsRange;
-class nsIRunnable;
namespace mozilla {
namespace dom {
@@ -78,6 +78,8 @@ class HTMLMediaElement : public nsGenericHTMLElement,
public MediaDecoderOwner,
public nsIAudioChannelAgentCallback
{
+ friend class AutoNotifyAudioChannelAgent;
+
public:
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::layers::ImageContainer ImageContainer;
@@ -1050,6 +1052,10 @@ protected:
// Notifies the audio channel agent when the element starts or stops playing.
void NotifyAudioChannelAgent(bool aPlaying);
+ // Creates the audio channel agent if needed. Returns true if the audio
+ // channel agent is ready to be used.
+ bool MaybeCreateAudioChannelAgent();
+
class nsAsyncEventRunner;
using nsGenericHTMLElement::DispatchEvent;
// For nsAsyncEventRunner.