OLD | NEW |
---|---|
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 |
OLD | NEW |