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 "webkit/media/crypto/ppapi/clear_key_cdm.h" | 5 #include "webkit/media/crypto/ppapi/clear_key_cdm.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <sstream> | 8 #include <sstream> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 samples_per_second_ = audio_decoder_config.samples_per_second; | 352 samples_per_second_ = audio_decoder_config.samples_per_second; |
353 return cdm::kSuccess; | 353 return cdm::kSuccess; |
354 #else | 354 #else |
355 NOTIMPLEMENTED(); | 355 NOTIMPLEMENTED(); |
356 return cdm::kSessionError; | 356 return cdm::kSessionError; |
357 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 357 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
358 } | 358 } |
359 | 359 |
360 cdm::Status ClearKeyCdm::InitializeVideoDecoder( | 360 cdm::Status ClearKeyCdm::InitializeVideoDecoder( |
361 const cdm::VideoDecoderConfig& video_decoder_config) { | 361 const cdm::VideoDecoderConfig& video_decoder_config) { |
362 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 362 if (video_decoder_ && video_decoder_->is_initialized()) { |
| 363 DCHECK(!video_decoder_->is_initialized()); |
| 364 return cdm::kSessionError; |
| 365 } |
| 366 |
| 367 // Any uninitialized decoder will be replaced. |
| 368 video_decoder_ = CreateVideoDecoder(allocator_, video_decoder_config); |
363 if (!video_decoder_) | 369 if (!video_decoder_) |
364 video_decoder_.reset(new webkit_media::FFmpegCdmVideoDecoder(allocator_)); | |
365 | |
366 if (!video_decoder_->Initialize(video_decoder_config)) | |
367 return cdm::kSessionError; | 370 return cdm::kSessionError; |
368 | 371 |
369 return cdm::kSuccess; | 372 return cdm::kSuccess; |
370 #elif defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER) | |
371 video_size_ = video_decoder_config.coded_size; | |
372 return cdm::kSuccess; | |
373 #else | |
374 NOTIMPLEMENTED(); | |
375 return cdm::kSessionError; | |
376 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | |
377 } | 373 } |
378 | 374 |
379 void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) { | 375 void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) { |
380 DVLOG(1) << "ResetDecoder()"; | 376 DVLOG(1) << "ResetDecoder()"; |
381 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 377 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
382 switch (decoder_type) { | 378 switch (decoder_type) { |
383 case cdm::kStreamTypeVideo: | 379 case cdm::kStreamTypeVideo: |
384 video_decoder_->Reset(); | 380 video_decoder_->Reset(); |
385 break; | 381 break; |
386 case cdm::kStreamTypeAudio: | 382 case cdm::kStreamTypeAudio: |
387 audio_decoder_->Reset(); | 383 audio_decoder_->Reset(); |
388 break; | 384 break; |
389 default: | 385 default: |
390 NOTREACHED() << "ResetDecoder(): invalid cdm::StreamType"; | 386 NOTREACHED() << "ResetDecoder(): invalid cdm::StreamType"; |
391 } | 387 } |
392 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 388 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
393 if (decoder_type == cdm::kStreamTypeAudio) { | 389 if (decoder_type == cdm::kStreamTypeAudio) { |
394 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 390 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
395 total_samples_generated_ = 0; | 391 total_samples_generated_ = 0; |
396 } | 392 } |
397 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 393 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
398 } | 394 } |
399 | 395 |
400 void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) { | 396 void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) { |
401 DVLOG(1) << "DeinitializeDecoder()"; | 397 DVLOG(1) << "DeinitializeDecoder()"; |
402 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | |
403 switch (decoder_type) { | 398 switch (decoder_type) { |
404 case cdm::kStreamTypeVideo: | 399 case cdm::kStreamTypeVideo: |
405 video_decoder_->Deinitialize(); | 400 video_decoder_->Deinitialize(); |
406 break; | 401 break; |
407 case cdm::kStreamTypeAudio: | 402 case cdm::kStreamTypeAudio: |
| 403 #if !defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
408 audio_decoder_->Deinitialize(); | 404 audio_decoder_->Deinitialize(); |
| 405 #else |
| 406 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
| 407 total_samples_generated_ = 0; |
| 408 #endif |
409 break; | 409 break; |
410 default: | 410 default: |
411 NOTREACHED() << "DeinitializeDecoder(): invalid cdm::StreamType"; | 411 NOTREACHED() << "DeinitializeDecoder(): invalid cdm::StreamType"; |
412 } | 412 } |
413 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | |
414 if (decoder_type == cdm::kStreamTypeAudio) { | |
415 output_timestamp_base_in_microseconds_ = kNoTimestamp; | |
416 total_samples_generated_ = 0; | |
417 } | |
418 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | |
419 } | 413 } |
420 | 414 |
421 cdm::Status ClearKeyCdm::DecryptAndDecodeFrame( | 415 cdm::Status ClearKeyCdm::DecryptAndDecodeFrame( |
422 const cdm::InputBuffer& encrypted_buffer, | 416 const cdm::InputBuffer& encrypted_buffer, |
423 cdm::VideoFrame* decoded_frame) { | 417 cdm::VideoFrame* decoded_frame) { |
424 DVLOG(1) << "DecryptAndDecodeFrame()"; | 418 DVLOG(1) << "DecryptAndDecodeFrame()"; |
425 TRACE_EVENT0("eme", "ClearKeyCdm::DecryptAndDecodeFrame"); | 419 TRACE_EVENT0("eme", "ClearKeyCdm::DecryptAndDecodeFrame"); |
426 | 420 |
427 scoped_refptr<media::DecoderBuffer> buffer; | 421 scoped_refptr<media::DecoderBuffer> buffer; |
428 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); | 422 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); |
429 | 423 |
430 if (status != cdm::kSuccess) | 424 if (status != cdm::kSuccess) |
431 return status; | 425 return status; |
432 | 426 |
433 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | |
434 DCHECK(status == cdm::kSuccess); | 427 DCHECK(status == cdm::kSuccess); |
435 DCHECK(buffer); | 428 DCHECK(buffer); |
436 return video_decoder_->DecodeFrame(buffer.get()->GetData(), | 429 return video_decoder_->DecodeFrame(buffer.get()->GetData(), |
437 buffer->GetDataSize(), | 430 buffer->GetDataSize(), |
438 encrypted_buffer.timestamp, | 431 encrypted_buffer.timestamp, |
439 decoded_frame); | 432 decoded_frame); |
440 #elif defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER) | |
441 // The fake decoder does not buffer any frames internally. So if the input is | |
442 // empty (EOS), just return kNeedMoreData. | |
443 if (buffer->IsEndOfStream()) | |
444 return cdm::kNeedMoreData; | |
445 | |
446 GenerateFakeVideoFrame(buffer->GetTimestamp(), decoded_frame); | |
447 return cdm::kSuccess; | |
448 #else | |
449 NOTIMPLEMENTED(); | |
450 return cdm::kDecodeError; | |
451 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | |
452 } | 433 } |
453 | 434 |
454 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples( | 435 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples( |
455 const cdm::InputBuffer& encrypted_buffer, | 436 const cdm::InputBuffer& encrypted_buffer, |
456 cdm::AudioFrames* audio_frames) { | 437 cdm::AudioFrames* audio_frames) { |
457 DVLOG(1) << "DecryptAndDecodeSamples()"; | 438 DVLOG(1) << "DecryptAndDecodeSamples()"; |
458 | 439 |
459 scoped_refptr<media::DecoderBuffer> buffer; | 440 scoped_refptr<media::DecoderBuffer> buffer; |
460 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); | 441 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); |
461 | 442 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 | 541 |
561 int samples_generated = GenerateFakeAudioFramesFromDuration( | 542 int samples_generated = GenerateFakeAudioFramesFromDuration( |
562 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), | 543 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), |
563 audio_frames); | 544 audio_frames); |
564 total_samples_generated_ += samples_generated; | 545 total_samples_generated_ += samples_generated; |
565 | 546 |
566 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; | 547 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; |
567 } | 548 } |
568 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 549 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
569 | 550 |
570 #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER) | |
571 void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp, | |
572 cdm::VideoFrame* video_frame) { | |
573 // Choose non-zero alignment and padding on purpose for testing. | |
574 const int kAlignment = 8; | |
575 const int kPadding = 16; | |
576 const int kPlanePadding = 128; | |
577 | |
578 int width = video_size_.width; | |
579 int height = video_size_.height; | |
580 DCHECK_EQ(width % 2, 0); | |
581 DCHECK_EQ(height % 2, 0); | |
582 | |
583 int y_stride = (width + kAlignment - 1) / kAlignment * kAlignment + kPadding; | |
584 int uv_stride = | |
585 (width / 2 + kAlignment - 1) / kAlignment * kAlignment + kPadding; | |
586 int y_rows = height; | |
587 int uv_rows = height / 2; | |
588 int y_offset = 0; | |
589 int v_offset = y_stride * y_rows + kPlanePadding; | |
590 int u_offset = v_offset + uv_stride * uv_rows + kPlanePadding; | |
591 int frame_size = u_offset + uv_stride * uv_rows + kPlanePadding; | |
592 | |
593 video_frame->set_format(cdm::kYv12); | |
594 video_frame->set_size(video_size_); | |
595 video_frame->set_frame_buffer(allocator_->Allocate(frame_size)); | |
596 video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, y_offset); | |
597 video_frame->set_plane_offset(cdm::VideoFrame::kVPlane, v_offset); | |
598 video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, u_offset); | |
599 video_frame->set_stride(cdm::VideoFrame::kYPlane, y_stride); | |
600 video_frame->set_stride(cdm::VideoFrame::kVPlane, uv_stride); | |
601 video_frame->set_stride(cdm::VideoFrame::kUPlane, uv_stride); | |
602 video_frame->set_timestamp(timestamp.InMicroseconds()); | |
603 | |
604 static unsigned char color = 0; | |
605 color += 10; | |
606 | |
607 memset(reinterpret_cast<void*>(video_frame->frame_buffer()->data()), | |
608 color, frame_size); | |
609 } | |
610 #endif // CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER | |
611 | |
612 } // namespace webkit_media | 551 } // namespace webkit_media |
OLD | NEW |