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

Side by Side Diff: media/filters/audio_renderer_impl.cc

Issue 11492003: Encrypted Media: Support Audio Decrypt-Only. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: working and not hacky; need to update comments and tests Created 8 years 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 #include "media/filters/audio_renderer_impl.h" 5 #include "media/filters/audio_renderer_impl.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback.h" 12 #include "base/callback.h"
13 #include "base/callback_helpers.h" 13 #include "base/callback_helpers.h"
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/message_loop_proxy.h" 16 #include "base/message_loop_proxy.h"
17 #include "media/audio/audio_util.h" 17 #include "media/audio/audio_util.h"
18 #include "media/base/audio_splicer.h" 18 #include "media/base/audio_splicer.h"
19 #include "media/base/bind_to_loop.h" 19 #include "media/base/bind_to_loop.h"
20 #include "media/base/demuxer_stream.h" 20 #include "media/base/demuxer_stream.h"
21 #include "media/base/media_switches.h" 21 #include "media/base/media_switches.h"
22 #include "media/filters/audio_decoder_factory.h"
23 #include "media/filters/decrypting_demuxer_stream.h"
22 24
23 namespace media { 25 namespace media {
24 26
25 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink) 27 AudioRendererImpl::AudioRendererImpl(media::AudioRendererSink* sink)
26 : sink_(sink), 28 : sink_(sink),
27 state_(kUninitialized), 29 state_(kUninitialized),
28 pending_read_(false), 30 pending_read_(false),
29 received_end_of_stream_(false), 31 received_end_of_stream_(false),
30 rendered_end_of_stream_(false), 32 rendered_end_of_stream_(false),
31 audio_time_buffered_(kNoTimestamp()), 33 audio_time_buffered_(kNoTimestamp()),
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 } 87 }
86 88
87 void AudioRendererImpl::DoPause() { 89 void AudioRendererImpl::DoPause() {
88 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 90 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
89 DCHECK(sink_); 91 DCHECK(sink_);
90 sink_->Pause(false); 92 sink_->Pause(false);
91 } 93 }
92 94
93 void AudioRendererImpl::Flush(const base::Closure& callback) { 95 void AudioRendererImpl::Flush(const base::Closure& callback) {
94 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 96 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
97
98 // XXX(xhwang): We we want to wait for decrypting_demuxer_stream_->Reset() to
99 // fire the callback? It seems it's not strictly necessary. If that's true,
100 // shall we remove the completion callback in DecyrptingDemuxerStream::Reset()
101 // all together?
102 if (decrypting_demuxer_stream_)
103 decrypting_demuxer_stream_->Reset(base::Bind(&base::DoNothing));
xhwang 2012/12/11 02:27:40 Similar to what we are doing in media pipeline, th
ddorwin 2012/12/11 05:13:34 I defer to scherkus.
scherkus (not reviewing) 2012/12/11 20:52:15 Why do we not need to wait? Is it because it's syn
xhwang 2012/12/12 23:43:28 Added another callback so we actually wait.
104
95 decoder_->Reset(callback); 105 decoder_->Reset(callback);
96 } 106 }
97 107
98 void AudioRendererImpl::Stop(const base::Closure& callback) { 108 void AudioRendererImpl::Stop(const base::Closure& callback) {
99 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 109 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
100 DCHECK(!callback.is_null()); 110 DCHECK(!callback.is_null());
101 111
102 if (sink_) { 112 if (sink_) {
103 sink_->Stop(); 113 sink_->Stop();
104 sink_ = NULL; 114 sink_ = NULL;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 152
143 // |algorithm_| will request more reads. 153 // |algorithm_| will request more reads.
144 algorithm_->FlushBuffers(); 154 algorithm_->FlushBuffers();
145 earliest_end_time_ = base::Time::Now(); 155 earliest_end_time_ = base::Time::Now();
146 } 156 }
147 157
148 // Pause and flush the stream when we preroll to a new location. 158 // Pause and flush the stream when we preroll to a new location.
149 sink_->Pause(true); 159 sink_->Pause(true);
150 } 160 }
151 161
152 void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream, 162 void AudioRendererImpl::Initialize(
153 const AudioDecoderList& decoders, 163 const scoped_refptr<DemuxerStream>& stream,
154 const PipelineStatusCB& init_cb, 164 const AudioDecoderList& decoders,
155 const StatisticsCB& statistics_cb, 165 const RequestDecryptorNotificationCB& request_decryptor_notification_cb,
156 const base::Closure& underflow_cb, 166 const PipelineStatusCB& init_cb,
157 const TimeCB& time_cb, 167 const StatisticsCB& statistics_cb,
158 const base::Closure& ended_cb, 168 const base::Closure& underflow_cb,
159 const base::Closure& disabled_cb, 169 const TimeCB& time_cb,
160 const PipelineStatusCB& error_cb) { 170 const base::Closure& ended_cb,
171 const base::Closure& disabled_cb,
172 const PipelineStatusCB& error_cb) {
161 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 173 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
162 DCHECK(stream); 174 DCHECK(stream);
163 DCHECK(!decoders.empty()); 175 DCHECK(!decoders.empty());
164 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 176 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
165 DCHECK(!init_cb.is_null()); 177 DCHECK(!init_cb.is_null());
166 DCHECK(!statistics_cb.is_null()); 178 DCHECK(!statistics_cb.is_null());
167 DCHECK(!underflow_cb.is_null()); 179 DCHECK(!underflow_cb.is_null());
168 DCHECK(!time_cb.is_null()); 180 DCHECK(!time_cb.is_null());
169 DCHECK(!ended_cb.is_null()); 181 DCHECK(!ended_cb.is_null());
170 DCHECK(!disabled_cb.is_null()); 182 DCHECK(!disabled_cb.is_null());
171 DCHECK(!error_cb.is_null()); 183 DCHECK(!error_cb.is_null());
172 DCHECK_EQ(kUninitialized, state_); 184 DCHECK_EQ(kUninitialized, state_);
173 DCHECK(sink_); 185 DCHECK(sink_);
174 186
175 init_cb_ = init_cb; 187 init_cb_ = init_cb;
176 statistics_cb_ = statistics_cb; 188 statistics_cb_ = statistics_cb;
177 underflow_cb_ = underflow_cb; 189 underflow_cb_ = underflow_cb;
178 time_cb_ = time_cb; 190 time_cb_ = time_cb;
179 ended_cb_ = ended_cb; 191 ended_cb_ = ended_cb;
180 disabled_cb_ = disabled_cb; 192 disabled_cb_ = disabled_cb;
181 error_cb_ = error_cb; 193 error_cb_ = error_cb;
182 194
183 scoped_ptr<AudioDecoderList> decoder_list(new AudioDecoderList(decoders)); 195 factory_.reset(new AudioDecoderFactory(base::MessageLoopProxy::current(),
184 InitializeNextDecoder(stream, decoder_list.Pass()); 196 decoders,
185 } 197 request_decryptor_notification_cb));
186 198 factory_->InitAudioDecoder(
187 void AudioRendererImpl::InitializeNextDecoder( 199 stream,
188 const scoped_refptr<DemuxerStream>& demuxer_stream, 200 statistics_cb,
189 scoped_ptr<AudioDecoderList> decoders) { 201 base::Bind(&AudioRendererImpl::OnDecoderInitDone, this));
190 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
191 DCHECK(!decoders->empty());
192
193 scoped_refptr<AudioDecoder> decoder = decoders->front();
194 decoders->pop_front();
195
196 DCHECK(decoder);
197 decoder_ = decoder;
198 decoder->Initialize(
199 demuxer_stream, BindToLoop(base::MessageLoopProxy::current(), base::Bind(
200 &AudioRendererImpl::OnDecoderInitDone, this, demuxer_stream,
201 base::Passed(&decoders))),
202 statistics_cb_);
203 } 202 }
204 203
205 void AudioRendererImpl::OnDecoderInitDone( 204 void AudioRendererImpl::OnDecoderInitDone(
206 const scoped_refptr<DemuxerStream>& demuxer_stream, 205 const scoped_refptr<AudioDecoder>& audio_decoder,
ddorwin 2012/12/11 05:13:34 Would selected_decoder be a more helpful name?
xhwang 2012/12/12 23:43:28 Done.
207 scoped_ptr<AudioDecoderList> decoders, 206 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) {
208 PipelineStatus status) {
209 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 207 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
210 208
209 decoder_ = audio_decoder;
210 decrypting_demuxer_stream_ = decrypting_demuxer_stream;
211 factory_.reset();
ddorwin 2012/12/11 05:13:34 Should we have the factory manage its own lifetime
xhwang 2012/12/11 19:43:04 After the audio decoder (and decrypting_demuxer_st
ddorwin 2012/12/12 00:30:25 Init() AddRef()'s then errors or success DeRef() a
xhwang 2012/12/12 23:43:28 Pass the scoped_ptr in the callback to keep it ali
212
211 if (state_ == kStopped) { 213 if (state_ == kStopped) {
212 DCHECK(!sink_); 214 DCHECK(!sink_);
ddorwin 2012/12/11 05:13:34 Should we have stored decoder_ at 209 in this case
xhwang 2012/12/11 19:43:04 It's a little tricky. We are passing const-ref of
213 return; 215 return;
214 } 216 }
215 217
216 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) { 218 if (!decoder_) {
217 InitializeNextDecoder(demuxer_stream, decoders.Pass()); 219 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
218 return; 220 return;
219 } 221 }
220 222
221 if (status != PIPELINE_OK) {
222 base::ResetAndReturn(&init_cb_).Run(status);
223 return;
224 }
225
226 int sample_rate = decoder_->samples_per_second(); 223 int sample_rate = decoder_->samples_per_second();
227 int buffer_size = GetHighLatencyOutputBufferSize(sample_rate); 224 int buffer_size = GetHighLatencyOutputBufferSize(sample_rate);
228 AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR; 225 AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR;
229 226
230 // On Windows and Mac we can use the low latency pipeline because they provide 227 // On Windows and Mac we can use the low latency pipeline because they provide
231 // accurate and smooth delay information. On other platforms like Linux there 228 // accurate and smooth delay information. On other platforms like Linux there
232 // are jitter issues. 229 // are jitter issues.
233 // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757 230 // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757
234 #if defined(OS_WIN) || defined(OS_MAC) 231 #if defined(OS_WIN) || defined(OS_MAC)
235 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 232 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 case kUnderflow: 626 case kUnderflow:
630 case kRebuffering: 627 case kRebuffering:
631 case kStopped: 628 case kStopped:
632 if (status != PIPELINE_OK) 629 if (status != PIPELINE_OK)
633 error_cb_.Run(status); 630 error_cb_.Run(status);
634 return; 631 return;
635 } 632 }
636 } 633 }
637 634
638 } // namespace media 635 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698