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() { |
| 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 |
OLD | NEW |