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