OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef PushPullFIFO_h | 5 #ifndef PushPullFIFO_h |
6 #define PushPullFIFO_h | 6 #define PushPullFIFO_h |
7 | 7 |
8 #include "platform/audio/AudioBus.h" | 8 #include "platform/audio/AudioBus.h" |
9 #include "platform/wtf/Allocator.h" | 9 #include "platform/wtf/Allocator.h" |
| 10 #include "platform/wtf/Threading.h" |
| 11 #include "platform/wtf/ThreadingPrimitives.h" |
10 #include "public/platform/WebCommon.h" | 12 #include "public/platform/WebCommon.h" |
11 | 13 |
| 14 #include "platform/audio/AudioIOCallback.h" |
| 15 |
12 namespace blink { | 16 namespace blink { |
13 | 17 |
14 // A configuration data container for PushPullFIFO unit test. | 18 // A configuration data container for PushPullFIFO unit test. |
15 struct PushPullFIFOStateForTest { | 19 struct PushPullFIFOStateForTest { |
16 const size_t fifo_length; | 20 const size_t fifo_length; |
17 const unsigned number_of_channels; | 21 const unsigned number_of_channels; |
18 const size_t frames_available; | 22 const size_t frames_available; |
19 const size_t index_read; | 23 const size_t index_read; |
20 const size_t index_write; | 24 const size_t index_write; |
21 const unsigned overflow_count; | 25 const unsigned overflow_count; |
22 const unsigned underflow_count; | 26 const unsigned underflow_count; |
23 }; | 27 }; |
24 | 28 |
25 // PushPullFIFO class is an intermediate audio sample storage between | 29 // PushPullFIFO class is an intermediate audio sample storage between |
26 // Blink-WebAudio and the renderer. The renderer's hardware callback buffer size | 30 // Blink-WebAudio and the renderer. The renderer's hardware callback buffer size |
27 // varies on the platform, but the WebAudio always renders 128 frames (render | 31 // varies on the platform, but the WebAudio always renders 128 frames (render |
28 // quantum, RQ) thus FIFO is needed to handle the general case. | 32 // quantum, RQ) thus FIFO is needed to handle the general case. |
| 33 // |
| 34 // Note that this object is concurrently accessed by two threads; WebAudio |
| 35 // rendering thread (WebThread) in Blink and the audio device thread |
| 36 // (AudioDeviceThread) from the media renderer. The push/pull operations touch |
| 37 // most of variables in the class (index_write_, index_read_, frames_available_, |
| 38 // and fifo_Bus_) so the thread safety must be handled with care. |
| 39 // |
| 40 // TODO(hongchan): add a unit test for multi-thread access. |
29 class BLINK_PLATFORM_EXPORT PushPullFIFO { | 41 class BLINK_PLATFORM_EXPORT PushPullFIFO { |
30 USING_FAST_MALLOC(PushPullFIFO); | 42 USING_FAST_MALLOC(PushPullFIFO); |
31 WTF_MAKE_NONCOPYABLE(PushPullFIFO); | 43 WTF_MAKE_NONCOPYABLE(PushPullFIFO); |
32 | 44 |
33 public: | 45 public: |
34 // Maximum FIFO length. (512 render quanta) | 46 // Maximum FIFO length. (512 render quanta) |
35 static const size_t kMaxFIFOLength; | 47 static const size_t kMaxFIFOLength; |
36 | 48 |
37 // |fifoLength| cannot exceed |kMaxFIFOLength|. Otherwise it crashes. | 49 // |fifo_length| cannot exceed |kMaxFIFOLength|. Otherwise it crashes. |
38 explicit PushPullFIFO(unsigned number_of_channels, size_t fifo_length); | 50 explicit PushPullFIFO(unsigned number_of_channels, |
| 51 size_t fifo_length, |
| 52 ThreadIdentifier rendering_thread_id, |
| 53 AudioIOCallback& web_audio_render_callback); |
39 ~PushPullFIFO(); | 54 ~PushPullFIFO(); |
40 | 55 |
41 // Pushes the rendered frames by WebAudio engine. | 56 void FillRequestedFrames(size_t frames_requested, |
42 // - The |inputBus| length is 128 frames (1 render quantum), fixed. | 57 size_t callback_buffer_size, |
| 58 AudioIOPosition output_position); |
| 59 |
| 60 // Pushes the rendered frames by WebAudio rendering thread. |
| 61 // - The |input_bus| length is 128 frames (1 render quantum), fixed. |
43 // - In case of overflow (FIFO full while push), the existing frames in FIFO | 62 // - In case of overflow (FIFO full while push), the existing frames in FIFO |
44 // will be overwritten and |indexRead| will be forcibly moved to | 63 // will be overwritten and |index_read_| will be forcibly moved to |
45 // |indexWrite| to avoid reading overwritten frames. | 64 // |index_write_| to avoid reading overwritten frames. |
46 void Push(const AudioBus* input_bus); | 65 void Push(const AudioBus* input_bus); |
47 | 66 |
48 // Pulling |framesRequested| by the audio device thread. | 67 // Pulling |frames_requested| by the audio device thread. |
49 // - If |framesRequested| is bigger than the length of |outputBus|, it | 68 // - If |frames_requested| is bigger than the length of |output_bus|, it |
50 // violates SECURITY_CHECK(). | 69 // violates SECURITY_CHECK(). |
51 // - If |framesRequested| is bigger than FIFO length, it violates | 70 // - If |frames_requested| is bigger than FIFO length, it violates |
52 // SECURITY_CHECK(). | 71 // SECURITY_CHECK(). |
53 // - In case of underflow (FIFO empty while pull), the remaining space in the | 72 // - In case of underflow (FIFO empty while pull), the remaining space in the |
54 // requested output bus will be filled with silence. Thus it will fulfill | 73 // requested output bus will be filled with silence. Thus it will fulfill |
55 // the request from the consumer without causing error, but with a glitch. | 74 // the request from the consumer without causing error, but with a glitch. |
56 void Pull(AudioBus* output_bus, size_t frames_requested); | 75 void Pull(AudioBus* output_bus, size_t frames_requested); |
57 | 76 |
58 size_t FramesAvailable() const { return frames_available_; } | |
59 size_t length() const { return fifo_length_; } | 77 size_t length() const { return fifo_length_; } |
60 unsigned NumberOfChannels() const { return fifo_bus_->NumberOfChannels(); } | 78 unsigned NumberOfChannels() const { return fifo_bus_->NumberOfChannels(); } |
61 AudioBus* Bus() const { return fifo_bus_.Get(); } | 79 AudioBus* GetFIFOBusForTest() const; |
62 | 80 |
63 // For unit test. Get the current configuration that consists of FIFO length, | 81 // For unit test. Get the current configuration that consists of FIFO length, |
64 // number of channels, read/write index position and under/overflow count. | 82 // number of channels, read/write index position and under/overflow count. |
65 const PushPullFIFOStateForTest GetStateForTest() const; | 83 const PushPullFIFOStateForTest GetStateForTest() const; |
66 | 84 |
67 private: | 85 private: |
| 86 bool IsRenderingThread(); |
| 87 |
| 88 // This lock protects: fifo_bus_, frames_available_, index_read_ and |
| 89 // index_write_. |
| 90 mutable Mutex lock_; |
| 91 |
| 92 const ThreadIdentifier rendering_thread_id_; |
| 93 |
| 94 // The render callback function of WebAudio engine. (i.e. DestinationNode) |
| 95 AudioIOCallback& web_audio_render_callback_; |
| 96 |
68 // The size of the FIFO. | 97 // The size of the FIFO. |
69 const size_t fifo_length_ = 0; | 98 const size_t fifo_length_ = 0; |
70 | 99 |
| 100 // To push the rendered result from WebAudio graph into the FIFO. |
| 101 RefPtr<AudioBus> render_bus_; |
| 102 |
71 RefPtr<AudioBus> fifo_bus_; | 103 RefPtr<AudioBus> fifo_bus_; |
72 | 104 |
73 // The number of frames in the FIFO actually available for pulling. | 105 // The number of frames in the FIFO actually available for pulling. |
74 size_t frames_available_; | 106 size_t frames_available_; |
75 | 107 |
76 size_t index_read_; | 108 size_t index_read_; |
77 size_t index_write_; | 109 size_t index_write_; |
78 | 110 |
79 unsigned overflow_count_; | 111 unsigned overflow_count_; |
80 unsigned underflow_count_; | 112 unsigned underflow_count_; |
81 }; | 113 }; |
82 | 114 |
83 } // namespace blink | 115 } // namespace blink |
84 | 116 |
85 #endif // PushPullFIFO_h | 117 #endif // PushPullFIFO_h |
OLD | NEW |