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

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: resolved comments and fixed unittest 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(
28 media::AudioRendererSink* sink,
29 const SetDecryptorReadyCB& set_decryptor_ready_cb)
26 : sink_(sink), 30 : sink_(sink),
31 set_decryptor_ready_cb_(set_decryptor_ready_cb),
27 state_(kUninitialized), 32 state_(kUninitialized),
28 pending_read_(false), 33 pending_read_(false),
29 received_end_of_stream_(false), 34 received_end_of_stream_(false),
30 rendered_end_of_stream_(false), 35 rendered_end_of_stream_(false),
31 audio_time_buffered_(kNoTimestamp()), 36 audio_time_buffered_(kNoTimestamp()),
32 current_time_(kNoTimestamp()), 37 current_time_(kNoTimestamp()),
33 underflow_disabled_(false), 38 underflow_disabled_(false),
34 preroll_aborted_(false), 39 preroll_aborted_(false),
35 actual_frames_per_buffer_(0) { 40 actual_frames_per_buffer_(0) {
36 // We're created on the render thread, but this thread checker is for another. 41 // We're created on the render thread, but this thread checker is for another.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 } 90 }
86 91
87 void AudioRendererImpl::DoPause() { 92 void AudioRendererImpl::DoPause() {
88 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 93 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
89 DCHECK(sink_); 94 DCHECK(sink_);
90 sink_->Pause(false); 95 sink_->Pause(false);
91 } 96 }
92 97
93 void AudioRendererImpl::Flush(const base::Closure& callback) { 98 void AudioRendererImpl::Flush(const base::Closure& callback) {
94 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 99 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
100
101 if (decrypting_demuxer_stream_) {
102 decrypting_demuxer_stream_->Reset(base::Bind(
103 &AudioRendererImpl::ResetDecoder, this, callback));
104 return;
105 }
106
107 decoder_->Reset(callback);
108 }
109
110 void AudioRendererImpl::ResetDecoder(const base::Closure& callback) {
111 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
95 decoder_->Reset(callback); 112 decoder_->Reset(callback);
96 } 113 }
97 114
98 void AudioRendererImpl::Stop(const base::Closure& callback) { 115 void AudioRendererImpl::Stop(const base::Closure& callback) {
99 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 116 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
100 DCHECK(!callback.is_null()); 117 DCHECK(!callback.is_null());
101 118
102 if (sink_) { 119 if (sink_) {
103 sink_->Stop(); 120 sink_->Stop();
104 sink_ = NULL; 121 sink_ = NULL;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 159
143 // |algorithm_| will request more reads. 160 // |algorithm_| will request more reads.
144 algorithm_->FlushBuffers(); 161 algorithm_->FlushBuffers();
145 earliest_end_time_ = base::Time::Now(); 162 earliest_end_time_ = base::Time::Now();
146 } 163 }
147 164
148 // Pause and flush the stream when we preroll to a new location. 165 // Pause and flush the stream when we preroll to a new location.
149 sink_->Pause(true); 166 sink_->Pause(true);
150 } 167 }
151 168
152 void AudioRendererImpl::Initialize(const scoped_refptr<DemuxerStream>& stream, 169 void AudioRendererImpl::Initialize(
153 const AudioDecoderList& decoders, 170 const scoped_refptr<DemuxerStream>& stream,
154 const PipelineStatusCB& init_cb, 171 const AudioDecoderList& decoders,
155 const StatisticsCB& statistics_cb, 172 const PipelineStatusCB& init_cb,
156 const base::Closure& underflow_cb, 173 const StatisticsCB& statistics_cb,
157 const TimeCB& time_cb, 174 const base::Closure& underflow_cb,
158 const base::Closure& ended_cb, 175 const TimeCB& time_cb,
159 const base::Closure& disabled_cb, 176 const base::Closure& ended_cb,
160 const PipelineStatusCB& error_cb) { 177 const base::Closure& disabled_cb,
178 const PipelineStatusCB& error_cb) {
161 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 179 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
162 DCHECK(stream); 180 DCHECK(stream);
163 DCHECK(!decoders.empty()); 181 DCHECK(!decoders.empty());
164 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO); 182 DCHECK_EQ(stream->type(), DemuxerStream::AUDIO);
165 DCHECK(!init_cb.is_null()); 183 DCHECK(!init_cb.is_null());
166 DCHECK(!statistics_cb.is_null()); 184 DCHECK(!statistics_cb.is_null());
167 DCHECK(!underflow_cb.is_null()); 185 DCHECK(!underflow_cb.is_null());
168 DCHECK(!time_cb.is_null()); 186 DCHECK(!time_cb.is_null());
169 DCHECK(!ended_cb.is_null()); 187 DCHECK(!ended_cb.is_null());
170 DCHECK(!disabled_cb.is_null()); 188 DCHECK(!disabled_cb.is_null());
171 DCHECK(!error_cb.is_null()); 189 DCHECK(!error_cb.is_null());
172 DCHECK_EQ(kUninitialized, state_); 190 DCHECK_EQ(kUninitialized, state_);
173 DCHECK(sink_); 191 DCHECK(sink_);
174 192
175 init_cb_ = init_cb; 193 init_cb_ = init_cb;
176 statistics_cb_ = statistics_cb; 194 statistics_cb_ = statistics_cb;
177 underflow_cb_ = underflow_cb; 195 underflow_cb_ = underflow_cb;
178 time_cb_ = time_cb; 196 time_cb_ = time_cb;
179 ended_cb_ = ended_cb; 197 ended_cb_ = ended_cb;
180 disabled_cb_ = disabled_cb; 198 disabled_cb_ = disabled_cb;
181 error_cb_ = error_cb; 199 error_cb_ = error_cb;
182 200
183 scoped_ptr<AudioDecoderList> decoder_list(new AudioDecoderList(decoders)); 201 scoped_ptr<AudioDecoderSelector> decoder_selector(
184 InitializeNextDecoder(stream, decoder_list.Pass()); 202 new AudioDecoderSelector(base::MessageLoopProxy::current(),
203 decoders,
204 set_decryptor_ready_cb_));
205
206 // To avoid calling |decoder_selector| methods and passing ownership of
207 // |decoder_selector| in the same line.
208 AudioDecoderSelector* decoder_selector_ptr = decoder_selector.get();
209
210 decoder_selector_ptr->SelectAudioDecoder(
211 stream,
212 statistics_cb,
213 base::Bind(&AudioRendererImpl::OnDecoderSelected, this,
214 base::Passed(&decoder_selector)));
185 } 215 }
186 216
187 void AudioRendererImpl::InitializeNextDecoder( 217 void AudioRendererImpl::OnDecoderSelected(
188 const scoped_refptr<DemuxerStream>& demuxer_stream, 218 scoped_ptr<AudioDecoderSelector> decoder_selector,
189 scoped_ptr<AudioDecoderList> decoders) { 219 const scoped_refptr<AudioDecoder>& selected_decoder,
190 DCHECK(pipeline_thread_checker_.CalledOnValidThread()); 220 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()); 221 DCHECK(pipeline_thread_checker_.CalledOnValidThread());
210 222
211 if (state_ == kStopped) { 223 if (state_ == kStopped) {
212 DCHECK(!sink_); 224 DCHECK(!sink_);
213 return; 225 return;
214 } 226 }
215 227
216 if (!decoders->empty() && status == DECODER_ERROR_NOT_SUPPORTED) { 228 if (!selected_decoder) {
217 InitializeNextDecoder(demuxer_stream, decoders.Pass()); 229 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
218 return; 230 return;
219 } 231 }
220 232
221 if (status != PIPELINE_OK) { 233 decoder_ = selected_decoder;
222 base::ResetAndReturn(&init_cb_).Run(status); 234 decrypting_demuxer_stream_ = decrypting_demuxer_stream;
223 return;
224 }
225 235
226 int sample_rate = decoder_->samples_per_second(); 236 int sample_rate = decoder_->samples_per_second();
227 int buffer_size = GetHighLatencyOutputBufferSize(sample_rate); 237 int buffer_size = GetHighLatencyOutputBufferSize(sample_rate);
228 AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR; 238 AudioParameters::Format format = AudioParameters::AUDIO_PCM_LINEAR;
229 239
230 // On Windows and Mac we can use the low latency pipeline because they provide 240 // 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 241 // accurate and smooth delay information. On other platforms like Linux there
232 // are jitter issues. 242 // are jitter issues.
233 // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757 243 // TODO(dalecurtis): Fix bugs: http://crbug.com/138098 http://crbug.com/32757
234 #if defined(OS_WIN) || defined(OS_MAC) 244 #if defined(OS_WIN) || defined(OS_MAC)
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 case kUnderflow: 639 case kUnderflow:
630 case kRebuffering: 640 case kRebuffering:
631 case kStopped: 641 case kStopped:
632 if (status != PIPELINE_OK) 642 if (status != PIPELINE_OK)
633 error_cb_.Run(status); 643 error_cb_.Run(status);
634 return; 644 return;
635 } 645 }
636 } 646 }
637 647
638 } // namespace media 648 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698