| 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_proxy.h" | 12 #include "base/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" | 16 #include "media/base/demuxer_stream.h" |
| 17 #include "media/base/pipeline.h" | 17 #include "media/base/pipeline.h" |
| 18 #include "media/base/video_decoder_config.h" | 18 #include "media/base/video_decoder_config.h" |
| 19 #include "media/base/video_frame.h" | 19 #include "media/base/video_frame.h" |
| 20 | 20 |
| 21 namespace media { | 21 namespace media { |
| 22 | 22 |
| 23 DecryptingVideoDecoder::DecryptingVideoDecoder( | 23 DecryptingVideoDecoder::DecryptingVideoDecoder( |
| 24 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 24 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| 25 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 25 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
| 26 : message_loop_(message_loop), | 26 : message_loop_(message_loop), |
| 27 weak_factory_(this), |
| 27 state_(kUninitialized), | 28 state_(kUninitialized), |
| 28 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 29 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
| 29 decryptor_(NULL), | 30 decryptor_(NULL), |
| 30 key_added_while_decode_pending_(false), | 31 key_added_while_decode_pending_(false), |
| 31 trace_id_(0) { | 32 trace_id_(0) { |
| 32 } | 33 } |
| 33 | 34 |
| 34 void DecryptingVideoDecoder::Initialize( | 35 void DecryptingVideoDecoder::Initialize( |
| 35 const scoped_refptr<DemuxerStream>& stream, | 36 const scoped_refptr<DemuxerStream>& stream, |
| 36 const PipelineStatusCB& status_cb, | 37 const PipelineStatusCB& status_cb, |
| 37 const StatisticsCB& statistics_cb) { | 38 const StatisticsCB& statistics_cb) { |
| 38 DVLOG(2) << "Initialize()"; | 39 DVLOG(2) << "Initialize()"; |
| 39 DCHECK(message_loop_->BelongsToCurrentThread()); | 40 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 40 DCHECK_EQ(state_, kUninitialized) << state_; | 41 DCHECK_EQ(state_, kUninitialized) << state_; |
| 41 DCHECK(stream); | 42 DCHECK(stream); |
| 42 init_cb_ = BindToCurrentLoop(status_cb); | 43 init_cb_ = BindToCurrentLoop(status_cb); |
| 44 weak_this_ = weak_factory_.GetWeakPtr(); |
| 43 | 45 |
| 44 const VideoDecoderConfig& config = stream->video_decoder_config(); | 46 const VideoDecoderConfig& config = stream->video_decoder_config(); |
| 45 if (!config.IsValidConfig()) { | 47 if (!config.IsValidConfig()) { |
| 46 DLOG(ERROR) << "Invalid video stream config: " | 48 DLOG(ERROR) << "Invalid video stream config: " |
| 47 << config.AsHumanReadableString(); | 49 << config.AsHumanReadableString(); |
| 48 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); | 50 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); |
| 49 return; | 51 return; |
| 50 } | 52 } |
| 51 | 53 |
| 52 // DecryptingVideoDecoder only accepts potentially encrypted stream. | 54 // DecryptingVideoDecoder only accepts potentially encrypted stream. |
| 53 if (!config.is_encrypted()) { | 55 if (!config.is_encrypted()) { |
| 54 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 56 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 55 return; | 57 return; |
| 56 } | 58 } |
| 57 | 59 |
| 58 DCHECK(!demuxer_stream_); | 60 DCHECK(!demuxer_stream_); |
| 59 demuxer_stream_ = stream; | 61 demuxer_stream_ = stream; |
| 60 statistics_cb_ = statistics_cb; | 62 statistics_cb_ = statistics_cb; |
| 61 | 63 |
| 62 state_ = kDecryptorRequested; | 64 state_ = kDecryptorRequested; |
| 63 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( | 65 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( |
| 64 &DecryptingVideoDecoder::SetDecryptor, this))); | 66 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); |
| 65 } | 67 } |
| 66 | 68 |
| 67 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { | 69 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { |
| 68 DVLOG(3) << "Read()"; | 70 DVLOG(3) << "Read()"; |
| 69 DCHECK(message_loop_->BelongsToCurrentThread()); | 71 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 70 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 72 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| 71 DCHECK(!read_cb.is_null()); | 73 DCHECK(!read_cb.is_null()); |
| 72 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 74 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 73 read_cb_ = BindToCurrentLoop(read_cb); | 75 read_cb_ = BindToCurrentLoop(read_cb); |
| 74 | 76 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 161 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
| 160 DCHECK(!init_cb_.is_null()); | 162 DCHECK(!init_cb_.is_null()); |
| 161 DCHECK(!set_decryptor_ready_cb_.is_null()); | 163 DCHECK(!set_decryptor_ready_cb_.is_null()); |
| 162 set_decryptor_ready_cb_.Reset(); | 164 set_decryptor_ready_cb_.Reset(); |
| 163 | 165 |
| 164 decryptor_ = decryptor; | 166 decryptor_ = decryptor; |
| 165 | 167 |
| 166 state_ = kPendingDecoderInit; | 168 state_ = kPendingDecoderInit; |
| 167 decryptor_->InitializeVideoDecoder( | 169 decryptor_->InitializeVideoDecoder( |
| 168 demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( | 170 demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( |
| 169 &DecryptingVideoDecoder::FinishInitialization, this))); | 171 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); |
| 170 } | 172 } |
| 171 | 173 |
| 172 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 174 void DecryptingVideoDecoder::FinishInitialization(bool success) { |
| 173 DVLOG(2) << "FinishInitialization()"; | 175 DVLOG(2) << "FinishInitialization()"; |
| 174 DCHECK(message_loop_->BelongsToCurrentThread()); | 176 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 175 | 177 |
| 176 if (state_ == kStopped) | 178 if (state_ == kStopped) |
| 177 return; | 179 return; |
| 178 | 180 |
| 179 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 181 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
| 180 DCHECK(!init_cb_.is_null()); | 182 DCHECK(!init_cb_.is_null()); |
| 181 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 183 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| 182 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 184 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
| 183 | 185 |
| 184 if (!success) { | 186 if (!success) { |
| 185 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 187 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 186 state_ = kStopped; | 188 state_ = kStopped; |
| 187 return; | 189 return; |
| 188 } | 190 } |
| 189 | 191 |
| 190 decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( | 192 decryptor_->RegisterNewKeyCB(Decryptor::kVideo, BindToCurrentLoop( |
| 191 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, this))); | 193 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); |
| 192 | 194 |
| 193 // Success! | 195 // Success! |
| 194 state_ = kIdle; | 196 state_ = kIdle; |
| 195 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 197 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 196 } | 198 } |
| 197 | 199 |
| 198 void DecryptingVideoDecoder::FinishConfigChange(bool success) { | 200 void DecryptingVideoDecoder::FinishConfigChange(bool success) { |
| 199 DVLOG(2) << "FinishConfigChange()"; | 201 DVLOG(2) << "FinishConfigChange()"; |
| 200 DCHECK(message_loop_->BelongsToCurrentThread()); | 202 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 201 | 203 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 223 state_ = kPendingDemuxerRead; | 225 state_ = kPendingDemuxerRead; |
| 224 ReadFromDemuxerStream(); | 226 ReadFromDemuxerStream(); |
| 225 } | 227 } |
| 226 | 228 |
| 227 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | 229 void DecryptingVideoDecoder::ReadFromDemuxerStream() { |
| 228 DCHECK(message_loop_->BelongsToCurrentThread()); | 230 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 229 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 231 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 230 DCHECK(!read_cb_.is_null()); | 232 DCHECK(!read_cb_.is_null()); |
| 231 | 233 |
| 232 demuxer_stream_->Read( | 234 demuxer_stream_->Read( |
| 233 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); | 235 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, weak_this_)); |
| 234 } | 236 } |
| 235 | 237 |
| 236 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( | 238 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( |
| 237 DemuxerStream::Status status, | 239 DemuxerStream::Status status, |
| 238 const scoped_refptr<DecoderBuffer>& buffer) { | 240 const scoped_refptr<DecoderBuffer>& buffer) { |
| 239 DVLOG(3) << "DecryptAndDecodeBuffer()"; | 241 DVLOG(3) << "DecryptAndDecodeBuffer()"; |
| 240 DCHECK(message_loop_->BelongsToCurrentThread()); | 242 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 241 | 243 |
| 242 if (state_ == kStopped) | 244 if (state_ == kStopped) |
| 243 return; | 245 return; |
| 244 | 246 |
| 245 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 247 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 246 DCHECK(!read_cb_.is_null()); | 248 DCHECK(!read_cb_.is_null()); |
| 247 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 249 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
| 248 | 250 |
| 249 if (status == DemuxerStream::kConfigChanged) { | 251 if (status == DemuxerStream::kConfigChanged) { |
| 250 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged"; | 252 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged"; |
| 251 | 253 |
| 252 state_ = kPendingConfigChange; | 254 state_ = kPendingConfigChange; |
| 253 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 255 decryptor_->DeinitializeDecoder(Decryptor::kVideo); |
| 254 decryptor_->InitializeVideoDecoder( | 256 decryptor_->InitializeVideoDecoder( |
| 255 demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( | 257 demuxer_stream_->video_decoder_config(), BindToCurrentLoop(base::Bind( |
| 256 &DecryptingVideoDecoder::FinishConfigChange, this))); | 258 &DecryptingVideoDecoder::FinishConfigChange, weak_this_))); |
| 257 return; | 259 return; |
| 258 } | 260 } |
| 259 | 261 |
| 260 if (!reset_cb_.is_null()) { | 262 if (!reset_cb_.is_null()) { |
| 261 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 263 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 262 DoReset(); | 264 DoReset(); |
| 263 return; | 265 return; |
| 264 } | 266 } |
| 265 | 267 |
| 266 if (status == DemuxerStream::kAborted) { | 268 if (status == DemuxerStream::kAborted) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 282 TRACE_EVENT_ASYNC_BEGIN0( | 284 TRACE_EVENT_ASYNC_BEGIN0( |
| 283 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); | 285 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); |
| 284 | 286 |
| 285 int buffer_size = 0; | 287 int buffer_size = 0; |
| 286 if (!pending_buffer_to_decode_->IsEndOfStream()) { | 288 if (!pending_buffer_to_decode_->IsEndOfStream()) { |
| 287 buffer_size = pending_buffer_to_decode_->GetDataSize(); | 289 buffer_size = pending_buffer_to_decode_->GetDataSize(); |
| 288 } | 290 } |
| 289 | 291 |
| 290 decryptor_->DecryptAndDecodeVideo( | 292 decryptor_->DecryptAndDecodeVideo( |
| 291 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind( | 293 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind( |
| 292 &DecryptingVideoDecoder::DeliverFrame, this, buffer_size))); | 294 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size))); |
| 293 } | 295 } |
| 294 | 296 |
| 295 void DecryptingVideoDecoder::DeliverFrame( | 297 void DecryptingVideoDecoder::DeliverFrame( |
| 296 int buffer_size, | 298 int buffer_size, |
| 297 Decryptor::Status status, | 299 Decryptor::Status status, |
| 298 const scoped_refptr<VideoFrame>& frame) { | 300 const scoped_refptr<VideoFrame>& frame) { |
| 299 DVLOG(3) << "DeliverFrame() - status: " << status; | 301 DVLOG(3) << "DeliverFrame() - status: " << status; |
| 300 DCHECK(message_loop_->BelongsToCurrentThread()); | 302 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 301 TRACE_EVENT_ASYNC_END0( | 303 TRACE_EVENT_ASYNC_END0( |
| 302 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_); | 304 "eme", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 } | 392 } |
| 391 | 393 |
| 392 void DecryptingVideoDecoder::DoReset() { | 394 void DecryptingVideoDecoder::DoReset() { |
| 393 DCHECK(init_cb_.is_null()); | 395 DCHECK(init_cb_.is_null()); |
| 394 DCHECK(read_cb_.is_null()); | 396 DCHECK(read_cb_.is_null()); |
| 395 state_ = kIdle; | 397 state_ = kIdle; |
| 396 base::ResetAndReturn(&reset_cb_).Run(); | 398 base::ResetAndReturn(&reset_cb_).Run(); |
| 397 } | 399 } |
| 398 | 400 |
| 399 } // namespace media | 401 } // namespace media |
| OLD | NEW |