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(); | |
Ami GONE FROM CHROMIUM
2013/03/22 23:48:01
Nothing ever invalidates the underlying WeakRefere
xhwang
2013/03/22 23:59:03
Hmm, is this required for all classes that uses We
Ami GONE FROM CHROMIUM
2013/03/23 00:02:01
Oh good, I think you're right!
(this is how I _tho
| |
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_)); |
Ami GONE FROM CHROMIUM
2013/03/22 23:48:01
What guarantees you get called back on this thread
scherkus (not reviewing)
2013/03/28 02:00:01
short term: it's part of the API contract to call
| |
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 |