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

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

Issue 11198017: Add DecryptingAudioDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 2 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 #include "media/filters/decrypting_video_decoder.h" 5 #include "media/filters/decrypting_audio_decoder.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback_helpers.h" 8 #include "base/callback_helpers.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
11 #include "media/base/audio_decoder_config.h"
11 #include "media/base/bind_to_loop.h" 12 #include "media/base/bind_to_loop.h"
13 #include "media/base/buffers.h"
14 #include "media/base/data_buffer.h"
12 #include "media/base/decoder_buffer.h" 15 #include "media/base/decoder_buffer.h"
13 #include "media/base/decryptor.h" 16 #include "media/base/decryptor.h"
14 #include "media/base/demuxer_stream.h" 17 #include "media/base/demuxer_stream.h"
15 #include "media/base/pipeline.h" 18 #include "media/base/pipeline.h"
16 #include "media/base/video_decoder_config.h"
17 #include "media/base/video_frame.h"
18 19
19 namespace media { 20 namespace media {
20 21
21 #define BIND_TO_LOOP(function) \ 22 #define BIND_TO_LOOP(function) \
22 media::BindToLoop(message_loop_, base::Bind(function, this)) 23 media::BindToLoop(message_loop_, base::Bind(function, this))
23 24
24 DecryptingVideoDecoder::DecryptingVideoDecoder( 25 DecryptingAudioDecoder::DecryptingAudioDecoder(
25 const MessageLoopFactoryCB& message_loop_factory_cb, 26 const MessageLoopFactoryCB& message_loop_factory_cb,
26 const RequestDecryptorNotificationCB& request_decryptor_notification_cb) 27 const RequestDecryptorNotificationCB& request_decryptor_notification_cb)
27 : message_loop_factory_cb_(message_loop_factory_cb), 28 : message_loop_factory_cb_(message_loop_factory_cb),
28 state_(kUninitialized), 29 state_(kUninitialized),
29 request_decryptor_notification_cb_(request_decryptor_notification_cb), 30 request_decryptor_notification_cb_(request_decryptor_notification_cb),
30 decryptor_(NULL), 31 decryptor_(NULL),
31 key_added_while_pending_decode_(false) { 32 key_added_while_pending_decode_(false),
33 bits_per_channel_(0),
34 channel_layout_(CHANNEL_LAYOUT_NONE),
35 samples_per_second_(0) {
32 } 36 }
33 37
34 void DecryptingVideoDecoder::Initialize( 38 void DecryptingAudioDecoder::Initialize(
35 const scoped_refptr<DemuxerStream>& stream, 39 const scoped_refptr<DemuxerStream>& stream,
36 const PipelineStatusCB& status_cb, 40 const PipelineStatusCB& status_cb,
37 const StatisticsCB& statistics_cb) { 41 const StatisticsCB& statistics_cb) {
38 DCHECK(!message_loop_); 42 DCHECK(!message_loop_);
39 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run(); 43 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run();
40 message_loop_->PostTask(FROM_HERE, base::Bind( 44 message_loop_->PostTask(FROM_HERE, base::Bind(
41 &DecryptingVideoDecoder::DoInitialize, this, 45 &DecryptingAudioDecoder::DoInitialize, this,
42 stream, status_cb, statistics_cb)); 46 stream, status_cb, statistics_cb));
43 } 47 }
44 48
45 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { 49 void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
46 // Complete operation asynchronously on different stack of execution as per 50 // Complete operation asynchronously on different stack of execution as per
47 // the API contract of VideoDecoder::Read() 51 // the API contract of AudioDecoder::Read()
48 message_loop_->PostTask(FROM_HERE, base::Bind( 52 message_loop_->PostTask(FROM_HERE, base::Bind(
49 &DecryptingVideoDecoder::DoRead, this, read_cb)); 53 &DecryptingAudioDecoder::DoRead, this, read_cb));
50 } 54 }
51 55
52 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { 56 void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
53 if (!message_loop_->BelongsToCurrentThread()) { 57 if (!message_loop_->BelongsToCurrentThread()) {
54 message_loop_->PostTask(FROM_HERE, base::Bind( 58 message_loop_->PostTask(FROM_HERE, base::Bind(
55 &DecryptingVideoDecoder::Reset, this, closure)); 59 &DecryptingAudioDecoder::Reset, this, closure));
56 return; 60 return;
57 } 61 }
58 62
59 DVLOG(2) << "Reset() - state: " << state_; 63 DVLOG(2) << "Reset() - state: " << state_;
60 DCHECK(state_ == kIdle || 64 DCHECK(state_ == kIdle ||
61 state_ == kPendingDemuxerRead || 65 state_ == kPendingDemuxerRead ||
62 state_ == kPendingDecode || 66 state_ == kPendingDecode ||
63 state_ == kWaitingForKey || 67 state_ == kWaitingForKey ||
64 state_ == kDecodeFinished) << state_; 68 state_ == kDecodeFinished) << state_;
65 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. 69 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
66 DCHECK(reset_cb_.is_null()); 70 DCHECK(reset_cb_.is_null());
67 71
68 reset_cb_ = closure; 72 reset_cb_ = closure;
69 73
70 decryptor_->ResetDecoder(Decryptor::kVideo); 74 decryptor_->ResetDecoder(Decryptor::kAudio);
71 75
72 // Reset() cannot complete if the read callback is still pending. 76 // Reset() cannot complete if the read callback is still pending.
73 // Defer the resetting process in this case. The |reset_cb_| will be fired 77 // Defer the resetting process in this case. The |reset_cb_| will be fired
74 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and 78 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and
75 // DoDeliverFrame(). 79 // DoDeliverFrame().
76 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { 80 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) {
77 DCHECK(!read_cb_.is_null()); 81 DCHECK(!read_cb_.is_null());
78 return; 82 return;
79 } 83 }
80 84
81 if (state_ == kWaitingForKey) { 85 if (state_ == kWaitingForKey) {
82 DCHECK(!read_cb_.is_null()); 86 DCHECK(!read_cb_.is_null());
83 pending_buffer_to_decode_ = NULL; 87 pending_buffer_to_decode_ = NULL;
84 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 88 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
85 } 89 }
86 90
87 DCHECK(read_cb_.is_null()); 91 DCHECK(read_cb_.is_null());
88 DoReset(); 92 DoReset();
89 } 93 }
90 94
91 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { 95 int DecryptingAudioDecoder::bits_per_channel() {
92 if (!message_loop_->BelongsToCurrentThread()) { 96 return bits_per_channel_;
93 message_loop_->PostTask(FROM_HERE, base::Bind(
94 &DecryptingVideoDecoder::Stop, this, closure));
95 return;
96 }
97
98 DVLOG(2) << "Stop() - state: " << state_;
99
100 // At this point the render thread is likely paused (in WebMediaPlayerImpl's
101 // Destroy()), so running |closure| can't wait for anything that requires the
102 // render thread to be processing messages to complete (such as PPAPI
103 // callbacks).
104 if (decryptor_)
105 decryptor_->DeinitializeDecoder(Decryptor::kVideo);
106 if (!request_decryptor_notification_cb_.is_null()) {
107 base::ResetAndReturn(&request_decryptor_notification_cb_).Run(
108 DecryptorNotificationCB());
109 }
110 pending_buffer_to_decode_ = NULL;
111 if (!init_cb_.is_null())
112 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
113 if (!read_cb_.is_null())
114 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
115 if (!reset_cb_.is_null())
116 base::ResetAndReturn(&reset_cb_).Run();
117 state_ = kStopped;
118 closure.Run();
119 } 97 }
120 98
121 DecryptingVideoDecoder::~DecryptingVideoDecoder() { 99 ChannelLayout DecryptingAudioDecoder::channel_layout() {
122 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; 100 return channel_layout_;
123 } 101 }
124 102
125 void DecryptingVideoDecoder::DoInitialize( 103 int DecryptingAudioDecoder::samples_per_second() {
104 return samples_per_second_;
105 }
106
107 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
108 }
109
110 void DecryptingAudioDecoder::DoInitialize(
126 const scoped_refptr<DemuxerStream>& stream, 111 const scoped_refptr<DemuxerStream>& stream,
127 const PipelineStatusCB& status_cb, 112 const PipelineStatusCB& status_cb,
128 const StatisticsCB& statistics_cb) { 113 const StatisticsCB& statistics_cb) {
129 DVLOG(2) << "DoInitialize()"; 114 DVLOG(2) << "DoInitialize()";
130 DCHECK(message_loop_->BelongsToCurrentThread()); 115 DCHECK(message_loop_->BelongsToCurrentThread());
131 DCHECK_EQ(state_, kUninitialized) << state_; 116 DCHECK_EQ(state_, kUninitialized) << state_;
132 DCHECK(stream); 117 DCHECK(stream);
133 118
134 const VideoDecoderConfig& config = stream->video_decoder_config(); 119 const AudioDecoderConfig& config = stream->audio_decoder_config();
135 if (!config.IsValidConfig()) { 120 if (!config.IsValidConfig()) {
136 DLOG(ERROR) << "Invalid video stream config: " 121 DLOG(ERROR) << "Invalid audio stream config.";
137 << config.AsHumanReadableString();
138 status_cb.Run(PIPELINE_ERROR_DECODE); 122 status_cb.Run(PIPELINE_ERROR_DECODE);
139 return; 123 return;
140 } 124 }
141 125
142 // DecryptingVideoDecoder only accepts potentially encrypted stream. 126 // DecryptingAudioDecoder only accepts potentially encrypted stream.
143 if (!config.is_encrypted()) { 127 if (!config.is_encrypted()) {
144 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 128 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
145 return; 129 return;
146 } 130 }
147 131
148 DCHECK(!demuxer_stream_); 132 DCHECK(!demuxer_stream_);
149 demuxer_stream_ = stream; 133 demuxer_stream_ = stream;
150 statistics_cb_ = statistics_cb; 134 statistics_cb_ = statistics_cb;
151 135
152 init_cb_ = status_cb; 136 init_cb_ = status_cb;
153 137
154 state_ = kDecryptorRequested; 138 state_ = kDecryptorRequested;
155 request_decryptor_notification_cb_.Run( 139 request_decryptor_notification_cb_.Run(
156 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor)); 140 BIND_TO_LOOP(&DecryptingAudioDecoder::SetDecryptor));
157 } 141 }
158 142
159 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { 143 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
160 DVLOG(2) << "SetDecryptor()"; 144 DVLOG(2) << "SetDecryptor()";
161 DCHECK(message_loop_->BelongsToCurrentThread()); 145 DCHECK(message_loop_->BelongsToCurrentThread());
162
163 if (state_ == kStopped)
164 return;
165
166 DCHECK_EQ(state_, kDecryptorRequested) << state_; 146 DCHECK_EQ(state_, kDecryptorRequested) << state_;
167 DCHECK(!init_cb_.is_null()); 147 DCHECK(!init_cb_.is_null());
168 DCHECK(!request_decryptor_notification_cb_.is_null()); 148 DCHECK(!request_decryptor_notification_cb_.is_null());
149
169 request_decryptor_notification_cb_.Reset(); 150 request_decryptor_notification_cb_.Reset();
170
171 decryptor_ = decryptor; 151 decryptor_ = decryptor;
172 152
173 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); 153 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
174 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); 154 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config());
175 155
176 state_ = kPendingDecoderInit; 156 state_ = kPendingDecoderInit;
177 decryptor_->InitializeVideoDecoder( 157 decryptor_->InitializeAudioDecoder(
178 scoped_config.Pass(), 158 scoped_config.Pass(),
179 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), 159 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization),
180 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); 160 BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded));
181 } 161 }
182 162
183 void DecryptingVideoDecoder::FinishInitialization(bool success) { 163 void DecryptingAudioDecoder::FinishInitialization(bool success) {
184 DVLOG(2) << "FinishInitialization()"; 164 DVLOG(2) << "FinishInitialization()";
185 DCHECK(message_loop_->BelongsToCurrentThread()); 165 DCHECK(message_loop_->BelongsToCurrentThread());
186
187 if (state_ == kStopped)
188 return;
189
190 DCHECK_EQ(state_, kPendingDecoderInit) << state_; 166 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
191 DCHECK(!init_cb_.is_null()); 167 DCHECK(!init_cb_.is_null());
192 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. 168 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
193 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. 169 DCHECK(read_cb_.is_null()); // No Read() before initialization finished.
194 170
195 if (!success) { 171 if (!success) {
196 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 172 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
197 state_ = kStopped; 173 state_ = kDecodeFinished;
198 return; 174 return;
199 } 175 }
200 176
201 // Success! 177 // Success!
178 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config();
179 bits_per_channel_ = config.bits_per_channel();
180 channel_layout_ = config.channel_layout();
181 samples_per_second_ = config.samples_per_second();
202 state_ = kIdle; 182 state_ = kIdle;
203 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 183 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
204 } 184 }
205 185
206 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { 186 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) {
207 DVLOG(3) << "DoRead()"; 187 DVLOG(3) << "DoRead()";
208 DCHECK(message_loop_->BelongsToCurrentThread()); 188 DCHECK(message_loop_->BelongsToCurrentThread());
209 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; 189 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
210 DCHECK(!read_cb.is_null()); 190 DCHECK(!read_cb.is_null());
211 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 191 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
212 192
213 // Return empty frames if decoding has finished. 193 // Return empty (end-of-stream) frames if decoding has finished.
214 if (state_ == kDecodeFinished) { 194 if (state_ == kDecodeFinished) {
215 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); 195 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0)));
216 return; 196 return;
217 } 197 }
218 198
199 if (!queued_audio_frames_.empty()) {
200 if (queued_audio_frames_.front()->IsEndOfStream())
201 state_ = kDecodeFinished;
202 read_cb.Run(kOk, queued_audio_frames_.front());
203 queued_audio_frames_.pop_front();
204 return;
205 }
206
219 read_cb_ = read_cb; 207 read_cb_ = read_cb;
220 state_ = kPendingDemuxerRead; 208 state_ = kPendingDemuxerRead;
221 ReadFromDemuxerStream(); 209 ReadFromDemuxerStream();
222 } 210 }
223 211
224 void DecryptingVideoDecoder::ReadFromDemuxerStream() { 212 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
225 DCHECK(message_loop_->BelongsToCurrentThread()); 213 DCHECK(message_loop_->BelongsToCurrentThread());
226 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 214 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
227 DCHECK(!read_cb_.is_null()); 215 DCHECK(!read_cb_.is_null());
228 216
229 demuxer_stream_->Read( 217 demuxer_stream_->Read(
230 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); 218 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this));
231 } 219 }
232 220
233 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( 221 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
234 DemuxerStream::Status status, 222 DemuxerStream::Status status,
235 const scoped_refptr<DecoderBuffer>& buffer) { 223 const scoped_refptr<DecoderBuffer>& buffer) {
236 // In theory, we don't need to force post the task here, because we do a 224 // In theory, we don't need to force post the task here, because we do a
237 // force task post in DeliverFrame(). Therefore, even if 225 // force task post in DeliverFrame(). Therefore, even if
238 // demuxer_stream_->Read() execute the read callback on the same execution 226 // demuxer_stream_->Read() execute the read callback on the same execution
239 // stack we are still fine. But it looks like a force post task makes the 227 // stack we are still fine. But it looks like a force post task makes the
240 // logic more understandable and manageable, so why not? 228 // logic more understandable and manageable, so why not?
241 message_loop_->PostTask(FROM_HERE, base::Bind( 229 message_loop_->PostTask(FROM_HERE, base::Bind(
242 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); 230 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer));
243 } 231 }
244 232
245 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( 233 void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer(
246 DemuxerStream::Status status, 234 DemuxerStream::Status status,
247 const scoped_refptr<DecoderBuffer>& buffer) { 235 const scoped_refptr<DecoderBuffer>& buffer) {
248 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; 236 DVLOG(3) << "DoDecryptAndDecodeBuffer()";
249 DCHECK(message_loop_->BelongsToCurrentThread()); 237 DCHECK(message_loop_->BelongsToCurrentThread());
250
251 if (state_ == kStopped)
252 return;
253
254 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 238 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
255 DCHECK(!read_cb_.is_null()); 239 DCHECK(!read_cb_.is_null());
256 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; 240 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;
257 241
258 if (!reset_cb_.is_null()) { 242 if (!reset_cb_.is_null()) {
259 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 243 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
260 if (!reset_cb_.is_null()) 244 DoReset();
261 DoReset();
262 return; 245 return;
263 } 246 }
264 247
265 if (status == DemuxerStream::kAborted) { 248 if (status == DemuxerStream::kAborted) {
266 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; 249 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted";
267 state_ = kIdle; 250 state_ = kIdle;
268 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 251 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
269 return; 252 return;
270 } 253 }
271 254
272 if (status == DemuxerStream::kConfigChanged) { 255 if (status == DemuxerStream::kConfigChanged) {
273 // TODO(xhwang): Add config change support. 256 // TODO(xhwang): Add config change support.
274 // The |state_| is chosen to be kDecodeFinished here to be consistent with 257 // The |state_| is chosen to be kDecodeFinished here to be consistent with
275 // the implementation of FFmpegVideoDecoder. 258 // the implementation of FFmpegVideoDecoder.
276 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; 259 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";
277 state_ = kDecodeFinished; 260 state_ = kDecodeFinished;
278 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 261 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
279 return; 262 return;
280 } 263 }
281 264
282 DCHECK_EQ(status, DemuxerStream::kOk); 265 DCHECK_EQ(status, DemuxerStream::kOk);
283 pending_buffer_to_decode_ = buffer; 266 pending_buffer_to_decode_ = buffer;
284 state_ = kPendingDecode; 267 state_ = kPendingDecode;
285 DecodePendingBuffer(); 268 DecodePendingBuffer();
286 } 269 }
287 270
288 void DecryptingVideoDecoder::DecodePendingBuffer() { 271 void DecryptingAudioDecoder::DecodePendingBuffer() {
289 DCHECK(message_loop_->BelongsToCurrentThread()); 272 DCHECK(message_loop_->BelongsToCurrentThread());
290 DCHECK_EQ(state_, kPendingDecode) << state_; 273 DCHECK_EQ(state_, kPendingDecode) << state_;
291 decryptor_->DecryptAndDecodeVideo( 274 decryptor_->DecryptAndDecodeAudio(
292 pending_buffer_to_decode_, 275 pending_buffer_to_decode_,
293 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, 276 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this,
294 pending_buffer_to_decode_->GetDataSize())); 277 pending_buffer_to_decode_->GetDataSize()));
295 } 278 }
296 279
297 void DecryptingVideoDecoder::DeliverFrame( 280 void DecryptingAudioDecoder::DeliverFrame(
298 int buffer_size, 281 int buffer_size,
299 Decryptor::Status status, 282 Decryptor::Status status,
300 const scoped_refptr<VideoFrame>& frame) { 283 const Decryptor::AudioBuffers& frames) {
301 // We need to force task post here because the VideoDecodeCB can be executed 284 // We need to force task post here because the AudioDecodeCB can be executed
302 // synchronously in Reset()/Stop(). Instead of using more complicated logic in 285 // synchronously in Reset(). Instead of using more complicated logic in
303 // those function to fix it, why not force task post here to make everything 286 // those function to fix it, why not force task post here to make everything
304 // simple and clear? 287 // simple and clear?
305 message_loop_->PostTask(FROM_HERE, base::Bind( 288 message_loop_->PostTask(FROM_HERE, base::Bind(
306 &DecryptingVideoDecoder::DoDeliverFrame, this, 289 &DecryptingAudioDecoder::DoDeliverFrame, this,
307 buffer_size, status, frame)); 290 buffer_size, status, frames));
308 } 291 }
309 292
310 void DecryptingVideoDecoder::DoDeliverFrame( 293 void DecryptingAudioDecoder::DoDeliverFrame(
311 int buffer_size, 294 int buffer_size,
312 Decryptor::Status status, 295 Decryptor::Status status,
313 const scoped_refptr<VideoFrame>& frame) { 296 const Decryptor::AudioBuffers& frames) {
314 DVLOG(3) << "DoDeliverFrame()"; 297 DVLOG(3) << "DoDeliverFrame()";
315 DCHECK(message_loop_->BelongsToCurrentThread()); 298 DCHECK(message_loop_->BelongsToCurrentThread());
316
317 if (state_ == kStopped)
318 return;
319
320 DCHECK_EQ(state_, kPendingDecode) << state_; 299 DCHECK_EQ(state_, kPendingDecode) << state_;
321 DCHECK(!read_cb_.is_null()); 300 DCHECK(!read_cb_.is_null());
322 DCHECK(pending_buffer_to_decode_); 301 DCHECK(pending_buffer_to_decode_);
302 DCHECK(queued_audio_frames_.empty());
323 303
324 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; 304 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_;
325 key_added_while_pending_decode_ = false; 305 key_added_while_pending_decode_ = false;
326 306
327 if (!reset_cb_.is_null()) { 307 if (!reset_cb_.is_null()) {
328 pending_buffer_to_decode_ = NULL; 308 pending_buffer_to_decode_ = NULL;
329 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 309 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
330 if (!reset_cb_.is_null()) 310 DoReset();
331 DoReset();
332 return; 311 return;
333 } 312 }
334 313
335 if (status == Decryptor::kError) { 314 if (status == Decryptor::kError) {
336 DCHECK(!frame); 315 DCHECK(frames.empty());
337 state_ = kDecodeFinished; 316 state_ = kDecodeFinished;
338 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 317 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
339 return; 318 return;
340 } 319 }
341 320
342 if (status == Decryptor::kNoKey) { 321 if (status == Decryptor::kNoKey) {
343 DCHECK(!frame); 322 DCHECK(frames.empty());
344 if (need_to_try_again_if_nokey_is_returned) { 323 if (need_to_try_again_if_nokey_is_returned) {
345 // The |state_| is still kPendingDecode. 324 // The |state_| is still kPendingDecode.
346 DecodePendingBuffer(); 325 DecodePendingBuffer();
347 return; 326 return;
348 } 327 }
349 328
350 state_ = kWaitingForKey; 329 state_ = kWaitingForKey;
351 return; 330 return;
352 } 331 }
353 332
354 // The buffer has been accepted by the decoder, let's report statistics. 333 // The buffer has been accepted by the decoder, let's report statistics.
355 if (buffer_size) { 334 if (buffer_size) {
356 PipelineStatistics statistics; 335 PipelineStatistics statistics;
357 statistics.video_bytes_decoded = buffer_size; 336 statistics.audio_bytes_decoded = buffer_size;
358 statistics_cb_.Run(statistics); 337 statistics_cb_.Run(statistics);
359 } 338 }
360 339
361 if (status == Decryptor::kNeedMoreData) { 340 if (status == Decryptor::kNeedMoreData) {
362 DCHECK(!frame); 341 DCHECK(frames.empty());
363 state_ = kPendingDemuxerRead; 342 state_ = kPendingDemuxerRead;
364 ReadFromDemuxerStream(); 343 ReadFromDemuxerStream();
365 return; 344 return;
366 } 345 }
367 346
368 DCHECK_EQ(status, Decryptor::kSuccess); 347 DCHECK_EQ(status, Decryptor::kSuccess);
369 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; 348
370 base::ResetAndReturn(&read_cb_).Run(kOk, frame); 349 DCHECK(!frames.empty());
350 queued_audio_frames_ = frames;
351
352 scoped_refptr<Buffer> first_frame = queued_audio_frames_.front();
353 queued_audio_frames_.pop_front();
354 state_ = first_frame->IsEndOfStream() ? kDecodeFinished : kIdle;
355 base::ResetAndReturn(&read_cb_).Run(kOk, first_frame);
371 } 356 }
372 357
373 void DecryptingVideoDecoder::OnKeyAdded() { 358 void DecryptingAudioDecoder::OnKeyAdded() {
374 DVLOG(2) << "OnKeyAdded()";
375 DCHECK(message_loop_->BelongsToCurrentThread()); 359 DCHECK(message_loop_->BelongsToCurrentThread());
376 360
377 if (state_ == kPendingDecode) { 361 if (state_ == kPendingDecode) {
378 key_added_while_pending_decode_ = true; 362 key_added_while_pending_decode_ = true;
379 return; 363 return;
380 } 364 }
381 365
382 if (state_ == kWaitingForKey) { 366 if (state_ == kWaitingForKey) {
383 state_ = kPendingDecode; 367 state_ = kPendingDecode;
384 DecodePendingBuffer(); 368 DecodePendingBuffer();
385 } 369 }
386 } 370 }
387 371
388 void DecryptingVideoDecoder::DoReset() { 372 void DecryptingAudioDecoder::DoReset() {
389 DCHECK(init_cb_.is_null()); 373 DCHECK(init_cb_.is_null());
390 DCHECK(read_cb_.is_null()); 374 DCHECK(read_cb_.is_null());
391 state_ = kIdle; 375 state_ = kIdle;
392 base::ResetAndReturn(&reset_cb_).Run(); 376 base::ResetAndReturn(&reset_cb_).Run();
393 } 377 }
394 378
395 } // namespace media 379 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decrypting_audio_decoder.h ('k') | media/filters/decrypting_audio_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698