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

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

Issue 13813016: Remove reference counting from media::Demuxer and friends. (Closed) Base URL: http://git.chromium.org/chromium/src.git@vd_scoped
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
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"
11 #include "base/message_loop_proxy.h" 11 #include "base/message_loop_proxy.h"
12 #include "media/base/audio_decoder_config.h" 12 #include "media/base/audio_decoder_config.h"
13 #include "media/base/video_decoder_config.h" 13 #include "media/base/video_decoder_config.h"
14 #include "media/base/bind_to_loop.h" 14 #include "media/base/bind_to_loop.h"
15 #include "media/base/decoder_buffer.h" 15 #include "media/base/decoder_buffer.h"
16 #include "media/base/decryptor.h" 16 #include "media/base/decryptor.h"
17 #include "media/base/demuxer_stream.h" 17 #include "media/base/demuxer_stream.h"
18 #include "media/base/pipeline.h" 18 #include "media/base/pipeline.h"
19 19
20 namespace media { 20 namespace media {
21 21
22 #define BIND_TO_LOOP(function) \ 22 #define BIND_TO_LOOP(function) \
23 media::BindToLoop(message_loop_, base::Bind(function, this)) 23 media::BindToLoop(message_loop_, base::Bind(function, weak_this_))
24 24
25 static bool IsStreamValidAndEncrypted( 25 static bool IsStreamValidAndEncrypted(DemuxerStream* stream) {
26 const scoped_refptr<DemuxerStream>& stream) {
27 return ((stream->type() == DemuxerStream::AUDIO && 26 return ((stream->type() == DemuxerStream::AUDIO &&
28 stream->audio_decoder_config().IsValidConfig() && 27 stream->audio_decoder_config().IsValidConfig() &&
29 stream->audio_decoder_config().is_encrypted()) || 28 stream->audio_decoder_config().is_encrypted()) ||
30 (stream->type() == DemuxerStream::VIDEO && 29 (stream->type() == DemuxerStream::VIDEO &&
31 stream->video_decoder_config().IsValidConfig() && 30 stream->video_decoder_config().IsValidConfig() &&
32 stream->video_decoder_config().is_encrypted())); 31 stream->video_decoder_config().is_encrypted()));
33 } 32 }
34 33
35 DecryptingDemuxerStream::DecryptingDemuxerStream( 34 DecryptingDemuxerStream::DecryptingDemuxerStream(
36 const scoped_refptr<base::MessageLoopProxy>& message_loop, 35 const scoped_refptr<base::MessageLoopProxy>& message_loop,
37 const SetDecryptorReadyCB& set_decryptor_ready_cb) 36 const SetDecryptorReadyCB& set_decryptor_ready_cb)
38 : message_loop_(message_loop), 37 : message_loop_(message_loop),
38 weak_factory_(this),
39 state_(kUninitialized), 39 state_(kUninitialized),
40 demuxer_stream_(NULL),
40 stream_type_(UNKNOWN), 41 stream_type_(UNKNOWN),
41 set_decryptor_ready_cb_(set_decryptor_ready_cb), 42 set_decryptor_ready_cb_(set_decryptor_ready_cb),
42 decryptor_(NULL), 43 decryptor_(NULL),
43 key_added_while_decrypt_pending_(false) { 44 key_added_while_decrypt_pending_(false) {
44 } 45 }
45 46
46 void DecryptingDemuxerStream::Initialize( 47 void DecryptingDemuxerStream::Initialize(
47 const scoped_refptr<DemuxerStream>& stream, 48 DemuxerStream* stream,
48 const PipelineStatusCB& status_cb) { 49 const PipelineStatusCB& status_cb) {
49 if (!message_loop_->BelongsToCurrentThread()) { 50 DVLOG(2) << "Initialize()";
acolwell GONE FROM CHROMIUM 2013/04/17 20:24:53 Would you mind moving these transformations to a s
scherkus (not reviewing) 2013/04/19 01:07:22 Done and landed http://crrev.com/194721
50 message_loop_->PostTask(FROM_HERE, base::Bind( 51 DCHECK(message_loop_->BelongsToCurrentThread());
51 &DecryptingDemuxerStream::DoInitialize, this, stream, status_cb)); 52 DCHECK_EQ(state_, kUninitialized) << state_;
52 return; 53
53 } 54 DCHECK(!demuxer_stream_);
54 DoInitialize(stream, status_cb); 55 weak_this_ = weak_factory_.GetWeakPtr();
56 demuxer_stream_ = stream;
57 stream_type_ = stream->type();
58 init_cb_ = status_cb;
59
60 SetDecoderConfig(stream);
61
62 state_ = kDecryptorRequested;
63 set_decryptor_ready_cb_.Run(
64 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor));
55 } 65 }
56 66
57 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) { 67 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) {
58 DVLOG(3) << "Read()"; 68 DVLOG(3) << "Read()";
59 DCHECK(message_loop_->BelongsToCurrentThread()); 69 DCHECK(message_loop_->BelongsToCurrentThread());
60 DCHECK_EQ(state_, kIdle) << state_; 70 DCHECK_EQ(state_, kIdle) << state_;
61 DCHECK(!read_cb.is_null()); 71 DCHECK(!read_cb.is_null());
62 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported."; 72 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported.";
63 73
64 read_cb_ = read_cb; 74 read_cb_ = read_cb;
65 state_ = kPendingDemuxerRead; 75 state_ = kPendingDemuxerRead;
66 demuxer_stream_->Read( 76 demuxer_stream_->Read(
67 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, this)); 77 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_));
68 } 78 }
69 79
70 void DecryptingDemuxerStream::Reset(const base::Closure& closure) { 80 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_; 81 DVLOG(2) << "Reset() - state: " << state_;
82 DCHECK(message_loop_->BelongsToCurrentThread());
78 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; 83 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
79 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. 84 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
80 DCHECK(reset_cb_.is_null()); 85 DCHECK(reset_cb_.is_null());
81 86
82 reset_cb_ = BindToCurrentLoop(closure); 87 reset_cb_ = BindToCurrentLoop(closure);
83 88
84 decryptor_->CancelDecrypt(GetDecryptorStreamType()); 89 decryptor_->CancelDecrypt(GetDecryptorStreamType());
85 90
86 // Reset() cannot complete if the read callback is still pending. 91 // Reset() cannot complete if the read callback is still pending.
87 // Defer the resetting process in this case. The |reset_cb_| will be fired 92 // Defer the resetting process in this case. The |reset_cb_| will be fired
(...skipping 30 matching lines...) Expand all
118 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; 123 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
119 return stream_type_; 124 return stream_type_;
120 } 125 }
121 126
122 void DecryptingDemuxerStream::EnableBitstreamConverter() { 127 void DecryptingDemuxerStream::EnableBitstreamConverter() {
123 demuxer_stream_->EnableBitstreamConverter(); 128 demuxer_stream_->EnableBitstreamConverter();
124 } 129 }
125 130
126 DecryptingDemuxerStream::~DecryptingDemuxerStream() {} 131 DecryptingDemuxerStream::~DecryptingDemuxerStream() {}
127 132
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) { 133 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) {
148 DVLOG(2) << "SetDecryptor()"; 134 DVLOG(2) << "SetDecryptor()";
149 DCHECK(message_loop_->BelongsToCurrentThread()); 135 DCHECK(message_loop_->BelongsToCurrentThread());
150 DCHECK_EQ(state_, kDecryptorRequested) << state_; 136 DCHECK_EQ(state_, kDecryptorRequested) << state_;
151 DCHECK(!init_cb_.is_null()); 137 DCHECK(!init_cb_.is_null());
152 DCHECK(!set_decryptor_ready_cb_.is_null()); 138 DCHECK(!set_decryptor_ready_cb_.is_null());
153 139
154 set_decryptor_ready_cb_.Reset(); 140 set_decryptor_ready_cb_.Reset();
155 decryptor_ = decryptor; 141 decryptor_ = decryptor;
156 142
157 decryptor_->RegisterNewKeyCB( 143 decryptor_->RegisterNewKeyCB(
158 GetDecryptorStreamType(), 144 GetDecryptorStreamType(),
159 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded)); 145 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded));
160 146
161 state_ = kIdle; 147 state_ = kIdle;
162 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 148 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
163 } 149 }
164 150
165 void DecryptingDemuxerStream::DecryptBuffer( 151 void DecryptingDemuxerStream::DecryptBuffer(
166 DemuxerStream::Status status, 152 DemuxerStream::Status status,
167 const scoped_refptr<DecoderBuffer>& buffer) { 153 const scoped_refptr<DecoderBuffer>& buffer) {
168 // In theory, we don't need to force post the task here, because we do a 154 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()); 155 DCHECK(message_loop_->BelongsToCurrentThread());
182 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 156 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
183 DCHECK(!read_cb_.is_null()); 157 DCHECK(!read_cb_.is_null());
184 DCHECK_EQ(buffer != NULL, status == kOk) << status; 158 DCHECK_EQ(buffer != NULL, status == kOk) << status;
185 159
186 if (!reset_cb_.is_null()) { 160 if (!reset_cb_.is_null()) {
187 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); 161 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
188 DoReset(); 162 DoReset();
189 return; 163 return;
190 } 164 }
(...skipping 28 matching lines...) Expand all
219 state_ = kPendingDecrypt; 193 state_ = kPendingDecrypt;
220 DecryptPendingBuffer(); 194 DecryptPendingBuffer();
221 } 195 }
222 196
223 void DecryptingDemuxerStream::DecryptPendingBuffer() { 197 void DecryptingDemuxerStream::DecryptPendingBuffer() {
224 DCHECK(message_loop_->BelongsToCurrentThread()); 198 DCHECK(message_loop_->BelongsToCurrentThread());
225 DCHECK_EQ(state_, kPendingDecrypt) << state_; 199 DCHECK_EQ(state_, kPendingDecrypt) << state_;
226 decryptor_->Decrypt( 200 decryptor_->Decrypt(
227 GetDecryptorStreamType(), 201 GetDecryptorStreamType(),
228 pending_buffer_to_decrypt_, 202 pending_buffer_to_decrypt_,
229 base::Bind(&DecryptingDemuxerStream::DeliverBuffer, this)); 203 BIND_TO_LOOP(&DecryptingDemuxerStream::DeliverBuffer));
230 } 204 }
231 205
232 void DecryptingDemuxerStream::DeliverBuffer( 206 void DecryptingDemuxerStream::DeliverBuffer(
233 Decryptor::Status status, 207 Decryptor::Status status,
234 const scoped_refptr<DecoderBuffer>& decrypted_buffer) { 208 const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
235 // We need to force task post here because the DecryptCB can be executed 209 DVLOG(3) << "DeliverBuffer() - status: " << status;
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()); 210 DCHECK(message_loop_->BelongsToCurrentThread());
249 DCHECK_EQ(state_, kPendingDecrypt) << state_; 211 DCHECK_EQ(state_, kPendingDecrypt) << state_;
250 DCHECK_NE(status, Decryptor::kNeedMoreData); 212 DCHECK_NE(status, Decryptor::kNeedMoreData);
251 DCHECK(!read_cb_.is_null()); 213 DCHECK(!read_cb_.is_null());
252 DCHECK(pending_buffer_to_decrypt_); 214 DCHECK(pending_buffer_to_decrypt_);
253 215
254 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_; 216 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_;
255 key_added_while_decrypt_pending_ = false; 217 key_added_while_decrypt_pending_ = false;
256 218
257 if (!reset_cb_.is_null()) { 219 if (!reset_cb_.is_null()) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 DCHECK(read_cb_.is_null()); 270 DCHECK(read_cb_.is_null());
309 state_ = kIdle; 271 state_ = kIdle;
310 base::ResetAndReturn(&reset_cb_).Run(); 272 base::ResetAndReturn(&reset_cb_).Run();
311 } 273 }
312 274
313 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { 275 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const {
314 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO); 276 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO);
315 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo; 277 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo;
316 } 278 }
317 279
318 void DecryptingDemuxerStream::SetDecoderConfig( 280 void DecryptingDemuxerStream::SetDecoderConfig(DemuxerStream* stream) {
acolwell GONE FROM CHROMIUM 2013/04/17 20:24:53 nit: All callers essentially pass demuxer_stream_
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(stream));
323 284
324 switch (stream_type_) { 285 switch (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 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(),
(...skipping 24 matching lines...) Expand all
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

Powered by Google App Engine
This is Rietveld 408576698