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_proxy.h" | 12 #include "base/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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 | 165 |
169 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 166 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
170 DCHECK(!init_cb_.is_null()); | 167 DCHECK(!init_cb_.is_null()); |
171 DCHECK(!set_decryptor_ready_cb_.is_null()); | 168 DCHECK(!set_decryptor_ready_cb_.is_null()); |
172 set_decryptor_ready_cb_.Reset(); | 169 set_decryptor_ready_cb_.Reset(); |
173 | 170 |
174 decryptor_ = decryptor; | 171 decryptor_ = decryptor; |
175 | 172 |
176 state_ = kPendingDecoderInit; | 173 state_ = kPendingDecoderInit; |
177 decryptor_->InitializeVideoDecoder( | 174 decryptor_->InitializeVideoDecoder( |
178 demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( | 175 config_, |
| 176 BindToCurrentLoop(base::Bind( |
179 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); | 177 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); |
180 } | 178 } |
181 | 179 |
182 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 180 void DecryptingVideoDecoder::FinishInitialization(bool success) { |
183 DVLOG(2) << "FinishInitialization()"; | 181 DVLOG(2) << "FinishInitialization()"; |
184 DCHECK(message_loop_->BelongsToCurrentThread()); | 182 DCHECK(message_loop_->BelongsToCurrentThread()); |
185 | 183 |
186 if (state_ == kStopped) | 184 if (state_ == kStopped) |
187 return; | 185 return; |
188 | 186 |
189 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 187 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
190 DCHECK(!init_cb_.is_null()); | 188 DCHECK(!init_cb_.is_null()); |
191 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 189 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
192 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 190 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
193 | 191 |
194 if (!success) { | 192 if (!success) { |
195 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 193 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
196 state_ = kStopped; | 194 state_ = kStopped; |
197 return; | 195 return; |
198 } | 196 } |
199 | 197 |
200 decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( | 198 decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( |
201 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); | 199 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); |
202 | 200 |
203 // Success! | 201 // Success! |
204 state_ = kIdle; | 202 state_ = kIdle; |
205 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 203 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
206 } | 204 } |
207 | 205 |
208 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | |
209 DCHECK(message_loop_->BelongsToCurrentThread()); | |
210 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | |
211 DCHECK(!read_cb_.is_null()); | |
212 | |
213 demuxer_stream_->Read( | |
214 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, weak_this_)); | |
215 } | |
216 | |
217 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( | |
218 DemuxerStream::Status status, | |
219 const scoped_refptr<DecoderBuffer>& buffer) { | |
220 DVLOG(3) << "DecryptAndDecodeBuffer()"; | |
221 DCHECK(message_loop_->BelongsToCurrentThread()); | |
222 | |
223 if (state_ == kStopped) | |
224 return; | |
225 | |
226 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | |
227 DCHECK(!read_cb_.is_null()); | |
228 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | |
229 | |
230 if (!reset_cb_.is_null()) { | |
231 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | |
232 DoReset(); | |
233 return; | |
234 } | |
235 | |
236 if (status == DemuxerStream::kAborted) { | |
237 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted"; | |
238 state_ = kIdle; | |
239 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | |
240 return; | |
241 } | |
242 | |
243 // VideoFrameStream ensures no kConfigChanged is passed to VideoDecoders. | |
244 DCHECK_EQ(status, DemuxerStream::kOk) << status; | |
245 pending_buffer_to_decode_ = buffer; | |
246 state_ = kPendingDecode; | |
247 DecodePendingBuffer(); | |
248 } | |
249 | 206 |
250 void DecryptingVideoDecoder::DecodePendingBuffer() { | 207 void DecryptingVideoDecoder::DecodePendingBuffer() { |
251 DCHECK(message_loop_->BelongsToCurrentThread()); | 208 DCHECK(message_loop_->BelongsToCurrentThread()); |
252 DCHECK_EQ(state_, kPendingDecode) << state_; | 209 DCHECK_EQ(state_, kPendingDecode) << state_; |
253 TRACE_EVENT_ASYNC_BEGIN0( | 210 TRACE_EVENT_ASYNC_BEGIN0( |
254 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); | 211 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); |
255 | 212 |
256 int buffer_size = 0; | 213 int buffer_size = 0; |
257 if (!pending_buffer_to_decode_->IsEndOfStream()) { | 214 if (!pending_buffer_to_decode_->IsEndOfStream()) { |
258 buffer_size = pending_buffer_to_decode_->GetDataSize(); | 215 buffer_size = pending_buffer_to_decode_->GetDataSize(); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 | 283 |
327 if (status == Decryptor::kNeedMoreData) { | 284 if (status == Decryptor::kNeedMoreData) { |
328 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; | 285 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; |
329 if (scoped_pending_buffer_to_decode->IsEndOfStream()) { | 286 if (scoped_pending_buffer_to_decode->IsEndOfStream()) { |
330 state_ = kDecodeFinished; | 287 state_ = kDecodeFinished; |
331 base::ResetAndReturn(&read_cb_).Run( | 288 base::ResetAndReturn(&read_cb_).Run( |
332 kOk, media::VideoFrame::CreateEmptyFrame()); | 289 kOk, media::VideoFrame::CreateEmptyFrame()); |
333 return; | 290 return; |
334 } | 291 } |
335 | 292 |
336 state_ = kPendingDemuxerRead; | 293 state_ = kIdle; |
337 ReadFromDemuxerStream(); | 294 base::ResetAndReturn(&read_cb_).Run(kNotEnoughData, NULL); |
338 return; | 295 return; |
339 } | 296 } |
340 | 297 |
341 DCHECK_EQ(status, Decryptor::kSuccess); | 298 DCHECK_EQ(status, Decryptor::kSuccess); |
342 // No frame returned with kSuccess should be end-of-stream frame. | 299 // No frame returned with kSuccess should be end-of-stream frame. |
343 DCHECK(!frame->IsEndOfStream()); | 300 DCHECK(!frame->IsEndOfStream()); |
344 state_ = kIdle; | 301 state_ = kIdle; |
345 base::ResetAndReturn(&read_cb_).Run(kOk, frame); | 302 base::ResetAndReturn(&read_cb_).Run(kOk, frame); |
346 } | 303 } |
347 | 304 |
(...skipping 13 matching lines...) Expand all Loading... |
361 } | 318 } |
362 | 319 |
363 void DecryptingVideoDecoder::DoReset() { | 320 void DecryptingVideoDecoder::DoReset() { |
364 DCHECK(init_cb_.is_null()); | 321 DCHECK(init_cb_.is_null()); |
365 DCHECK(read_cb_.is_null()); | 322 DCHECK(read_cb_.is_null()); |
366 state_ = kIdle; | 323 state_ = kIdle; |
367 base::ResetAndReturn(&reset_cb_).Run(); | 324 base::ResetAndReturn(&reset_cb_).Run(); |
368 } | 325 } |
369 | 326 |
370 } // namespace media | 327 } // namespace media |
OLD | NEW |