OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include <algorithm> | 5 #include <algorithm> |
6 #include <cmath> | 6 #include <cmath> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
11 #include "media/base/filter_host.h" | 11 #include "media/base/filter_host.h" |
12 #include "media/filters/null_audio_renderer.h" | 12 #include "media/filters/null_audio_renderer.h" |
13 | 13 |
14 namespace media { | 14 namespace media { |
15 | 15 |
16 // How "long" our buffer should be in terms of milliseconds. In OnInitialize | 16 // How "long" our buffer should be in terms of milliseconds. In OnInitialize |
17 // we calculate the size of one second of audio data and use this number to | 17 // we calculate the size of one second of audio data and use this number to |
18 // allocate a buffer to pass to FillBuffer. | 18 // allocate a buffer to pass to FillBuffer. |
19 static const size_t kBufferSizeInMilliseconds = 100; | 19 static const size_t kBufferSizeInMilliseconds = 100; |
20 | 20 |
21 NullAudioRenderer::NullAudioRenderer() | 21 NullAudioRenderer::NullAudioRenderer() |
22 : AudioRendererBase(), | 22 : AudioRendererBase(), |
23 bytes_per_millisecond_(0), | 23 bytes_per_millisecond_(0), |
24 buffer_size_(0), | 24 buffer_size_(0), |
| 25 bytes_per_frame_(0), |
25 thread_("AudioThread") { | 26 thread_("AudioThread") { |
26 } | 27 } |
27 | 28 |
28 NullAudioRenderer::~NullAudioRenderer() { | 29 NullAudioRenderer::~NullAudioRenderer() { |
29 DCHECK(!thread_.IsRunning()); | 30 DCHECK(!thread_.IsRunning()); |
30 } | 31 } |
31 | 32 |
32 void NullAudioRenderer::SetVolume(float volume) { | 33 void NullAudioRenderer::SetVolume(float volume) { |
33 // Do nothing. | 34 // Do nothing. |
34 } | 35 } |
35 | 36 |
36 bool NullAudioRenderer::OnInitialize(int bits_per_channel, | 37 bool NullAudioRenderer::OnInitialize(int bits_per_channel, |
37 ChannelLayout channel_layout, | 38 ChannelLayout channel_layout, |
38 int sample_rate) { | 39 int sample_rate) { |
39 // Calculate our bytes per millisecond value and allocate our buffer. | 40 // Calculate our bytes per millisecond value and allocate our buffer. |
40 bytes_per_millisecond_ = | 41 int channels = ChannelLayoutToChannelCount(channel_layout); |
41 (ChannelLayoutToChannelCount(channel_layout) * sample_rate * | 42 int bytes_per_channel = bits_per_channel / 8; |
42 bits_per_channel / 8) / base::Time::kMillisecondsPerSecond; | 43 bytes_per_frame_ = channels * bytes_per_channel; |
43 buffer_size_ = bytes_per_millisecond_ * kBufferSizeInMilliseconds; | 44 |
| 45 bytes_per_millisecond_ = (bytes_per_frame_ * sample_rate) / |
| 46 base::Time::kMillisecondsPerSecond; |
| 47 |
| 48 buffer_size_ = |
| 49 bytes_per_millisecond_ * kBufferSizeInMilliseconds; |
| 50 |
44 buffer_.reset(new uint8[buffer_size_]); | 51 buffer_.reset(new uint8[buffer_size_]); |
45 DCHECK(buffer_.get()); | 52 DCHECK(buffer_.get()); |
46 | 53 |
47 if (!thread_.Start()) | 54 if (!thread_.Start()) |
48 return false; | 55 return false; |
49 | 56 |
50 thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | 57 thread_.message_loop()->PostTask(FROM_HERE, base::Bind( |
51 &NullAudioRenderer::FillBufferTask, this)); | 58 &NullAudioRenderer::FillBufferTask, this)); |
52 return true; | 59 return true; |
53 } | 60 } |
54 | 61 |
55 void NullAudioRenderer::OnStop() { | 62 void NullAudioRenderer::OnStop() { |
56 thread_.Stop(); | 63 thread_.Stop(); |
57 } | 64 } |
58 | 65 |
59 void NullAudioRenderer::FillBufferTask() { | 66 void NullAudioRenderer::FillBufferTask() { |
60 base::TimeDelta delay; | 67 base::TimeDelta delay; |
61 | 68 |
62 // Only consume buffers when actually playing. | 69 // Only consume buffers when actually playing. |
63 if (GetPlaybackRate() > 0.0f) { | 70 if (GetPlaybackRate() > 0.0f) { |
64 size_t bytes = FillBuffer(buffer_.get(), buffer_size_, base::TimeDelta()); | 71 size_t requested_frames = buffer_size_ / bytes_per_frame_; |
| 72 size_t frames = FillBuffer( |
| 73 buffer_.get(), requested_frames, base::TimeDelta()); |
| 74 size_t bytes = frames * bytes_per_frame_; |
65 | 75 |
66 // Calculate our sleep duration, taking playback rate into consideration. | 76 // Calculate our sleep duration, taking playback rate into consideration. |
67 delay = base::TimeDelta::FromMilliseconds( | 77 delay = base::TimeDelta::FromMilliseconds( |
68 bytes / (bytes_per_millisecond_ * GetPlaybackRate())); | 78 bytes / (bytes_per_millisecond_ * GetPlaybackRate())); |
69 } else { | 79 } else { |
70 // If paused, sleep for 10 milliseconds before polling again. | 80 // If paused, sleep for 10 milliseconds before polling again. |
71 delay = base::TimeDelta::FromMilliseconds(10); | 81 delay = base::TimeDelta::FromMilliseconds(10); |
72 } | 82 } |
73 | 83 |
74 // Sleep for at least one millisecond so we don't spin the CPU. | 84 // Sleep for at least one millisecond so we don't spin the CPU. |
75 MessageLoop::current()->PostDelayedTask( | 85 MessageLoop::current()->PostDelayedTask( |
76 FROM_HERE, | 86 FROM_HERE, |
77 base::Bind(&NullAudioRenderer::FillBufferTask, this), | 87 base::Bind(&NullAudioRenderer::FillBufferTask, this), |
78 std::max(delay, base::TimeDelta::FromMilliseconds(1))); | 88 std::max(delay, base::TimeDelta::FromMilliseconds(1))); |
79 } | 89 } |
80 | 90 |
81 void NullAudioRenderer::OnRenderEndOfStream() { | 91 void NullAudioRenderer::OnRenderEndOfStream() { |
82 SignalEndOfStream(); | 92 SignalEndOfStream(); |
83 } | 93 } |
84 | 94 |
85 } // namespace media | 95 } // namespace media |
OLD | NEW |