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

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: Stop() removed. 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() {
scherkus (not reviewing) 2012/10/18 21:13:12 can't we still DCHECK for uninitialized?
xhwang 2012/10/18 22:49:08 ISTM dtor can happen in a lot of states now, e.g.
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());
148 DCHECK(!request_decryptor_notification_cb_.is_null());
168 149
150 request_decryptor_notification_cb_.Reset();
169 decryptor_ = decryptor; 151 decryptor_ = decryptor;
170 152
171 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); 153 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
172 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); 154 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config());
173 155
174 state_ = kPendingDecoderInit; 156 state_ = kPendingDecoderInit;
175 decryptor_->InitializeVideoDecoder( 157 decryptor_->InitializeAudioDecoder(
176 scoped_config.Pass(), 158 scoped_config.Pass(),
177 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), 159 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization),
178 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); 160 BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded));
179 } 161 }
180 162
181 void DecryptingVideoDecoder::FinishInitialization(bool success) { 163 void DecryptingAudioDecoder::FinishInitialization(bool success) {
182 DVLOG(2) << "FinishInitialization()"; 164 DVLOG(2) << "FinishInitialization()";
183 DCHECK(message_loop_->BelongsToCurrentThread()); 165 DCHECK(message_loop_->BelongsToCurrentThread());
184
185 if (state_ == kStopped)
186 return;
187
188 DCHECK_EQ(state_, kPendingDecoderInit) << state_; 166 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
189 DCHECK(!init_cb_.is_null()); 167 DCHECK(!init_cb_.is_null());
190 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. 168 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
191 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. 169 DCHECK(read_cb_.is_null()); // No Read() before initialization finished.
192 170
193 if (!success) { 171 if (!success) {
194 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 172 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
195 state_ = kStopped; 173 state_ = kDecodeFinished;
196 return; 174 return;
197 } 175 }
198 176
199 // 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();
200 state_ = kIdle; 182 state_ = kIdle;
201 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 183 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
202 } 184 }
203 185
204 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { 186 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) {
205 DVLOG(3) << "DoRead()"; 187 DVLOG(3) << "DoRead()";
206 DCHECK(message_loop_->BelongsToCurrentThread()); 188 DCHECK(message_loop_->BelongsToCurrentThread());
207 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; 189 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
208 DCHECK(!read_cb.is_null()); 190 DCHECK(!read_cb.is_null());
209 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 191 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
210 192
211 // Return empty frames if decoding has finished. 193 // Return empty (end-of-stream) frames if decoding has finished.
212 if (state_ == kDecodeFinished) { 194 if (state_ == kDecodeFinished) {
213 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); 195 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0)));
214 return; 196 return;
215 } 197 }
216 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
217 read_cb_ = read_cb; 207 read_cb_ = read_cb;
218 state_ = kPendingDemuxerRead; 208 state_ = kPendingDemuxerRead;
219 ReadFromDemuxerStream(); 209 ReadFromDemuxerStream();
220 } 210 }
221 211
222 void DecryptingVideoDecoder::ReadFromDemuxerStream() { 212 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
223 DCHECK(message_loop_->BelongsToCurrentThread()); 213 DCHECK(message_loop_->BelongsToCurrentThread());
224 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 214 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
225 DCHECK(!read_cb_.is_null()); 215 DCHECK(!read_cb_.is_null());
226 216
227 demuxer_stream_->Read( 217 demuxer_stream_->Read(
228 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); 218 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this));
229 } 219 }
230 220
231 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( 221 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
232 DemuxerStream::Status status, 222 DemuxerStream::Status status,
233 const scoped_refptr<DecoderBuffer>& buffer) { 223 const scoped_refptr<DecoderBuffer>& buffer) {
234 // 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
235 // force task post in DeliverFrame(). Therefore, even if 225 // force task post in DeliverFrame(). Therefore, even if
236 // demuxer_stream_->Read() execute the read callback on the same execution 226 // demuxer_stream_->Read() execute the read callback on the same execution
237 // 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
238 // logic more understandable and manageable, so why not? 228 // logic more understandable and manageable, so why not?
239 message_loop_->PostTask(FROM_HERE, base::Bind( 229 message_loop_->PostTask(FROM_HERE, base::Bind(
240 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); 230 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer));
241 } 231 }
242 232
243 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( 233 void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer(
244 DemuxerStream::Status status, 234 DemuxerStream::Status status,
245 const scoped_refptr<DecoderBuffer>& buffer) { 235 const scoped_refptr<DecoderBuffer>& buffer) {
246 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; 236 DVLOG(3) << "DoDecryptAndDecodeBuffer()";
247 DCHECK(message_loop_->BelongsToCurrentThread()); 237 DCHECK(message_loop_->BelongsToCurrentThread());
248
249 if (state_ == kStopped)
250 return;
251
252 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 238 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
253 DCHECK(!read_cb_.is_null()); 239 DCHECK(!read_cb_.is_null());
254 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; 240 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;
255 241
256 if (!reset_cb_.is_null()) { 242 if (!reset_cb_.is_null()) {
257 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 243 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
258 if (!reset_cb_.is_null()) 244 DoReset();
259 DoReset();
260 return; 245 return;
261 } 246 }
262 247
263 if (status == DemuxerStream::kAborted) { 248 if (status == DemuxerStream::kAborted) {
264 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; 249 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted";
265 state_ = kIdle; 250 state_ = kIdle;
266 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 251 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
267 return; 252 return;
268 } 253 }
269 254
270 if (status == DemuxerStream::kConfigChanged) { 255 if (status == DemuxerStream::kConfigChanged) {
271 // TODO(xhwang): Add config change support. 256 // TODO(xhwang): Add config change support.
272 // 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
273 // the implementation of FFmpegVideoDecoder. 258 // the implementation of FFmpegVideoDecoder.
274 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; 259 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";
275 state_ = kDecodeFinished; 260 state_ = kDecodeFinished;
276 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 261 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
277 return; 262 return;
278 } 263 }
279 264
280 DCHECK_EQ(status, DemuxerStream::kOk); 265 DCHECK_EQ(status, DemuxerStream::kOk);
281 pending_buffer_to_decode_ = buffer; 266 pending_buffer_to_decode_ = buffer;
282 state_ = kPendingDecode; 267 state_ = kPendingDecode;
283 DecodePendingBuffer(); 268 DecodePendingBuffer();
284 } 269 }
285 270
286 void DecryptingVideoDecoder::DecodePendingBuffer() { 271 void DecryptingAudioDecoder::DecodePendingBuffer() {
287 DCHECK(message_loop_->BelongsToCurrentThread()); 272 DCHECK(message_loop_->BelongsToCurrentThread());
288 DCHECK_EQ(state_, kPendingDecode) << state_; 273 DCHECK_EQ(state_, kPendingDecode) << state_;
289 decryptor_->DecryptAndDecodeVideo( 274 decryptor_->DecryptAndDecodeAudio(
290 pending_buffer_to_decode_, 275 pending_buffer_to_decode_,
291 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, 276 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this,
292 pending_buffer_to_decode_->GetDataSize())); 277 pending_buffer_to_decode_->GetDataSize()));
293 } 278 }
294 279
295 void DecryptingVideoDecoder::DeliverFrame( 280 void DecryptingAudioDecoder::DeliverFrame(
296 int buffer_size, 281 int buffer_size,
297 Decryptor::Status status, 282 Decryptor::Status status,
298 const scoped_refptr<VideoFrame>& frame) { 283 const Decryptor::AudioBuffers& frames) {
299 // 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
300 // synchronously in Reset()/Stop(). Instead of using more complicated logic in 285 // synchronously in Reset(). Instead of using more complicated logic in
301 // 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
302 // simple and clear? 287 // simple and clear?
303 message_loop_->PostTask(FROM_HERE, base::Bind( 288 message_loop_->PostTask(FROM_HERE, base::Bind(
304 &DecryptingVideoDecoder::DoDeliverFrame, this, 289 &DecryptingAudioDecoder::DoDeliverFrame, this,
305 buffer_size, status, frame)); 290 buffer_size, status, frames));
306 } 291 }
307 292
308 void DecryptingVideoDecoder::DoDeliverFrame( 293 void DecryptingAudioDecoder::DoDeliverFrame(
309 int buffer_size, 294 int buffer_size,
310 Decryptor::Status status, 295 Decryptor::Status status,
311 const scoped_refptr<VideoFrame>& frame) { 296 const Decryptor::AudioBuffers& frames) {
312 DVLOG(3) << "DoDeliverFrame()"; 297 DVLOG(3) << "DoDeliverFrame()";
313 DCHECK(message_loop_->BelongsToCurrentThread()); 298 DCHECK(message_loop_->BelongsToCurrentThread());
314
315 if (state_ == kStopped)
316 return;
317
318 DCHECK_EQ(state_, kPendingDecode) << state_; 299 DCHECK_EQ(state_, kPendingDecode) << state_;
319 DCHECK(!read_cb_.is_null()); 300 DCHECK(!read_cb_.is_null());
320 DCHECK(pending_buffer_to_decode_); 301 DCHECK(pending_buffer_to_decode_);
302 DCHECK(queued_audio_frames_.empty());
321 303
322 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_;
323 key_added_while_pending_decode_ = false; 305 key_added_while_pending_decode_ = false;
324 306
325 if (!reset_cb_.is_null()) { 307 if (!reset_cb_.is_null()) {
326 pending_buffer_to_decode_ = NULL; 308 pending_buffer_to_decode_ = NULL;
327 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 309 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
328 if (!reset_cb_.is_null()) 310 DoReset();
329 DoReset();
330 return; 311 return;
331 } 312 }
332 313
333 if (status == Decryptor::kError) { 314 if (status == Decryptor::kError) {
334 DCHECK(!frame); 315 DCHECK(frames.empty());
335 state_ = kDecodeFinished; 316 state_ = kDecodeFinished;
336 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 317 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
337 return; 318 return;
338 } 319 }
339 320
340 if (status == Decryptor::kNoKey) { 321 if (status == Decryptor::kNoKey) {
341 DCHECK(!frame); 322 DCHECK(frames.empty());
342 if (need_to_try_again_if_nokey_is_returned) { 323 if (need_to_try_again_if_nokey_is_returned) {
343 // The |state_| is still kPendingDecode. 324 // The |state_| is still kPendingDecode.
344 DecodePendingBuffer(); 325 DecodePendingBuffer();
345 return; 326 return;
346 } 327 }
347 328
348 state_ = kWaitingForKey; 329 state_ = kWaitingForKey;
349 return; 330 return;
350 } 331 }
351 332
352 // 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.
353 if (buffer_size) { 334 if (buffer_size) {
354 PipelineStatistics statistics; 335 PipelineStatistics statistics;
355 statistics.video_bytes_decoded = buffer_size; 336 statistics.audio_bytes_decoded = buffer_size;
356 statistics_cb_.Run(statistics); 337 statistics_cb_.Run(statistics);
357 } 338 }
358 339
359 if (status == Decryptor::kNeedMoreData) { 340 if (status == Decryptor::kNeedMoreData) {
360 DCHECK(!frame); 341 DCHECK(frames.empty());
361 state_ = kPendingDemuxerRead; 342 state_ = kPendingDemuxerRead;
362 ReadFromDemuxerStream(); 343 ReadFromDemuxerStream();
363 return; 344 return;
364 } 345 }
365 346
366 DCHECK_EQ(status, Decryptor::kSuccess); 347 DCHECK_EQ(status, Decryptor::kSuccess);
367 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; 348
368 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);
369 } 356 }
370 357
371 void DecryptingVideoDecoder::OnKeyAdded() { 358 void DecryptingAudioDecoder::OnKeyAdded() {
372 DVLOG(2) << "OnKeyAdded()";
373 DCHECK(message_loop_->BelongsToCurrentThread()); 359 DCHECK(message_loop_->BelongsToCurrentThread());
374 360
375 if (state_ == kPendingDecode) { 361 if (state_ == kPendingDecode) {
376 key_added_while_pending_decode_ = true; 362 key_added_while_pending_decode_ = true;
377 return; 363 return;
378 } 364 }
379 365
380 if (state_ == kWaitingForKey) { 366 if (state_ == kWaitingForKey) {
381 state_ = kPendingDecode; 367 state_ = kPendingDecode;
382 DecodePendingBuffer(); 368 DecodePendingBuffer();
383 } 369 }
384 } 370 }
385 371
386 void DecryptingVideoDecoder::DoReset() { 372 void DecryptingAudioDecoder::DoReset() {
387 DCHECK(init_cb_.is_null()); 373 DCHECK(init_cb_.is_null());
388 DCHECK(read_cb_.is_null()); 374 DCHECK(read_cb_.is_null());
389 state_ = kIdle; 375 state_ = kIdle;
390 base::ResetAndReturn(&reset_cb_).Run(); 376 base::ResetAndReturn(&reset_cb_).Run();
391 } 377 }
392 378
393 } // 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