Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: content/renderer/media/audio_renderer_impl.h

Issue 9347029: Decouple 'give me more data' and 'rendered end of stream' audio callbacks. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 // Audio rendering unit utilizing AudioDevice. 5 // Audio rendering unit utilizing AudioDevice.
6 // 6 //
7 // This class lives inside three threads during it's lifetime, namely: 7 // This class lives inside three threads during it's lifetime, namely:
8 // 1. Render thread. 8 // 1. Render thread.
9 // This object is created on the render thread. 9 // This object is created on the render thread.
10 // 2. Pipeline thread 10 // 2. Pipeline thread
11 // OnInitialize() is called here with the audio format. 11 // OnInitialize() is called here with the audio format.
12 // Play/Pause/Seek also happens here. 12 // Play/Pause/Seek also happens here.
13 // 3. Audio thread created by the AudioDevice. 13 // 3. Audio thread created by the AudioDevice.
14 // Render() is called here where audio data is decoded into raw PCM data. 14 // Render() is called here where audio data is decoded into raw PCM data.
15 15
16 #ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ 16 #ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
17 #define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ 17 #define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
18 #pragma once 18 #pragma once
19 19
20 #include <vector> 20 #include <vector>
21 21
22 #include "base/callback.h"
23 #include "base/cancelable_callback.h"
22 #include "base/gtest_prod_util.h" 24 #include "base/gtest_prod_util.h"
23 #include "base/memory/scoped_ptr.h" 25 #include "base/memory/scoped_ptr.h"
26 #include "base/memory/weak_ptr.h"
27 #include "base/message_loop_proxy.h"
24 #include "base/synchronization/lock.h" 28 #include "base/synchronization/lock.h"
29 #include "base/time.h"
25 #include "content/renderer/media/audio_device.h" 30 #include "content/renderer/media/audio_device.h"
26 #include "media/audio/audio_io.h" 31 #include "media/audio/audio_io.h"
27 #include "media/audio/audio_parameters.h" 32 #include "media/audio/audio_parameters.h"
28 #include "media/base/audio_renderer_sink.h" 33 #include "media/base/audio_renderer_sink.h"
29 #include "media/filters/audio_renderer_base.h" 34 #include "media/filters/audio_renderer_base.h"
30 35
31 class AudioMessageFilter; 36 class AudioMessageFilter;
32 37
33 class CONTENT_EXPORT AudioRendererImpl 38 class CONTENT_EXPORT AudioRendererImpl
34 : public media::AudioRendererBase, 39 : public media::AudioRendererBase,
40 NON_EXPORTED_BASE(public base::SupportsWeakPtr<AudioRendererImpl>),
35 NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback) { 41 NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback) {
36 public: 42 public:
37 // Methods called on Render thread ------------------------------------------ 43 // Methods called on Render thread ------------------------------------------
38 // An AudioRendererSink is used as the destination for the rendered audio. 44 // An AudioRendererSink is used as the destination for the rendered audio.
39 explicit AudioRendererImpl(media::AudioRendererSink* sink); 45 explicit AudioRendererImpl(media::AudioRendererSink* sink);
40 virtual ~AudioRendererImpl(); 46 virtual ~AudioRendererImpl();
41 47
42 // Methods called on pipeline thread ---------------------------------------- 48 // Methods called on pipeline thread ----------------------------------------
43 // media::Filter implementation. 49 // media::Filter implementation.
44 virtual void SetPlaybackRate(float rate) OVERRIDE; 50 virtual void SetPlaybackRate(float rate) OVERRIDE;
(...skipping 15 matching lines...) Expand all
60 virtual void OnRenderEndOfStream() OVERRIDE; 66 virtual void OnRenderEndOfStream() OVERRIDE;
61 67
62 private: 68 private:
63 // For access to constructor and IO thread methods. 69 // For access to constructor and IO thread methods.
64 friend class AudioRendererImplTest; 70 friend class AudioRendererImplTest;
65 friend class DelegateCaller; 71 friend class DelegateCaller;
66 FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, Stop); 72 FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, Stop);
67 FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, 73 FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest,
68 DestroyedMessageLoop_ConsumeAudioSamples); 74 DestroyedMessageLoop_ConsumeAudioSamples);
69 FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, UpdateEarliestEndTime); 75 FRIEND_TEST_ALL_PREFIXES(AudioRendererImplTest, UpdateEarliestEndTime);
76
77 enum state { NOT_PLAYING, PLAYING, ENDED_EVENT_SCHEDULED, STOPPED };
78
79 // Thread-safe accessor. Not necessary on all current platforms,
80 // state can be set to STOPPED only on the pipeline thread,
81 // but better to have it safe for the future.
82 bool stopped() {
83 base::AutoLock auto_lock(audio_renderer_impl_lock_);
84 return (state_ == STOPPED);
85 }
86
70 // Helper methods. 87 // Helper methods.
71 // Convert number of bytes to duration of time using information about the 88 // Convert number of bytes to duration of time using information about the
72 // number of channels, sample rate and sample bits. 89 // number of channels, sample rate and sample bits.
73 base::TimeDelta ConvertToDuration(int bytes); 90 base::TimeDelta ConvertToDuration(int bytes);
74 91
75 // Methods called on pipeline thread ---------------------------------------- 92 // Methods called on pipeline thread ----------------------------------------
76 void DoPlay(); 93 void DoPlay();
77 void DoPause(); 94 void DoPause();
78 void DoSeek(); 95 void DoSeek();
96 void DoSignalEndOfStream();
97 // We cannot set pipeline message loop in the constructor/initializer because
98 // message loop is not created at that moment. So set it after it is created,
99 // in the DoPlay(). Also DCHECK() that all functions we are expecting to be
100 // called from the pipeline message loop are actually called from it.
101 void DoSetOrCheckMessageLoopProxy();
79 102
80 // media::AudioRendererSink::RenderCallback implementation. 103 // media::AudioRendererSink::RenderCallback implementation.
81 virtual size_t Render(const std::vector<float*>& audio_data, 104 virtual size_t Render(const std::vector<float*>& audio_data,
82 size_t number_of_frames, 105 size_t number_of_frames,
83 size_t audio_delay_milliseconds) OVERRIDE; 106 size_t audio_delay_milliseconds) OVERRIDE;
84 virtual void OnRenderError() OVERRIDE; 107 virtual void OnRenderError() OVERRIDE;
85 108
109 // Returns current message loop proxy.
110 // Made virtual so test can override -- tests use
111 // ChildProcess::current()->io_message_loop_proxy() instead of
112 // MessageLoop::current()->message_loop_proxy().
113 virtual base::MessageLoopProxy* current_message_loop_proxy() {
114 return MessageLoop::current()->message_loop_proxy();
115 }
116
117 // Returns delay in ms before call to OnRenderEndOfStream().
118 // Made virtual so test can override.
119 virtual int64 OnRenderEndOfStreamDelay();
120
86 // Accessors used by tests. 121 // Accessors used by tests.
87 base::Time earliest_end_time() const { 122 base::Time earliest_end_time() {
88 return earliest_end_time_; 123 return earliest_end_time_;
89 } 124 }
90 125
91 void set_earliest_end_time(const base::Time& earliest_end_time) { 126 void set_earliest_end_time(const base::Time& earliest_end_time) {
92 earliest_end_time_ = earliest_end_time; 127 earliest_end_time_ = earliest_end_time;
93 } 128 }
94 129
95 uint32 bytes_per_second() const { 130 uint32 bytes_per_second() const {
96 return bytes_per_second_; 131 return bytes_per_second_;
97 } 132 }
98 133
99 // Estimate earliest time when current buffer can stop playing. 134 // Estimate earliest time when current buffer can stop playing.
100 void UpdateEarliestEndTime(int bytes_filled, 135 void UpdateEarliestEndTime(int bytes_filled,
101 base::TimeDelta request_delay, 136 base::TimeDelta request_delay,
102 base::Time time_now); 137 base::Time time_now);
103 138
139 // Lock protecting data that can be accessed form pipeline and audio threads.
140 base::Lock audio_renderer_impl_lock_;
141
104 // Used to calculate audio delay given bytes. 142 // Used to calculate audio delay given bytes.
105 uint32 bytes_per_second_; 143 uint32 bytes_per_second_;
106 144
107 // A flag that indicates this filter is called to stop. 145 // Current state.
108 bool stopped_; 146 state state_;
109 147
110 // The sink (destination) for rendered audio. 148 // The sink (destination) for rendered audio.
111 scoped_refptr<media::AudioRendererSink> sink_; 149 scoped_refptr<media::AudioRendererSink> sink_;
112 150
113 // Set to true when OnInitialize() is called. 151 // Set to true when OnInitialize() is called.
114 bool is_initialized_; 152 bool is_initialized_;
115 153
116 // We're supposed to know amount of audio data OS or hardware buffered, but 154 // We're supposed to know amount of audio data OS or hardware buffered, but
117 // that is not always so -- on my Linux box 155 // that is not always so -- on my Linux box
118 // AudioBuffersState::hardware_delay_bytes never reaches 0. 156 // AudioBuffersState::hardware_delay_bytes never reaches 0.
119 // 157 //
120 // As a result we cannot use it to find when stream ends. If we just ignore 158 // As a result we cannot use it to find when stream ends. If we just ignore
121 // buffered data we will notify host that stream ended before it is actually 159 // buffered data we will notify host that stream ended before it is actually
122 // did so, I've seen it done ~140ms too early when playing ~150ms file. 160 // did so, I've seen it done ~140ms too early when playing ~150ms file.
123 // 161 //
124 // Instead of trying to invent OS-specific solution for each and every OS we 162 // Instead of trying to invent OS-specific solution for each and every OS we
125 // are supporting, use simple workaround: every time we fill the buffer we 163 // are supporting, use simple workaround: every time we fill the buffer we
126 // remember when it should stop playing, and do not assume that buffer is 164 // remember when it should stop playing, and do not assume that buffer is
127 // empty till that time. Workaround is not bulletproof, as we don't exactly 165 // empty till that time. Workaround is not bulletproof, as we don't exactly
128 // know when that particular data would start playing, but it is much better 166 // know when that particular data would start playing, but it is much better
129 // than nothing. 167 // than nothing.
168 // Access should be protected by lock as it can be accessed by pipeline and
169 // audio threads.
130 base::Time earliest_end_time_; 170 base::Time earliest_end_time_;
131 171
132 AudioParameters audio_parameters_; 172 AudioParameters audio_parameters_;
133 173
174 // Use message loop proxy, not message loop itself, to avoid crash
175 // because of message loop that ended while we are still playing.
176 // We don't need complex shutdown operations, just not posting tasks
177 // is enough, so we can use message loop proxy.
178 scoped_refptr<base::MessageLoopProxy> pipeline_message_loop_proxy_;
179
180 // Cancellable closure called on end of stream.
181 // We may schedule the task but later cancel it on seek / pause.
182 base::CancelableClosure signal_end_of_stream_callback_;
183
134 DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl); 184 DISALLOW_COPY_AND_ASSIGN(AudioRendererImpl);
135 }; 185 };
136 186
137 #endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_ 187 #endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_IMPL_H_
OLDNEW
« no previous file with comments | « no previous file | content/renderer/media/audio_renderer_impl.cc » ('j') | content/renderer/media/audio_renderer_impl.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698