mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 927245 - Remove deprecated Audio Data API implementation. r=cajbir,smaug
This commit is contained in:
parent
c3a8061349
commit
69f11197c5
@ -28,7 +28,6 @@ DEPRECATED_OPERATION(MutationEvent)
|
||||
DEPRECATED_OPERATION(Components)
|
||||
DEPRECATED_OPERATION(PrefixedVisibilityAPI)
|
||||
DEPRECATED_OPERATION(NodeIteratorDetach)
|
||||
DEPRECATED_OPERATION(MozAudioData)
|
||||
DEPRECATED_OPERATION(LenientThis)
|
||||
DEPRECATED_OPERATION(GetPreventDefault)
|
||||
DEPRECATED_OPERATION(GetSetUserData)
|
||||
|
@ -1891,14 +1891,6 @@ public:
|
||||
|
||||
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) = 0;
|
||||
|
||||
// Called to notify the document that a listener on the "mozaudioavailable"
|
||||
// event has been added. Media elements in the document need to ensure they
|
||||
// fire the event.
|
||||
virtual void NotifyAudioAvailableListener() = 0;
|
||||
|
||||
// Returns true if the document has "mozaudioavailable" event listeners.
|
||||
virtual bool HasAudioAvailableListeners() = 0;
|
||||
|
||||
// Add aLink to the set of links that need their status resolved.
|
||||
void RegisterPendingLinkUpdate(mozilla::dom::Link* aLink);
|
||||
|
||||
|
@ -9866,23 +9866,6 @@ nsDocument::AddImage(imgIRequest* aImage)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
NotifyAudioAvailableListener(nsIContent *aContent, void *aUnused)
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aContent));
|
||||
if (domMediaElem) {
|
||||
HTMLMediaElement* mediaElem = static_cast<HTMLMediaElement*>(aContent);
|
||||
mediaElem->NotifyAudioAvailableListener();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::NotifyAudioAvailableListener()
|
||||
{
|
||||
mHasAudioAvailableListener = true;
|
||||
EnumerateFreezableElements(::NotifyAudioAvailableListener, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::RemoveImage(imgIRequest* aImage, uint32_t aFlags)
|
||||
{
|
||||
|
@ -1107,13 +1107,6 @@ public:
|
||||
|
||||
virtual Element* FindImageMap(const nsAString& aNormalizedMapName) MOZ_OVERRIDE;
|
||||
|
||||
virtual void NotifyAudioAvailableListener() MOZ_OVERRIDE;
|
||||
|
||||
bool HasAudioAvailableListeners() MOZ_OVERRIDE
|
||||
{
|
||||
return mHasAudioAvailableListener;
|
||||
}
|
||||
|
||||
virtual Element* GetFullScreenElement() MOZ_OVERRIDE;
|
||||
virtual void AsyncRequestFullScreen(Element* aElement) MOZ_OVERRIDE;
|
||||
virtual void RestorePreviousFullScreenState() MOZ_OVERRIDE;
|
||||
@ -1471,10 +1464,6 @@ public:
|
||||
// Whether we currently require our images to animate
|
||||
bool mAnimatingImages:1;
|
||||
|
||||
// Whether some node in this document has a listener for the
|
||||
// "mozaudioavailable" event.
|
||||
bool mHasAudioAvailableListener:1;
|
||||
|
||||
// Whether we're currently under a FlushPendingNotifications call to
|
||||
// our presshell. This is used to handle flush reentry correctly.
|
||||
bool mInFlush:1;
|
||||
|
@ -1919,7 +1919,6 @@ GK_ATOM(onended, "onended")
|
||||
GK_ATOM(onratechange, "onratechange")
|
||||
GK_ATOM(ondurationchange, "ondurationchange")
|
||||
GK_ATOM(onvolumechange, "onvolumechange")
|
||||
GK_ATOM(onMozAudioAvailable, "onMozAudioAvailable")
|
||||
GK_ATOM(onaddtrack, "onaddtrack")
|
||||
GK_ATOM(oncuechange, "oncuechange")
|
||||
GK_ATOM(onenter, "onenter")
|
||||
|
@ -495,9 +495,6 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, bool aClone, bool aDeep,
|
||||
if (elm->MayHavePaintEventListener()) {
|
||||
window->SetHasPaintEventListeners();
|
||||
}
|
||||
if (elm->MayHaveAudioAvailableEventListener()) {
|
||||
window->SetHasAudioAvailableEventListeners();
|
||||
}
|
||||
if (elm->MayHaveTouchEventListener()) {
|
||||
window->SetHasTouchEventListeners();
|
||||
}
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
||||
class nsITimer;
|
||||
|
||||
typedef uint16_t nsMediaNetworkState;
|
||||
typedef uint16_t nsMediaReadyState;
|
||||
|
||||
@ -20,7 +18,6 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class HTMLAudioElement MOZ_FINAL : public HTMLMediaElement,
|
||||
public nsITimerCallback,
|
||||
public nsIDOMHTMLAudioElement
|
||||
{
|
||||
public:
|
||||
@ -34,12 +31,6 @@ public:
|
||||
using HTMLMediaElement::GetPaused;
|
||||
NS_FORWARD_NSIDOMHTMLMEDIAELEMENT(HTMLMediaElement::)
|
||||
|
||||
// nsIAudioChannelAgentCallback
|
||||
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
|
||||
|
||||
// NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel);
|
||||
|
||||
@ -51,33 +42,9 @@ public:
|
||||
Audio(const GlobalObject& aGlobal,
|
||||
const Optional<nsAString>& aSrc, ErrorResult& aRv);
|
||||
|
||||
void MozSetup(uint32_t aChannels, uint32_t aRate, ErrorResult& aRv);
|
||||
|
||||
uint32_t MozWriteAudio(const Float32Array& aData, ErrorResult& aRv)
|
||||
{
|
||||
return MozWriteAudio(aData.Data(), aData.Length(), aRv);
|
||||
}
|
||||
uint32_t MozWriteAudio(const Sequence<float>& aData, ErrorResult& aRv)
|
||||
{
|
||||
return MozWriteAudio(aData.Elements(), aData.Length(), aRv);
|
||||
}
|
||||
uint32_t MozWriteAudio(const float* aData, uint32_t aLength,
|
||||
ErrorResult& aRv);
|
||||
|
||||
uint64_t MozCurrentSampleOffset(ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
virtual JSObject* WrapNode(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
// Update the audio channel playing state
|
||||
virtual void UpdateAudioChannelPlayingState() MOZ_OVERRIDE;
|
||||
|
||||
// Due to that audio data API doesn't indicate the timing of pause or end,
|
||||
// the timer is used to defer the timing of pause/stop after writing data.
|
||||
nsCOMPtr<nsITimer> mDeferStopPlayTimer;
|
||||
// To indicate mDeferStopPlayTimer is on fire or not.
|
||||
bool mTimerActivated;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -32,7 +32,6 @@ typedef uint16_t nsMediaNetworkState;
|
||||
typedef uint16_t nsMediaReadyState;
|
||||
|
||||
namespace mozilla {
|
||||
class AudioStream;
|
||||
class ErrorResult;
|
||||
class MediaResource;
|
||||
class MediaDecoder;
|
||||
@ -197,13 +196,6 @@ public:
|
||||
// suspended the channel.
|
||||
virtual void NotifySuspendedByCache(bool aIsSuspended) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
// Called when a "MozAudioAvailable" event listener is added. The media
|
||||
// element will then notify its decoder that it needs to make a copy of
|
||||
// the audio data sent to hardware and dispatch it in "mozaudioavailable"
|
||||
// events. This allows us to not perform the copy and thus reduce overhead
|
||||
// in the common case where we don't have a "MozAudioAvailable" listener.
|
||||
void NotifyAudioAvailableListener();
|
||||
|
||||
// Called by the media decoder and the video frame to get the
|
||||
// ImageContainer containing the video data.
|
||||
virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
|
||||
@ -213,9 +205,6 @@ public:
|
||||
using nsGenericHTMLElement::DispatchEvent;
|
||||
virtual nsresult DispatchEvent(const nsAString& aName) MOZ_FINAL MOZ_OVERRIDE;
|
||||
virtual nsresult DispatchAsyncEvent(const nsAString& aName) MOZ_FINAL MOZ_OVERRIDE;
|
||||
nsresult DispatchAudioAvailableEvent(float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime);
|
||||
|
||||
// Dispatch events that were raised while in the bfcache
|
||||
nsresult DispatchPendingMediaEvents();
|
||||
@ -279,12 +268,6 @@ public:
|
||||
*/
|
||||
void NotifyLoadError();
|
||||
|
||||
/**
|
||||
* Called when data has been written to the underlying audio stream.
|
||||
*/
|
||||
virtual void NotifyAudioAvailable(float* aFrameBuffer, uint32_t aFrameBufferLength,
|
||||
float aTime) MOZ_FINAL MOZ_OVERRIDE;
|
||||
|
||||
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
@ -506,14 +489,6 @@ public:
|
||||
return mAudioCaptured;
|
||||
}
|
||||
|
||||
uint32_t GetMozChannels(ErrorResult& aRv) const;
|
||||
|
||||
uint32_t GetMozSampleRate(ErrorResult& aRv) const;
|
||||
|
||||
uint32_t GetMozFrameBufferLength(ErrorResult& aRv) const;
|
||||
|
||||
void SetMozFrameBufferLength(uint32_t aValue, ErrorResult& aRv);
|
||||
|
||||
JSObject* MozGetMetadata(JSContext* aCx, ErrorResult& aRv);
|
||||
|
||||
double MozFragmentEnd();
|
||||
@ -871,7 +846,7 @@ protected:
|
||||
void Seek(double aTime, SeekTarget::Type aSeekType, ErrorResult& aRv);
|
||||
|
||||
// Update the audio channel playing state
|
||||
virtual void UpdateAudioChannelPlayingState();
|
||||
void UpdateAudioChannelPlayingState();
|
||||
|
||||
// Adds to the element's list of pending text tracks each text track
|
||||
// in the element's list of text tracks whose text track mode is not disabled
|
||||
@ -963,12 +938,6 @@ protected:
|
||||
// Current audio volume
|
||||
double mVolume;
|
||||
|
||||
// Current number of audio channels.
|
||||
uint32_t mChannels;
|
||||
|
||||
// Current audio sample rate.
|
||||
uint32_t mRate;
|
||||
|
||||
// Helper function to iterate over a hash table
|
||||
// and convert it to a JSObject.
|
||||
static PLDHashOperator BuildObjectFromTags(nsCStringHashKey::KeyType aKey,
|
||||
@ -1031,19 +1000,12 @@ protected:
|
||||
// This is the child source element which we're trying to load from.
|
||||
nsCOMPtr<nsIContent> mSourceLoadCandidate;
|
||||
|
||||
// An audio stream for writing audio directly from JS.
|
||||
nsAutoPtr<AudioStream> mAudioStream;
|
||||
|
||||
// Range of time played.
|
||||
nsRefPtr<TimeRanges> mPlayed;
|
||||
|
||||
// Stores the time at the start of the current 'played' range.
|
||||
double mCurrentPlayRangeStart;
|
||||
|
||||
// True if MozAudioAvailable events can be safely dispatched, based on
|
||||
// a media and element same-origin check.
|
||||
bool mAllowAudioData;
|
||||
|
||||
// If true then we have begun downloading the media content.
|
||||
// Set to false when completed, or not yet started.
|
||||
bool mBegun;
|
||||
|
@ -29,16 +29,14 @@ namespace dom {
|
||||
|
||||
extern bool IsAudioAPIEnabled();
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED4(HTMLAudioElement, HTMLMediaElement,
|
||||
nsIDOMHTMLMediaElement, nsIDOMHTMLAudioElement,
|
||||
nsITimerCallback, nsIAudioChannelAgentCallback)
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(HTMLAudioElement, HTMLMediaElement,
|
||||
nsIDOMHTMLMediaElement, nsIDOMHTMLAudioElement)
|
||||
|
||||
NS_IMPL_ELEMENT_CLONE(HTMLAudioElement)
|
||||
|
||||
|
||||
HTMLAudioElement::HTMLAudioElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
|
||||
: HTMLMediaElement(aNodeInfo),
|
||||
mTimerActivated(false)
|
||||
: HTMLMediaElement(aNodeInfo)
|
||||
{
|
||||
}
|
||||
|
||||
@ -77,128 +75,6 @@ HTMLAudioElement::Audio(const GlobalObject& aGlobal,
|
||||
return audio.forget();
|
||||
}
|
||||
|
||||
void
|
||||
HTMLAudioElement::MozSetup(uint32_t aChannels, uint32_t aRate, ErrorResult& aRv)
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
OwnerDoc()->WarnOnceAbout(nsIDocument::eMozAudioData);
|
||||
|
||||
// If there is already a src provided, don't setup another stream
|
||||
if (mDecoder) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// MozWriteAudio divides by mChannels, so validate now.
|
||||
if (0 == aChannels) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAudioStream) {
|
||||
mAudioStream->Shutdown();
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
if (mTimerActivated) {
|
||||
mDeferStopPlayTimer->Cancel();
|
||||
mTimerActivated = false;
|
||||
UpdateAudioChannelPlayingState();
|
||||
}
|
||||
#endif
|
||||
|
||||
mAudioStream = new AudioStream();
|
||||
aRv = mAudioStream->Init(aChannels, aRate, mAudioChannelType, AudioStream::HighLatency);
|
||||
if (aRv.Failed()) {
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
MetadataLoaded(aChannels, aRate, true, false, nullptr);
|
||||
mAudioStream->SetVolume(mMuted ? 0.0 : mVolume);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLAudioElement::MozWriteAudio(const float* aData, uint32_t aLength,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mAudioStream) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure that we are going to write the correct amount of data based
|
||||
// on number of channels.
|
||||
if (aLength % mChannels != 0) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
if (!mDeferStopPlayTimer) {
|
||||
mDeferStopPlayTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
}
|
||||
|
||||
if (mTimerActivated) {
|
||||
mDeferStopPlayTimer->Cancel();
|
||||
}
|
||||
// The maximum buffer size of audio backend is 1 second, so waiting for 1
|
||||
// second is sufficient enough.
|
||||
mDeferStopPlayTimer->InitWithCallback(this, 1000, nsITimer::TYPE_ONE_SHOT);
|
||||
mTimerActivated = true;
|
||||
UpdateAudioChannelPlayingState();
|
||||
#endif
|
||||
|
||||
// Don't write more than can be written without blocking.
|
||||
uint32_t writeLen = std::min(mAudioStream->Available(), aLength / mChannels);
|
||||
|
||||
// Convert the samples back to integers as we are using fixed point audio in
|
||||
// the AudioStream.
|
||||
// This could be optimized to avoid allocation and memcpy when
|
||||
// AudioDataValue is 'float', but it's not worth it for this deprecated API.
|
||||
nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[writeLen * mChannels]);
|
||||
ConvertAudioSamples(aData, audioData.get(), writeLen * mChannels);
|
||||
aRv = mAudioStream->Write(audioData.get(), writeLen);
|
||||
if (aRv.Failed()) {
|
||||
return 0;
|
||||
}
|
||||
mAudioStream->Start();
|
||||
|
||||
// Return the actual amount written.
|
||||
return writeLen * mChannels;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
HTMLAudioElement::MozCurrentSampleOffset(ErrorResult& aRv)
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mAudioStream) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t position = mAudioStream->GetPositionInFrames();
|
||||
if (position < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return position * mChannels;
|
||||
}
|
||||
|
||||
nsresult HTMLAudioElement::SetAcceptHeader(nsIHttpChannel* aChannel)
|
||||
{
|
||||
nsAutoCString value(
|
||||
@ -224,78 +100,5 @@ HTMLAudioElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
return HTMLAudioElementBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
/* void canPlayChanged (in boolean canPlay); */
|
||||
NS_IMETHODIMP
|
||||
HTMLAudioElement::CanPlayChanged(int32_t canPlay)
|
||||
{
|
||||
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
|
||||
// Only Audio_Data API will initialize the mAudioStream, so we call the parent
|
||||
// one when this audio tag is not used by Audio_Data API.
|
||||
if (!mAudioStream) {
|
||||
return HTMLMediaElement::CanPlayChanged(canPlay);
|
||||
}
|
||||
#ifdef MOZ_B2G
|
||||
if (canPlay != AUDIO_CHANNEL_STATE_MUTED) {
|
||||
SetMutedInternal(mMuted & ~MUTED_BY_AUDIO_CHANNEL);
|
||||
} else {
|
||||
SetMutedInternal(mMuted | MUTED_BY_AUDIO_CHANNEL);
|
||||
}
|
||||
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLAudioElement::WindowVolumeChanged()
|
||||
{
|
||||
return HTMLMediaElement::WindowVolumeChanged();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLAudioElement::Notify(nsITimer* aTimer)
|
||||
{
|
||||
#ifdef MOZ_B2G
|
||||
mTimerActivated = false;
|
||||
UpdateAudioChannelPlayingState();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLAudioElement::UpdateAudioChannelPlayingState()
|
||||
{
|
||||
if (!mAudioStream) {
|
||||
HTMLMediaElement::UpdateAudioChannelPlayingState();
|
||||
return;
|
||||
}
|
||||
// The HTMLAudioElement is registered to the AudioChannelService only on B2G.
|
||||
#ifdef MOZ_B2G
|
||||
if (mTimerActivated != mPlayingThroughTheAudioChannel) {
|
||||
mPlayingThroughTheAudioChannel = mTimerActivated;
|
||||
|
||||
if (!mAudioChannelAgent) {
|
||||
nsresult rv;
|
||||
mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
|
||||
if (!mAudioChannelAgent) {
|
||||
return;
|
||||
}
|
||||
// Use a weak ref so the audio channel agent can't leak |this|.
|
||||
mAudioChannelAgent->InitWithWeakCallback(OwnerDoc()->GetWindow(),
|
||||
mAudioChannelType, this);
|
||||
|
||||
mAudioChannelAgent->SetVisibilityState(!OwnerDoc()->Hidden());
|
||||
}
|
||||
|
||||
if (mPlayingThroughTheAudioChannel) {
|
||||
int32_t canPlay;
|
||||
mAudioChannelAgent->StartPlaying(&canPlay);
|
||||
CanPlayChanged(canPlay);
|
||||
} else {
|
||||
mAudioChannelAgent->StopPlaying();
|
||||
mAudioChannelAgent = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -59,7 +59,6 @@
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsIDOMNotifyAudioAvailableEvent.h"
|
||||
#include "nsMediaFragmentURIParser.h"
|
||||
#include "nsURIHashKey.h"
|
||||
#include "nsJSUtils.h"
|
||||
@ -624,10 +623,6 @@ void HTMLMediaElement::AbortExistingLoads()
|
||||
mMediaSource->Detach();
|
||||
mMediaSource = nullptr;
|
||||
}
|
||||
if (mAudioStream) {
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nullptr;
|
||||
}
|
||||
|
||||
mLoadingSrc = nullptr;
|
||||
|
||||
@ -648,8 +643,6 @@ void HTMLMediaElement::AbortExistingLoads()
|
||||
mDownloadSuspendedByCache = false;
|
||||
mSourcePointer = nullptr;
|
||||
|
||||
mChannels = 0;
|
||||
mRate = 0;
|
||||
mTags = nullptr;
|
||||
|
||||
if (mNetworkState != nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
|
||||
@ -864,27 +857,6 @@ void HTMLMediaElement::NotifyLoadError()
|
||||
}
|
||||
}
|
||||
|
||||
void HTMLMediaElement::NotifyAudioAvailable(float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime)
|
||||
{
|
||||
// Auto manage the memory for the frame buffer, so that if we add an early
|
||||
// return-on-error here in future, we won't forget to release the memory.
|
||||
// Otherwise we hand ownership of the memory over to the event created by
|
||||
// DispatchAudioAvailableEvent().
|
||||
nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
|
||||
// Do same-origin check on element and media before allowing MozAudioAvailable events.
|
||||
if (!mMediaSecurityVerified) {
|
||||
nsCOMPtr<nsIPrincipal> principal = GetCurrentPrincipal();
|
||||
nsresult rv = NodePrincipal()->Subsumes(principal, &mAllowAudioData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mAllowAudioData = false;
|
||||
}
|
||||
}
|
||||
|
||||
DispatchAudioAvailableEvent(frameBuffer.forget(), aFrameBufferLength, aTime);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::LoadFromSourceChildren()
|
||||
{
|
||||
NS_ASSERTION(mDelayingLoadEvent,
|
||||
@ -1013,12 +985,6 @@ static bool UseAudioChannelService()
|
||||
return Preferences::GetBool("media.useAudioChannelService");
|
||||
}
|
||||
|
||||
// Not static because it's used in HTMLAudioElement.
|
||||
bool IsAudioAPIEnabled()
|
||||
{
|
||||
return mozilla::Preferences::GetBool("media.audio_data.enabled", false);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::UpdatePreloadAction()
|
||||
{
|
||||
PreloadAction nextAction = PRELOAD_UNDEFINED;
|
||||
@ -1673,54 +1639,6 @@ NS_IMETHODIMP HTMLMediaElement::SetVolume(double aVolume)
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLMediaElement::GetMozChannels(ErrorResult& aRv) const
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mDecoder && !mAudioStream) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mChannels;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozChannels(uint32_t* aMozChannels)
|
||||
{
|
||||
ErrorResult rv;
|
||||
*aMozChannels = GetMozChannels(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLMediaElement::GetMozSampleRate(ErrorResult& aRv) const
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mDecoder && !mAudioStream) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mRate;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozSampleRate(uint32_t* aMozSampleRate)
|
||||
{
|
||||
ErrorResult rv;
|
||||
*aMozSampleRate = GetMozSampleRate(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
// Helper struct with arguments for our hash iterator.
|
||||
typedef struct MOZ_STACK_CLASS {
|
||||
JSContext* cx;
|
||||
@ -1793,56 +1711,6 @@ HTMLMediaElement::MozGetMetadata(JSContext* cx, JS::MutableHandle<JS::Value> aVa
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
HTMLMediaElement::GetMozFrameBufferLength(ErrorResult& aRv) const
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The framebuffer (via MozAudioAvailable events) is only available
|
||||
// when reading vs. writing audio directly.
|
||||
if (!mDecoder) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mDecoder->GetFrameBufferLength();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::GetMozFrameBufferLength(uint32_t* aMozFrameBufferLength)
|
||||
{
|
||||
ErrorResult rv;
|
||||
*aMozFrameBufferLength = GetMozFrameBufferLength(rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
void
|
||||
HTMLMediaElement::SetMozFrameBufferLength(uint32_t aMozFrameBufferLength, ErrorResult& aRv)
|
||||
{
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mDecoder) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mDecoder->RequestFrameBufferLength(aMozFrameBufferLength);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::SetMozFrameBufferLength(uint32_t aMozFrameBufferLength)
|
||||
{
|
||||
ErrorResult rv;
|
||||
SetMozFrameBufferLength(aMozFrameBufferLength, rv);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
/* attribute boolean muted; */
|
||||
NS_IMETHODIMP HTMLMediaElement::GetMuted(bool* aMuted)
|
||||
{
|
||||
@ -1877,8 +1745,6 @@ void HTMLMediaElement::SetVolumeInternal()
|
||||
|
||||
if (mDecoder) {
|
||||
mDecoder->SetVolume(effectiveVolume);
|
||||
} else if (mAudioStream) {
|
||||
mAudioStream->SetVolume(effectiveVolume);
|
||||
} else if (mSrcStream) {
|
||||
GetSrcMediaStream()->SetAudioOutputVolume(this, effectiveVolume);
|
||||
}
|
||||
@ -2105,8 +1971,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
|
||||
mReadyState(nsIDOMHTMLMediaElement::HAVE_NOTHING),
|
||||
mLoadWaitStatus(NOT_WAITING),
|
||||
mVolume(1.0),
|
||||
mChannels(0),
|
||||
mRate(0),
|
||||
mPreloadAction(PRELOAD_UNDEFINED),
|
||||
mMediaSize(-1,-1),
|
||||
mLastCurrentTime(0.0),
|
||||
@ -2117,7 +1981,6 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
|
||||
mPreservesPitch(true),
|
||||
mPlayed(new TimeRanges),
|
||||
mCurrentPlayRangeStart(-1.0),
|
||||
mAllowAudioData(false),
|
||||
mBegun(false),
|
||||
mLoadedFirstFrame(false),
|
||||
mAutoplaying(true),
|
||||
@ -2189,9 +2052,6 @@ HTMLMediaElement::~HTMLMediaElement()
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
if (mAudioStream) {
|
||||
mAudioStream->Shutdown();
|
||||
}
|
||||
|
||||
WakeLockRelease();
|
||||
}
|
||||
@ -2591,13 +2451,6 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
|
||||
// The preload action depends on the value of the autoplay attribute.
|
||||
// It's value may have changed, so update it.
|
||||
UpdatePreloadAction();
|
||||
|
||||
if (aDocument->HasAudioAvailableListeners()) {
|
||||
// The document already has listeners for the "MozAudioAvailable"
|
||||
// event, so the decoder must be notified so it initiates
|
||||
// "MozAudioAvailable" event dispatch.
|
||||
NotifyAudioAvailableListener();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -2798,10 +2651,6 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
|
||||
}
|
||||
}
|
||||
|
||||
if (OwnerDoc()->HasAudioAvailableListeners()) {
|
||||
NotifyAudioAvailableListener();
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
ShutdownDecoder();
|
||||
}
|
||||
@ -3001,8 +2850,6 @@ void HTMLMediaElement::MetadataLoaded(int aChannels,
|
||||
bool aHasVideo,
|
||||
const MetadataTags* aTags)
|
||||
{
|
||||
mChannels = aChannels;
|
||||
mRate = aRate;
|
||||
mHasAudio = aHasAudio;
|
||||
mTags = aTags;
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
@ -3401,39 +3248,6 @@ VideoFrameContainer* HTMLMediaElement::GetVideoFrameContainer()
|
||||
return mVideoFrameContainer;
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::DispatchAudioAvailableEvent(float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime)
|
||||
{
|
||||
// Auto manage the memory for the frame buffer. If we fail and return
|
||||
// an error, this ensures we free the memory in the frame buffer. Otherwise
|
||||
// we hand off ownership of the frame buffer to the audioavailable event,
|
||||
// which frees the memory when it's destroyed.
|
||||
nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
|
||||
|
||||
if (!IsAudioAPIEnabled()) {
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(OwnerDoc());
|
||||
nsRefPtr<HTMLMediaElement> kungFuDeathGrip = this;
|
||||
NS_ENSURE_TRUE(domDoc, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
nsresult rv = domDoc->CreateEvent(NS_LITERAL_STRING("MozAudioAvailableEvent"),
|
||||
getter_AddRefs(event));
|
||||
nsCOMPtr<nsIDOMNotifyAudioAvailableEvent> audioavailableEvent(do_QueryInterface(event));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = audioavailableEvent->InitAudioAvailableEvent(NS_LITERAL_STRING("MozAudioAvailable"),
|
||||
false, false, frameBuffer.forget(), aFrameBufferLength,
|
||||
aTime, mAllowAudioData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool dummy;
|
||||
return DispatchEvent(event, &dummy);
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::DispatchEvent(const nsAString& aName)
|
||||
{
|
||||
LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching event %s", this,
|
||||
@ -3884,14 +3698,6 @@ NS_IMETHODIMP HTMLMediaElement::GetMozFragmentEnd(double* aTime)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::NotifyAudioAvailableListener()
|
||||
{
|
||||
OwnerDoc()->WarnOnceAbout(nsIDocument::eMozAudioData);
|
||||
if (mDecoder) {
|
||||
mDecoder->NotifyAudioAvailableListener();
|
||||
}
|
||||
}
|
||||
|
||||
static double ClampPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
if (aPlaybackRate == 0.0) {
|
||||
@ -3944,7 +3750,7 @@ HTMLMediaElement::SetPlaybackRate(double aPlaybackRate, ErrorResult& aRv)
|
||||
{
|
||||
// Changing the playback rate of a media that has more than two channels is
|
||||
// not supported.
|
||||
if (aPlaybackRate < 0 || (mChannels > 2 && aPlaybackRate != 1.0)) {
|
||||
if (aPlaybackRate < 0) {
|
||||
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
|
||||
return;
|
||||
}
|
||||
|
@ -1,249 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioAvailableEventManager.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static const nsTArray< nsCOMPtr<nsIRunnable> >::size_type MAX_PENDING_EVENTS = 100;
|
||||
|
||||
class nsAudioAvailableEventRunner : public nsRunnable
|
||||
{
|
||||
private:
|
||||
nsRefPtr<MediaDecoder> mDecoder;
|
||||
nsAutoArrayPtr<float> mFrameBuffer;
|
||||
public:
|
||||
nsAudioAvailableEventRunner(MediaDecoder* aDecoder, float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength, float aTime) :
|
||||
mDecoder(aDecoder),
|
||||
mFrameBuffer(aFrameBuffer),
|
||||
mFrameBufferLength(aFrameBufferLength),
|
||||
mTime(aTime)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsAudioAvailableEventRunner);
|
||||
}
|
||||
|
||||
~nsAudioAvailableEventRunner() {
|
||||
MOZ_COUNT_DTOR(nsAudioAvailableEventRunner);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mDecoder->AudioAvailable(mFrameBuffer.forget(), mFrameBufferLength, mTime);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const uint32_t mFrameBufferLength;
|
||||
|
||||
// Start time of the buffer data (in seconds).
|
||||
const float mTime;
|
||||
};
|
||||
|
||||
|
||||
AudioAvailableEventManager::AudioAvailableEventManager(MediaDecoder* aDecoder) :
|
||||
mDecoder(aDecoder),
|
||||
mSignalBuffer(new float[mDecoder->GetFrameBufferLength()]),
|
||||
mSignalBufferLength(mDecoder->GetFrameBufferLength()),
|
||||
mNewSignalBufferLength(mSignalBufferLength),
|
||||
mSignalBufferPosition(0),
|
||||
mReentrantMonitor("media.audioavailableeventmanager"),
|
||||
mHasListener(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AudioAvailableEventManager);
|
||||
}
|
||||
|
||||
AudioAvailableEventManager::~AudioAvailableEventManager()
|
||||
{
|
||||
MOZ_COUNT_DTOR(AudioAvailableEventManager);
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::Init(uint32_t aChannels, uint32_t aRate)
|
||||
{
|
||||
NS_ASSERTION(aChannels != 0 && aRate != 0, "Audio metadata not known.");
|
||||
mSamplesPerSecond = static_cast<float>(aChannels * aRate);
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::DispatchPendingEvents(uint64_t aCurrentTime)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (!mHasListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (mPendingEvents.Length() > 0) {
|
||||
nsAudioAvailableEventRunner* e =
|
||||
(nsAudioAvailableEventRunner*)mPendingEvents[0].get();
|
||||
if (e->mTime * USECS_PER_S > aCurrentTime) {
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> event = mPendingEvents[0];
|
||||
mPendingEvents.RemoveElementAt(0);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::QueueWrittenAudioData(AudioDataValue* aAudioData,
|
||||
uint32_t aAudioDataLength,
|
||||
uint64_t aEndTimeSampleOffset)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (!mHasListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t currentBufferSize = mNewSignalBufferLength;
|
||||
if (currentBufferSize == 0) {
|
||||
NS_WARNING("Decoder framebuffer length not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mSignalBuffer ||
|
||||
(mSignalBufferPosition == 0 && mSignalBufferLength != currentBufferSize)) {
|
||||
if (!mSignalBuffer || (mSignalBufferLength < currentBufferSize)) {
|
||||
// Only resize if buffer is empty or smaller.
|
||||
mSignalBuffer = new float[currentBufferSize];
|
||||
}
|
||||
mSignalBufferLength = currentBufferSize;
|
||||
}
|
||||
AudioDataValue* audioData = aAudioData;
|
||||
uint32_t audioDataLength = aAudioDataLength;
|
||||
uint32_t signalBufferTail = mSignalBufferLength - mSignalBufferPosition;
|
||||
|
||||
// Group audio samples into optimal size for event dispatch, and queue.
|
||||
while (signalBufferTail <= audioDataLength) {
|
||||
float time = 0.0;
|
||||
// Guard against unsigned number overflow during first frame time calculation.
|
||||
if (aEndTimeSampleOffset > mSignalBufferPosition + audioDataLength) {
|
||||
time = (aEndTimeSampleOffset - mSignalBufferPosition - audioDataLength) /
|
||||
mSamplesPerSecond;
|
||||
}
|
||||
|
||||
// Fill the signalBuffer.
|
||||
uint32_t i;
|
||||
float *signalBuffer = mSignalBuffer.get() + mSignalBufferPosition;
|
||||
if (audioData) {
|
||||
for (i = 0; i < signalBufferTail; ++i) {
|
||||
signalBuffer[i] = AudioSampleToFloat(audioData[i]);
|
||||
}
|
||||
} else {
|
||||
memset(signalBuffer, 0, signalBufferTail*sizeof(signalBuffer[0]));
|
||||
}
|
||||
if (audioData) {
|
||||
audioData += signalBufferTail;
|
||||
}
|
||||
|
||||
NS_ASSERTION(audioDataLength >= signalBufferTail,
|
||||
"audioDataLength about to wrap past zero to +infinity!");
|
||||
audioDataLength -= signalBufferTail;
|
||||
|
||||
if (mPendingEvents.Length() > 0) {
|
||||
// Check last event timecode to make sure that all queued events
|
||||
// are in non-descending sequence.
|
||||
nsAudioAvailableEventRunner* lastPendingEvent =
|
||||
(nsAudioAvailableEventRunner*)mPendingEvents[mPendingEvents.Length() - 1].get();
|
||||
if (lastPendingEvent->mTime > time) {
|
||||
// Clear the queue to start a fresh sequence.
|
||||
mPendingEvents.Clear();
|
||||
} else if (mPendingEvents.Length() >= MAX_PENDING_EVENTS) {
|
||||
NS_WARNING("Hit audio event queue max.");
|
||||
mPendingEvents.RemoveElementsAt(0, mPendingEvents.Length() - MAX_PENDING_EVENTS + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform the element that we've written audio data.
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
new nsAudioAvailableEventRunner(mDecoder, mSignalBuffer.forget(),
|
||||
mSignalBufferLength, time);
|
||||
mPendingEvents.AppendElement(event);
|
||||
|
||||
// Reset the buffer
|
||||
mSignalBufferLength = currentBufferSize;
|
||||
mSignalBuffer = new float[currentBufferSize];
|
||||
mSignalBufferPosition = 0;
|
||||
signalBufferTail = currentBufferSize;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mSignalBufferPosition + audioDataLength < mSignalBufferLength,
|
||||
"Intermediate signal buffer must fit at least one more item.");
|
||||
|
||||
if (audioDataLength > 0) {
|
||||
// Add data to the signalBuffer.
|
||||
uint32_t i;
|
||||
float *signalBuffer = mSignalBuffer.get() + mSignalBufferPosition;
|
||||
if (audioData) {
|
||||
for (i = 0; i < audioDataLength; ++i) {
|
||||
signalBuffer[i] = AudioSampleToFloat(audioData[i]);
|
||||
}
|
||||
} else {
|
||||
memset(signalBuffer, 0, audioDataLength*sizeof(signalBuffer[0]));
|
||||
}
|
||||
mSignalBufferPosition += audioDataLength;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::Clear()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
mPendingEvents.Clear();
|
||||
mSignalBufferPosition = 0;
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::Drain(uint64_t aEndTime)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (!mHasListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Force all pending events to go now.
|
||||
for (uint32_t i = 0; i < mPendingEvents.Length(); ++i) {
|
||||
nsCOMPtr<nsIRunnable> event = mPendingEvents[i];
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
mPendingEvents.Clear();
|
||||
|
||||
// If there is anything left in the signal buffer, put it in an event and fire.
|
||||
if (0 == mSignalBufferPosition)
|
||||
return;
|
||||
|
||||
// Zero-pad the end of the signal buffer so it's complete.
|
||||
memset(mSignalBuffer.get() + mSignalBufferPosition, 0,
|
||||
(mSignalBufferLength - mSignalBufferPosition) * sizeof(float));
|
||||
|
||||
// Force this last event to go now.
|
||||
float time = (aEndTime / static_cast<float>(USECS_PER_S)) -
|
||||
(mSignalBufferPosition / mSamplesPerSecond);
|
||||
nsCOMPtr<nsIRunnable> lastEvent =
|
||||
new nsAudioAvailableEventRunner(mDecoder, mSignalBuffer.forget(),
|
||||
mSignalBufferLength, time);
|
||||
NS_DispatchToMainThread(lastEvent, NS_DISPATCH_NORMAL);
|
||||
|
||||
mSignalBufferPosition = 0;
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::SetSignalBufferLength(uint32_t aLength)
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
mNewSignalBufferLength = aLength;
|
||||
}
|
||||
|
||||
void AudioAvailableEventManager::NotifyAudioAvailableListener()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
mHasListener = true;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1,97 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef AudioAvailableEventManager_h__
|
||||
#define AudioAvailableEventManager_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "AudioSampleFormat.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
|
||||
class nsIRunnable;
|
||||
template <class T> class nsCOMPtr;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaDecoder;
|
||||
|
||||
class AudioAvailableEventManager
|
||||
{
|
||||
public:
|
||||
AudioAvailableEventManager(MediaDecoder* aDecoder);
|
||||
~AudioAvailableEventManager();
|
||||
|
||||
// Initialize the event manager with audio metadata. Called before
|
||||
// audio begins to get queued or events are dispatched.
|
||||
void Init(uint32_t aChannels, uint32_t aRate);
|
||||
|
||||
// Dispatch pending MozAudioAvailable events in the queue. Called
|
||||
// from the state machine thread.
|
||||
void DispatchPendingEvents(uint64_t aCurrentTime);
|
||||
|
||||
// Queues audio sample data and re-packages it into equal sized
|
||||
// framebuffers. Called from the audio thread.
|
||||
void QueueWrittenAudioData(AudioDataValue* aAudioData,
|
||||
uint32_t aAudioDataLength,
|
||||
uint64_t aEndTimeSampleOffset);
|
||||
|
||||
// Clears the queue of any existing events. Called from both the state
|
||||
// machine and audio threads.
|
||||
void Clear();
|
||||
|
||||
// Fires one last event for any extra samples that didn't fit in a whole
|
||||
// framebuffer. This is meant to be called only once when the audio finishes.
|
||||
// Called from the state machine thread.
|
||||
void Drain(uint64_t aTime);
|
||||
|
||||
// Sets the size of the signal buffer.
|
||||
// Called from the main and the state machine thread.
|
||||
void SetSignalBufferLength(uint32_t aLength);
|
||||
|
||||
// Called by the media element to notify the manager that there is a
|
||||
// listener on the "MozAudioAvailable" event, and that we need to dispatch
|
||||
// such events. Called from the main thread.
|
||||
void NotifyAudioAvailableListener();
|
||||
|
||||
private:
|
||||
// The decoder associated with the event manager. The event manager shares
|
||||
// the same lifetime as the decoder (the decoder holds a reference to the
|
||||
// manager).
|
||||
MediaDecoder* mDecoder;
|
||||
|
||||
// The number of samples per second.
|
||||
float mSamplesPerSecond;
|
||||
|
||||
// A buffer for audio data to be dispatched in DOM events.
|
||||
nsAutoArrayPtr<float> mSignalBuffer;
|
||||
|
||||
// The current size of the signal buffer, may change due to DOM calls.
|
||||
uint32_t mSignalBufferLength;
|
||||
|
||||
// The size of the new signal buffer, may change due to DOM calls.
|
||||
uint32_t mNewSignalBufferLength;
|
||||
|
||||
// The position of the first available item in mSignalBuffer
|
||||
uint32_t mSignalBufferPosition;
|
||||
|
||||
// The MozAudioAvailable events to be dispatched. This queue is shared
|
||||
// between the state machine and audio threads.
|
||||
nsTArray< nsCOMPtr<nsIRunnable> > mPendingEvents;
|
||||
|
||||
// ReentrantMonitor for shared access to mPendingEvents queue or
|
||||
// buffer length.
|
||||
ReentrantMonitor mReentrantMonitor;
|
||||
|
||||
// True if something in the owning document has a listener on the
|
||||
// "MozAudioAvailable" event. If not, we don't need to bother copying played
|
||||
// audio data and dispatching the event. Synchronized by mReentrantMonitor.
|
||||
bool mHasListener;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -424,7 +424,6 @@ MediaDecoder::MediaDecoder() :
|
||||
mIgnoreProgressData(false),
|
||||
mInfiniteStream(false),
|
||||
mOwner(nullptr),
|
||||
mFrameBufferLength(0),
|
||||
mPinnedForSeek(false),
|
||||
mShuttingDown(false),
|
||||
mPausedForPlaybackRateNull(false),
|
||||
@ -555,10 +554,6 @@ nsresult MediaDecoder::InitializeStateMachine(MediaDecoder* aCloneDonor)
|
||||
if (mMinimizePreroll) {
|
||||
mDecoderStateMachine->SetMinimizePrerollUntilPlaybackStarts();
|
||||
}
|
||||
if (mFrameBufferLength > 0) {
|
||||
// The valid mFrameBufferLength value was specified earlier
|
||||
mDecoderStateMachine->SetFrameBufferLength(mFrameBufferLength);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeState(PLAY_STATE_LOADING);
|
||||
@ -572,20 +567,6 @@ void MediaDecoder::SetMinimizePrerollUntilPlaybackStarts()
|
||||
mMinimizePreroll = true;
|
||||
}
|
||||
|
||||
nsresult MediaDecoder::RequestFrameBufferLength(uint32_t aLength)
|
||||
{
|
||||
if (aLength < FRAMEBUFFER_LENGTH_MIN || aLength > FRAMEBUFFER_LENGTH_MAX) {
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
}
|
||||
mFrameBufferLength = aLength;
|
||||
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mDecoderStateMachine) {
|
||||
mDecoderStateMachine->SetFrameBufferLength(aLength);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaDecoder::ScheduleStateMachineThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -668,21 +649,6 @@ already_AddRefed<nsIPrincipal> MediaDecoder::GetCurrentPrincipal()
|
||||
return mResource ? mResource->GetCurrentPrincipal() : nullptr;
|
||||
}
|
||||
|
||||
void MediaDecoder::AudioAvailable(float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime)
|
||||
{
|
||||
// Auto manage the frame buffer's memory. If we return due to an error
|
||||
// here, this ensures we free the memory. Otherwise, we pass off ownership
|
||||
// to HTMLMediaElement::NotifyAudioAvailable().
|
||||
nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mShuttingDown || !mOwner) {
|
||||
return;
|
||||
}
|
||||
mOwner->NotifyAudioAvailable(frameBuffer.forget(), aFrameBufferLength, aTime);
|
||||
}
|
||||
|
||||
void MediaDecoder::QueueMetadata(int64_t aPublishTime,
|
||||
int aChannels,
|
||||
int aRate,
|
||||
@ -1435,15 +1401,6 @@ bool MediaDecoder::OnStateMachineThread() const
|
||||
return mDecoderStateMachine->OnStateMachineThread();
|
||||
}
|
||||
|
||||
void MediaDecoder::NotifyAudioAvailableListener()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mDecoderStateMachine) {
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
mDecoderStateMachine->NotifyAudioAvailableListener();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaDecoder::SetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
if (aPlaybackRate == 0) {
|
||||
|
@ -210,16 +210,6 @@ class VideoFrameContainer;
|
||||
class MediaDecoderStateMachine;
|
||||
class MediaDecoderOwner;
|
||||
|
||||
// The size to use for audio data frames in MozAudioAvailable events.
|
||||
// This value is per channel, and is chosen to give ~43 fps of events,
|
||||
// for example, 44100 with 2 channels, 2*1024 = 2048.
|
||||
static const uint32_t FRAMEBUFFER_LENGTH_PER_CHANNEL = 1024;
|
||||
|
||||
// The total size of the framebuffer used for MozAudioAvailable events
|
||||
// has to be within the following range.
|
||||
static const uint32_t FRAMEBUFFER_LENGTH_MIN = 512;
|
||||
static const uint32_t FRAMEBUFFER_LENGTH_MAX = 16384;
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount() and conflicts with MediaDecoder::GetCurrentTime implementation.
|
||||
#ifdef GetCurrentTime
|
||||
@ -659,12 +649,6 @@ public:
|
||||
// Returns a weak reference to the media decoder owner.
|
||||
MediaDecoderOwner* GetMediaOwner() const;
|
||||
|
||||
// Returns the current size of the framebuffer used in
|
||||
// MozAudioAvailable events.
|
||||
uint32_t GetFrameBufferLength() { return mFrameBufferLength; }
|
||||
|
||||
void AudioAvailable(float* aFrameBuffer, uint32_t aFrameBufferLength, float aTime);
|
||||
|
||||
// Called by the state machine to notify the decoder that the duration
|
||||
// has changed.
|
||||
void DurationChanged();
|
||||
@ -695,10 +679,6 @@ public:
|
||||
}
|
||||
layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
|
||||
|
||||
// Sets the length of the framebuffer used in MozAudioAvailable events.
|
||||
// The new size must be between 512 and 16384.
|
||||
virtual nsresult RequestFrameBufferLength(uint32_t aLength);
|
||||
|
||||
// Return the current state. Can be called on any thread. If called from
|
||||
// a non-main thread, the decoder monitor must be held.
|
||||
PlayState GetState() {
|
||||
@ -841,11 +821,6 @@ public:
|
||||
// Drop reference to state machine. Only called during shutdown dance.
|
||||
virtual void ReleaseStateMachine();
|
||||
|
||||
// Called when a "MozAudioAvailable" event listener is added. This enables
|
||||
// the decoder to only dispatch "MozAudioAvailable" events when a
|
||||
// handler exists, reducing overhead. Called on the main thread.
|
||||
virtual void NotifyAudioAvailableListener();
|
||||
|
||||
// Notifies the element that decoding has failed.
|
||||
virtual void DecodeError();
|
||||
|
||||
@ -1211,9 +1186,6 @@ protected:
|
||||
// time of the last decoded video frame).
|
||||
MediaChannelStatistics mPlaybackStatistics;
|
||||
|
||||
// The framebuffer size to use for audioavailable events.
|
||||
uint32_t mFrameBufferLength;
|
||||
|
||||
// True when our media stream has been pinned. We pin the stream
|
||||
// while seeking.
|
||||
bool mPinnedForSeek;
|
||||
|
@ -46,12 +46,6 @@ public:
|
||||
// Return true if decoding should be paused
|
||||
virtual bool GetPaused() = 0;
|
||||
|
||||
/**
|
||||
* Called when data has been written to the underlying audio stream.
|
||||
*/
|
||||
virtual void NotifyAudioAvailable(float* aFrameBuffer, uint32_t aFrameBufferLength,
|
||||
float aTime) = 0;
|
||||
|
||||
// Called by the video decoder object, on the main thread,
|
||||
// when it has read the metadata containing video dimensions,
|
||||
// etc.
|
||||
|
@ -197,7 +197,6 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mDispatchedRunEvent(false),
|
||||
mDecodeThreadWaiting(false),
|
||||
mRealTime(aRealTime),
|
||||
mEventManager(aDecoder),
|
||||
mLastFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
|
||||
@ -945,8 +944,6 @@ void MediaDecoderStateMachine::AudioLoop()
|
||||
ReentrantMonitorAutoExit exit(mDecoder->GetReentrantMonitor());
|
||||
mAudioStream->Drain();
|
||||
}
|
||||
// Fire one last event for any extra frames that didn't fill a framebuffer.
|
||||
mEventManager.Drain(mAudioEndTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -957,7 +954,6 @@ void MediaDecoderStateMachine::AudioLoop()
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nullptr;
|
||||
mEventManager.Clear();
|
||||
if (!mAudioCaptured) {
|
||||
mAudioCompleted = true;
|
||||
UpdateReadyState();
|
||||
@ -979,9 +975,6 @@ uint32_t MediaDecoderStateMachine::PlaySilence(uint32_t aFrames,
|
||||
uint32_t maxFrames = SILENCE_BYTES_CHUNK / aChannels / sizeof(AudioDataValue);
|
||||
uint32_t frames = std::min(aFrames, maxFrames);
|
||||
WriteSilence(mAudioStream, frames);
|
||||
// Dispatch events to the DOM for the audio just written.
|
||||
mEventManager.QueueWrittenAudioData(nullptr, frames * aChannels,
|
||||
(aFrameOffset + frames) * aChannels);
|
||||
return frames;
|
||||
}
|
||||
|
||||
@ -1014,10 +1007,6 @@ uint32_t MediaDecoderStateMachine::PlayFromAudioQueue(uint64_t aFrameOffset,
|
||||
offset = audio->mOffset;
|
||||
frames = audio->mFrames;
|
||||
|
||||
// Dispatch events to the DOM for the audio just written.
|
||||
mEventManager.QueueWrittenAudioData(audio->mAudioData.get(),
|
||||
audio->mFrames * aChannels,
|
||||
(aFrameOffset + frames) * aChannels);
|
||||
if (offset != -1) {
|
||||
mDecoder->UpdatePlaybackOffset(offset);
|
||||
}
|
||||
@ -1142,9 +1131,6 @@ void MediaDecoderStateMachine::UpdatePlaybackPosition(int64_t aTime)
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// Notify DOM of any queued up audioavailable events
|
||||
mEventManager.DispatchPendingEvents(GetMediaTime());
|
||||
|
||||
mMetadataManager.DispatchMetadataIfNeeded(mDecoder, aTime);
|
||||
|
||||
if (fragmentEnded) {
|
||||
@ -1776,14 +1762,6 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs) const
|
||||
return stream->GetCachedDataEnd(currentPos) < requiredPos;
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetFrameBufferLength(uint32_t aLength)
|
||||
{
|
||||
NS_ASSERTION(aLength >= 512 && aLength <= 16384,
|
||||
"The length must be between 512 and 16384");
|
||||
AssertCurrentThreadInMonitor();
|
||||
mEventManager.SetSignalBufferLength(aLength);
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::DecodeError()
|
||||
{
|
||||
@ -1887,19 +1865,7 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
||||
mLowAudioThresholdUsecs /= NO_VIDEO_AMPLE_AUDIO_DIVISOR;
|
||||
}
|
||||
|
||||
// Inform the element that we've loaded the metadata and the first frame,
|
||||
// setting the default framebuffer size for audioavailable events. Also,
|
||||
// if there is audio, let the MozAudioAvailable event manager know about
|
||||
// the metadata.
|
||||
if (HasAudio()) {
|
||||
mEventManager.Init(mInfo.mAudio.mChannels, mInfo.mAudio.mRate);
|
||||
// Set the buffer length at the decoder level to be able, to be able
|
||||
// to retrive the value via media element method. The RequestFrameBufferLength
|
||||
// will call the MediaDecoderStateMachine::SetFrameBufferLength().
|
||||
uint32_t frameBufferLength = mInfo.mAudio.mChannels * FRAMEBUFFER_LENGTH_PER_CHANNEL;
|
||||
mDecoder->RequestFrameBufferLength(frameBufferLength);
|
||||
}
|
||||
|
||||
// Inform the element that we've loaded the metadata and the first frame.
|
||||
nsCOMPtr<nsIRunnable> metadataLoadedEvent =
|
||||
new AudioMetadataEventRunner(mDecoder,
|
||||
mInfo.mAudio.mChannels,
|
||||
@ -2852,12 +2818,6 @@ nsIEventTarget* MediaDecoderStateMachine::GetStateMachineThread()
|
||||
return mStateMachineThreadPool->GetEventTarget();
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::NotifyAudioAvailableListener()
|
||||
{
|
||||
AssertCurrentThreadInMonitor();
|
||||
mEventManager.NotifyAudioAvailableListener();
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||
|
@ -79,7 +79,6 @@ hardware (via AudioStream).
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "AudioAvailableEventManager.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "MediaDecoderOwner.h"
|
||||
@ -297,10 +296,6 @@ public:
|
||||
return mMediaSeekable;
|
||||
}
|
||||
|
||||
// Sets the current frame buffer length for the MozAudioAvailable event.
|
||||
// Accessed on the main and state machine threads.
|
||||
void SetFrameBufferLength(uint32_t aLength);
|
||||
|
||||
// Returns the shared state machine thread.
|
||||
nsIEventTarget* GetStateMachineThread();
|
||||
|
||||
@ -336,10 +331,6 @@ public:
|
||||
void SetSyncPointForMediaStream();
|
||||
int64_t GetCurrentTimeViaMediaStreamSync();
|
||||
|
||||
// Called when a "MozAudioAvailable" event listener is added to the media
|
||||
// element. Called on the main thread.
|
||||
void NotifyAudioAvailableListener();
|
||||
|
||||
// Copy queued audio/video data in the reader to any output MediaStreams that
|
||||
// need it.
|
||||
void SendStreamData();
|
||||
@ -512,8 +503,7 @@ private:
|
||||
uint64_t aFrameOffset);
|
||||
|
||||
// Pops an audio chunk from the front of the audio queue, and pushes its
|
||||
// audio data to the audio hardware. MozAudioAvailable data is also queued
|
||||
// here. Called on the audio thread.
|
||||
// audio data to the audio hardware.
|
||||
uint32_t PlayFromAudioQueue(uint64_t aFrameOffset, uint32_t aChannels);
|
||||
|
||||
// Stops the audio thread. The decoder monitor must be held with exactly
|
||||
@ -955,11 +945,6 @@ private:
|
||||
// True is we are decoding a realtime stream, like a camera stream
|
||||
bool mRealTime;
|
||||
|
||||
// Manager for queuing and dispatching MozAudioAvailable events. The
|
||||
// event manager is accessed from the state machine and audio threads,
|
||||
// and takes care of synchronizing access to its internal queue.
|
||||
AudioAvailableEventManager mEventManager;
|
||||
|
||||
// Stores presentation info required for playback. The decoder monitor
|
||||
// must be held when accessing this.
|
||||
MediaInfo mInfo;
|
||||
|
@ -54,7 +54,6 @@ TEST_DIRS += [
|
||||
|
||||
EXPORTS += [
|
||||
'AbstractMediaDecoder.h',
|
||||
'AudioAvailableEventManager.h',
|
||||
'AudioChannelFormat.h',
|
||||
'AudioCompactor.h',
|
||||
'AudioEventTimeline.h',
|
||||
@ -111,7 +110,6 @@ EXPORTS.mozilla.dom += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AudioAvailableEventManager.cpp',
|
||||
'AudioChannelFormat.cpp',
|
||||
'AudioCompactor.cpp',
|
||||
'AudioNodeEngine.cpp',
|
||||
|
Binary file not shown.
@ -1 +0,0 @@
|
||||
Cache-Control: no-store
|
@ -1,16 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function audioAvailable(e) {
|
||||
document.getElementById("wasAudioAvailableCalled").checked = true;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<audio id="a1" src="sound.ogg" controls></audio>
|
||||
<script>
|
||||
document.getElementById("a1").addEventListener("MozAudioAvailable", audioAvailable, false);
|
||||
</script>
|
||||
<input id="wasAudioAvailableCalled" type="checkbox" readonly />
|
||||
</body>
|
||||
</html>
|
@ -142,10 +142,7 @@ support-files =
|
||||
dirac.ogg^headers^
|
||||
dynamic_redirect.sjs
|
||||
dynamic_resource.sjs
|
||||
file_a4_tone.ogg
|
||||
file_a4_tone.ogg^headers^
|
||||
file_access_controls.html
|
||||
file_audio_event_adopt_iframe.html
|
||||
fragment_noplay.js
|
||||
fragment_play.js
|
||||
gizmo.mp4
|
||||
@ -295,12 +292,10 @@ support-files =
|
||||
wavedata_u8.wav
|
||||
wavedata_u8.wav^headers^
|
||||
|
||||
[test_a4_tone.html]
|
||||
[test_access_control.html]
|
||||
[test_aspectratio_mp4.html]
|
||||
[test_audio1.html]
|
||||
[test_audio2.html]
|
||||
[test_audio_event_adopt.html]
|
||||
[test_autoplay.html]
|
||||
[test_bug448534.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests) b2g-debug(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests) b2g-desktop(Timed out, bug 894922? Bug 902677 is for the timing out of a lot of media tests)
|
||||
@ -311,7 +306,6 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
|
||||
[test_bug654550.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
|
||||
[test_bug686137.html]
|
||||
[test_bug686942.html]
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
|
||||
# [test_bug726904.html] # disabled - See bug 754860
|
||||
@ -348,8 +342,6 @@ skip-if = buildapp == 'b2g' # b2g(6 failures) b2g-debug(6 failures) b2g-desktop(
|
||||
[test_error_on_404.html]
|
||||
skip-if = buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(timed out) b2g-desktop(timed out)
|
||||
[test_fastSeek.html]
|
||||
[test_framebuffer.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(timed out) b2g-debug(timed out) b2g-desktop(timed out)
|
||||
[test_info_leak.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(2 failures) b2g-debug(2 failures) b2g-desktop(2 failures)
|
||||
[test_invalid_reject.html]
|
||||
@ -399,7 +391,6 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
|
||||
[test_standalone.html]
|
||||
[test_volume.html]
|
||||
[test_video_to_canvas.html]
|
||||
[test_audiowrite.html]
|
||||
[test_mediarecorder_creation.html]
|
||||
[test_mediarecorder_creation_fail.html]
|
||||
[test_mediarecorder_avoid_recursion.html]
|
||||
@ -504,7 +495,3 @@ skip-if = wave
|
||||
run-if = wave
|
||||
[test_fragment_play.html]
|
||||
run-if = wave
|
||||
[test_wave_data_s16.html]
|
||||
run-if = wave
|
||||
[test_wave_data_u8.html]
|
||||
run-if = wave
|
||||
|
@ -1,263 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=490705
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title>Media test: simple audioAvalailable event checks</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=490705">Mozilla Bug 490705</a>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/**
|
||||
* FFT is a class for calculating the Discrete Fourier Transform of a signal
|
||||
* with the Fast Fourier Transform algorithm.
|
||||
*
|
||||
* Source: github.com/corbanbrook/dsp.js; License: MIT; Copyright: Corban Brook
|
||||
*
|
||||
* @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
|
||||
* @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
FFT = function(bufferSize, sampleRate) {
|
||||
this.bufferSize = bufferSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.spectrum = new Float32Array(bufferSize/2);
|
||||
this.real = new Float32Array(bufferSize);
|
||||
this.imag = new Float32Array(bufferSize);
|
||||
|
||||
this.reverseTable = new Uint32Array(bufferSize);
|
||||
|
||||
var limit = 1;
|
||||
var bit = bufferSize >> 1;
|
||||
|
||||
while ( limit < bufferSize ) {
|
||||
for ( var i = 0; i < limit; i++ ) {
|
||||
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
|
||||
}
|
||||
|
||||
limit = limit << 1;
|
||||
bit = bit >> 1;
|
||||
}
|
||||
|
||||
this.sinTable = new Float32Array(bufferSize);
|
||||
this.cosTable = new Float32Array(bufferSize);
|
||||
|
||||
for ( var i = 0; i < bufferSize; i++ ) {
|
||||
this.sinTable[i] = Math.sin(-Math.PI/i);
|
||||
this.cosTable[i] = Math.cos(-Math.PI/i);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a forward tranform on the sample buffer.
|
||||
* Converts a time domain signal to frequency domain spectra.
|
||||
*
|
||||
* @param {Array} buffer The sample buffer. Buffer Length must be power of 2
|
||||
*
|
||||
* @returns The frequency spectrum array
|
||||
*/
|
||||
FFT.prototype.forward = function(buffer) {
|
||||
// Locally scope variables for speed up
|
||||
var bufferSize = this.bufferSize,
|
||||
cosTable = this.cosTable,
|
||||
sinTable = this.sinTable,
|
||||
reverseTable = this.reverseTable,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
spectrum = this.spectrum;
|
||||
|
||||
var k = Math.floor(Math.log(bufferSize) / Math.LN2);
|
||||
if ( Math.pow(2, k) !== bufferSize ) {
|
||||
throw "Invalid buffer size, must be a power of 2.";
|
||||
}
|
||||
if ( bufferSize !== buffer.length ) {
|
||||
throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length;
|
||||
}
|
||||
|
||||
for ( var i = 0; i < bufferSize; i++ ) {
|
||||
real[i] = buffer[reverseTable[i]];
|
||||
imag[i] = 0;
|
||||
}
|
||||
|
||||
var halfSize = 1,
|
||||
phaseShiftStepReal,
|
||||
phaseShiftStepImag,
|
||||
currentPhaseShiftReal,
|
||||
currentPhaseShiftImag,
|
||||
off,
|
||||
tr,
|
||||
ti,
|
||||
tmpReal,
|
||||
i;
|
||||
|
||||
while ( halfSize < bufferSize ) {
|
||||
phaseShiftStepReal = cosTable[halfSize];
|
||||
phaseShiftStepImag = sinTable[halfSize];
|
||||
currentPhaseShiftReal = 1;
|
||||
currentPhaseShiftImag = 0;
|
||||
|
||||
for ( var fftStep = 0; fftStep < halfSize; fftStep++ ) {
|
||||
i = fftStep;
|
||||
|
||||
while ( i < bufferSize ) {
|
||||
off = i + halfSize;
|
||||
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
|
||||
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
|
||||
|
||||
real[off] = real[i] - tr;
|
||||
imag[off] = imag[i] - ti;
|
||||
real[i] += tr;
|
||||
imag[i] += ti;
|
||||
|
||||
i += halfSize << 1;
|
||||
}
|
||||
|
||||
tmpReal = currentPhaseShiftReal;
|
||||
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
|
||||
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
|
||||
}
|
||||
|
||||
halfSize = halfSize << 1;
|
||||
}
|
||||
|
||||
i = bufferSize/2;
|
||||
while(i--) {
|
||||
spectrum[i] = 2 * Math.sqrt(real[i] * real[i] + imag[i] * imag[i]) / bufferSize;
|
||||
}
|
||||
|
||||
return spectrum;
|
||||
};
|
||||
/* end of FFT */
|
||||
|
||||
|
||||
var testFile = "file_a4_tone.ogg";
|
||||
var testFileDuration = 3.0;
|
||||
var testFileChannelCount = 1;
|
||||
var testFileSampleRate = 44100;
|
||||
var testFileFrameBufferLength = 1024;
|
||||
var signal = [{start:1.1, end: 1.9, fftBin: 10 } ];
|
||||
var noSignal = [{start:0.1, end: 0.9 }, {start:2.1, end: 2.9 } ];
|
||||
|
||||
var undef;
|
||||
var fft, fftBufferSize;
|
||||
var currentSampleOffset = 0;
|
||||
var spectrumMaxs = [];
|
||||
var isTimePropertyValid = true;
|
||||
|
||||
function audioAvailable(event) {
|
||||
var buffer = event.frameBuffer;
|
||||
|
||||
if(fft === undef) {
|
||||
fftBufferSize = buffer.length;
|
||||
fft = new FFT(fftBufferSize, testFileSampleRate);
|
||||
}
|
||||
|
||||
fft.forward(buffer);
|
||||
|
||||
var spectrum = fft.spectrum;
|
||||
// Finding pick frequency
|
||||
var maxIndex = 0, maxValue = spectrum[0];
|
||||
for(var i=0;i<spectrum.length;i++) {
|
||||
if(maxValue < spectrum[i]) {
|
||||
maxValue = spectrum[maxIndex = i];
|
||||
}
|
||||
}
|
||||
|
||||
spectrumMaxs.push({ value: maxValue, index: maxIndex, time: (currentSampleOffset / testFileSampleRate) });
|
||||
|
||||
if( (typeof event.time !== "number") ||
|
||||
(Math.abs(event.time - currentSampleOffset / testFileSampleRate) >= 0.001) ) {
|
||||
isTimePropertyValid = false;
|
||||
}
|
||||
|
||||
currentSampleOffset += buffer.length;
|
||||
}
|
||||
|
||||
var loadedMetadataCalled = false;
|
||||
function loadedMetadata() {
|
||||
loadedMetadataCalled = true;
|
||||
var a1 = document.getElementById('a1');
|
||||
is(a1.mozChannels, testFileChannelCount, "mozChannels should be " + testFileChannelCount + ".");
|
||||
is(a1.mozSampleRate, testFileSampleRate, "mozSampleRate should be " + testFileSampleRate + ".");
|
||||
is(a1.mozFrameBufferLength, testFileFrameBufferLength, "mozFrameBufferLength should be " + testFileFrameBufferLength + ".");
|
||||
}
|
||||
|
||||
function checkResults() {
|
||||
ok(loadedMetadataCalled, "loadedmetadata event not dispatched.");
|
||||
ok(isTimePropertyValid, "The audioAvailable event's time attribute was invalid.");
|
||||
|
||||
var expectedOffset = Math.ceil(testFileDuration * testFileSampleRate);
|
||||
if(expectedOffset % fftBufferSize !== 0) { expectedOffset += (fftBufferSize - (expectedOffset % fftBufferSize)); }
|
||||
is(currentSampleOffset, expectedOffset, "Check amount of signal data processed");
|
||||
|
||||
var i, j;
|
||||
var signalPresent = true;
|
||||
for(i=0;i<signal.length;++i) {
|
||||
var signalAnalysed = false;
|
||||
for(j=0;j<spectrumMaxs.length;++j) {
|
||||
if(signal[i].start <= spectrumMaxs[j].time && spectrumMaxs[j].time < signal[i].end) {
|
||||
signalAnalysed = true;
|
||||
signalPresent = spectrumMaxs[j].index == signal[i].fftBin;
|
||||
}
|
||||
if(!signalPresent) break;
|
||||
}
|
||||
if(!signalAnalysed) signalPresent = false;;
|
||||
if(!signalPresent) break;
|
||||
}
|
||||
is(signalPresent, true, "Check signal present");
|
||||
|
||||
var noSignalPresent = true;
|
||||
for(i=0;i<noSignal.length;++i) {
|
||||
var signalAnalysed = false;
|
||||
for(j=0;j<spectrumMaxs.length;++j) {
|
||||
if(noSignal[i].start <= spectrumMaxs[j].time && spectrumMaxs[j].time < noSignal[i].end) {
|
||||
signalAnalysed = true;
|
||||
noSignalPresent = spectrumMaxs[j].index == 0;
|
||||
}
|
||||
if(!noSignalPresent) break;
|
||||
}
|
||||
if(!signalAnalysed) noSignalPresent = false;;
|
||||
if(!noSignalPresent) break;
|
||||
}
|
||||
is(signalPresent, true, "Check mute fragments present");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function audioEnded() {
|
||||
checkResults();
|
||||
}
|
||||
|
||||
function initTest() {
|
||||
var a1 = document.createElement("audio");
|
||||
a1.id = "a1";
|
||||
a1.addEventListener("ended", audioEnded, false);
|
||||
a1.addEventListener("loadedmetadata", loadedMetadata, false);
|
||||
a1.addEventListener("MozAudioAvailable", audioAvailable, false);
|
||||
a1.src = testFile;
|
||||
a1.muted = true;
|
||||
a1.play();
|
||||
document.body.appendChild(a1);
|
||||
}
|
||||
|
||||
window.addEventListener("load", function(e) {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, initTest);
|
||||
}, false);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,42 +0,0 @@
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=490705
|
||||
-->
|
||||
<head>
|
||||
<title>Media test: addEventListener optimization and adoptNode</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
|
||||
<script>
|
||||
function adopt() {
|
||||
var a1Node = document.getElementById("f1").contentDocument.getElementById("a1");
|
||||
var adopted = document.adoptNode(a1Node);
|
||||
document.body.appendChild(adopted);
|
||||
return adopted;
|
||||
}
|
||||
function wasAudioAvailableCalled() {
|
||||
var resultNode = document.getElementById("f1").contentDocument.getElementById("wasAudioAvailableCalled");
|
||||
return document.adoptNode(resultNode).checked;
|
||||
}
|
||||
function endTest() {
|
||||
is(wasAudioAvailableCalled(), true, "audioAvailable was not called");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
function startTest() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, function () {
|
||||
var audio = adopt();
|
||||
audio.addEventListener("ended", endTest, false);
|
||||
audio.play();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=490705">Mozilla Bug 490705</a>
|
||||
<iframe id="f1" src="file_audio_event_adopt_iframe.html" onload="startTest()"></iframe>
|
||||
</body>
|
||||
</html>
|
@ -1,79 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=490705
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title>Media test: simple audio write checks</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=490705">Mozilla Bug 490705</a>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var channels = 2;
|
||||
var rate = 44100;
|
||||
|
||||
function runTests() {
|
||||
var a1 = new Audio();
|
||||
|
||||
ok("mozSetup" in a1, "mozSetup should be supported");
|
||||
ok("mozWriteAudio" in a1, "mozWriteAudio should be supported");
|
||||
ok("mozCurrentSampleOffset" in a1, "mozCurrentSampleOffset should be supported");
|
||||
|
||||
try {
|
||||
a1.mozSetup(channels, rate);
|
||||
} catch (ex) {
|
||||
todo(false, "Audio hardware is disabled, can't test audio write API");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
is(a1.mozChannels, channels, "mozChannels should be " + channels + ".");
|
||||
is(a1.mozSampleRate, rate, "mozSampleRate should be " + rate + ".");
|
||||
is(a1.volume, 1.0, "volume should be 1.0 by default.");
|
||||
|
||||
// Make sure changing volume on audio changes write audio stream.
|
||||
a1.volume = 0.5;
|
||||
is(a1.volume, 0.5, "volume should have been changed to 0.5.");
|
||||
a1.muted = true;
|
||||
ok(a1.muted, "volume should be muted.");
|
||||
|
||||
is(a1.mozCurrentSampleOffset(), 0, "mozCurrentSampleOffset() not working.");
|
||||
|
||||
// Test writing with js array
|
||||
var samples1 = [.5, .5];
|
||||
var written = sampleOffset = a1.mozWriteAudio(samples1);
|
||||
is(written, samples1.length, "Not all samples in JS Array written.");
|
||||
|
||||
// Test writing with Float32Array
|
||||
var samples2 = new Float32Array([.2, .3, .2, .3]);
|
||||
written = a1.mozWriteAudio(samples2);
|
||||
is(written, samples2.length, "Not all samples in Float32Array written.");
|
||||
|
||||
// Test passing the wrong arguments to mozWriteAudio.
|
||||
var writeArgsOK = false;
|
||||
try {
|
||||
// incorrect, should throw
|
||||
written = a1.mozWriteAudio(samples2.length, samples2);
|
||||
} catch(e) {
|
||||
writeArgsOK = true;
|
||||
}
|
||||
ok(writeArgsOK, "mozWriteAudio args test failed.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", function(e) {
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, runTests);
|
||||
}, false);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,47 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=686137
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title>Media test: changing mozFrameBufferLength</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=686137">Mozilla Bug 686137</a>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, function () {
|
||||
var a1 = document.createElement("audio");
|
||||
a1.controls = true;
|
||||
a1.muted = true;
|
||||
a1.preload = "metadata";
|
||||
a1.addEventListener("loadedmetadata", metaDataLoaded, false);
|
||||
a1.src = "bug495794.ogg";
|
||||
a1.load();
|
||||
});
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function audioAvailable(event) {
|
||||
var a1 = event.target;
|
||||
a1.removeEventListener("MozAudioAvailable", audioAvailable);
|
||||
is( event.frameBuffer.length, 9001, "event.frameBuffer.length should be 9001.");
|
||||
is( event.frameBuffer.length, a1.mozFrameBufferLength, "event.frameBuffer.length should be " + a1.mozFrameBufferLength + ".");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function metaDataLoaded(event){
|
||||
var a1 = event.target;
|
||||
a1.addEventListener("MozAudioAvailable", audioAvailable, false);
|
||||
a1.mozFrameBufferLength = 9001;
|
||||
a1.play();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,112 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=490705
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title>Media test: framebuffer size checks</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=490705">Mozilla Bug 490705</a>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var testFile = "bug495794.ogg";
|
||||
var testFileDuration = 0.30;
|
||||
var testFileChannelCount = 6;
|
||||
var testFileSampleRate = 48000;
|
||||
var testFileFrameBufferLength = testFileChannelCount * 1024;
|
||||
|
||||
var undef;
|
||||
|
||||
var currentSampleOffset = 0;
|
||||
var isTimePropertyValid = true;
|
||||
|
||||
function audioAvailable(event) {
|
||||
var buffer = event.frameBuffer;
|
||||
|
||||
if ( (typeof event.time !== "number") ||
|
||||
(Math.abs(event.time - currentSampleOffset / testFileSampleRate / testFileChannelCount) > testFileDuration) ) {
|
||||
isTimePropertyValid = false;
|
||||
}
|
||||
|
||||
currentSampleOffset += buffer.length;
|
||||
}
|
||||
|
||||
var loadedMetadataCalled = false;
|
||||
function loadedMetadata() {
|
||||
loadedMetadataCalled = true;
|
||||
var a1 = document.getElementById('a1');
|
||||
is(a1.mozChannels, testFileChannelCount, "mozChannels should be " + testFileChannelCount + ".");
|
||||
is(a1.mozSampleRate, testFileSampleRate, "mozSampleRate should be " + testFileSampleRate + ".");
|
||||
is(a1.mozFrameBufferLength, testFileFrameBufferLength, "default mozFrameBufferLength should be " + testFileFrameBufferLength + ".");
|
||||
|
||||
var minFailed = false;
|
||||
try {
|
||||
a1.mozFrameBufferLength = 4;
|
||||
} catch(e) {
|
||||
minFailed = true;
|
||||
}
|
||||
ok(minFailed, "mozFrameBufferLength min fail check");
|
||||
|
||||
var maxFailed = false;
|
||||
try {
|
||||
a1.mozFrameBufferLength = 44444;
|
||||
} catch(e) {
|
||||
maxFailed = true;
|
||||
}
|
||||
ok(maxFailed, "mozFrameBufferLength max fail check");
|
||||
|
||||
a1.mozFrameBufferLength = testFileFrameBufferLength;
|
||||
}
|
||||
|
||||
function checkResults() {
|
||||
ok(loadedMetadataCalled, "loadedmetadata event not dispatched.");
|
||||
ok(isTimePropertyValid, "The audioAvailable event's time attribute was invalid.");
|
||||
|
||||
var expectedOffset = Math.ceil(testFileDuration * testFileSampleRate * testFileChannelCount);
|
||||
if (expectedOffset % testFileFrameBufferLength !== 0) {
|
||||
expectedOffset += (testFileFrameBufferLength - (expectedOffset % testFileFrameBufferLength));
|
||||
}
|
||||
is(currentSampleOffset, expectedOffset, "Check amount of signal data processed");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function audioEnded() {
|
||||
checkResults();
|
||||
}
|
||||
|
||||
function initTest() {
|
||||
var a1 = document.createElement("audio");
|
||||
a1.id = "a1";
|
||||
a1.preload = "metadata";
|
||||
a1.controls = true;
|
||||
document.body.appendChild(a1);
|
||||
|
||||
a1.addEventListener("ended", audioEnded, false);
|
||||
a1.addEventListener("loadedmetadata", loadedMetadata, false);
|
||||
a1.addEventListener("MozAudioAvailable", audioAvailable, false);
|
||||
a1.src = testFile;
|
||||
a1.muted = true;
|
||||
a1.play();
|
||||
}
|
||||
|
||||
window.addEventListener("load", function(e) {
|
||||
if (SpecialPowers.getBoolPref("media.audio_data.enabled")) {
|
||||
initTest();
|
||||
} else {
|
||||
ok(true, "old audio data api behind a pref");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}, false);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1,54 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Wave Media test: ended</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
// Test if the ended event works correctly.
|
||||
var endPassed = false;
|
||||
var completed = false;
|
||||
|
||||
function audioavailable(e) {
|
||||
if (completed)
|
||||
return;
|
||||
|
||||
completed = true;
|
||||
var samples = e.frameBuffer;
|
||||
var time = e.time;
|
||||
|
||||
ok(samples.length >= 3, "Must be 3 or more samples. There were " + samples.length);
|
||||
if (samples.length >= 3) {
|
||||
ok(samples[0] > 0.99 && samples[0] < 1.01, "First sound sample should be close to 1.0. It was " + samples[0]);
|
||||
ok(samples[1] > -1.01 && samples [1] < -0.99, "Second sound sample should be close to -1.0. It was " + samples[1]);
|
||||
ok(samples[2] > -0.01 && samples[2] < 0.01, "Third sound sample should be close to 0. It was " + samples[2]);
|
||||
}
|
||||
|
||||
// Only care about the first few samples
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
if (completed)
|
||||
return;
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]},
|
||||
function () {
|
||||
var v = document.getElementById('v');
|
||||
v.addEventListener('MozAudioAvailable', audioavailable, false);
|
||||
v.play();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
<audio id='v'
|
||||
preload="metadata"
|
||||
onloadedmetadata='return startTest();'>
|
||||
<source type='audio/x-wav' src='wavedata_s16.wav'>
|
||||
</audio>
|
||||
</body>
|
||||
</html>
|
@ -1,54 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Wave Media test: ended</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
// Test if the ended event works correctly.
|
||||
var endPassed = false;
|
||||
var completed = false;
|
||||
|
||||
function audioavailable(e) {
|
||||
if (completed)
|
||||
return;
|
||||
|
||||
completed = true;
|
||||
var samples = e.frameBuffer;
|
||||
var time = e.time;
|
||||
|
||||
ok(samples.length >= 3, "Must be 3 or more samples. There were " + samples.length);
|
||||
if (samples.length >= 3) {
|
||||
ok(samples[0] > 0.99 && samples[0] < 1.01, "First sound sample should be close to 1.0. It was " + samples[0]);
|
||||
ok(samples[1] > -1.01 && samples [1] < -0.99, "Second sound sample should be close to -1.0. It was " + samples[1]);
|
||||
ok(samples[2] > -0.01 && samples[2] < 0.01, "Third sound sample should be close to 0. It was " + samples[2]);
|
||||
}
|
||||
|
||||
// Only care about the first few samples
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
if (completed)
|
||||
return;
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]},
|
||||
function () {
|
||||
var v = document.getElementById('v');
|
||||
v.addEventListener('MozAudioAvailable', audioavailable, false);
|
||||
v.play();
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
<audio id='v'
|
||||
preload="metadata"
|
||||
onloadedmetadata='return startTest();'>
|
||||
<source type='audio/x-wav' src='wavedata_u8.wav'>
|
||||
</audio>
|
||||
</body>
|
||||
</html>
|
@ -13441,16 +13441,6 @@ nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::SetHasAudioAvailableEventListeners()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
|
||||
if (mDoc) {
|
||||
mDoc->NotifyAudioAvailableListener();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetConsole(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aConsole)
|
||||
|
@ -547,9 +547,6 @@ public:
|
||||
void DisableDialogs();
|
||||
bool AreDialogsEnabled();
|
||||
|
||||
// Inner windows only.
|
||||
virtual void SetHasAudioAvailableEventListeners();
|
||||
|
||||
nsIScriptContext *GetContextInternal()
|
||||
{
|
||||
if (mOuterWindow) {
|
||||
|
@ -472,12 +472,6 @@ public:
|
||||
*/
|
||||
virtual nsresult SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust) = 0;
|
||||
|
||||
/**
|
||||
* Call this to indicate that some node (this window, its document,
|
||||
* or content in that document) has a "MozAudioAvailable" event listener.
|
||||
*/
|
||||
virtual void SetHasAudioAvailableEventListeners() = 0;
|
||||
|
||||
/**
|
||||
* Call this to check whether some node (this window, its document,
|
||||
* or content in that document) has a mouseenter/leave event listener.
|
||||
|
@ -816,8 +816,6 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
|
||||
return NS_NewDOMScrollAreaEvent(aDOMEvent, aOwner, aPresContext, nullptr);
|
||||
if (aEventType.LowerCaseEqualsLiteral("popstateevent"))
|
||||
return NS_NewDOMPopStateEvent(aDOMEvent, aOwner, aPresContext, nullptr);
|
||||
if (aEventType.LowerCaseEqualsLiteral("mozaudioavailableevent"))
|
||||
return NS_NewDOMAudioAvailableEvent(aDOMEvent, aOwner, aPresContext, nullptr);
|
||||
if (aEventType.LowerCaseEqualsLiteral("closeevent"))
|
||||
return NS_NewDOMCloseEvent(aDOMEvent, aOwner, aPresContext, nullptr);
|
||||
if (aEventType.LowerCaseEqualsLiteral("touchevent") &&
|
||||
|
@ -92,7 +92,6 @@ EventListenerManager::EventListenerManager(EventTarget* aTarget)
|
||||
, mMayHaveMutationListeners(false)
|
||||
, mMayHaveCapturingListeners(false)
|
||||
, mMayHaveSystemGroupListeners(false)
|
||||
, mMayHaveAudioAvailableEventListener(false)
|
||||
, mMayHaveTouchEventListener(false)
|
||||
, mMayHaveMouseEnterLeaveEventListener(false)
|
||||
, mMayHavePointerEnterLeaveEventListener(false)
|
||||
@ -282,12 +281,6 @@ EventListenerManager::AddEventListenerInternal(
|
||||
if (window) {
|
||||
window->SetHasPaintEventListeners();
|
||||
}
|
||||
} else if (aType == NS_MOZAUDIOAVAILABLE) {
|
||||
mMayHaveAudioAvailableEventListener = true;
|
||||
nsPIDOMWindow* window = GetInnerWindowForTarget();
|
||||
if (window) {
|
||||
window->SetHasAudioAvailableEventListeners();
|
||||
}
|
||||
} else if (aType >= NS_MUTATION_START && aType <= NS_MUTATION_END) {
|
||||
// For mutation listeners, we need to update the global bit on the DOM window.
|
||||
// Otherwise we won't actually fire the mutation event.
|
||||
|
@ -386,12 +386,6 @@ public:
|
||||
*/
|
||||
bool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
|
||||
|
||||
/**
|
||||
* Returns true if there may be a MozAudioAvailable event listener registered,
|
||||
* false if there definitely isn't.
|
||||
*/
|
||||
bool MayHaveAudioAvailableEventListener() { return mMayHaveAudioAvailableEventListener; }
|
||||
|
||||
/**
|
||||
* Returns true if there may be a touch event listener registered,
|
||||
* false if there definitely isn't.
|
||||
@ -543,13 +537,12 @@ protected:
|
||||
uint32_t mMayHaveMutationListeners : 1;
|
||||
uint32_t mMayHaveCapturingListeners : 1;
|
||||
uint32_t mMayHaveSystemGroupListeners : 1;
|
||||
uint32_t mMayHaveAudioAvailableEventListener : 1;
|
||||
uint32_t mMayHaveTouchEventListener : 1;
|
||||
uint32_t mMayHaveMouseEnterLeaveEventListener : 1;
|
||||
uint32_t mMayHavePointerEnterLeaveEventListener : 1;
|
||||
uint32_t mClearingListeners : 1;
|
||||
uint32_t mIsMainThreadELM : 1;
|
||||
uint32_t mNoListenerForEvent : 22;
|
||||
uint32_t mNoListenerForEvent : 23;
|
||||
|
||||
nsAutoTObserverArray<Listener, 2> mListeners;
|
||||
dom::EventTarget* mTarget; // WEAK
|
||||
|
@ -790,10 +790,6 @@ NON_IDL_EVENT(repeatEvent,
|
||||
EventNameType_None,
|
||||
NS_SMIL_TIME_EVENT)
|
||||
|
||||
NON_IDL_EVENT(MozAudioAvailable,
|
||||
NS_MOZAUDIOAVAILABLE,
|
||||
EventNameType_None,
|
||||
NS_EVENT)
|
||||
NON_IDL_EVENT(MozAfterPaint,
|
||||
NS_AFTERPAINT,
|
||||
EventNameType_None,
|
||||
|
@ -1,184 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/NotifyAudioAvailableEvent.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "nsError.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NotifyAudioAvailableEvent::NotifyAudioAvailableEvent(
|
||||
EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
uint32_t aEventType,
|
||||
float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime)
|
||||
: Event(aOwner, aPresContext, aEvent)
|
||||
, mFrameBuffer(aFrameBuffer)
|
||||
, mFrameBufferLength(aFrameBufferLength)
|
||||
, mTime(aTime)
|
||||
, mCachedArray(nullptr)
|
||||
, mAllowAudioData(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(NotifyAudioAvailableEvent);
|
||||
if (mEvent) {
|
||||
mEvent->message = aEventType;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(NotifyAudioAvailableEvent, Event)
|
||||
NS_IMPL_RELEASE_INHERITED(NotifyAudioAvailableEvent, Event)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(NotifyAudioAvailableEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(NotifyAudioAvailableEvent,
|
||||
Event)
|
||||
if (tmp->mCachedArray) {
|
||||
tmp->mCachedArray = nullptr;
|
||||
DropJSObjects(tmp);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(NotifyAudioAvailableEvent,
|
||||
Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(NotifyAudioAvailableEvent,
|
||||
Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCachedArray)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NotifyAudioAvailableEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMNotifyAudioAvailableEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
||||
|
||||
NotifyAudioAvailableEvent::~NotifyAudioAvailableEvent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(NotifyAudioAvailableEvent);
|
||||
if (mCachedArray) {
|
||||
mCachedArray = nullptr;
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotifyAudioAvailableEvent::GetFrameBuffer(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
if (!mAllowAudioData) {
|
||||
// Media is not same-origin, don't allow the data out.
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
if (mCachedArray) {
|
||||
aResult.setObject(*mCachedArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Cache this array so we don't recreate on next call.
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
mCachedArray = JS_NewFloat32Array(aCx, mFrameBufferLength);
|
||||
if (!mCachedArray) {
|
||||
mozilla::DropJSObjects(this);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
memcpy(JS_GetFloat32ArrayData(mCachedArray), mFrameBuffer.get(),
|
||||
mFrameBufferLength * sizeof(float));
|
||||
|
||||
aResult.setObject(*mCachedArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotifyAudioAvailableEvent::GetTime(float* aRetVal)
|
||||
{
|
||||
*aRetVal = Time();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotifyAudioAvailableEvent::InitAudioAvailableEvent(const nsAString& aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime,
|
||||
bool aAllowAudioData)
|
||||
{
|
||||
// Auto manage the memory which stores the frame buffer. This ensures
|
||||
// that if we exit due to some error, the memory will be freed. Otherwise,
|
||||
// the framebuffer's memory will be freed when this event is destroyed.
|
||||
nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
|
||||
nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mFrameBuffer = frameBuffer.forget();
|
||||
mFrameBufferLength = aFrameBufferLength;
|
||||
mTime = aTime;
|
||||
mAllowAudioData = aAllowAudioData;
|
||||
mCachedArray = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
NotifyAudioAvailableEvent::InitAudioAvailableEvent(
|
||||
const nsAString& aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
const Nullable<Sequence<float> >& aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime,
|
||||
bool aAllowAudioData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if ((aFrameBuffer.IsNull() && aFrameBufferLength > 0) ||
|
||||
(!aFrameBuffer.IsNull() &&
|
||||
aFrameBuffer.Value().Length() < aFrameBufferLength)) {
|
||||
aRv = NS_ERROR_UNEXPECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoArrayPtr<float> buffer;
|
||||
if (!aFrameBuffer.IsNull()) {
|
||||
buffer = new float[aFrameBufferLength];
|
||||
memcpy(buffer.get(), aFrameBuffer.Value().Elements(),
|
||||
aFrameBufferLength * sizeof(float));
|
||||
}
|
||||
|
||||
aRv = InitAudioAvailableEvent(aType, aCanBubble, aCancelable,
|
||||
buffer.forget(),
|
||||
aFrameBufferLength,
|
||||
aTime, aAllowAudioData);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsresult
|
||||
NS_NewDOMAudioAvailableEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
uint32_t aEventType,
|
||||
float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime)
|
||||
{
|
||||
NotifyAudioAvailableEvent* it =
|
||||
new NotifyAudioAvailableEvent(aOwner, aPresContext, aEvent, aEventType,
|
||||
aFrameBuffer, aFrameBufferLength, aTime);
|
||||
NS_ADDREF(it);
|
||||
*aInstancePtrResult = static_cast<Event*>(it);
|
||||
return NS_OK;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_NotifyAudioAvailableEvent_h_
|
||||
#define mozilla_dom_NotifyAudioAvailableEvent_h_
|
||||
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/NotifyAudioAvailableEventBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDOMNotifyAudioAvailableEvent.h"
|
||||
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class NotifyAudioAvailableEvent : public Event,
|
||||
public nsIDOMNotifyAudioAvailableEvent
|
||||
{
|
||||
public:
|
||||
NotifyAudioAvailableEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent,
|
||||
uint32_t aEventType,
|
||||
float* aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(
|
||||
NotifyAudioAvailableEvent, Event)
|
||||
|
||||
NS_DECL_NSIDOMNOTIFYAUDIOAVAILABLEEVENT
|
||||
NS_FORWARD_NSIDOMEVENT(Event::)
|
||||
|
||||
~NotifyAudioAvailableEvent();
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
|
||||
{
|
||||
return NotifyAudioAvailableEventBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
JSObject* GetFrameBuffer(JSContext* aCx, ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JS::Value> dummy(aCx);
|
||||
aRv = GetFrameBuffer(aCx, &dummy);
|
||||
return mCachedArray;
|
||||
}
|
||||
|
||||
float Time()
|
||||
{
|
||||
return mTime;
|
||||
}
|
||||
|
||||
void InitAudioAvailableEvent(const nsAString& aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
const Nullable<Sequence<float> >& aFrameBuffer,
|
||||
uint32_t aFrameBufferLength,
|
||||
float aTime,
|
||||
bool aAllowAudioData,
|
||||
ErrorResult& aRv);
|
||||
private:
|
||||
nsAutoArrayPtr<float> mFrameBuffer;
|
||||
uint32_t mFrameBufferLength;
|
||||
float mTime;
|
||||
JS::Heap<JSObject*> mCachedArray;
|
||||
bool mAllowAudioData;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_NotifyAudioAvailableEvent_h_
|
@ -49,7 +49,6 @@ EXPORTS.mozilla.dom += [
|
||||
'MouseEvent.h',
|
||||
'MouseScrollEvent.h',
|
||||
'MutationEvent.h',
|
||||
'NotifyAudioAvailableEvent.h',
|
||||
'NotifyPaintEvent.h',
|
||||
'PointerEvent.h',
|
||||
'ScrollAreaEvent.h',
|
||||
@ -92,7 +91,6 @@ UNIFIED_SOURCES += [
|
||||
'MouseEvent.cpp',
|
||||
'MouseScrollEvent.cpp',
|
||||
'MutationEvent.cpp',
|
||||
'NotifyAudioAvailableEvent.cpp',
|
||||
'NotifyPaintEvent.cpp',
|
||||
'nsPaintRequest.cpp',
|
||||
'PointerEvent.cpp',
|
||||
|
@ -118,7 +118,6 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug742376.html]
|
||||
[test_bug812744.html]
|
||||
[test_bug847597.html]
|
||||
[test_bug855741.html]
|
||||
[test_bug864040.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(failing when the test gets moved around, and on debug) b2g-debug(failing when the test gets moved around, and on debug) b2g-desktop(failing when the test gets moved around, and on debug)
|
||||
|
@ -282,14 +282,6 @@ const kEventConstructors = {
|
||||
return e;
|
||||
},
|
||||
},
|
||||
NotifyAudioAvailableEvent: { create: function (aName, aProps) {
|
||||
var e = document.createEvent("mozaudioavailableevent");
|
||||
e.initAudioAvailableEvent(aName, aProps.bubbles, aProps.cancelable,
|
||||
aProps.frameBuffer, aProps.frameBufferLength,
|
||||
aProps.time || 0.0, aProps.allowAudioData);
|
||||
return e;
|
||||
},
|
||||
},
|
||||
NotifyPaintEvent: { create: function (aName, aProps) {
|
||||
var e = document.createEvent("notifypaintevent");
|
||||
e.initEvent(aName, aProps.bubbles, aProps.cancelable);
|
||||
|
@ -1,81 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=847597
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 847597</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 847597 **/
|
||||
|
||||
|
||||
var e = document.createEvent("mozaudioavailableevent");
|
||||
e.initAudioAvailableEvent("foo", true, true, [1], 1, 123456, false);
|
||||
is(e.type, "foo");
|
||||
is(e.bubbles, true);
|
||||
is(e.cancelable, true);
|
||||
is(e.time, 123456);
|
||||
|
||||
try {
|
||||
e.frameBuffer;
|
||||
ok(false, "Should not be possible to access frameBuffer in unsafe context when the last parameter to init is false.");
|
||||
} catch(ex) {
|
||||
ok(true);
|
||||
}
|
||||
|
||||
try {
|
||||
e.initAudioAvailableEvent("foo", true, true, [1, 2, 3], 4, 123456, false);
|
||||
ok(false, "Should have thrown an exception because too short array");
|
||||
} catch(ex) {
|
||||
ok(true);
|
||||
}
|
||||
|
||||
try {
|
||||
e.initAudioAvailableEvent("foo", true, true, [], 1, 123456, false);
|
||||
ok(false, "Should have thrown an exception because too short array");
|
||||
} catch(ex) {
|
||||
ok(true);
|
||||
}
|
||||
|
||||
try {
|
||||
e.initAudioAvailableEvent("foo", true, true, null, 1, 123456, false);
|
||||
ok(false, "Should have thrown an exception because too short array");
|
||||
} catch(ex) {
|
||||
ok(true);
|
||||
}
|
||||
|
||||
e.initAudioAvailableEvent("foo", true, true, null, 0, 123456, false);
|
||||
e.initAudioAvailableEvent("foo", true, true, [], 0, 123456, false);
|
||||
e.initAudioAvailableEvent("foo", true, true, [1], 0, 123456, false);
|
||||
|
||||
e.initAudioAvailableEvent("foo", true, true, [0, 1, 2], 0, 123456, true);
|
||||
is(e.frameBuffer.length, 0);
|
||||
e.initAudioAvailableEvent("foo", true, true, [0, 1, 2], 1, 123456, true);
|
||||
is(e.frameBuffer.length, 1);
|
||||
is(e.frameBuffer[0], 0);
|
||||
e.initAudioAvailableEvent("foo", true, true, [0, 1, 2], 2, 123456, true);
|
||||
is(e.frameBuffer.length, 2);
|
||||
is(e.frameBuffer[0], 0);
|
||||
is(e.frameBuffer[1], 1);
|
||||
e.initAudioAvailableEvent("foo", true, true, [0, 1, 2], 3, 123456, true);
|
||||
is(e.frameBuffer.length, 3);
|
||||
is(e.frameBuffer[0], 0);
|
||||
is(e.frameBuffer[1], 1);
|
||||
is(e.frameBuffer[2], 2);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=847597">Mozilla Bug 847597</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -28,7 +28,6 @@ XPIDL_SOURCES += [
|
||||
'nsIDOMMouseEvent.idl',
|
||||
'nsIDOMMouseScrollEvent.idl',
|
||||
'nsIDOMMutationEvent.idl',
|
||||
'nsIDOMNotifyAudioAvailableEvent.idl',
|
||||
'nsIDOMNotifyPaintEvent.idl',
|
||||
'nsIDOMNSEvent.idl',
|
||||
'nsIDOMPageTransitionEvent.idl',
|
||||
|
@ -337,15 +337,6 @@ NS_NewDOMNotifyPaintEvent(nsIDOMEvent** aResult,
|
||||
uint32_t aEventType = 0,
|
||||
nsInvalidateRequestList* aInvalidateRequests = nullptr);
|
||||
nsresult
|
||||
NS_NewDOMAudioAvailableEvent(nsIDOMEvent** aResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::WidgetEvent* aEvent,
|
||||
uint32_t aEventType = 0,
|
||||
float* aFrameBuffer = nullptr,
|
||||
uint32_t aFrameBufferLength = 0,
|
||||
float aTime = 0);
|
||||
nsresult
|
||||
NS_NewDOMSimpleGestureEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
|
@ -1,25 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
#include "nsIVariant.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(2345d43d-197a-4589-a4b7-983b41b76c25)]
|
||||
interface nsIDOMNotifyAudioAvailableEvent : nsIDOMEvent
|
||||
{
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval frameBuffer;
|
||||
|
||||
readonly attribute float time;
|
||||
|
||||
void initAudioAvailableEvent(in DOMString typeArg,
|
||||
in boolean canBubbleArg,
|
||||
in boolean cancelableArg,
|
||||
[array, size_is(frameBufferLength)] in float frameBufferPtr,
|
||||
in unsigned long frameBufferLength,
|
||||
in float time,
|
||||
in boolean allowAudioData);
|
||||
};
|
@ -27,7 +27,7 @@ interface nsIDOMMediaStream;
|
||||
#endif
|
||||
%}
|
||||
|
||||
[scriptable, uuid(d83d38f3-68b9-4ea2-8748-1cc738d74333)]
|
||||
[scriptable, uuid(1f9393e8-2df0-4072-87b9-c26999b09acc)]
|
||||
interface nsIDOMHTMLMediaElement : nsISupports
|
||||
{
|
||||
// error state
|
||||
@ -84,16 +84,6 @@ interface nsIDOMHTMLMediaElement : nsISupports
|
||||
nsIDOMMediaStream mozCaptureStreamUntilEnded();
|
||||
readonly attribute boolean mozAudioCaptured;
|
||||
|
||||
// Mozilla extension: extra stream metadata information, used as part
|
||||
// of MozAudioAvailable events and the mozWriteAudio() method. The
|
||||
// mozFrameBufferLength method allows for the size of the framebuffer
|
||||
// used within MozAudioAvailable events to be changed. The new size must
|
||||
// be between 512 and 16384. The default size, for a media element with
|
||||
// audio is (mozChannels * 1024).
|
||||
readonly attribute unsigned long mozChannels;
|
||||
readonly attribute unsigned long mozSampleRate;
|
||||
attribute unsigned long mozFrameBufferLength;
|
||||
|
||||
// Mozilla extension: return embedded metadata from the stream as a
|
||||
// JSObject with key:value pairs for each tag. This can be used by
|
||||
// player interfaces to display the song title, artist, etc.
|
||||
|
@ -121,8 +121,6 @@ PluginHangUIStopButton=Stop plugin
|
||||
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
||||
# LOCALIZATION NOTE: Do not translate "NodeIterator" or "detach()".
|
||||
NodeIteratorDetachWarning=Calling detach() on a NodeIterator no longer has an effect.
|
||||
# LOCALIZATION NOTE: Do not translate "Mozilla Audio Data API" and "Web Audio API".
|
||||
MozAudioDataWarning=The Mozilla Audio Data API is deprecated. Please use the Web Audio API instead.
|
||||
# LOCALIZATION NOTE: Do not translate "LenientThis" and "this"
|
||||
LenientThisWarning=Ignoring get or set of property that has [LenientThis] because the "this" object is incorrect.
|
||||
# LOCALIZATION NOTE: Do not translate "nsIDOMWindowUtils", "getWindowWithOuterId", or "nsIWindowMediator"
|
||||
|
@ -713,8 +713,6 @@ var interfaceNamesInGlobalScope =
|
||||
"NodeIterator",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"NodeList",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"NotifyAudioAvailableEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Notification",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
@ -14,20 +14,3 @@
|
||||
[NamedConstructor=Audio(optional DOMString src)]
|
||||
interface HTMLAudioElement : HTMLMediaElement {};
|
||||
|
||||
partial interface HTMLAudioElement
|
||||
{
|
||||
// Setup the audio stream for writing
|
||||
[Pref="media.audio_data.enabled", Throws]
|
||||
void mozSetup(unsigned long channels, unsigned long rate);
|
||||
|
||||
// Write audio to the audio stream
|
||||
[Pref="media.audio_data.enabled", Throws]
|
||||
unsigned long mozWriteAudio(Float32Array data);
|
||||
[Pref="media.audio_data.enabled", Throws]
|
||||
unsigned long mozWriteAudio(sequence<unrestricted float> data);
|
||||
|
||||
// Get the current offset (measured in samples since the start) of the audio
|
||||
// stream created using mozWriteAudio().
|
||||
[Pref="media.audio_data.enabled", Throws]
|
||||
unsigned long long mozCurrentSampleOffset();
|
||||
};
|
||||
|
@ -109,19 +109,6 @@ partial interface HTMLMediaElement {
|
||||
MediaStream mozCaptureStreamUntilEnded();
|
||||
readonly attribute boolean mozAudioCaptured;
|
||||
|
||||
// Mozilla extension: extra stream metadata information, used as part
|
||||
// of MozAudioAvailable events and the mozWriteAudio() method. The
|
||||
// mozFrameBufferLength method allows for the size of the framebuffer
|
||||
// used within MozAudioAvailable events to be changed. The new size must
|
||||
// be between 512 and 16384. The default size, for a media element with
|
||||
// audio is (mozChannels * 1024).
|
||||
[Pref="media.audio_data.enabled", GetterThrows]
|
||||
readonly attribute unsigned long mozChannels;
|
||||
[Pref="media.audio_data.enabled", GetterThrows]
|
||||
readonly attribute unsigned long mozSampleRate;
|
||||
[Pref="media.audio_data.enabled", Throws]
|
||||
attribute unsigned long mozFrameBufferLength;
|
||||
|
||||
// Mozilla extension: return embedded metadata from the stream as a
|
||||
// JSObject with key:value pairs for each tag. This can be used by
|
||||
// player interfaces to display the song title, artist, etc.
|
||||
|
@ -1,22 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
interface NotifyAudioAvailableEvent : Event
|
||||
{
|
||||
[Throws]
|
||||
readonly attribute Float32Array frameBuffer;
|
||||
|
||||
readonly attribute float time;
|
||||
|
||||
[Throws]
|
||||
void initAudioAvailableEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
sequence<float>? frameBuffer,
|
||||
unsigned long frameBufferLength,
|
||||
float time,
|
||||
boolean allowAudioData);
|
||||
};
|
@ -257,7 +257,6 @@ WEBIDL_FILES = [
|
||||
'NodeIterator.webidl',
|
||||
'NodeList.webidl',
|
||||
'Notification.webidl',
|
||||
'NotifyAudioAvailableEvent.webidl',
|
||||
'NotifyPaintEvent.webidl',
|
||||
'OfflineAudioCompletionEvent.webidl',
|
||||
'OfflineAudioContext.webidl',
|
||||
|
@ -121,8 +121,6 @@ PluginHangUIStopButton=Stop plugin
|
||||
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
||||
# LOCALIZATION NOTE: Do not translate "NodeIterator" or "detach()".
|
||||
NodeIteratorDetachWarning=Calling detach() on a NodeIterator no longer has an effect.
|
||||
# LOCALIZATION NOTE: Do not translate "Mozilla Audio Data API" and "Web Audio API".
|
||||
MozAudioDataWarning=The Mozilla Audio Data API is deprecated. Please use the Web Audio API instead.
|
||||
# LOCALIZATION NOTE: Do not translate "LenientThis" and "this"
|
||||
LenientThisWarning=Ignoring get or set of property that has [LenientThis] because the "this" object is incorrect.
|
||||
# LOCALIZATION NOTE: Do not translate "nsIDOMWindowUtils", "getWindowWithOuterId", or "nsIWindowMediator"
|
||||
|
@ -318,7 +318,6 @@ enum nsEventStructType
|
||||
#define NS_RATECHANGE (NS_MEDIA_EVENT_START+17)
|
||||
#define NS_DURATIONCHANGE (NS_MEDIA_EVENT_START+18)
|
||||
#define NS_VOLUMECHANGE (NS_MEDIA_EVENT_START+19)
|
||||
#define NS_MOZAUDIOAVAILABLE (NS_MEDIA_EVENT_START+20)
|
||||
|
||||
// paint notification events
|
||||
#define NS_NOTIFYPAINT_START 3400
|
||||
|
Loading…
Reference in New Issue
Block a user