| 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 |