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_video_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/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/message_loop/message_loop_proxy.h" | 12 #include "base/message_loop/message_loop_proxy.h" |
13 #include "media/base/bind_to_loop.h" | 13 #include "media/base/bind_to_loop.h" |
14 #include "media/base/decoder_buffer.h" | 14 #include "media/base/decoder_buffer.h" |
15 #include "media/base/decryptor.h" | 15 #include "media/base/decryptor.h" |
16 #include "media/base/demuxer_stream.h" | |
17 #include "media/base/pipeline.h" | 16 #include "media/base/pipeline.h" |
18 #include "media/base/video_decoder_config.h" | 17 #include "media/base/video_decoder_config.h" |
19 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
20 | 19 |
21 namespace media { | 20 namespace media { |
22 | 21 |
23 DecryptingVideoDecoder::DecryptingVideoDecoder( | 22 DecryptingVideoDecoder::DecryptingVideoDecoder( |
24 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 23 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
25 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 24 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
26 : message_loop_(message_loop), | 25 : message_loop_(message_loop), |
27 weak_factory_(this), | 26 weak_factory_(this), |
28 state_(kUninitialized), | 27 state_(kUninitialized), |
29 demuxer_stream_(NULL), | |
30 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 28 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
31 decryptor_(NULL), | 29 decryptor_(NULL), |
32 key_added_while_decode_pending_(false), | 30 key_added_while_decode_pending_(false), |
33 trace_id_(0) { | 31 trace_id_(0) { |
34 } | 32 } |
35 | 33 |
36 void DecryptingVideoDecoder::Initialize( | 34 void DecryptingVideoDecoder::Initialize( |
37 DemuxerStream* stream, | 35 const VideoDecoderConfig& config, |
38 const PipelineStatusCB& status_cb, | 36 const PipelineStatusCB& status_cb, |
39 const StatisticsCB& statistics_cb) { | 37 const StatisticsCB& statistics_cb) { |
40 DVLOG(2) << "Initialize()"; | 38 DVLOG(2) << "Initialize()"; |
41 DCHECK(message_loop_->BelongsToCurrentThread()); | 39 DCHECK(message_loop_->BelongsToCurrentThread()); |
42 DCHECK(state_ == kUninitialized || | 40 DCHECK(state_ == kUninitialized || |
43 state_ == kIdle || | 41 state_ == kIdle || |
44 state_ == kDecodeFinished) << state_; | 42 state_ == kDecodeFinished) << state_; |
45 DCHECK(read_cb_.is_null()); | 43 DCHECK(read_cb_.is_null()); |
46 DCHECK(reset_cb_.is_null()); | 44 DCHECK(reset_cb_.is_null()); |
47 DCHECK(stream); | 45 DCHECK(config.IsValidConfig()); |
| 46 DCHECK(config.is_encrypted()); |
48 | 47 |
49 init_cb_ = BindToCurrentLoop(status_cb); | 48 init_cb_ = BindToCurrentLoop(status_cb); |
50 weak_this_ = weak_factory_.GetWeakPtr(); | 49 weak_this_ = weak_factory_.GetWeakPtr(); |
51 demuxer_stream_ = stream; | 50 config_ = config; |
52 statistics_cb_ = statistics_cb; | 51 statistics_cb_ = statistics_cb; |
53 | 52 |
54 const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config(); | |
55 DCHECK(config.IsValidConfig()); | |
56 DCHECK(config.is_encrypted()); | |
57 | |
58 if (state_ == kUninitialized) { | 53 if (state_ == kUninitialized) { |
59 state_ = kDecryptorRequested; | 54 state_ = kDecryptorRequested; |
60 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( | 55 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( |
61 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); | 56 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); |
62 return; | 57 return; |
63 } | 58 } |
64 | 59 |
65 // Reinitialization. | 60 // Reinitialization. |
66 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 61 decryptor_->DeinitializeDecoder(Decryptor::kVideo); |
67 state_ = kPendingDecoderInit; | 62 state_ = kPendingDecoderInit; |
68 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind( | 63 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind( |
69 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); | 64 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); |
70 } | 65 } |
71 | 66 |
72 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { | 67 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
73 DVLOG(3) << "Read()"; | 68 const ReadCB& read_cb) { |
| 69 DVLOG(3) << "Decode()"; |
74 DCHECK(message_loop_->BelongsToCurrentThread()); | 70 DCHECK(message_loop_->BelongsToCurrentThread()); |
75 DCHECK(state_ == kIdle || | 71 DCHECK(state_ == kIdle || |
76 state_ == kDecodeFinished || | 72 state_ == kDecodeFinished || |
77 state_ == kError) << state_; | 73 state_ == kError) << state_; |
78 DCHECK(!read_cb.is_null()); | 74 DCHECK(!read_cb.is_null()); |
79 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 75 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 76 |
80 read_cb_ = BindToCurrentLoop(read_cb); | 77 read_cb_ = BindToCurrentLoop(read_cb); |
81 | 78 |
82 if (state_ == kError) { | 79 if (state_ == kError) { |
83 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 80 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
84 return; | 81 return; |
85 } | 82 } |
86 | 83 |
87 // Return empty frames if decoding has finished. | 84 // Return empty frames if decoding has finished. |
88 if (state_ == kDecodeFinished) { | 85 if (state_ == kDecodeFinished) { |
89 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); | 86 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); |
90 return; | 87 return; |
91 } | 88 } |
92 | 89 |
93 state_ = kPendingDemuxerRead; | 90 pending_buffer_to_decode_ = buffer; |
94 ReadFromDemuxerStream(); | 91 state_ = kPendingDecode; |
| 92 DecodePendingBuffer(); |
95 } | 93 } |
96 | 94 |
97 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { | 95 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { |
98 DVLOG(2) << "Reset() - state: " << state_; | 96 DVLOG(2) << "Reset() - state: " << state_; |
99 DCHECK(message_loop_->BelongsToCurrentThread()); | 97 DCHECK(message_loop_->BelongsToCurrentThread()); |
100 DCHECK(state_ == kIdle || | 98 DCHECK(state_ == kIdle || |
101 state_ == kPendingDemuxerRead || | |
102 state_ == kPendingDecode || | 99 state_ == kPendingDecode || |
103 state_ == kWaitingForKey || | 100 state_ == kWaitingForKey || |
104 state_ == kDecodeFinished || | 101 state_ == kDecodeFinished || |
105 state_ == kError) << state_; | 102 state_ == kError) << state_; |
106 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 103 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
107 DCHECK(reset_cb_.is_null()); | 104 DCHECK(reset_cb_.is_null()); |
108 | 105 |
109 reset_cb_ = BindToCurrentLoop(closure); | 106 reset_cb_ = BindToCurrentLoop(closure); |
110 | 107 |
111 decryptor_->ResetDecoder(Decryptor::kVideo); | 108 decryptor_->ResetDecoder(Decryptor::kVideo); |
112 | 109 |
113 // Reset() cannot complete if the read callback is still pending. | 110 // Reset() cannot complete if the read callback is still pending. |
114 // Defer the resetting process in this case. The |reset_cb_| will be fired | 111 // Defer the resetting process in this case. The |reset_cb_| will be fired |
115 // after the read callback is fired - see DecryptAndDecodeBuffer() and | 112 // after the read callback is fired - see DecryptAndDecodeBuffer() and |
116 // DeliverFrame(). | 113 // DeliverFrame(). |
117 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { | 114 if (state_ == kPendingDecode) { |
118 DCHECK(!read_cb_.is_null()); | 115 DCHECK(!read_cb_.is_null()); |
119 return; | 116 return; |
120 } | 117 } |
121 | 118 |
122 if (state_ == kWaitingForKey) { | 119 if (state_ == kWaitingForKey) { |
123 DCHECK(!read_cb_.is_null()); | 120 DCHECK(!read_cb_.is_null()); |
124 pending_buffer_to_decode_ = NULL; | 121 pending_buffer_to_decode_ = NULL; |
125 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 122 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
126 } | 123 } |
127 | 124 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 if (!decryptor) { | 171 if (!decryptor) { |
175 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 172 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
176 state_ = kStopped; | 173 state_ = kStopped; |
177 return; | 174 return; |
178 } | 175 } |
179 | 176 |
180 decryptor_ = decryptor; | 177 decryptor_ = decryptor; |
181 | 178 |
182 state_ = kPendingDecoderInit; | 179 state_ = kPendingDecoderInit; |
183 decryptor_->InitializeVideoDecoder( | 180 decryptor_->InitializeVideoDecoder( |
184 demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( | 181 config_, |
| 182 BindToCurrentLoop(base::Bind( |
185 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); | 183 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); |
186 } | 184 } |
187 | 185 |
188 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 186 void DecryptingVideoDecoder::FinishInitialization(bool success) { |
189 DVLOG(2) << "FinishInitialization()"; | 187 DVLOG(2) << "FinishInitialization()"; |
190 DCHECK(message_loop_->BelongsToCurrentThread()); | 188 DCHECK(message_loop_->BelongsToCurrentThread()); |
191 | 189 |
192 if (state_ == kStopped) | 190 if (state_ == kStopped) |
193 return; | 191 return; |
194 | 192 |
195 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 193 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
196 DCHECK(!init_cb_.is_null()); | 194 DCHECK(!init_cb_.is_null()); |
197 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 195 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
198 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 196 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
199 | 197 |
200 if (!success) { | 198 if (!success) { |
201 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 199 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
202 state_ = kStopped; | 200 state_ = kStopped; |
203 return; | 201 return; |
204 } | 202 } |
205 | 203 |
206 decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( | 204 decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( |
207 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); | 205 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); |
208 | 206 |
209 // Success! | 207 // Success! |
210 state_ = kIdle; | 208 state_ = kIdle; |
211 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 209 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
212 } | 210 } |
213 | 211 |
214 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | |
215 DCHECK(message_loop_->BelongsToCurrentThread()); | |
216 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | |
217 DCHECK(!read_cb_.is_null()); | |
218 | |
219 demuxer_stream_->Read( | |
220 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, weak_this_)); | |
221 } | |
222 | |
223 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( | |
224 DemuxerStream::Status status, | |
225 const scoped_refptr<DecoderBuffer>& buffer) { | |
226 DVLOG(3) << "DecryptAndDecodeBuffer()"; | |
227 DCHECK(message_loop_->BelongsToCurrentThread()); | |
228 | |
229 if (state_ == kStopped) | |
230 return; | |
231 | |
232 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | |
233 DCHECK(!read_cb_.is_null()); | |
234 DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; | |
235 | |
236 if (!reset_cb_.is_null()) { | |
237 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | |
238 DoReset(); | |
239 return; | |
240 } | |
241 | |
242 if (status == DemuxerStream::kAborted) { | |
243 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted"; | |
244 state_ = kIdle; | |
245 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | |
246 return; | |
247 } | |
248 | |
249 // VideoFrameStream ensures no kConfigChanged is passed to VideoDecoders. | |
250 DCHECK_EQ(status, DemuxerStream::kOk) << status; | |
251 pending_buffer_to_decode_ = buffer; | |
252 state_ = kPendingDecode; | |
253 DecodePendingBuffer(); | |
254 } | |
255 | 212 |
256 void DecryptingVideoDecoder::DecodePendingBuffer() { | 213 void DecryptingVideoDecoder::DecodePendingBuffer() { |
257 DCHECK(message_loop_->BelongsToCurrentThread()); | 214 DCHECK(message_loop_->BelongsToCurrentThread()); |
258 DCHECK_EQ(state_, kPendingDecode) << state_; | 215 DCHECK_EQ(state_, kPendingDecode) << state_; |
259 TRACE_EVENT_ASYNC_BEGIN0( | 216 TRACE_EVENT_ASYNC_BEGIN0( |
260 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); | 217 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); |
261 | 218 |
262 int buffer_size = 0; | 219 int buffer_size = 0; |
263 if (!pending_buffer_to_decode_->IsEndOfStream()) { | 220 if (!pending_buffer_to_decode_->IsEndOfStream()) { |
264 buffer_size = pending_buffer_to_decode_->GetDataSize(); | 221 buffer_size = pending_buffer_to_decode_->GetDataSize(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 | 289 |
333 if (status == Decryptor::kNeedMoreData) { | 290 if (status == Decryptor::kNeedMoreData) { |
334 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; | 291 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; |
335 if (scoped_pending_buffer_to_decode->IsEndOfStream()) { | 292 if (scoped_pending_buffer_to_decode->IsEndOfStream()) { |
336 state_ = kDecodeFinished; | 293 state_ = kDecodeFinished; |
337 base::ResetAndReturn(&read_cb_).Run( | 294 base::ResetAndReturn(&read_cb_).Run( |
338 kOk, media::VideoFrame::CreateEmptyFrame()); | 295 kOk, media::VideoFrame::CreateEmptyFrame()); |
339 return; | 296 return; |
340 } | 297 } |
341 | 298 |
342 state_ = kPendingDemuxerRead; | 299 state_ = kIdle; |
343 ReadFromDemuxerStream(); | 300 base::ResetAndReturn(&read_cb_).Run(kNotEnoughData, NULL); |
344 return; | 301 return; |
345 } | 302 } |
346 | 303 |
347 DCHECK_EQ(status, Decryptor::kSuccess); | 304 DCHECK_EQ(status, Decryptor::kSuccess); |
348 // No frame returned with kSuccess should be end-of-stream frame. | 305 // No frame returned with kSuccess should be end-of-stream frame. |
349 DCHECK(!frame->IsEndOfStream()); | 306 DCHECK(!frame->IsEndOfStream()); |
350 state_ = kIdle; | 307 state_ = kIdle; |
351 base::ResetAndReturn(&read_cb_).Run(kOk, frame); | 308 base::ResetAndReturn(&read_cb_).Run(kOk, frame); |
352 } | 309 } |
353 | 310 |
(...skipping 13 matching lines...) Expand all Loading... |
367 } | 324 } |
368 | 325 |
369 void DecryptingVideoDecoder::DoReset() { | 326 void DecryptingVideoDecoder::DoReset() { |
370 DCHECK(init_cb_.is_null()); | 327 DCHECK(init_cb_.is_null()); |
371 DCHECK(read_cb_.is_null()); | 328 DCHECK(read_cb_.is_null()); |
372 state_ = kIdle; | 329 state_ = kIdle; |
373 base::ResetAndReturn(&reset_cb_).Run(); | 330 base::ResetAndReturn(&reset_cb_).Run(); |
374 } | 331 } |
375 | 332 |
376 } // namespace media | 333 } // namespace media |
OLD | NEW |