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

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

Issue 11091005: Update PluginInstance for decrypt-and-decode video. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix a bug in ppp_content_decryptor_private_proxy.cc Created 8 years, 2 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_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/location.h" 9 #include "base/location.h"
10 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 &DecryptingVideoDecoder::DoRead, this, read_cb)); 49 &DecryptingVideoDecoder::DoRead, this, read_cb));
50 } 50 }
51 51
52 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { 52 void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
53 if (!message_loop_->BelongsToCurrentThread()) { 53 if (!message_loop_->BelongsToCurrentThread()) {
54 message_loop_->PostTask(FROM_HERE, base::Bind( 54 message_loop_->PostTask(FROM_HERE, base::Bind(
55 &DecryptingVideoDecoder::Reset, this, closure)); 55 &DecryptingVideoDecoder::Reset, this, closure));
56 return; 56 return;
57 } 57 }
58 58
59 DVLOG(2) << "Reset() - state: " << state_;
59 DCHECK(state_ == kIdle || 60 DCHECK(state_ == kIdle ||
60 state_ == kPendingDemuxerRead || 61 state_ == kPendingDemuxerRead ||
61 state_ == kPendingDecode || 62 state_ == kPendingDecode ||
62 state_ == kWaitingForKey || 63 state_ == kWaitingForKey ||
63 state_ == kDecodeFinished) << state_; 64 state_ == kDecodeFinished) << state_;
64 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. 65 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
65 DCHECK(stop_cb_.is_null()); // No Reset() during pending Stop(). 66 DCHECK(stop_cb_.is_null()); // No Reset() during pending Stop().
66 DCHECK(reset_cb_.is_null()); 67 DCHECK(reset_cb_.is_null());
67 68
68 reset_cb_ = closure; 69 reset_cb_ = closure;
(...skipping 19 matching lines...) Expand all
88 DoReset(); 89 DoReset();
89 } 90 }
90 91
91 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { 92 void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
92 if (!message_loop_->BelongsToCurrentThread()) { 93 if (!message_loop_->BelongsToCurrentThread()) {
93 message_loop_->PostTask(FROM_HERE, base::Bind( 94 message_loop_->PostTask(FROM_HERE, base::Bind(
94 &DecryptingVideoDecoder::Stop, this, closure)); 95 &DecryptingVideoDecoder::Stop, this, closure));
95 return; 96 return;
96 } 97 }
97 98
99 DVLOG(2) << "Stop() - state: " << state_;
98 DCHECK(stop_cb_.is_null()); 100 DCHECK(stop_cb_.is_null());
99 stop_cb_ = closure; 101 stop_cb_ = closure;
100 102
101 // We need to call Decryptor::StopVideoDecoder() if we ever called 103 // We need to call Decryptor::StopVideoDecoder() if we ever called
102 // Decryptor::InitializeVideoDecoder() to cancel the pending initialization if 104 // Decryptor::InitializeVideoDecoder() to cancel the pending initialization if
103 // the initialization is still pending, or to stop the video decoder if 105 // the initialization is still pending, or to stop the video decoder if
104 // the initialization has completed. 106 // the initialization has completed.
105 // When the state is kUninitialized and kDecryptorRequested, 107 // When the state is kUninitialized and kDecryptorRequested,
106 // InitializeVideoDecoder() has not been called, so we are okay. 108 // InitializeVideoDecoder() has not been called, so we are okay.
107 // When the state is kStopped, the video decoder should have already been 109 // When the state is kStopped, the video decoder should have already been
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 } 149 }
148 150
149 DecryptingVideoDecoder::~DecryptingVideoDecoder() { 151 DecryptingVideoDecoder::~DecryptingVideoDecoder() {
150 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; 152 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
151 } 153 }
152 154
153 void DecryptingVideoDecoder::DoInitialize( 155 void DecryptingVideoDecoder::DoInitialize(
154 const scoped_refptr<DemuxerStream>& stream, 156 const scoped_refptr<DemuxerStream>& stream,
155 const PipelineStatusCB& status_cb, 157 const PipelineStatusCB& status_cb,
156 const StatisticsCB& statistics_cb) { 158 const StatisticsCB& statistics_cb) {
159 DVLOG(2) << "DoInitialize()";
157 DCHECK(message_loop_->BelongsToCurrentThread()); 160 DCHECK(message_loop_->BelongsToCurrentThread());
158 DCHECK_EQ(state_, kUninitialized) << state_; 161 DCHECK_EQ(state_, kUninitialized) << state_;
159 DCHECK(stream); 162 DCHECK(stream);
160 163
161 const VideoDecoderConfig& config = stream->video_decoder_config(); 164 const VideoDecoderConfig& config = stream->video_decoder_config();
162 if (!config.IsValidConfig()) { 165 if (!config.IsValidConfig()) {
163 DLOG(ERROR) << "Invalid video stream config: " 166 DLOG(ERROR) << "Invalid video stream config: "
164 << config.AsHumanReadableString(); 167 << config.AsHumanReadableString();
165 status_cb.Run(PIPELINE_ERROR_DECODE); 168 status_cb.Run(PIPELINE_ERROR_DECODE);
166 return; 169 return;
(...skipping 10 matching lines...) Expand all
177 statistics_cb_ = statistics_cb; 180 statistics_cb_ = statistics_cb;
178 181
179 init_cb_ = status_cb; 182 init_cb_ = status_cb;
180 183
181 state_ = kDecryptorRequested; 184 state_ = kDecryptorRequested;
182 request_decryptor_notification_cb_.Run( 185 request_decryptor_notification_cb_.Run(
183 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor)); 186 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor));
184 } 187 }
185 188
186 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { 189 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) {
190 DVLOG(2) << "SetDecryptor()";
187 DCHECK(message_loop_->BelongsToCurrentThread()); 191 DCHECK(message_loop_->BelongsToCurrentThread());
188 DCHECK_EQ(state_, kDecryptorRequested) << state_; 192 DCHECK_EQ(state_, kDecryptorRequested) << state_;
189 DCHECK(!init_cb_.is_null()); 193 DCHECK(!init_cb_.is_null());
190 194
191 if (!stop_cb_.is_null()) { 195 if (!stop_cb_.is_null()) {
192 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 196 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
193 DoStop(); 197 DoStop();
194 return; 198 return;
195 } 199 }
196 200
197 decryptor_ = decryptor; 201 decryptor_ = decryptor;
198 202
199 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); 203 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig());
200 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); 204 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config());
201 205
202 state_ = kPendingDecoderInit; 206 state_ = kPendingDecoderInit;
203 decryptor_->InitializeVideoDecoder( 207 decryptor_->InitializeVideoDecoder(
204 scoped_config.Pass(), 208 scoped_config.Pass(),
205 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), 209 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization),
206 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); 210 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded));
207 } 211 }
208 212
209 void DecryptingVideoDecoder::FinishInitialization(bool success) { 213 void DecryptingVideoDecoder::FinishInitialization(bool success) {
214 DVLOG(2) << "FinishInitialization()";
210 DCHECK(message_loop_->BelongsToCurrentThread()); 215 DCHECK(message_loop_->BelongsToCurrentThread());
211 DCHECK_EQ(state_, kPendingDecoderInit) << state_; 216 DCHECK_EQ(state_, kPendingDecoderInit) << state_;
212 DCHECK(!init_cb_.is_null()); 217 DCHECK(!init_cb_.is_null());
213 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. 218 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
214 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. 219 DCHECK(read_cb_.is_null()); // No Read() before initialization finished.
215 220
216 if (!stop_cb_.is_null()) { 221 if (!stop_cb_.is_null()) {
217 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 222 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
218 DoStop(); 223 DoStop();
219 return; 224 return;
220 } 225 }
221 226
222 if (!success) { 227 if (!success) {
223 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 228 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
224 state_ = kStopped; 229 state_ = kStopped;
225 return; 230 return;
226 } 231 }
227 232
228 // Success! 233 // Success!
229 state_ = kIdle; 234 state_ = kIdle;
230 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 235 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
231 } 236 }
232 237
233 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { 238 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) {
239 DVLOG(3) << "DoRead()";
234 DCHECK(message_loop_->BelongsToCurrentThread()); 240 DCHECK(message_loop_->BelongsToCurrentThread());
235 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; 241 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
236 DCHECK(!read_cb.is_null()); 242 DCHECK(!read_cb.is_null());
237 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; 243 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
238 244
239 // Return empty frames if decoding has finished. 245 // Return empty frames if decoding has finished.
240 if (state_ == kDecodeFinished) { 246 if (state_ == kDecodeFinished) {
241 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); 247 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
242 return; 248 return;
243 } 249 }
(...skipping 20 matching lines...) Expand all
264 // demuxer_stream_->Read() execute the read callback on the same execution 270 // demuxer_stream_->Read() execute the read callback on the same execution
265 // stack we are still fine. But it looks like a force post task makes the 271 // stack we are still fine. But it looks like a force post task makes the
266 // logic more understandable and manageable, so why not? 272 // logic more understandable and manageable, so why not?
267 message_loop_->PostTask(FROM_HERE, base::Bind( 273 message_loop_->PostTask(FROM_HERE, base::Bind(
268 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); 274 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer));
269 } 275 }
270 276
271 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( 277 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
272 DemuxerStream::Status status, 278 DemuxerStream::Status status,
273 const scoped_refptr<DecoderBuffer>& buffer) { 279 const scoped_refptr<DecoderBuffer>& buffer) {
280 DVLOG(3) << "DoDecryptAndDecodeBuffer()";
274 DCHECK(message_loop_->BelongsToCurrentThread()); 281 DCHECK(message_loop_->BelongsToCurrentThread());
275 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; 282 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
276 DCHECK(!read_cb_.is_null()); 283 DCHECK(!read_cb_.is_null());
277 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; 284 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;
278 285
279 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { 286 if (!reset_cb_.is_null() || !stop_cb_.is_null()) {
280 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 287 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
281 if (!reset_cb_.is_null()) 288 if (!reset_cb_.is_null())
282 DoReset(); 289 DoReset();
283 if (!stop_cb_.is_null()) 290 if (!stop_cb_.is_null())
284 DoStop(); 291 DoStop();
285 return; 292 return;
286 } 293 }
287 294
288 if (status == DemuxerStream::kAborted) { 295 if (status == DemuxerStream::kAborted) {
296 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted";
297 state_ = kIdle;
289 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); 298 base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
290 state_ = kIdle;
291 return; 299 return;
292 } 300 }
293 301
294 if (status == DemuxerStream::kConfigChanged) { 302 if (status == DemuxerStream::kConfigChanged) {
295 // TODO(xhwang): Add config change support. 303 // TODO(xhwang): Add config change support.
296 // The |state_| is chosen to be kDecodeFinished here to be consistent with 304 // The |state_| is chosen to be kDecodeFinished here to be consistent with
297 // the implementation of FFmpegVideoDecoder. 305 // the implementation of FFmpegVideoDecoder.
306 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";
298 state_ = kDecodeFinished; 307 state_ = kDecodeFinished;
299 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 308 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
300 return; 309 return;
301 } 310 }
302 311
303 DCHECK_EQ(status, DemuxerStream::kOk); 312 DCHECK_EQ(status, DemuxerStream::kOk);
304 pending_buffer_to_decode_ = buffer; 313 pending_buffer_to_decode_ = buffer;
305 state_ = kPendingDecode; 314 state_ = kPendingDecode;
306 DecodePendingBuffer(); 315 DecodePendingBuffer();
307 } 316 }
(...skipping 17 matching lines...) Expand all
325 // simple and clear? 334 // simple and clear?
326 message_loop_->PostTask(FROM_HERE, base::Bind( 335 message_loop_->PostTask(FROM_HERE, base::Bind(
327 &DecryptingVideoDecoder::DoDeliverFrame, this, 336 &DecryptingVideoDecoder::DoDeliverFrame, this,
328 buffer_size, status, frame)); 337 buffer_size, status, frame));
329 } 338 }
330 339
331 void DecryptingVideoDecoder::DoDeliverFrame( 340 void DecryptingVideoDecoder::DoDeliverFrame(
332 int buffer_size, 341 int buffer_size,
333 Decryptor::Status status, 342 Decryptor::Status status,
334 const scoped_refptr<VideoFrame>& frame) { 343 const scoped_refptr<VideoFrame>& frame) {
344 DVLOG(3) << "DoDeliverFrame()";
335 DCHECK(message_loop_->BelongsToCurrentThread()); 345 DCHECK(message_loop_->BelongsToCurrentThread());
336 DCHECK_EQ(state_, kPendingDecode) << state_; 346 DCHECK_EQ(state_, kPendingDecode) << state_;
337 DCHECK(!read_cb_.is_null()); 347 DCHECK(!read_cb_.is_null());
338 DCHECK(pending_buffer_to_decode_); 348 DCHECK(pending_buffer_to_decode_);
339 349
340 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; 350 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_;
341 key_added_while_pending_decode_ = false; 351 key_added_while_pending_decode_ = false;
342 352
343 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { 353 if (!reset_cb_.is_null() || !stop_cb_.is_null()) {
344 pending_buffer_to_decode_ = NULL; 354 pending_buffer_to_decode_ = NULL;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 ReadFromDemuxerStream(); 392 ReadFromDemuxerStream();
383 return; 393 return;
384 } 394 }
385 395
386 DCHECK_EQ(status, Decryptor::kSuccess); 396 DCHECK_EQ(status, Decryptor::kSuccess);
387 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; 397 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle;
388 base::ResetAndReturn(&read_cb_).Run(kOk, frame); 398 base::ResetAndReturn(&read_cb_).Run(kOk, frame);
389 } 399 }
390 400
391 void DecryptingVideoDecoder::OnKeyAdded() { 401 void DecryptingVideoDecoder::OnKeyAdded() {
402 DVLOG(2) << "OnKeyAdded()";
392 DCHECK(message_loop_->BelongsToCurrentThread()); 403 DCHECK(message_loop_->BelongsToCurrentThread());
393 404
394 if (state_ == kPendingDecode) { 405 if (state_ == kPendingDecode) {
395 key_added_while_pending_decode_ = true; 406 key_added_while_pending_decode_ = true;
396 return; 407 return;
397 } 408 }
398 409
399 if (state_ == kWaitingForKey) { 410 if (state_ == kWaitingForKey) {
400 state_ = kPendingDecode; 411 state_ = kPendingDecode;
401 DecodePendingBuffer(); 412 DecodePendingBuffer();
402 } 413 }
403 } 414 }
404 415
405 void DecryptingVideoDecoder::DoReset() { 416 void DecryptingVideoDecoder::DoReset() {
406 DCHECK(init_cb_.is_null()); 417 DCHECK(init_cb_.is_null());
407 DCHECK(read_cb_.is_null()); 418 DCHECK(read_cb_.is_null());
408 state_ = kIdle; 419 state_ = kIdle;
409 base::ResetAndReturn(&reset_cb_).Run(); 420 base::ResetAndReturn(&reset_cb_).Run();
410 } 421 }
411 422
412 void DecryptingVideoDecoder::DoStop() { 423 void DecryptingVideoDecoder::DoStop() {
413 DCHECK(init_cb_.is_null()); 424 DCHECK(init_cb_.is_null());
414 DCHECK(read_cb_.is_null()); 425 DCHECK(read_cb_.is_null());
415 state_ = kStopped; 426 state_ = kStopped;
416 base::ResetAndReturn(&stop_cb_).Run(); 427 base::ResetAndReturn(&stop_cb_).Run();
417 } 428 }
418 429
419 } // namespace media 430 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | ppapi/cpp/private/content_decryptor_private.h » ('j') | ppapi/proxy/ppp_content_decryptor_private_proxy.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698