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

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: comments mostly resolved (I believe); need to add/update tests if this looks good 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_selector.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 if (decrypting_demuxer_stream_) {
99 decrypting_demuxer_stream_->Reset(base::Bind(
100 &AudioRendererImpl::OnDecryptingDemuxerStreamReset, this, callback));
101 return;
102 }
103
104 decoder_->Reset(callback);
105 }
106
107 void AudioRendererImpl::OnDecryptingDemuxerStreamReset(
ddorwin 2012/12/13 05:08:25 How about calling this DoReset() and just calling
xhwang 2012/12/13 11:24:36 Done.
108 const base::Closure& callback) {
109 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
95 decoder_->Reset(callback); 110 decoder_->Reset(callback);
96 } 111 }
97 112
98 void AudioRendererImpl::Stop(const base::Closure& callback) { 113 void AudioRendererImpl::Stop(const base::Closure& callback) {
99 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 114 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
100 DCHECK(!callback.is_null()); 115 DCHECK(!callback.is_null());
101 116
102 if (sink_) { 117 if (sink_) {
103 sink_->Stop(); 118 sink_->Stop();
104 sink_ = NULL; 119 sink_ = NULL;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 157
143 // |algorithm_| will request more reads. 158 // |algorithm_| will request more reads.
144 algorithm_->FlushBuffers(); 159 algorithm_->FlushBuffers();
145 earliest_end_time_ = base::Time::Now(); 160 earliest_end_time_ = base::Time::Now();
146 } 161 }
147 162
148 // Pause and flush the stream when we preroll to a new location. 163 // Pause and flush the stream when we preroll to a new location.
149 sink_->Pause(true); 164 sink_->Pause(true);
150 } 165 }
151 166
152 void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream, 167 void AudioRendererImpl::Initialize(
153 const AudioDecoderList& decoders, 168 const scoped_refptr<DemuxerStream>& stream,
154 const PipelineStatusCB& init_cb, 169 const AudioDecoderList& decoders,
155 const StatisticsCB& statistics_cb, 170 const SetDecryptorReadyCB& set_decryptor_ready_cb,
156 const base::Closure& underflow_cb, 171 const PipelineStatusCB& init_cb,
157 const TimeCB& time_cb, 172 const StatisticsCB& statistics_cb,
158 const base::Closure& ended_cb, 173 const base::Closure& underflow_cb,
159 const base::Closure& disabled_cb, 174 const TimeCB& time_cb,
160 const PipelineStatusCB& error_cb) { 175 const base::Closure& ended_cb,
176 const base::Closure& disabled_cb,
177 const PipelineStatusCB& error_cb) {
161 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 178 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
162 DCHECK(stream); 179 DCHECK(stream);
163 DCHECK(!decoders.empty()); 180 DCHECK(!decoders.empty());
164 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 181 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
165 DCHECK(!init_cb.is_null()); 182 DCHECK(!init_cb.is_null());
166 DCHECK(!statistics_cb.is_null()); 183 DCHECK(!statistics_cb.is_null());
167 DCHECK(!underflow_cb.is_null()); 184 DCHECK(!underflow_cb.is_null());
168 DCHECK(!time_cb.is_null()); 185 DCHECK(!time_cb.is_null());
169 DCHECK(!ended_cb.is_null()); 186 DCHECK(!ended_cb.is_null());
170 DCHECK(!disabled_cb.is_null()); 187 DCHECK(!disabled_cb.is_null());
171 DCHECK(!error_cb.is_null()); 188 DCHECK(!error_cb.is_null());
172 DCHECK_EQ(kUninitialized, state_); 189 DCHECK_EQ(kUninitialized, state_);
173 DCHECK(sink_); 190 DCHECK(sink_);
174 191
175 init_cb_ = init_cb; 192 init_cb_ = init_cb;
176 statistics_cb_ = statistics_cb; 193 statistics_cb_ = statistics_cb;
177 underflow_cb_ = underflow_cb; 194 underflow_cb_ = underflow_cb;
178 time_cb_ = time_cb; 195 time_cb_ = time_cb;
179 ended_cb_ = ended_cb; 196 ended_cb_ = ended_cb;
180 disabled_cb_ = disabled_cb; 197 disabled_cb_ = disabled_cb;
181 error_cb_ = error_cb; 198 error_cb_ = error_cb;
182 199
183 scoped_ptr<AudioDecoderList> decoder_list(new AudioDecoderList(decoders)); 200 scoped_ptr<AudioDecoderSelector> decoder_selector(
184 InitializeNextDecoder(stream, decoder_list.Pass()); 201 new AudioDecoderSelector(base::MessageLoopProxy::current(),
202 decoders,
203 set_decryptor_ready_cb));
204
205 // To avoid calling |decoder_selector| methods and passing ownership of
206 // |decoder_selector| in the same line.
ddorwin 2012/12/13 05:08:25 I'm not sure what the issue you're trying to avoid
xhwang 2012/12/13 11:24:36 The problem is that the evaluation order is undefi
207 AudioDecoderSelector* decoder_selector_ptr = decoder_selector.get();
208
209 decoder_selector_ptr->SelectAudioDecoder(
210 stream,
211 statistics_cb,
212 base::Bind(&AudioRendererImpl::OnDecoderSelected, this,
213 base::Passed(&decoder_selector)));
185 } 214 }
186 215
187 void AudioRendererImpl::InitializeNextDecoder( 216 void AudioRendererImpl::OnDecoderSelected(
188 const scoped_refptr<DemuxerStream>& demuxer_stream, 217 scoped_ptr<AudioDecoderSelector> decoder_selector,
189 scoped_ptr<AudioDecoderList> decoders) { 218 const scoped_refptr<AudioDecoder>& selected_decoder,
190 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 219 const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) {
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 }
204
205 void AudioRendererImpl::OnDecoderInitDone(
206 const scoped_refptr<DemuxerStream>& demuxer_stream,
207 scoped_ptr<AudioDecoderList> decoders,
208 PipelineStatus status) {
209 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 220 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
210 221
211 if (state_ == kStopped) { 222 if (state_ == kStopped) {
212 DCHECK(!sink_); 223 DCHECK(!sink_);
213 return; 224 return;
214 } 225 }
215 226
216 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) { 227 if (!selected_decoder) {
217 InitializeNextDecoder(demuxer_stream, decoders.Pass()); 228 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
218 return; 229 return;
219 } 230 }
220 231
221 if (status != PIPELINE_OK) { 232 decoder_ = selected_decoder;
222 base::ResetAndReturn(&init_cb_).Run(status); 233 decrypting_demuxer_stream_ = decrypting_demuxer_stream;
223 return;
224 }
225 234
226 int sample_rate = decoder_->samples_per_second(); 235 int sample_rate = decoder_->samples_per_second();
227 int buffer_size = GetHighLatencyOutputBufferSize(sample_rate); 236 int buffer_size = GetHighLatencyOutputBufferSize(sample_rate);
228 AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR; 237 AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR;
229 238
230 // On Windows and Mac we can use the low latency pipeline because they provide 239 // 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 240 // accurate and smooth delay information. On other platforms like Linux there
232 // are jitter issues. 241 // are jitter issues.
233 // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757 242 // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757
234 #if defined(OS_WIN) || defined(OS_MAC) 243 #if defined(OS_WIN) || defined(OS_MAC)
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 case kUnderflow: 638 case kUnderflow:
630 case kRebuffering: 639 case kRebuffering:
631 case kStopped: 640 case kStopped:
632 if (status != PIPELINE_OK) 641 if (status != PIPELINE_OK)
633 error_cb_.Run(status); 642 error_cb_.Run(status);
634 return; 643 return;
635 } 644 }
636 } 645 }
637 646
638 } // namespace media 647 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698