| 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/bind_to_current_loop.h" |
| 8 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 9 #include "base/location.h" | 10 #include "base/location.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 12 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
| 13 #include "media/base/bind_to_current_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/pipeline.h" | 16 #include "media/base/pipeline.h" |
| 17 #include "media/base/video_decoder_config.h" | 17 #include "media/base/video_decoder_config.h" |
| 18 #include "media/base/video_frame.h" | 18 #include "media/base/video_frame.h" |
| 19 | 19 |
| 20 namespace media { | 20 namespace media { |
| 21 | 21 |
| 22 const char DecryptingVideoDecoder::kDecoderName[] = "DecryptingVideoDecoder"; | 22 const char DecryptingVideoDecoder::kDecoderName[] = "DecryptingVideoDecoder"; |
| 23 | 23 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 46 DVLOG(2) << "Initialize()"; | 46 DVLOG(2) << "Initialize()"; |
| 47 DCHECK(task_runner_->BelongsToCurrentThread()); | 47 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 48 DCHECK(state_ == kUninitialized || | 48 DCHECK(state_ == kUninitialized || |
| 49 state_ == kIdle || | 49 state_ == kIdle || |
| 50 state_ == kDecodeFinished) << state_; | 50 state_ == kDecodeFinished) << state_; |
| 51 DCHECK(decode_cb_.is_null()); | 51 DCHECK(decode_cb_.is_null()); |
| 52 DCHECK(reset_cb_.is_null()); | 52 DCHECK(reset_cb_.is_null()); |
| 53 DCHECK(config.IsValidConfig()); | 53 DCHECK(config.IsValidConfig()); |
| 54 DCHECK(config.is_encrypted()); | 54 DCHECK(config.is_encrypted()); |
| 55 | 55 |
| 56 init_cb_ = BindToCurrentLoop(status_cb); | 56 init_cb_ = base::BindToCurrentLoop(status_cb); |
| 57 output_cb_ = BindToCurrentLoop(output_cb); | 57 output_cb_ = base::BindToCurrentLoop(output_cb); |
| 58 weak_this_ = weak_factory_.GetWeakPtr(); | 58 weak_this_ = weak_factory_.GetWeakPtr(); |
| 59 config_ = config; | 59 config_ = config; |
| 60 | 60 |
| 61 if (state_ == kUninitialized) { | 61 if (state_ == kUninitialized) { |
| 62 state_ = kDecryptorRequested; | 62 state_ = kDecryptorRequested; |
| 63 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( | 63 set_decryptor_ready_cb_.Run(base::BindToCurrentLoop(base::Bind( |
| 64 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); | 64 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); |
| 65 return; | 65 return; |
| 66 } | 66 } |
| 67 | 67 |
| 68 // Reinitialization. | 68 // Reinitialization. |
| 69 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 69 decryptor_->DeinitializeDecoder(Decryptor::kVideo); |
| 70 state_ = kPendingDecoderInit; | 70 state_ = kPendingDecoderInit; |
| 71 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind( | 71 decryptor_->InitializeVideoDecoder(config, base::BindToCurrentLoop(base::Bind( |
| 72 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); | 72 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); |
| 73 } | 73 } |
| 74 | 74 |
| 75 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 75 void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 76 const DecodeCB& decode_cb) { | 76 const DecodeCB& decode_cb) { |
| 77 DVLOG(3) << "Decode()"; | 77 DVLOG(3) << "Decode()"; |
| 78 DCHECK(task_runner_->BelongsToCurrentThread()); | 78 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 79 DCHECK(state_ == kIdle || | 79 DCHECK(state_ == kIdle || |
| 80 state_ == kDecodeFinished || | 80 state_ == kDecodeFinished || |
| 81 state_ == kError) << state_; | 81 state_ == kError) << state_; |
| 82 DCHECK(!decode_cb.is_null()); | 82 DCHECK(!decode_cb.is_null()); |
| 83 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; | 83 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 84 | 84 |
| 85 decode_cb_ = BindToCurrentLoop(decode_cb); | 85 decode_cb_ = base::BindToCurrentLoop(decode_cb); |
| 86 | 86 |
| 87 if (state_ == kError) { | 87 if (state_ == kError) { |
| 88 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); | 88 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); |
| 89 return; | 89 return; |
| 90 } | 90 } |
| 91 | 91 |
| 92 // Return empty frames if decoding has finished. | 92 // Return empty frames if decoding has finished. |
| 93 if (state_ == kDecodeFinished) { | 93 if (state_ == kDecodeFinished) { |
| 94 base::ResetAndReturn(&decode_cb_).Run(kOk); | 94 base::ResetAndReturn(&decode_cb_).Run(kOk); |
| 95 return; | 95 return; |
| 96 } | 96 } |
| 97 | 97 |
| 98 pending_buffer_to_decode_ = buffer; | 98 pending_buffer_to_decode_ = buffer; |
| 99 state_ = kPendingDecode; | 99 state_ = kPendingDecode; |
| 100 DecodePendingBuffer(); | 100 DecodePendingBuffer(); |
| 101 } | 101 } |
| 102 | 102 |
| 103 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { | 103 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { |
| 104 DVLOG(2) << "Reset() - state: " << state_; | 104 DVLOG(2) << "Reset() - state: " << state_; |
| 105 DCHECK(task_runner_->BelongsToCurrentThread()); | 105 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 106 DCHECK(state_ == kIdle || | 106 DCHECK(state_ == kIdle || |
| 107 state_ == kPendingDecode || | 107 state_ == kPendingDecode || |
| 108 state_ == kWaitingForKey || | 108 state_ == kWaitingForKey || |
| 109 state_ == kDecodeFinished || | 109 state_ == kDecodeFinished || |
| 110 state_ == kError) << state_; | 110 state_ == kError) << state_; |
| 111 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 111 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
| 112 DCHECK(reset_cb_.is_null()); | 112 DCHECK(reset_cb_.is_null()); |
| 113 | 113 |
| 114 reset_cb_ = BindToCurrentLoop(closure); | 114 reset_cb_ = base::BindToCurrentLoop(closure); |
| 115 | 115 |
| 116 decryptor_->ResetDecoder(Decryptor::kVideo); | 116 decryptor_->ResetDecoder(Decryptor::kVideo); |
| 117 | 117 |
| 118 // Reset() cannot complete if the decode callback is still pending. | 118 // Reset() cannot complete if the decode callback is still pending. |
| 119 // Defer the resetting process in this case. The |reset_cb_| will be fired | 119 // Defer the resetting process in this case. The |reset_cb_| will be fired |
| 120 // after the decode callback is fired - see DecryptAndDecodeBuffer() and | 120 // after the decode callback is fired - see DecryptAndDecodeBuffer() and |
| 121 // DeliverFrame(). | 121 // DeliverFrame(). |
| 122 if (state_ == kPendingDecode) { | 122 if (state_ == kPendingDecode) { |
| 123 DCHECK(!decode_cb_.is_null()); | 123 DCHECK(!decode_cb_.is_null()); |
| 124 return; | 124 return; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 state_ = kError; | 170 state_ = kError; |
| 171 decryptor_attached_cb.Run(false); | 171 decryptor_attached_cb.Run(false); |
| 172 return; | 172 return; |
| 173 } | 173 } |
| 174 | 174 |
| 175 decryptor_ = decryptor; | 175 decryptor_ = decryptor; |
| 176 | 176 |
| 177 state_ = kPendingDecoderInit; | 177 state_ = kPendingDecoderInit; |
| 178 decryptor_->InitializeVideoDecoder( | 178 decryptor_->InitializeVideoDecoder( |
| 179 config_, | 179 config_, |
| 180 BindToCurrentLoop(base::Bind( | 180 base::BindToCurrentLoop(base::Bind( |
| 181 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); | 181 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); |
| 182 decryptor_attached_cb.Run(true); | 182 decryptor_attached_cb.Run(true); |
| 183 } | 183 } |
| 184 | 184 |
| 185 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 185 void DecryptingVideoDecoder::FinishInitialization(bool success) { |
| 186 DVLOG(2) << "FinishInitialization()"; | 186 DVLOG(2) << "FinishInitialization()"; |
| 187 DCHECK(task_runner_->BelongsToCurrentThread()); | 187 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 188 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 188 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
| 189 DCHECK(!init_cb_.is_null()); | 189 DCHECK(!init_cb_.is_null()); |
| 190 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 190 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| 191 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. | 191 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. |
| 192 | 192 |
| 193 if (!success) { | 193 if (!success) { |
| 194 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 194 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 195 decryptor_ = NULL; | 195 decryptor_ = NULL; |
| 196 state_ = kError; | 196 state_ = kError; |
| 197 return; | 197 return; |
| 198 } | 198 } |
| 199 | 199 |
| 200 decryptor_->RegisterNewKeyCB( | 200 decryptor_->RegisterNewKeyCB( |
| 201 Decryptor::kVideo, | 201 Decryptor::kVideo, |
| 202 BindToCurrentLoop( | 202 base::BindToCurrentLoop( |
| 203 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); | 203 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); |
| 204 | 204 |
| 205 // Success! | 205 // Success! |
| 206 state_ = kIdle; | 206 state_ = kIdle; |
| 207 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 207 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 208 } | 208 } |
| 209 | 209 |
| 210 | 210 |
| 211 void DecryptingVideoDecoder::DecodePendingBuffer() { | 211 void DecryptingVideoDecoder::DecodePendingBuffer() { |
| 212 DCHECK(task_runner_->BelongsToCurrentThread()); | 212 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 213 DCHECK_EQ(state_, kPendingDecode) << state_; | 213 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 214 TRACE_EVENT_ASYNC_BEGIN0( | 214 TRACE_EVENT_ASYNC_BEGIN0( |
| 215 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); | 215 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); |
| 216 | 216 |
| 217 int buffer_size = 0; | 217 int buffer_size = 0; |
| 218 if (!pending_buffer_to_decode_->end_of_stream()) { | 218 if (!pending_buffer_to_decode_->end_of_stream()) { |
| 219 buffer_size = pending_buffer_to_decode_->data_size(); | 219 buffer_size = pending_buffer_to_decode_->data_size(); |
| 220 } | 220 } |
| 221 | 221 |
| 222 decryptor_->DecryptAndDecodeVideo( | 222 decryptor_->DecryptAndDecodeVideo( |
| 223 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind( | 223 pending_buffer_to_decode_, base::BindToCurrentLoop(base::Bind( |
| 224 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size))); | 224 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size))); |
| 225 } | 225 } |
| 226 | 226 |
| 227 void DecryptingVideoDecoder::DeliverFrame( | 227 void DecryptingVideoDecoder::DeliverFrame( |
| 228 int buffer_size, | 228 int buffer_size, |
| 229 Decryptor::Status status, | 229 Decryptor::Status status, |
| 230 const scoped_refptr<VideoFrame>& frame) { | 230 const scoped_refptr<VideoFrame>& frame) { |
| 231 DVLOG(3) << "DeliverFrame() - status: " << status; | 231 DVLOG(3) << "DeliverFrame() - status: " << status; |
| 232 DCHECK(task_runner_->BelongsToCurrentThread()); | 232 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 233 DCHECK_EQ(state_, kPendingDecode) << state_; | 233 DCHECK_EQ(state_, kPendingDecode) << state_; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 318 } |
| 319 | 319 |
| 320 void DecryptingVideoDecoder::DoReset() { | 320 void DecryptingVideoDecoder::DoReset() { |
| 321 DCHECK(init_cb_.is_null()); | 321 DCHECK(init_cb_.is_null()); |
| 322 DCHECK(decode_cb_.is_null()); | 322 DCHECK(decode_cb_.is_null()); |
| 323 state_ = kIdle; | 323 state_ = kIdle; |
| 324 base::ResetAndReturn(&reset_cb_).Run(); | 324 base::ResetAndReturn(&reset_cb_).Run(); |
| 325 } | 325 } |
| 326 | 326 |
| 327 } // namespace media | 327 } // namespace media |
| OLD | NEW |