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_demuxer_stream.h" | 5 #include "media/filters/decrypting_demuxer_stream.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/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 demuxer_stream_(NULL), | 36 demuxer_stream_(NULL), |
37 decryptor_(NULL), | 37 decryptor_(NULL), |
38 key_added_while_decrypt_pending_(false), | 38 key_added_while_decrypt_pending_(false), |
39 weak_factory_(this) {} | 39 weak_factory_(this) {} |
40 | 40 |
41 std::string DecryptingDemuxerStream::GetDisplayName() const { | 41 std::string DecryptingDemuxerStream::GetDisplayName() const { |
42 return "DecryptingDemuxerStream"; | 42 return "DecryptingDemuxerStream"; |
43 } | 43 } |
44 | 44 |
45 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream, | 45 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream, |
46 const SetCdmReadyCB& set_cdm_ready_cb, | 46 CdmContext* cdm_context, |
47 const PipelineStatusCB& status_cb) { | 47 const PipelineStatusCB& status_cb) { |
48 DVLOG(2) << __FUNCTION__; | 48 DVLOG(2) << __FUNCTION__; |
49 DCHECK(task_runner_->BelongsToCurrentThread()); | 49 DCHECK(task_runner_->BelongsToCurrentThread()); |
50 DCHECK_EQ(state_, kUninitialized) << state_; | 50 DCHECK_EQ(state_, kUninitialized) << state_; |
51 | 51 |
52 DCHECK(!demuxer_stream_); | 52 DCHECK(!demuxer_stream_); |
53 weak_this_ = weak_factory_.GetWeakPtr(); | 53 weak_this_ = weak_factory_.GetWeakPtr(); |
54 demuxer_stream_ = stream; | 54 demuxer_stream_ = stream; |
55 set_cdm_ready_cb_ = set_cdm_ready_cb; | |
56 init_cb_ = BindToCurrentLoop(status_cb); | 55 init_cb_ = BindToCurrentLoop(status_cb); |
57 | 56 |
58 InitializeDecoderConfig(); | 57 InitializeDecoderConfig(); |
59 | 58 |
60 state_ = kDecryptorRequested; | 59 DCHECK(cdm_context); |
61 set_cdm_ready_cb_.Run(BindToCurrentLoop( | 60 if (!cdm_context->GetDecryptor()) { |
62 base::Bind(&DecryptingDemuxerStream::SetCdm, weak_this_))); | 61 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor"; |
| 62 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 63 return; |
| 64 } |
| 65 |
| 66 decryptor_ = cdm_context->GetDecryptor(); |
| 67 |
| 68 decryptor_->RegisterNewKeyCB( |
| 69 GetDecryptorStreamType(), |
| 70 BindToCurrentLoop( |
| 71 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_))); |
| 72 |
| 73 state_ = kIdle; |
| 74 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
63 } | 75 } |
64 | 76 |
65 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) { | 77 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) { |
66 DVLOG(3) << __FUNCTION__; | 78 DVLOG(3) << __FUNCTION__; |
67 DCHECK(task_runner_->BelongsToCurrentThread()); | 79 DCHECK(task_runner_->BelongsToCurrentThread()); |
68 DCHECK_EQ(state_, kIdle) << state_; | 80 DCHECK_EQ(state_, kIdle) << state_; |
69 DCHECK(!read_cb.is_null()); | 81 DCHECK(!read_cb.is_null()); |
70 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported."; | 82 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported."; |
71 | 83 |
72 read_cb_ = BindToCurrentLoop(read_cb); | 84 read_cb_ = BindToCurrentLoop(read_cb); |
73 state_ = kPendingDemuxerRead; | 85 state_ = kPendingDemuxerRead; |
74 demuxer_stream_->Read( | 86 demuxer_stream_->Read( |
75 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_)); | 87 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_)); |
76 } | 88 } |
77 | 89 |
78 void DecryptingDemuxerStream::Reset(const base::Closure& closure) { | 90 void DecryptingDemuxerStream::Reset(const base::Closure& closure) { |
79 DVLOG(2) << __FUNCTION__ << " - state: " << state_; | 91 DVLOG(2) << __FUNCTION__ << " - state: " << state_; |
80 DCHECK(task_runner_->BelongsToCurrentThread()); | 92 DCHECK(task_runner_->BelongsToCurrentThread()); |
81 DCHECK(state_ != kUninitialized) << state_; | 93 DCHECK(state_ != kUninitialized) << state_; |
82 DCHECK(reset_cb_.is_null()); | 94 DCHECK(reset_cb_.is_null()); |
83 | 95 |
84 reset_cb_ = BindToCurrentLoop(closure); | 96 reset_cb_ = BindToCurrentLoop(closure); |
85 | 97 |
86 // TODO(xhwang): This should not happen. Remove it, DCHECK against the | |
87 // condition and clean up related tests. | |
88 if (state_ == kDecryptorRequested) { | |
89 DCHECK(!init_cb_.is_null()); | |
90 set_cdm_ready_cb_.Run(CdmReadyCB()); | |
91 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
92 DoReset(); | |
93 return; | |
94 } | |
95 | |
96 decryptor_->CancelDecrypt(GetDecryptorStreamType()); | 98 decryptor_->CancelDecrypt(GetDecryptorStreamType()); |
97 | 99 |
98 // Reset() cannot complete if the read callback is still pending. | 100 // Reset() cannot complete if the read callback is still pending. |
99 // Defer the resetting process in this case. The |reset_cb_| will be fired | 101 // Defer the resetting process in this case. The |reset_cb_| will be fired |
100 // after the read callback is fired - see DoDecryptBuffer() and | 102 // after the read callback is fired - see DoDecryptBuffer() and |
101 // DoDeliverBuffer(). | 103 // DoDeliverBuffer(). |
102 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) { | 104 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) { |
103 DCHECK(!read_cb_.is_null()); | 105 DCHECK(!read_cb_.is_null()); |
104 return; | 106 return; |
105 } | 107 } |
106 | 108 |
107 if (state_ == kWaitingForKey) { | 109 if (state_ == kWaitingForKey) { |
108 DCHECK(!read_cb_.is_null()); | 110 DCHECK(!read_cb_.is_null()); |
109 pending_buffer_to_decrypt_ = NULL; | 111 pending_buffer_to_decrypt_ = NULL; |
110 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 112 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
111 } | 113 } |
112 | 114 |
113 DCHECK(read_cb_.is_null()); | 115 DCHECK(read_cb_.is_null()); |
114 DoReset(); | 116 DoReset(); |
115 } | 117 } |
116 | 118 |
117 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() { | 119 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() { |
118 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 120 DCHECK(state_ != kUninitialized) << state_; |
119 CHECK_EQ(demuxer_stream_->type(), AUDIO); | 121 CHECK_EQ(demuxer_stream_->type(), AUDIO); |
120 return audio_config_; | 122 return audio_config_; |
121 } | 123 } |
122 | 124 |
123 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() { | 125 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() { |
124 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 126 DCHECK(state_ != kUninitialized) << state_; |
125 CHECK_EQ(demuxer_stream_->type(), VIDEO); | 127 CHECK_EQ(demuxer_stream_->type(), VIDEO); |
126 return video_config_; | 128 return video_config_; |
127 } | 129 } |
128 | 130 |
129 DemuxerStream::Type DecryptingDemuxerStream::type() const { | 131 DemuxerStream::Type DecryptingDemuxerStream::type() const { |
130 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 132 DCHECK(state_ != kUninitialized) << state_; |
131 return demuxer_stream_->type(); | 133 return demuxer_stream_->type(); |
132 } | 134 } |
133 | 135 |
134 DemuxerStream::Liveness DecryptingDemuxerStream::liveness() const { | 136 DemuxerStream::Liveness DecryptingDemuxerStream::liveness() const { |
135 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 137 DCHECK(state_ != kUninitialized) << state_; |
136 return demuxer_stream_->liveness(); | 138 return demuxer_stream_->liveness(); |
137 } | 139 } |
138 | 140 |
139 void DecryptingDemuxerStream::EnableBitstreamConverter() { | 141 void DecryptingDemuxerStream::EnableBitstreamConverter() { |
140 demuxer_stream_->EnableBitstreamConverter(); | 142 demuxer_stream_->EnableBitstreamConverter(); |
141 } | 143 } |
142 | 144 |
143 bool DecryptingDemuxerStream::SupportsConfigChanges() { | 145 bool DecryptingDemuxerStream::SupportsConfigChanges() { |
144 return demuxer_stream_->SupportsConfigChanges(); | 146 return demuxer_stream_->SupportsConfigChanges(); |
145 } | 147 } |
146 | 148 |
147 VideoRotation DecryptingDemuxerStream::video_rotation() { | 149 VideoRotation DecryptingDemuxerStream::video_rotation() { |
148 return demuxer_stream_->video_rotation(); | 150 return demuxer_stream_->video_rotation(); |
149 } | 151 } |
150 | 152 |
151 DecryptingDemuxerStream::~DecryptingDemuxerStream() { | 153 DecryptingDemuxerStream::~DecryptingDemuxerStream() { |
152 DVLOG(2) << __FUNCTION__ << " : state_ = " << state_; | 154 DVLOG(2) << __FUNCTION__ << " : state_ = " << state_; |
153 DCHECK(task_runner_->BelongsToCurrentThread()); | 155 DCHECK(task_runner_->BelongsToCurrentThread()); |
154 | 156 |
155 if (state_ == kUninitialized) | 157 if (state_ == kUninitialized) |
156 return; | 158 return; |
157 | 159 |
158 if (decryptor_) { | 160 if (decryptor_) { |
159 decryptor_->CancelDecrypt(GetDecryptorStreamType()); | 161 decryptor_->CancelDecrypt(GetDecryptorStreamType()); |
160 decryptor_ = NULL; | 162 decryptor_ = NULL; |
161 } | 163 } |
162 if (!set_cdm_ready_cb_.is_null()) | |
163 base::ResetAndReturn(&set_cdm_ready_cb_).Run(CdmReadyCB()); | |
164 if (!init_cb_.is_null()) | 164 if (!init_cb_.is_null()) |
165 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | 165 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
166 if (!read_cb_.is_null()) | 166 if (!read_cb_.is_null()) |
167 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 167 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
168 if (!reset_cb_.is_null()) | 168 if (!reset_cb_.is_null()) |
169 base::ResetAndReturn(&reset_cb_).Run(); | 169 base::ResetAndReturn(&reset_cb_).Run(); |
170 pending_buffer_to_decrypt_ = NULL; | 170 pending_buffer_to_decrypt_ = NULL; |
171 } | 171 } |
172 | 172 |
173 void DecryptingDemuxerStream::SetCdm(CdmContext* cdm_context, | |
174 const CdmAttachedCB& cdm_attached_cb) { | |
175 DVLOG(2) << __FUNCTION__; | |
176 DCHECK(task_runner_->BelongsToCurrentThread()); | |
177 DCHECK_EQ(state_, kDecryptorRequested) << state_; | |
178 DCHECK(!init_cb_.is_null()); | |
179 DCHECK(!set_cdm_ready_cb_.is_null()); | |
180 | |
181 set_cdm_ready_cb_.Reset(); | |
182 | |
183 if (!cdm_context || !cdm_context->GetDecryptor()) { | |
184 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": decryptor not set"; | |
185 state_ = kUninitialized; | |
186 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | |
187 cdm_attached_cb.Run(false); | |
188 return; | |
189 } | |
190 | |
191 decryptor_ = cdm_context->GetDecryptor(); | |
192 | |
193 decryptor_->RegisterNewKeyCB( | |
194 GetDecryptorStreamType(), | |
195 BindToCurrentLoop( | |
196 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_))); | |
197 | |
198 state_ = kIdle; | |
199 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | |
200 cdm_attached_cb.Run(true); | |
201 } | |
202 | |
203 void DecryptingDemuxerStream::DecryptBuffer( | 173 void DecryptingDemuxerStream::DecryptBuffer( |
204 DemuxerStream::Status status, | 174 DemuxerStream::Status status, |
205 const scoped_refptr<DecoderBuffer>& buffer) { | 175 const scoped_refptr<DecoderBuffer>& buffer) { |
206 DVLOG(3) << __FUNCTION__; | 176 DVLOG(3) << __FUNCTION__; |
207 DCHECK(task_runner_->BelongsToCurrentThread()); | 177 DCHECK(task_runner_->BelongsToCurrentThread()); |
208 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 178 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
209 DCHECK(!read_cb_.is_null()); | 179 DCHECK(!read_cb_.is_null()); |
210 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status; | 180 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status; |
211 | 181 |
212 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to | 182 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 state_ = kPendingDecrypt; | 316 state_ = kPendingDecrypt; |
347 DecryptPendingBuffer(); | 317 DecryptPendingBuffer(); |
348 } | 318 } |
349 } | 319 } |
350 | 320 |
351 void DecryptingDemuxerStream::DoReset() { | 321 void DecryptingDemuxerStream::DoReset() { |
352 DCHECK(state_ != kUninitialized); | 322 DCHECK(state_ != kUninitialized); |
353 DCHECK(init_cb_.is_null()); | 323 DCHECK(init_cb_.is_null()); |
354 DCHECK(read_cb_.is_null()); | 324 DCHECK(read_cb_.is_null()); |
355 | 325 |
356 if (state_ == kDecryptorRequested) | 326 state_ = kIdle; |
357 state_ = kUninitialized; | |
358 else | |
359 state_ = kIdle; | |
360 | |
361 base::ResetAndReturn(&reset_cb_).Run(); | 327 base::ResetAndReturn(&reset_cb_).Run(); |
362 } | 328 } |
363 | 329 |
364 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { | 330 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { |
365 if (demuxer_stream_->type() == AUDIO) | 331 if (demuxer_stream_->type() == AUDIO) |
366 return Decryptor::kAudio; | 332 return Decryptor::kAudio; |
367 | 333 |
368 DCHECK_EQ(demuxer_stream_->type(), VIDEO); | 334 DCHECK_EQ(demuxer_stream_->type(), VIDEO); |
369 return Decryptor::kVideo; | 335 return Decryptor::kVideo; |
370 } | 336 } |
(...skipping 30 matching lines...) Expand all Loading... |
401 break; | 367 break; |
402 } | 368 } |
403 | 369 |
404 default: | 370 default: |
405 NOTREACHED(); | 371 NOTREACHED(); |
406 return; | 372 return; |
407 } | 373 } |
408 } | 374 } |
409 | 375 |
410 } // namespace media | 376 } // namespace media |
OLD | NEW |