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" |
(...skipping 14 matching lines...) Expand all Loading... |
25 : task_runner_(task_runner), | 25 : task_runner_(task_runner), |
26 state_(kUninitialized), | 26 state_(kUninitialized), |
27 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 27 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
28 decryptor_(NULL), | 28 decryptor_(NULL), |
29 key_added_while_decode_pending_(false), | 29 key_added_while_decode_pending_(false), |
30 trace_id_(0), | 30 trace_id_(0), |
31 weak_factory_(this) {} | 31 weak_factory_(this) {} |
32 | 32 |
33 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config, | 33 void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config, |
34 bool live_mode, | 34 bool live_mode, |
35 const PipelineStatusCB& status_cb, | 35 const PipelineStatusCB& status_cb) { |
36 const OutputCB& output_cb) { | |
37 DVLOG(2) << "Initialize()"; | 36 DVLOG(2) << "Initialize()"; |
38 DCHECK(task_runner_->BelongsToCurrentThread()); | 37 DCHECK(task_runner_->BelongsToCurrentThread()); |
39 DCHECK(state_ == kUninitialized || | 38 DCHECK(state_ == kUninitialized || |
40 state_ == kIdle || | 39 state_ == kIdle || |
41 state_ == kDecodeFinished) << state_; | 40 state_ == kDecodeFinished) << state_; |
42 DCHECK(decode_cb_.is_null()); | 41 DCHECK(decode_cb_.is_null()); |
43 DCHECK(reset_cb_.is_null()); | 42 DCHECK(reset_cb_.is_null()); |
44 DCHECK(config.IsValidConfig()); | 43 DCHECK(config.IsValidConfig()); |
45 DCHECK(config.is_encrypted()); | 44 DCHECK(config.is_encrypted()); |
46 | 45 |
47 init_cb_ = BindToCurrentLoop(status_cb); | 46 init_cb_ = BindToCurrentLoop(status_cb); |
48 output_cb_ = BindToCurrentLoop(output_cb); | |
49 weak_this_ = weak_factory_.GetWeakPtr(); | 47 weak_this_ = weak_factory_.GetWeakPtr(); |
50 config_ = config; | 48 config_ = config; |
51 | 49 |
52 if (state_ == kUninitialized) { | 50 if (state_ == kUninitialized) { |
53 state_ = kDecryptorRequested; | 51 state_ = kDecryptorRequested; |
54 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( | 52 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( |
55 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); | 53 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); |
56 return; | 54 return; |
57 } | 55 } |
58 | 56 |
(...skipping 10 matching lines...) Expand all Loading... |
69 DCHECK(task_runner_->BelongsToCurrentThread()); | 67 DCHECK(task_runner_->BelongsToCurrentThread()); |
70 DCHECK(state_ == kIdle || | 68 DCHECK(state_ == kIdle || |
71 state_ == kDecodeFinished || | 69 state_ == kDecodeFinished || |
72 state_ == kError) << state_; | 70 state_ == kError) << state_; |
73 DCHECK(!decode_cb.is_null()); | 71 DCHECK(!decode_cb.is_null()); |
74 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; | 72 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
75 | 73 |
76 decode_cb_ = BindToCurrentLoop(decode_cb); | 74 decode_cb_ = BindToCurrentLoop(decode_cb); |
77 | 75 |
78 if (state_ == kError) { | 76 if (state_ == kError) { |
79 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); | 77 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); |
80 return; | 78 return; |
81 } | 79 } |
82 | 80 |
83 // Return empty frames if decoding has finished. | 81 // Return empty frames if decoding has finished. |
84 if (state_ == kDecodeFinished) { | 82 if (state_ == kDecodeFinished) { |
85 output_cb_.Run(VideoFrame::CreateEOSFrame()); | 83 base::ResetAndReturn(&decode_cb_).Run(kOk, VideoFrame::CreateEOSFrame()); |
86 base::ResetAndReturn(&decode_cb_).Run(kOk); | |
87 return; | 84 return; |
88 } | 85 } |
89 | 86 |
90 pending_buffer_to_decode_ = buffer; | 87 pending_buffer_to_decode_ = buffer; |
91 state_ = kPendingDecode; | 88 state_ = kPendingDecode; |
92 DecodePendingBuffer(); | 89 DecodePendingBuffer(); |
93 } | 90 } |
94 | 91 |
95 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { | 92 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { |
96 DVLOG(2) << "Reset() - state: " << state_; | 93 DVLOG(2) << "Reset() - state: " << state_; |
(...skipping 15 matching lines...) Expand all Loading... |
112 // after the decode callback is fired - see DecryptAndDecodeBuffer() and | 109 // after the decode callback is fired - see DecryptAndDecodeBuffer() and |
113 // DeliverFrame(). | 110 // DeliverFrame(). |
114 if (state_ == kPendingDecode) { | 111 if (state_ == kPendingDecode) { |
115 DCHECK(!decode_cb_.is_null()); | 112 DCHECK(!decode_cb_.is_null()); |
116 return; | 113 return; |
117 } | 114 } |
118 | 115 |
119 if (state_ == kWaitingForKey) { | 116 if (state_ == kWaitingForKey) { |
120 DCHECK(!decode_cb_.is_null()); | 117 DCHECK(!decode_cb_.is_null()); |
121 pending_buffer_to_decode_ = NULL; | 118 pending_buffer_to_decode_ = NULL; |
122 base::ResetAndReturn(&decode_cb_).Run(kAborted); | 119 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
123 } | 120 } |
124 | 121 |
125 DCHECK(decode_cb_.is_null()); | 122 DCHECK(decode_cb_.is_null()); |
126 DoReset(); | 123 DoReset(); |
127 } | 124 } |
128 | 125 |
129 void DecryptingVideoDecoder::Stop() { | 126 void DecryptingVideoDecoder::Stop() { |
130 DCHECK(task_runner_->BelongsToCurrentThread()); | 127 DCHECK(task_runner_->BelongsToCurrentThread()); |
131 DVLOG(2) << "Stop() - state: " << state_; | 128 DVLOG(2) << "Stop() - state: " << state_; |
132 | 129 |
133 // Invalidate all weak pointers so that pending callbacks won't be fired into | 130 // Invalidate all weak pointers so that pending callbacks won't be fired into |
134 // this object. | 131 // this object. |
135 weak_factory_.InvalidateWeakPtrs(); | 132 weak_factory_.InvalidateWeakPtrs(); |
136 | 133 |
137 // At this point the render thread is likely paused (in WebMediaPlayerImpl's | 134 // At this point the render thread is likely paused (in WebMediaPlayerImpl's |
138 // Destroy()), so running |closure| can't wait for anything that requires the | 135 // Destroy()), so running |closure| can't wait for anything that requires the |
139 // render thread to be processing messages to complete (such as PPAPI | 136 // render thread to be processing messages to complete (such as PPAPI |
140 // callbacks). | 137 // callbacks). |
141 if (decryptor_) { | 138 if (decryptor_) { |
142 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 139 decryptor_->DeinitializeDecoder(Decryptor::kVideo); |
143 decryptor_ = NULL; | 140 decryptor_ = NULL; |
144 } | 141 } |
145 if (!set_decryptor_ready_cb_.is_null()) | 142 if (!set_decryptor_ready_cb_.is_null()) |
146 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB()); | 143 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB()); |
147 pending_buffer_to_decode_ = NULL; | 144 pending_buffer_to_decode_ = NULL; |
148 if (!init_cb_.is_null()) | 145 if (!init_cb_.is_null()) |
149 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 146 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
150 if (!decode_cb_.is_null()) | 147 if (!decode_cb_.is_null()) |
151 base::ResetAndReturn(&decode_cb_).Run(kAborted); | 148 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
152 if (!reset_cb_.is_null()) | 149 if (!reset_cb_.is_null()) |
153 base::ResetAndReturn(&reset_cb_).Run(); | 150 base::ResetAndReturn(&reset_cb_).Run(); |
154 | 151 |
155 state_ = kStopped; | 152 state_ = kStopped; |
156 } | 153 } |
157 | 154 |
158 DecryptingVideoDecoder::~DecryptingVideoDecoder() { | 155 DecryptingVideoDecoder::~DecryptingVideoDecoder() { |
159 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 156 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; |
160 } | 157 } |
161 | 158 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_); | 234 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_); |
238 | 235 |
239 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; | 236 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; |
240 key_added_while_decode_pending_ = false; | 237 key_added_while_decode_pending_ = false; |
241 | 238 |
242 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = | 239 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = |
243 pending_buffer_to_decode_; | 240 pending_buffer_to_decode_; |
244 pending_buffer_to_decode_ = NULL; | 241 pending_buffer_to_decode_ = NULL; |
245 | 242 |
246 if (!reset_cb_.is_null()) { | 243 if (!reset_cb_.is_null()) { |
247 base::ResetAndReturn(&decode_cb_).Run(kAborted); | 244 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
248 DoReset(); | 245 DoReset(); |
249 return; | 246 return; |
250 } | 247 } |
251 | 248 |
252 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL); | 249 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL); |
253 | 250 |
254 if (status == Decryptor::kError) { | 251 if (status == Decryptor::kError) { |
255 DVLOG(2) << "DeliverFrame() - kError"; | 252 DVLOG(2) << "DeliverFrame() - kError"; |
256 state_ = kError; | 253 state_ = kError; |
257 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); | 254 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); |
258 return; | 255 return; |
259 } | 256 } |
260 | 257 |
261 if (status == Decryptor::kNoKey) { | 258 if (status == Decryptor::kNoKey) { |
262 DVLOG(2) << "DeliverFrame() - kNoKey"; | 259 DVLOG(2) << "DeliverFrame() - kNoKey"; |
263 // Set |pending_buffer_to_decode_| back as we need to try decoding the | 260 // Set |pending_buffer_to_decode_| back as we need to try decoding the |
264 // pending buffer again when new key is added to the decryptor. | 261 // pending buffer again when new key is added to the decryptor. |
265 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; | 262 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; |
266 | 263 |
267 if (need_to_try_again_if_nokey_is_returned) { | 264 if (need_to_try_again_if_nokey_is_returned) { |
268 // The |state_| is still kPendingDecode. | 265 // The |state_| is still kPendingDecode. |
269 DecodePendingBuffer(); | 266 DecodePendingBuffer(); |
270 return; | 267 return; |
271 } | 268 } |
272 | 269 |
273 state_ = kWaitingForKey; | 270 state_ = kWaitingForKey; |
274 return; | 271 return; |
275 } | 272 } |
276 | 273 |
277 if (status == Decryptor::kNeedMoreData) { | 274 if (status == Decryptor::kNeedMoreData) { |
278 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; | 275 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; |
279 if (scoped_pending_buffer_to_decode->end_of_stream()) { | 276 if (scoped_pending_buffer_to_decode->end_of_stream()) { |
280 state_ = kDecodeFinished; | 277 state_ = kDecodeFinished; |
281 output_cb_.Run(media::VideoFrame::CreateEOSFrame()); | 278 base::ResetAndReturn(&decode_cb_).Run( |
282 } else { | 279 kOk, media::VideoFrame::CreateEOSFrame()); |
283 state_ = kIdle; | 280 return; |
284 } | 281 } |
285 base::ResetAndReturn(&decode_cb_).Run(kOk); | 282 |
| 283 state_ = kIdle; |
| 284 base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL); |
286 return; | 285 return; |
287 } | 286 } |
288 | 287 |
289 DCHECK_EQ(status, Decryptor::kSuccess); | 288 DCHECK_EQ(status, Decryptor::kSuccess); |
290 // No frame returned with kSuccess should be end-of-stream frame. | 289 // No frame returned with kSuccess should be end-of-stream frame. |
291 DCHECK(!frame->end_of_stream()); | 290 DCHECK(!frame->end_of_stream()); |
292 state_ = kIdle; | 291 state_ = kIdle; |
293 output_cb_.Run(frame); | 292 base::ResetAndReturn(&decode_cb_).Run(kOk, frame); |
294 base::ResetAndReturn(&decode_cb_).Run(kOk); | |
295 } | 293 } |
296 | 294 |
297 void DecryptingVideoDecoder::OnKeyAdded() { | 295 void DecryptingVideoDecoder::OnKeyAdded() { |
298 DVLOG(2) << "OnKeyAdded()"; | 296 DVLOG(2) << "OnKeyAdded()"; |
299 DCHECK(task_runner_->BelongsToCurrentThread()); | 297 DCHECK(task_runner_->BelongsToCurrentThread()); |
300 | 298 |
301 if (state_ == kPendingDecode) { | 299 if (state_ == kPendingDecode) { |
302 key_added_while_decode_pending_ = true; | 300 key_added_while_decode_pending_ = true; |
303 return; | 301 return; |
304 } | 302 } |
305 | 303 |
306 if (state_ == kWaitingForKey) { | 304 if (state_ == kWaitingForKey) { |
307 state_ = kPendingDecode; | 305 state_ = kPendingDecode; |
308 DecodePendingBuffer(); | 306 DecodePendingBuffer(); |
309 } | 307 } |
310 } | 308 } |
311 | 309 |
312 void DecryptingVideoDecoder::DoReset() { | 310 void DecryptingVideoDecoder::DoReset() { |
313 DCHECK(init_cb_.is_null()); | 311 DCHECK(init_cb_.is_null()); |
314 DCHECK(decode_cb_.is_null()); | 312 DCHECK(decode_cb_.is_null()); |
315 state_ = kIdle; | 313 state_ = kIdle; |
316 base::ResetAndReturn(&reset_cb_).Run(); | 314 base::ResetAndReturn(&reset_cb_).Run(); |
317 } | 315 } |
318 | 316 |
319 } // namespace media | 317 } // namespace media |
OLD | NEW |