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