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