Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: media/filters/decrypting_demuxer_stream.cc

Issue 14232017: Clean up media::DecryptingDemuxerStream. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « media/filters/decrypting_demuxer_stream.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 19 matching lines...) Expand all
30 (stream->type() == DemuxerStream::VIDEO && 30 (stream->type() == DemuxerStream::VIDEO &&
31 stream->video_decoder_config().IsValidConfig() && 31 stream->video_decoder_config().IsValidConfig() &&
32 stream->video_decoder_config().is_encrypted())); 32 stream->video_decoder_config().is_encrypted()));
33 } 33 }
34 34
35 DecryptingDemuxerStream::DecryptingDemuxerStream( 35 DecryptingDemuxerStream::DecryptingDemuxerStream(
36 const scoped_refptr<base::MessageLoopProxy>& message_loop, 36 const scoped_refptr<base::MessageLoopProxy>& message_loop,
37 const SetDecryptorReadyCB& set_decryptor_ready_cb) 37 const SetDecryptorReadyCB& set_decryptor_ready_cb)
38 : message_loop_(message_loop), 38 : message_loop_(message_loop),
39 state_(kUninitialized), 39 state_(kUninitialized),
40 stream_type_(UNKNOWN),
41 set_decryptor_ready_cb_(set_decryptor_ready_cb), 40 set_decryptor_ready_cb_(set_decryptor_ready_cb),
42 decryptor_(NULL), 41 decryptor_(NULL),
43 key_added_while_decrypt_pending_(false) { 42 key_added_while_decrypt_pending_(false) {
44 } 43 }
45 44
46 void DecryptingDemuxerStream::Initialize( 45 void DecryptingDemuxerStream::Initialize(
47 const scoped_refptr<DemuxerStream>& stream, 46 const scoped_refptr<DemuxerStream>& stream,
48 const PipelineStatusCB& status_cb) { 47 const PipelineStatusCB& status_cb) {
49 if (!message_loop_->BelongsToCurrentThread()) { 48 DVLOG(2) << "Initialize()";
50 message_loop_->PostTask(FROM_HERE, base::Bind( 49 DCHECK(message_loop_->BelongsToCurrentThread());
51 &DecryptingDemuxerStream::DoInitialize, this, stream, status_cb)); 50 DCHECK_EQ(state_, kUninitialized) << state_;
52 return; 51
53 } 52 DCHECK(!demuxer_stream_);
54 DoInitialize(stream, status_cb); 53 demuxer_stream_ = stream;
54 init_cb_ = status_cb;
55
56 InitializeDecoderConfig();
57
58 state_ = kDecryptorRequested;
59 set_decryptor_ready_cb_.Run(
60 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor));
55 } 61 }
56 62
57 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) { 63 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) {
58 DVLOG(3) << "Read()"; 64 DVLOG(3) << "Read()";
59 DCHECK(message_loop_->BelongsToCurrentThread()); 65 DCHECK(message_loop_->BelongsToCurrentThread());
60 DCHECK_EQ(state_, kIdle) << state_; 66 DCHECK_EQ(state_, kIdle) << state_;
61 DCHECK(!read_cb.is_null()); 67 DCHECK(!read_cb.is_null());
62 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported."; 68 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported.";
63 69
64 read_cb_ = read_cb; 70 read_cb_ = read_cb;
65 state_ = kPendingDemuxerRead; 71 state_ = kPendingDemuxerRead;
66 demuxer_stream_->Read( 72 demuxer_stream_->Read(
67 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, this)); 73 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, this));
68 } 74 }
69 75
70 void DecryptingDemuxerStream::Reset(const base::Closure& closure) { 76 void DecryptingDemuxerStream::Reset(const base::Closure& closure) {
71 if (!message_loop_->BelongsToCurrentThread()) {
72 message_loop_->PostTask(FROM_HERE, base::Bind(
73 &DecryptingDemuxerStream::Reset, this, closure));
74 return;
75 }
76
77 DVLOG(2) << "Reset() - state: " << state_; 77 DVLOG(2) << "Reset() - state: " << state_;
78 DCHECK(message_loop_->BelongsToCurrentThread());
78 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; 79 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
79 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. 80 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
80 DCHECK(reset_cb_.is_null()); 81 DCHECK(reset_cb_.is_null());
81 82
82 reset_cb_ = BindToCurrentLoop(closure); 83 reset_cb_ = BindToCurrentLoop(closure);
83 84
84 decryptor_->CancelDecrypt(GetDecryptorStreamType()); 85 decryptor_->CancelDecrypt(GetDecryptorStreamType());
85 86
86 // Reset() cannot complete if the read callback is still pending. 87 // Reset() cannot complete if the read callback is still pending.
87 // Defer the resetting process in this case. The |reset_cb_| will be fired 88 // Defer the resetting process in this case. The |reset_cb_| will be fired
88 // after the read callback is fired - see DoDecryptBuffer() and 89 // after the read callback is fired - see DoDecryptBuffer() and
89 // DoDeliverBuffer(). 90 // DoDeliverBuffer().
90 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) { 91 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) {
91 DCHECK(!read_cb_.is_null()); 92 DCHECK(!read_cb_.is_null());
92 return; 93 return;
93 } 94 }
94 95
95 if (state_ == kWaitingForKey) { 96 if (state_ == kWaitingForKey) {
96 DCHECK(!read_cb_.is_null()); 97 DCHECK(!read_cb_.is_null());
97 pending_buffer_to_decrypt_ = NULL; 98 pending_buffer_to_decrypt_ = NULL;
98 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); 99 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
99 } 100 }
100 101
101 DCHECK(read_cb_.is_null()); 102 DCHECK(read_cb_.is_null());
102 DoReset(); 103 DoReset();
103 } 104 }
104 105
105 const AudioDecoderConfig& DecryptingDemuxerStream::audio_decoder_config() { 106 const AudioDecoderConfig& DecryptingDemuxerStream::audio_decoder_config() {
106 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; 107 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
107 CHECK_EQ(stream_type_, AUDIO); 108 CHECK_EQ(demuxer_stream_->type(), AUDIO);
ddorwin 2013/04/17 21:45:47 Do we need to protect against demuxer_stream_ bein
xhwang 2013/04/17 22:14:47 I think audio_decoder_config should only be called
108 return *audio_config_; 109 return *audio_config_;
109 } 110 }
110 111
111 const VideoDecoderConfig& DecryptingDemuxerStream::video_decoder_config() { 112 const VideoDecoderConfig& DecryptingDemuxerStream::video_decoder_config() {
112 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; 113 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
113 CHECK_EQ(stream_type_, VIDEO); 114 CHECK_EQ(demuxer_stream_->type(), VIDEO);
114 return *video_config_; 115 return *video_config_;
115 } 116 }
116 117
117 DemuxerStream::Type DecryptingDemuxerStream::type() { 118 DemuxerStream::Type DecryptingDemuxerStream::type() {
118 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; 119 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
119 return stream_type_; 120 return demuxer_stream_->type();
120 } 121 }
121 122
122 void DecryptingDemuxerStream::EnableBitstreamConverter() { 123 void DecryptingDemuxerStream::EnableBitstreamConverter() {
123 demuxer_stream_->EnableBitstreamConverter(); 124 demuxer_stream_->EnableBitstreamConverter();
124 } 125 }
125 126
126 DecryptingDemuxerStream::~DecryptingDemuxerStream() {} 127 DecryptingDemuxerStream::~DecryptingDemuxerStream() {}
127 128
128 void DecryptingDemuxerStream::DoInitialize(
129 const scoped_refptr<DemuxerStream>& stream,
130 const PipelineStatusCB& status_cb) {
131 DVLOG(2) << "DoInitialize()";
132 DCHECK(message_loop_->BelongsToCurrentThread());
133 DCHECK_EQ(state_, kUninitialized) << state_;
134
135 DCHECK(!demuxer_stream_);
136 demuxer_stream_ = stream;
137 stream_type_ = stream->type();
138 init_cb_ = status_cb;
139
140 SetDecoderConfig(stream);
141
142 state_ = kDecryptorRequested;
143 set_decryptor_ready_cb_.Run(
144 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor));
145 }
146
147 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) { 129 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) {
148 DVLOG(2) << "SetDecryptor()"; 130 DVLOG(2) << "SetDecryptor()";
149 DCHECK(message_loop_->BelongsToCurrentThread()); 131 DCHECK(message_loop_->BelongsToCurrentThread());
150 DCHECK_EQ(state_, kDecryptorRequested) << state_; 132 DCHECK_EQ(state_, kDecryptorRequested) << state_;
151 DCHECK(!init_cb_.is_null()); 133 DCHECK(!init_cb_.is_null());
152 DCHECK(!set_decryptor_ready_cb_.is_null()); 134 DCHECK(!set_decryptor_ready_cb_.is_null());
153 135
154 set_decryptor_ready_cb_.Reset(); 136 set_decryptor_ready_cb_.Reset();
155 decryptor_ = decryptor; 137 decryptor_ = decryptor;
156 138
157 decryptor_->RegisterNewKeyCB( 139 decryptor_->RegisterNewKeyCB(
158 GetDecryptorStreamType(), 140 GetDecryptorStreamType(),
159 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded)); 141 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded));
160 142
161 state_ = kIdle; 143 state_ = kIdle;
162 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 144 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
163 } 145 }
164 146
165 void DecryptingDemuxerStream::DecryptBuffer( 147 void DecryptingDemuxerStream::DecryptBuffer(
166 DemuxerStream::Status status, 148 DemuxerStream::Status status,
167 const scoped_refptr<DecoderBuffer>& buffer) { 149 const scoped_refptr<DecoderBuffer>& buffer) {
168 // In theory, we don't need to force post the task here, because we do a 150 DVLOG(3) << "DecryptBuffer()";
169 // force task post in DeliverBuffer(). Therefore, even if
170 // demuxer_stream_->Read() execute the read callback on the same execution
171 // stack we are still fine. But it looks like a force post task makes the
172 // logic more understandable and manageable, so why not?
173 message_loop_->PostTask(FROM_HERE, base::Bind(
174 &DecryptingDemuxerStream::DoDecryptBuffer, this, status, buffer));
175 }
176
177 void DecryptingDemuxerStream::DoDecryptBuffer(
178 DemuxerStream::Status status,
179 const scoped_refptr<DecoderBuffer>& buffer) {
180 DVLOG(3) << "DoDecryptBuffer()";
181 DCHECK(message_loop_->BelongsToCurrentThread()); 151 DCHECK(message_loop_->BelongsToCurrentThread());
182 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 152 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
183 DCHECK(!read_cb_.is_null()); 153 DCHECK(!read_cb_.is_null());
184 DCHECK_EQ(buffer != NULL, status == kOk) << status; 154 DCHECK_EQ(buffer != NULL, status == kOk) << status;
185 155
186 if (!reset_cb_.is_null()) { 156 if (!reset_cb_.is_null()) {
187 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); 157 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
188 DoReset(); 158 DoReset();
189 return; 159 return;
190 } 160 }
191 161
192 if (status == kAborted) { 162 if (status == kAborted) {
193 DVLOG(2) << "DoDecryptBuffer() - kAborted."; 163 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
194 state_ = kIdle; 164 state_ = kIdle;
195 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); 165 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
196 return; 166 return;
197 } 167 }
198 168
199 if (status == kConfigChanged) { 169 if (status == kConfigChanged) {
200 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged."; 170 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
201 DCHECK_EQ(demuxer_stream_->type(), stream_type_); 171 DCHECK_EQ(demuxer_stream_->type() == AUDIO, audio_config_ != NULL);
172 DCHECK_EQ(demuxer_stream_->type() == VIDEO, video_config_ != NULL);
202 173
203 // Update the decoder config, which the decoder will use when it is notified 174 // Update the decoder config, which the decoder will use when it is notified
204 // of kConfigChanged. 175 // of kConfigChanged.
205 SetDecoderConfig(demuxer_stream_); 176 InitializeDecoderConfig();
206 state_ = kIdle; 177 state_ = kIdle;
207 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL); 178 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL);
208 return; 179 return;
209 } 180 }
210 181
211 if (buffer->IsEndOfStream()) { 182 if (buffer->IsEndOfStream()) {
212 DVLOG(2) << "DoDecryptBuffer() - EOS buffer."; 183 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
213 state_ = kIdle; 184 state_ = kIdle;
214 base::ResetAndReturn(&read_cb_).Run(status, buffer); 185 base::ResetAndReturn(&read_cb_).Run(status, buffer);
215 return; 186 return;
216 } 187 }
217 188
218 pending_buffer_to_decrypt_ = buffer; 189 pending_buffer_to_decrypt_ = buffer;
219 state_ = kPendingDecrypt; 190 state_ = kPendingDecrypt;
220 DecryptPendingBuffer(); 191 DecryptPendingBuffer();
221 } 192 }
222 193
223 void DecryptingDemuxerStream::DecryptPendingBuffer() { 194 void DecryptingDemuxerStream::DecryptPendingBuffer() {
224 DCHECK(message_loop_->BelongsToCurrentThread()); 195 DCHECK(message_loop_->BelongsToCurrentThread());
225 DCHECK_EQ(state_, kPendingDecrypt) << state_; 196 DCHECK_EQ(state_, kPendingDecrypt) << state_;
226 decryptor_->Decrypt( 197 decryptor_->Decrypt(
227 GetDecryptorStreamType(), 198 GetDecryptorStreamType(),
228 pending_buffer_to_decrypt_, 199 pending_buffer_to_decrypt_,
229 base::Bind(&DecryptingDemuxerStream::DeliverBuffer, this)); 200 BIND_TO_LOOP(&DecryptingDemuxerStream::DeliverBuffer));
xhwang 2013/04/17 22:14:47 Now I feel bad about AesDecryptor firing callbacks
230 } 201 }
231 202
232 void DecryptingDemuxerStream::DeliverBuffer( 203 void DecryptingDemuxerStream::DeliverBuffer(
233 Decryptor::Status status, 204 Decryptor::Status status,
234 const scoped_refptr<DecoderBuffer>& decrypted_buffer) { 205 const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
235 // We need to force task post here because the DecryptCB can be executed 206 DVLOG(3) << "DeliverBuffer() - status: " << status;
ddorwin 2013/04/17 21:45:47 Synchronous calls from Reset() are no longer a con
xhwang 2013/04/17 22:14:47 The BIND_TO_LOOP force posts the DecryptCB so we s
236 // synchronously in Reset(). Instead of using more complicated logic in
237 // those function to fix it, why not force task post here to make everything
238 // simple and clear?
239 message_loop_->PostTask(FROM_HERE, base::Bind(
240 &DecryptingDemuxerStream::DoDeliverBuffer, this,
241 status, decrypted_buffer));
242 }
243
244 void DecryptingDemuxerStream::DoDeliverBuffer(
245 Decryptor::Status status,
246 const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
247 DVLOG(3) << "DoDeliverBuffer() - status: " << status;
248 DCHECK(message_loop_->BelongsToCurrentThread()); 207 DCHECK(message_loop_->BelongsToCurrentThread());
249 DCHECK_EQ(state_, kPendingDecrypt) << state_; 208 DCHECK_EQ(state_, kPendingDecrypt) << state_;
250 DCHECK_NE(status, Decryptor::kNeedMoreData); 209 DCHECK_NE(status, Decryptor::kNeedMoreData);
251 DCHECK(!read_cb_.is_null()); 210 DCHECK(!read_cb_.is_null());
252 DCHECK(pending_buffer_to_decrypt_); 211 DCHECK(pending_buffer_to_decrypt_);
253 212
254 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_; 213 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_;
255 key_added_while_decrypt_pending_ = false; 214 key_added_while_decrypt_pending_ = false;
256 215
257 if (!reset_cb_.is_null()) { 216 if (!reset_cb_.is_null()) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 } 263 }
305 264
306 void DecryptingDemuxerStream::DoReset() { 265 void DecryptingDemuxerStream::DoReset() {
307 DCHECK(init_cb_.is_null()); 266 DCHECK(init_cb_.is_null());
308 DCHECK(read_cb_.is_null()); 267 DCHECK(read_cb_.is_null());
309 state_ = kIdle; 268 state_ = kIdle;
310 base::ResetAndReturn(&reset_cb_).Run(); 269 base::ResetAndReturn(&reset_cb_).Run();
311 } 270 }
312 271
313 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { 272 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const {
314 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO); 273 if (demuxer_stream_->type() == AUDIO)
315 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo; 274 return Decryptor::kAudio;
275
276 DCHECK_EQ(demuxer_stream_->type(), VIDEO);
277 return Decryptor::kVideo;
316 } 278 }
317 279
318 void DecryptingDemuxerStream::SetDecoderConfig( 280 void DecryptingDemuxerStream::InitializeDecoderConfig() {
319 const scoped_refptr<DemuxerStream>& stream) {
320 // The decoder selector or upstream demuxer make sure the stream is valid and 281 // The decoder selector or upstream demuxer make sure the stream is valid and
321 // potentially encrypted. 282 // potentially encrypted.
322 DCHECK(IsStreamValidAndEncrypted(stream)); 283 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_));
323 284
324 switch (stream_type_) { 285 switch (demuxer_stream_->type()) {
325 case AUDIO: { 286 case AUDIO: {
326 const AudioDecoderConfig& input_audio_config = 287 const AudioDecoderConfig& input_audio_config =
327 stream->audio_decoder_config(); 288 demuxer_stream_->audio_decoder_config();
328 audio_config_.reset(new AudioDecoderConfig()); 289 audio_config_.reset(new AudioDecoderConfig());
329 audio_config_->Initialize(input_audio_config.codec(), 290 audio_config_->Initialize(input_audio_config.codec(),
330 input_audio_config.sample_format(), 291 input_audio_config.sample_format(),
331 input_audio_config.channel_layout(), 292 input_audio_config.channel_layout(),
332 input_audio_config.samples_per_second(), 293 input_audio_config.samples_per_second(),
333 input_audio_config.extra_data(), 294 input_audio_config.extra_data(),
334 input_audio_config.extra_data_size(), 295 input_audio_config.extra_data_size(),
335 false, // Output audio is not encrypted. 296 false, // Output audio is not encrypted.
336 false); 297 false);
337 break; 298 break;
338 } 299 }
339 300
340 case VIDEO: { 301 case VIDEO: {
341 const VideoDecoderConfig& input_video_config = 302 const VideoDecoderConfig& input_video_config =
342 stream->video_decoder_config(); 303 demuxer_stream_->video_decoder_config();
343 video_config_.reset(new VideoDecoderConfig()); 304 video_config_.reset(new VideoDecoderConfig());
344 video_config_->Initialize(input_video_config.codec(), 305 video_config_->Initialize(input_video_config.codec(),
345 input_video_config.profile(), 306 input_video_config.profile(),
346 input_video_config.format(), 307 input_video_config.format(),
347 input_video_config.coded_size(), 308 input_video_config.coded_size(),
348 input_video_config.visible_rect(), 309 input_video_config.visible_rect(),
349 input_video_config.natural_size(), 310 input_video_config.natural_size(),
350 input_video_config.extra_data(), 311 input_video_config.extra_data(),
351 input_video_config.extra_data_size(), 312 input_video_config.extra_data_size(),
352 false, // Output video is not encrypted. 313 false, // Output video is not encrypted.
353 false); 314 false);
354 break; 315 break;
355 } 316 }
356 317
357 default: 318 default:
358 NOTREACHED(); 319 NOTREACHED();
359 return; 320 return;
360 } 321 }
361 } 322 }
362 323
363 } // namespace media 324 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decrypting_demuxer_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698