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