Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "GainNode.h"
8 #include "mozilla/dom/GainNodeBinding.h"
9 #include "AudioNodeEngine.h"
10 #include "AudioNodeStream.h"
11 #include "AudioDestinationNode.h"
12 #include "WebAudioUtils.h"
14 namespace mozilla {
15 namespace dom {
17 NS_IMPL_CYCLE_COLLECTION_INHERITED(GainNode, AudioNode,
18 mGain)
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GainNode)
21 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
23 NS_IMPL_ADDREF_INHERITED(GainNode, AudioNode)
24 NS_IMPL_RELEASE_INHERITED(GainNode, AudioNode)
26 class GainNodeEngine : public AudioNodeEngine
27 {
28 public:
29 GainNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
30 : AudioNodeEngine(aNode)
31 , mSource(nullptr)
32 , mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
33 // Keep the default value in sync with the default value in GainNode::GainNode.
34 , mGain(1.f)
35 {
36 }
38 void SetSourceStream(AudioNodeStream* aSource)
39 {
40 mSource = aSource;
41 }
43 enum Parameters {
44 GAIN
45 };
46 void SetTimelineParameter(uint32_t aIndex,
47 const AudioParamTimeline& aValue,
48 TrackRate aSampleRate) MOZ_OVERRIDE
49 {
50 switch (aIndex) {
51 case GAIN:
52 MOZ_ASSERT(mSource && mDestination);
53 mGain = aValue;
54 WebAudioUtils::ConvertAudioParamToTicks(mGain, mSource, mDestination);
55 break;
56 default:
57 NS_ERROR("Bad GainNodeEngine TimelineParameter");
58 }
59 }
61 virtual void ProcessBlock(AudioNodeStream* aStream,
62 const AudioChunk& aInput,
63 AudioChunk* aOutput,
64 bool* aFinished)
65 {
66 MOZ_ASSERT(mSource == aStream, "Invalid source stream");
68 if (aInput.IsNull()) {
69 // If input is silent, so is the output
70 aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
71 } else if (mGain.HasSimpleValue()) {
72 // Optimize the case where we only have a single value set as the volume
73 float gain = mGain.GetValue();
74 if (gain == 0.0f) {
75 aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
76 } else {
77 *aOutput = aInput;
78 aOutput->mVolume *= gain;
79 }
80 } else {
81 // First, compute a vector of gains for each track tick based on the
82 // timeline at hand, and then for each channel, multiply the values
83 // in the buffer with the gain vector.
84 AllocateAudioBlock(aInput.mChannelData.Length(), aOutput);
86 // Compute the gain values for the duration of the input AudioChunk
87 // XXX we need to add a method to AudioEventTimeline to compute this buffer directly.
88 float computedGain[WEBAUDIO_BLOCK_SIZE];
89 for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
90 TrackTicks tick = aStream->GetCurrentPosition();
91 computedGain[counter] = mGain.GetValueAtTime(tick, counter) * aInput.mVolume;
92 }
94 // Apply the gain to the output buffer
95 for (size_t channel = 0; channel < aOutput->mChannelData.Length(); ++channel) {
96 const float* inputBuffer = static_cast<const float*> (aInput.mChannelData[channel]);
97 float* buffer = static_cast<float*> (const_cast<void*>
98 (aOutput->mChannelData[channel]));
99 AudioBlockCopyChannelWithScale(inputBuffer, computedGain, buffer);
100 }
101 }
102 }
104 virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
105 {
106 // Not owned:
107 // - mSource (probably)
108 // - mDestination (probably)
109 // - mGain - Internal ref owned by AudioNode
110 return AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
111 }
113 virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
114 {
115 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
116 }
118 AudioNodeStream* mSource;
119 AudioNodeStream* mDestination;
120 AudioParamTimeline mGain;
121 };
123 GainNode::GainNode(AudioContext* aContext)
124 : AudioNode(aContext,
125 2,
126 ChannelCountMode::Max,
127 ChannelInterpretation::Speakers)
128 , mGain(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(),
129 SendGainToStream, 1.0f))
130 {
131 GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());
132 mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
133 engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
134 }
136 size_t
137 GainNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
138 {
139 size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
140 amount += mGain->SizeOfIncludingThis(aMallocSizeOf);
141 return amount;
142 }
144 size_t
145 GainNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
146 {
147 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
148 }
150 JSObject*
151 GainNode::WrapObject(JSContext* aCx)
152 {
153 return GainNodeBinding::Wrap(aCx, this);
154 }
156 void
157 GainNode::SendGainToStream(AudioNode* aNode)
158 {
159 GainNode* This = static_cast<GainNode*>(aNode);
160 SendTimelineParameterToStream(This, GainNodeEngine::GAIN, *This->mGain);
161 }
163 }
164 }