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

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: Add unittests 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) {
32 } 33 }
33 34
34 void DecryptingVideoDecoder::Initialize( 35 void DecryptingAudioDecoder::Initialize(
35 const scoped_refptr<DemuxerStream>& stream, 36 const scoped_refptr<DemuxerStream>& stream,
36 const PipelineStatusCB& status_cb, 37 const PipelineStatusCB& status_cb,
37 const StatisticsCB& statistics_cb) { 38 const StatisticsCB& statistics_cb) {
38 DCHECK(!message_loop_); 39 DCHECK(!message_loop_);
39 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run(); 40 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run();
40 message_loop_->PostTask(FROM_HERE, base::Bind( 41 message_loop_->PostTask(FROM_HERE, base::Bind(
41 &DecryptingVideoDecoder::DoInitialize, this, 42 &DecryptingAudioDecoder::DoInitialize, this,
42 stream, status_cb, statistics_cb)); 43 stream, status_cb, statistics_cb));
43 } 44 }
44 45
45 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { 46 void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
46 // Complete operation asynchronously on different stack of execution as per 47 // Complete operation asynchronously on different stack of execution as per
47 // the API contract of VideoDecoder::Read() 48 // the API contract of AudioDecoder::Read()
48 message_loop_->PostTask(FROM_HERE, base::Bind( 49 message_loop_->PostTask(FROM_HERE, base::Bind(
49 &DecryptingVideoDecoder::DoRead, this, read_cb)); 50 &DecryptingAudioDecoder::DoRead, this, read_cb));
50 } 51 }
51 52
52 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { 53 void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
53 if (!message_loop_->BelongsToCurrentThread()) { 54 if (!message_loop_->BelongsToCurrentThread()) {
54 message_loop_->PostTask(FROM_HERE, base::Bind( 55 message_loop_->PostTask(FROM_HERE, base::Bind(
55 &DecryptingVideoDecoder::Reset, this, closure)); 56 &DecryptingAudioDecoder::Reset, this, closure));
56 return; 57 return;
57 } 58 }
58 59
59 DVLOG(2) << "Reset() - state: " << state_; 60 DVLOG(2) << "Reset() - state: " << state_;
60 DCHECK(state_ == kIdle || 61 DCHECK(state_ == kIdle ||
61 state_ == kPendingDemuxerRead || 62 state_ == kPendingDemuxerRead ||
62 state_ == kPendingDecode || 63 state_ == kPendingDecode ||
63 state_ == kWaitingForKey || 64 state_ == kWaitingForKey ||
64 state_ == kDecodeFinished) << state_; 65 state_ == kDecodeFinished) << state_;
65 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. 66 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
66 DCHECK(stop_cb_.is_null()); // No Reset() during pending Stop(). 67 DCHECK(stop_cb_.is_null()); // No Reset() during pending Stop().
67 DCHECK(reset_cb_.is_null()); 68 DCHECK(reset_cb_.is_null());
68 69
69 reset_cb_ = closure; 70 reset_cb_ = closure;
70 71
71 decryptor_->ResetDecoder(Decryptor::kVideo); 72 decryptor_->ResetDecoder(Decryptor::kAudio);
72 73
73 // Reset() cannot complete if the read callback is still pending. 74 // Reset() cannot complete if the read callback is still pending.
74 // Defer the resetting process in this case. The |reset_cb_| will be fired 75 // Defer the resetting process in this case. The |reset_cb_| will be fired
75 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and 76 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and
76 // DoDeliverFrame(). 77 // DoDeliverFrame().
77 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { 78 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) {
78 DCHECK(!read_cb_.is_null()); 79 DCHECK(!read_cb_.is_null());
79 return; 80 return;
80 } 81 }
81 82
82 if (state_ == kWaitingForKey) { 83 if (state_ == kWaitingForKey) {
83 DCHECK(!read_cb_.is_null()); 84 DCHECK(!read_cb_.is_null());
84 pending_buffer_to_decode_ = NULL; 85 pending_buffer_to_decode_ = NULL;
85 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 86 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
86 } 87 }
87 88
88 DCHECK(read_cb_.is_null()); 89 DCHECK(read_cb_.is_null());
89 DoReset(); 90 DoReset();
90 } 91 }
91 92
92 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { 93 int DecryptingAudioDecoder::bits_per_channel() {
94 return bits_per_channel_;
95 }
96
97 ChannelLayout DecryptingAudioDecoder::channel_layout() {
98 return channel_layout_;
99 }
100
101 int DecryptingAudioDecoder::samples_per_second() {
102 return samples_per_second_;
103 }
104
105 void DecryptingAudioDecoder::Stop(const base::Closure& closure) {
xhwang 2012/10/18 02:14:10 If we decided to have Stop(), this needs to be cha
93 if (!message_loop_->BelongsToCurrentThread()) { 106 if (!message_loop_->BelongsToCurrentThread()) {
94 message_loop_->PostTask(FROM_HERE, base::Bind( 107 message_loop_->PostTask(FROM_HERE, base::Bind(
95 &DecryptingVideoDecoder::Stop, this, closure)); 108 &DecryptingAudioDecoder::Stop, this, closure));
96 return; 109 return;
97 } 110 }
98 111
99 DVLOG(2) << "Stop() - state: " << state_; 112 DVLOG(2) << "Stop() - state: " << state_;
100 DCHECK(stop_cb_.is_null()); 113 DCHECK(stop_cb_.is_null());
101 stop_cb_ = closure; 114 stop_cb_ = closure;
102 115
103 // We need to call Decryptor::DeinitializeDecoder(Decryptor::kVideo) if we 116 // We need to call Decryptor::DeinitializeDecoder(Decryptor::kAudio) if we
104 // ever called Decryptor::InitializeVideoDecoder() to cancel the pending 117 // ever called Decryptor::InitializeAudioDecoder() to cancel the pending
105 // initialization if the initialization is still pending, or to stop the video 118 // initialization if the initialization is still pending, or to stop the
106 // decoder if the initialization has completed. 119 // audio decoder if the initialization has completed.
107 // When the state is kUninitialized and kDecryptorRequested, 120 // When the state is kUninitialized and kDecryptorRequested,
108 // InitializeVideoDecoder() has not been called, so we are okay. 121 // InitializeAudioDecoder() has not been called, so we are okay.
109 // When the state is kStopped, the video decoder should have already been 122 // When the state is kStopped, the audio decoder should have already been
110 // stopped, so no need to call DeinitializeDecoder(Decryptor::kVideo) either. 123 // stopped, so no need to call DeinitializeDecoder(Decryptor::kAudio) either.
111 // In all other cases, we need to call DeinitializeDecoder(Decryptor::kVideo)! 124 // In all other cases, we need to call DeinitializeDecoder(Decryptor::kAudio)!
112 switch (state_) { 125 switch (state_) {
113 case kUninitialized: 126 case kUninitialized:
114 case kStopped: 127 case kStopped:
115 DoStop(); 128 DoStop();
116 break; 129 break;
117 case kDecryptorRequested: 130 case kDecryptorRequested:
118 // Stop() cannot complete if the decryptor request is still pending. 131 // Stop() cannot complete if the decryptor request is still pending.
119 // Defer the stopping process in this case. The |stop_cb_| will be fired 132 // Defer the stopping process in this case. The |stop_cb_| will be fired
120 // after the request decryptor callback is fired - see SetDecryptor(). 133 // after the request decryptor callback is fired - see SetDecryptor().
121 request_decryptor_notification_cb_.Run(DecryptorNotificationCB()); 134 request_decryptor_notification_cb_.Run(DecryptorNotificationCB());
122 break; 135 break;
123 case kIdle: 136 case kIdle:
124 case kDecodeFinished: 137 case kDecodeFinished:
125 decryptor_->DeinitializeDecoder(Decryptor::kVideo); 138 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
126 DoStop(); 139 DoStop();
127 break; 140 break;
128 case kWaitingForKey: 141 case kWaitingForKey:
129 decryptor_->DeinitializeDecoder(Decryptor::kVideo); 142 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
130 DCHECK(!read_cb_.is_null()); 143 DCHECK(!read_cb_.is_null());
131 pending_buffer_to_decode_ = NULL; 144 pending_buffer_to_decode_ = NULL;
132 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 145 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
133 DoStop(); 146 DoStop();
134 break; 147 break;
135 case kPendingDecoderInit: 148 case kPendingDecoderInit:
136 case kPendingDemuxerRead: 149 case kPendingDemuxerRead:
137 case kPendingDecode: 150 case kPendingDecode:
138 // Stop() cannot complete if the init or read callback is still pending. 151 // Stop() cannot complete if the init or read callback is still pending.
139 // Defer the stopping process in these cases. The |stop_cb_| will be 152 // Defer the stopping process in these cases. The |stop_cb_| will be
140 // fired after the init or read callback is fired - see 153 // fired after the init or read callback is fired - see
141 // FinishInitialization(), DoDecryptAndDecodeBuffer() and 154 // FinishInitialization(), DoDecryptAndDecodeBuffer() and
142 // DoDeliverFrame(), respectively. 155 // DoDeliverFrame(), respectively.
143 decryptor_->DeinitializeDecoder(Decryptor::kVideo); 156 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
144 DCHECK(!init_cb_.is_null() || !read_cb_.is_null()); 157 DCHECK(!init_cb_.is_null() || !read_cb_.is_null());
145 break; 158 break;
146 default: 159 default:
147 NOTREACHED(); 160 NOTREACHED();
148 } 161 }
149 } 162 }
150 163
151 DecryptingVideoDecoder::~DecryptingVideoDecoder() { 164 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
152 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; 165 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
153 } 166 }
154 167
155 void DecryptingVideoDecoder::DoInitialize( 168 void DecryptingAudioDecoder::DoInitialize(
156 const scoped_refptr<DemuxerStream>& stream, 169 const scoped_refptr<DemuxerStream>& stream,
157 const PipelineStatusCB& status_cb, 170 const PipelineStatusCB& status_cb,
158 const StatisticsCB& statistics_cb) { 171 const StatisticsCB& statistics_cb) {
159 DVLOG(2) << "DoInitialize()";
160 DCHECK(message_loop_->BelongsToCurrentThread()); 172 DCHECK(message_loop_->BelongsToCurrentThread());
161 DCHECK_EQ(state_, kUninitialized) << state_; 173 DCHECK_EQ(state_, kUninitialized) << state_;
162 DCHECK(stream); 174 DCHECK(stream);
163 175
164 const VideoDecoderConfig& config = stream->video_decoder_config(); 176 const AudioDecoderConfig& config = stream->audio_decoder_config();
165 if (!config.IsValidConfig()) { 177 if (!config.IsValidConfig()) {
166 DLOG(ERROR) << "Invalid video stream config: " 178 DLOG(ERROR) << "Invalid audio stream config.";
167 << config.AsHumanReadableString();
168 status_cb.Run(PIPELINE_ERROR_DECODE); 179 status_cb.Run(PIPELINE_ERROR_DECODE);
169 return; 180 return;
170 } 181 }
171 182
172 // DecryptingVideoDecoder only accepts potentially encrypted stream. 183 // DecryptingAudioDecoder only accepts potentially encrypted stream.
173 if (!config.is_encrypted()) { 184 if (!config.is_encrypted()) {
174 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 185 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
175 return; 186 return;
176 } 187 }
177 188
178 DCHECK(!demuxer_stream_); 189 DCHECK(!demuxer_stream_);
179 demuxer_stream_ = stream; 190 demuxer_stream_ = stream;
180 statistics_cb_ = statistics_cb; 191 statistics_cb_ = statistics_cb;
181 192
182 init_cb_ = status_cb; 193 init_cb_ = status_cb;
183 194
184 state_ = kDecryptorRequested; 195 state_ = kDecryptorRequested;
185 request_decryptor_notification_cb_.Run( 196 request_decryptor_notification_cb_.Run(
186 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor)); 197 BIND_TO_LOOP(&DecryptingAudioDecoder::SetDecryptor));
187 } 198 }
188 199
189 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { 200 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
190 DVLOG(2) << "SetDecryptor()"; 201 DVLOG(2) << "SetDecryptor()";
191 DCHECK(message_loop_->BelongsToCurrentThread()); 202 DCHECK(message_loop_->BelongsToCurrentThread());
192 DCHECK_EQ(state_, kDecryptorRequested) << state_; 203 DCHECK_EQ(state_, kDecryptorRequested) << state_;
193 DCHECK(!init_cb_.is_null()); 204 DCHECK(!init_cb_.is_null());
194 205
195 if (!stop_cb_.is_null()) { 206 if (!stop_cb_.is_null()) {
196 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 207 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
197 DoStop(); 208 DoStop();
198 return; 209 return;
199 } 210 }
200 211
201 decryptor_ = decryptor; 212 decryptor_ = decryptor;
202 213
203 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); 214 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
204 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); 215 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config());
205 216
206 state_ = kPendingDecoderInit; 217 state_ = kPendingDecoderInit;
207 decryptor_->InitializeVideoDecoder( 218 decryptor_->InitializeAudioDecoder(
208 scoped_config.Pass(), 219 scoped_config.Pass(),
209 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), 220 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization),
210 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); 221 BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded));
211 } 222 }
212 223
213 void DecryptingVideoDecoder::FinishInitialization(bool success) { 224 void DecryptingAudioDecoder::FinishInitialization(bool success) {
214 DVLOG(2) << "FinishInitialization()";
215 DCHECK(message_loop_->BelongsToCurrentThread()); 225 DCHECK(message_loop_->BelongsToCurrentThread());
216 DCHECK_EQ(state_, kPendingDecoderInit) << state_; 226 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
217 DCHECK(!init_cb_.is_null()); 227 DCHECK(!init_cb_.is_null());
218 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. 228 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
219 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. 229 DCHECK(read_cb_.is_null()); // No Read() before initialization finished.
220 230
221 if (!stop_cb_.is_null()) { 231 if (!stop_cb_.is_null()) {
222 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 232 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
223 DoStop(); 233 DoStop();
224 return; 234 return;
225 } 235 }
226 236
227 if (!success) { 237 if (!success) {
228 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 238 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
229 state_ = kStopped; 239 state_ = kStopped;
230 return; 240 return;
231 } 241 }
232 242
233 // Success! 243 // Success!
244 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config();
245 bits_per_channel_ = config.bits_per_channel();
246 channel_layout_ = config.channel_layout();
247 samples_per_second_ = config.samples_per_second();
234 state_ = kIdle; 248 state_ = kIdle;
235 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 249 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
236 } 250 }
237 251
238 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { 252 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) {
239 DVLOG(3) << "DoRead()"; 253 DVLOG(3) << "DoRead()";
240 DCHECK(message_loop_->BelongsToCurrentThread()); 254 DCHECK(message_loop_->BelongsToCurrentThread());
241 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; 255 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
242 DCHECK(!read_cb.is_null()); 256 DCHECK(!read_cb.is_null());
243 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 257 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
244 258
245 // Return empty frames if decoding has finished. 259 // Return empty (end-of-stream) frames if decoding has finished.
246 if (state_ == kDecodeFinished) { 260 if (state_ == kDecodeFinished) {
247 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); 261 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0)));
248 return; 262 return;
249 } 263 }
250 264
265 if (!queued_audio_frames_.empty()) {
266 if (queued_audio_frames_.front()->IsEndOfStream())
267 state_ = kDecodeFinished;
268 read_cb.Run(kOk, queued_audio_frames_.front());
269 queued_audio_frames_.pop_front();
270 return;
271 }
272
251 read_cb_ = read_cb; 273 read_cb_ = read_cb;
252 state_ = kPendingDemuxerRead; 274 state_ = kPendingDemuxerRead;
253 ReadFromDemuxerStream(); 275 ReadFromDemuxerStream();
254 } 276 }
255 277
256 void DecryptingVideoDecoder::ReadFromDemuxerStream() { 278 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
257 DCHECK(message_loop_->BelongsToCurrentThread()); 279 DCHECK(message_loop_->BelongsToCurrentThread());
258 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 280 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
259 DCHECK(!read_cb_.is_null()); 281 DCHECK(!read_cb_.is_null());
260 282
261 demuxer_stream_->Read( 283 demuxer_stream_->Read(
262 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); 284 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this));
263 } 285 }
264 286
265 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( 287 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
266 DemuxerStream::Status status, 288 DemuxerStream::Status status,
267 const scoped_refptr<DecoderBuffer>& buffer) { 289 const scoped_refptr<DecoderBuffer>& buffer) {
268 // In theory, we don't need to force post the task here, because we do a 290 // In theory, we don't need to force post the task here, because we do a
269 // force task post in DeliverFrame(). Therefore, even if 291 // force task post in DeliverFrame(). Therefore, even if
270 // demuxer_stream_->Read() execute the read callback on the same execution 292 // demuxer_stream_->Read() execute the read callback on the same execution
271 // stack we are still fine. But it looks like a force post task makes the 293 // stack we are still fine. But it looks like a force post task makes the
272 // logic more understandable and manageable, so why not? 294 // logic more understandable and manageable, so why not?
273 message_loop_->PostTask(FROM_HERE, base::Bind( 295 message_loop_->PostTask(FROM_HERE, base::Bind(
274 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); 296 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer));
275 } 297 }
276 298
277 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( 299 void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer(
278 DemuxerStream::Status status, 300 DemuxerStream::Status status,
279 const scoped_refptr<DecoderBuffer>& buffer) { 301 const scoped_refptr<DecoderBuffer>& buffer) {
280 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; 302 DVLOG(3) << "DoDecryptAndDecodeBuffer()";
281 DCHECK(message_loop_->BelongsToCurrentThread()); 303 DCHECK(message_loop_->BelongsToCurrentThread());
282 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 304 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
283 DCHECK(!read_cb_.is_null()); 305 DCHECK(!read_cb_.is_null());
284 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; 306 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;
285 307
286 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { 308 if (!reset_cb_.is_null() || !stop_cb_.is_null()) {
287 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 309 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
288 if (!reset_cb_.is_null()) 310 if (!reset_cb_.is_null())
289 DoReset(); 311 DoReset();
290 if (!stop_cb_.is_null()) 312 if (!stop_cb_.is_null())
291 DoStop(); 313 DoStop();
292 return; 314 return;
293 } 315 }
294 316
295 if (status == DemuxerStream::kAborted) { 317 if (status == DemuxerStream::kAborted) {
296 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; 318 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted";
297 state_ = kIdle; 319 state_ = kIdle;
298 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 320 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
299 return; 321 return;
300 } 322 }
301 323
302 if (status == DemuxerStream::kConfigChanged) { 324 if (status == DemuxerStream::kConfigChanged) {
303 // TODO(xhwang): Add config change support. 325 // TODO(xhwang): Add config change support.
304 // The |state_| is chosen to be kDecodeFinished here to be consistent with 326 // The |state_| is chosen to be kDecodeFinished here to be consistent with
305 // the implementation of FFmpegVideoDecoder. 327 // the implementation of FFmpegAudioDecoder.
306 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; 328 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";
307 state_ = kDecodeFinished; 329 state_ = kDecodeFinished;
308 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 330 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
309 return; 331 return;
310 } 332 }
311 333
312 DCHECK_EQ(status, DemuxerStream::kOk); 334 DCHECK_EQ(status, DemuxerStream::kOk);
313 pending_buffer_to_decode_ = buffer; 335 pending_buffer_to_decode_ = buffer;
314 state_ = kPendingDecode; 336 state_ = kPendingDecode;
315 DecodePendingBuffer(); 337 DecodePendingBuffer();
316 } 338 }
317 339
318 void DecryptingVideoDecoder::DecodePendingBuffer() { 340 void DecryptingAudioDecoder::DecodePendingBuffer() {
319 DCHECK(message_loop_->BelongsToCurrentThread()); 341 DCHECK(message_loop_->BelongsToCurrentThread());
320 DCHECK_EQ(state_, kPendingDecode) << state_; 342 DCHECK_EQ(state_, kPendingDecode) << state_;
321 decryptor_->DecryptAndDecodeVideo( 343 decryptor_->DecryptAndDecodeAudio(
322 pending_buffer_to_decode_, 344 pending_buffer_to_decode_,
323 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, 345 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this,
324 pending_buffer_to_decode_->GetDataSize())); 346 pending_buffer_to_decode_->GetDataSize()));
325 } 347 }
326 348
327 void DecryptingVideoDecoder::DeliverFrame( 349 void DecryptingAudioDecoder::DeliverFrame(
328 int buffer_size, 350 int buffer_size,
329 Decryptor::Status status, 351 Decryptor::Status status,
330 const scoped_refptr<VideoFrame>& frame) { 352 const Decryptor::AudioBuffers& frames) {
331 // We need to force task post here because the VideoDecodeCB can be executed 353 // We need to force task post here because the AudioDecodeCB can be executed
332 // synchronously in Reset()/Stop(). Instead of using more complicated logic in 354 // synchronously in Reset()/Stop(). Instead of using more complicated logic in
333 // those function to fix it, why not force task post here to make everything 355 // those function to fix it, why not force task post here to make everything
334 // simple and clear? 356 // simple and clear?
335 message_loop_->PostTask(FROM_HERE, base::Bind( 357 message_loop_->PostTask(FROM_HERE, base::Bind(
336 &DecryptingVideoDecoder::DoDeliverFrame, this, 358 &DecryptingAudioDecoder::DoDeliverFrame, this,
337 buffer_size, status, frame)); 359 buffer_size, status, frames));
338 } 360 }
339 361
340 void DecryptingVideoDecoder::DoDeliverFrame( 362 void DecryptingAudioDecoder::DoDeliverFrame(
341 int buffer_size, 363 int buffer_size,
342 Decryptor::Status status, 364 Decryptor::Status status,
343 const scoped_refptr<VideoFrame>& frame) { 365 const Decryptor::AudioBuffers& frames) {
344 DVLOG(3) << "DoDeliverFrame()"; 366 DVLOG(3) << "DoDeliverFrame()";
345 DCHECK(message_loop_->BelongsToCurrentThread()); 367 DCHECK(message_loop_->BelongsToCurrentThread());
346 DCHECK_EQ(state_, kPendingDecode) << state_; 368 DCHECK_EQ(state_, kPendingDecode) << state_;
347 DCHECK(!read_cb_.is_null()); 369 DCHECK(!read_cb_.is_null());
348 DCHECK(pending_buffer_to_decode_); 370 DCHECK(pending_buffer_to_decode_);
371 DCHECK(queued_audio_frames_.empty());
349 372
350 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; 373 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_;
351 key_added_while_pending_decode_ = false; 374 key_added_while_pending_decode_ = false;
352 375
353 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { 376 if (!reset_cb_.is_null() || !stop_cb_.is_null()) {
354 pending_buffer_to_decode_ = NULL; 377 pending_buffer_to_decode_ = NULL;
355 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 378 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
356 if (!reset_cb_.is_null()) 379 if (!reset_cb_.is_null())
357 DoReset(); 380 DoReset();
358 if (!stop_cb_.is_null()) 381 if (!stop_cb_.is_null())
359 DoStop(); 382 DoStop();
360 return; 383 return;
361 } 384 }
362 385
363 if (status == Decryptor::kError) { 386 if (status == Decryptor::kError) {
364 DCHECK(!frame); 387 DCHECK(frames.empty());
365 state_ = kDecodeFinished; 388 state_ = kDecodeFinished;
366 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 389 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
367 return; 390 return;
368 } 391 }
369 392
370 if (status == Decryptor::kNoKey) { 393 if (status == Decryptor::kNoKey) {
371 DCHECK(!frame); 394 DCHECK(frames.empty());
372 if (need_to_try_again_if_nokey_is_returned) { 395 if (need_to_try_again_if_nokey_is_returned) {
373 // The |state_| is still kPendingDecode. 396 // The |state_| is still kPendingDecode.
374 DecodePendingBuffer(); 397 DecodePendingBuffer();
375 return; 398 return;
376 } 399 }
377 400
378 state_ = kWaitingForKey; 401 state_ = kWaitingForKey;
379 return; 402 return;
380 } 403 }
381 404
382 // The buffer has been accepted by the decoder, let's report statistics. 405 // The buffer has been accepted by the decoder, let's report statistics.
383 if (buffer_size) { 406 if (buffer_size) {
384 PipelineStatistics statistics; 407 PipelineStatistics statistics;
385 statistics.video_bytes_decoded = buffer_size; 408 statistics.audio_bytes_decoded = buffer_size;
386 statistics_cb_.Run(statistics); 409 statistics_cb_.Run(statistics);
387 } 410 }
388 411
389 if (status == Decryptor::kNeedMoreData) { 412 if (status == Decryptor::kNeedMoreData) {
390 DCHECK(!frame); 413 DCHECK(frames.empty());
391 state_ = kPendingDemuxerRead; 414 state_ = kPendingDemuxerRead;
392 ReadFromDemuxerStream(); 415 ReadFromDemuxerStream();
393 return; 416 return;
394 } 417 }
395 418
396 DCHECK_EQ(status, Decryptor::kSuccess); 419 DCHECK_EQ(status, Decryptor::kSuccess);
397 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; 420
398 base::ResetAndReturn(&read_cb_).Run(kOk, frame); 421 DCHECK(!frames.empty());
422 queued_audio_frames_ = frames;
423
424 scoped_refptr<Buffer> first_frame = queued_audio_frames_.front();
425 queued_audio_frames_.pop_front();
426 state_ = first_frame->IsEndOfStream() ? kDecodeFinished : kIdle;
427 base::ResetAndReturn(&read_cb_).Run(kOk, first_frame);
399 } 428 }
400 429
401 void DecryptingVideoDecoder::OnKeyAdded() { 430 void DecryptingAudioDecoder::OnKeyAdded() {
402 DVLOG(2) << "OnKeyAdded()";
403 DCHECK(message_loop_->BelongsToCurrentThread()); 431 DCHECK(message_loop_->BelongsToCurrentThread());
404 432
405 if (state_ == kPendingDecode) { 433 if (state_ == kPendingDecode) {
406 key_added_while_pending_decode_ = true; 434 key_added_while_pending_decode_ = true;
407 return; 435 return;
408 } 436 }
409 437
410 if (state_ == kWaitingForKey) { 438 if (state_ == kWaitingForKey) {
411 state_ = kPendingDecode; 439 state_ = kPendingDecode;
412 DecodePendingBuffer(); 440 DecodePendingBuffer();
413 } 441 }
414 } 442 }
415 443
416 void DecryptingVideoDecoder::DoReset() { 444 void DecryptingAudioDecoder::DoReset() {
417 DCHECK(init_cb_.is_null()); 445 DCHECK(init_cb_.is_null());
418 DCHECK(read_cb_.is_null()); 446 DCHECK(read_cb_.is_null());
419 state_ = kIdle; 447 state_ = kIdle;
420 base::ResetAndReturn(&reset_cb_).Run(); 448 base::ResetAndReturn(&reset_cb_).Run();
421 } 449 }
422 450
423 void DecryptingVideoDecoder::DoStop() { 451 void DecryptingAudioDecoder::DoStop() {
424 DCHECK(init_cb_.is_null()); 452 DCHECK(init_cb_.is_null());
425 DCHECK(read_cb_.is_null()); 453 DCHECK(read_cb_.is_null());
426 state_ = kStopped; 454 state_ = kStopped;
427 base::ResetAndReturn(&stop_cb_).Run(); 455 base::ResetAndReturn(&stop_cb_).Run();
428 } 456 }
429 457
430 } // namespace media 458 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698