| Index: webkit/media/crypto/ppapi/clear_key_cdm.cc
|
| diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.cc b/webkit/media/crypto/ppapi/clear_key_cdm.cc
|
| index 00a11a32cb48b05dd6c3f1a4347c358ae095704c..7ee9b332149b4616b861f2c5908ea02ceffbb966 100644
|
| --- a/webkit/media/crypto/ppapi/clear_key_cdm.cc
|
| +++ b/webkit/media/crypto/ppapi/clear_key_cdm.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/bind.h"
|
| #include "base/logging.h"
|
| #include "base/time.h"
|
| +#include "media/base/buffers.h"
|
| #include "media/base/decoder_buffer.h"
|
|
|
| #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
|
| @@ -16,8 +17,17 @@
|
| #include "base/file_path.h"
|
| #include "base/path_service.h"
|
| #include "media/base/media.h"
|
| +#include "webkit/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h"
|
| #include "webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
|
|
|
| +// Include FFmpeg avformat.h for av_register_all().
|
| +extern "C" {
|
| +// Temporarily disable possible loss of data warning.
|
| +MSVC_PUSH_DISABLE_WARNING(4244);
|
| +#include <libavformat/avformat.h>
|
| +MSVC_POP_WARNING();
|
| +} // extern "C"
|
| +
|
| // TODO(tomfinegan): When COMPONENT_BUILD is not defined an AtExitManager must
|
| // exist before the call to InitializeFFmpegLibraries(). This should no longer
|
| // be required after http://crbug.com/91970 because we'll be able to get rid of
|
| @@ -33,6 +43,7 @@ static bool InitializeFFmpegLibraries() {
|
| FilePath file_path;
|
| CHECK(PathService::Get(base::DIR_EXE, &file_path));
|
| CHECK(media::InitializeMediaLibrary(file_path));
|
| + av_register_all();
|
| return true;
|
| }
|
|
|
| @@ -81,9 +92,7 @@ template<typename Type>
|
| class ScopedResetter {
|
| public:
|
| explicit ScopedResetter(Type* object) : object_(object) {}
|
| - ~ScopedResetter() {
|
| - object_->Reset();
|
| - }
|
| + ~ScopedResetter() { object_->Reset(); }
|
|
|
| private:
|
| Type* const object_;
|
| @@ -162,8 +171,16 @@ void ClearKeyCdm::Client::NeedKey(const std::string& key_system,
|
| }
|
|
|
| ClearKeyCdm::ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost*)
|
| - : decryptor_(&client_), allocator_(allocator) {
|
| + : decryptor_(&client_),
|
| + allocator_(allocator) {
|
| DCHECK(allocator_);
|
| +#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
|
| + channel_count_ = 0;
|
| + bits_per_channel_ = 0;
|
| + samples_per_second_ = 0;
|
| + last_timestamp_ = media::kNoTimestamp();
|
| + last_duration_ = media::kInfiniteDuration();
|
| +#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
|
| }
|
|
|
| ClearKeyCdm::~ClearKeyCdm() {}
|
| @@ -262,8 +279,23 @@ cdm::Status ClearKeyCdm::Decrypt(
|
|
|
| cdm::Status ClearKeyCdm::InitializeAudioDecoder(
|
| const cdm::AudioDecoderConfig& audio_decoder_config) {
|
| +#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
|
| + if (!audio_decoder_)
|
| + audio_decoder_.reset(new webkit_media::FFmpegCdmAudioDecoder(allocator_));
|
| +
|
| + if (!audio_decoder_->Initialize(audio_decoder_config))
|
| + return cdm::kSessionError;
|
| +
|
| + return cdm::kSuccess;
|
| +#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
|
| + channel_count_ = audio_decoder_config.channel_count;
|
| + bits_per_channel_ = audio_decoder_config.bits_per_channel;
|
| + samples_per_second_ = audio_decoder_config.samples_per_second;
|
| + return cdm::kSuccess;
|
| +#else
|
| NOTIMPLEMENTED();
|
| return cdm::kSessionError;
|
| +#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
|
| }
|
|
|
| cdm::Status ClearKeyCdm::InitializeVideoDecoder(
|
| @@ -283,21 +315,46 @@ cdm::Status ClearKeyCdm::InitializeVideoDecoder(
|
| NOTIMPLEMENTED();
|
| return cdm::kSessionError;
|
| #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
|
| -
|
| }
|
|
|
| void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) {
|
| #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
|
| - DCHECK(decoder_type == cdm::kStreamTypeVideo);
|
| - video_decoder_->Reset();
|
| -#endif
|
| + switch (decoder_type) {
|
| + case cdm::kStreamTypeVideo:
|
| + video_decoder_->Reset();
|
| + break;
|
| + case cdm::kStreamTypeAudio:
|
| + audio_decoder_->Reset();
|
| + break;
|
| + default:
|
| + NOTREACHED() << "ResetDecoder(): invalid cdm::StreamType";
|
| + }
|
| +#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
|
| + if (decoder_type == cdm::kStreamTypeAudio) {
|
| + last_timestamp_ = media::kNoTimestamp();
|
| + last_duration_ = media::kInfiniteDuration();
|
| + }
|
| +#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
|
| }
|
|
|
| void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) {
|
| #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
|
| - DCHECK(decoder_type == cdm::kStreamTypeVideo);
|
| - video_decoder_->Deinitialize();
|
| -#endif
|
| + switch (decoder_type) {
|
| + case cdm::kStreamTypeVideo:
|
| + video_decoder_->Deinitialize();
|
| + break;
|
| + case cdm::kStreamTypeAudio:
|
| + audio_decoder_->Deinitialize();
|
| + break;
|
| + default:
|
| + NOTREACHED() << "DeinitializeDecoder(): invalid cdm::StreamType";
|
| + }
|
| +#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
|
| + if (decoder_type == cdm::kStreamTypeAudio) {
|
| + last_timestamp_ = media::kNoTimestamp();
|
| + last_duration_ = media::kInfiniteDuration();
|
| + }
|
| +#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
|
| }
|
|
|
| cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
|
| @@ -332,6 +389,57 @@ cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
|
| #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
|
| }
|
|
|
| +cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
|
| + const cdm::InputBuffer& encrypted_buffer,
|
| + cdm::AudioFrames* audio_frames) {
|
| + DVLOG(1) << "DecryptAndDecodeSamples()";
|
| +
|
| + scoped_refptr<media::DecoderBuffer> buffer;
|
| + cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);
|
| +
|
| + if (status != cdm::kSuccess)
|
| + return status;
|
| +
|
| +#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
|
| + DCHECK(status == cdm::kSuccess);
|
| + DCHECK(buffer);
|
| + return audio_decoder_->DecodeBuffer(buffer.get()->GetData(),
|
| + buffer->GetDataSize(),
|
| + encrypted_buffer.timestamp,
|
| + audio_frames);
|
| +#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
|
| + if (buffer->IsEndOfStream()) {
|
| + // Upon the first EOS frame, return a frame with |last_duration_|.
|
| + if (last_duration_ != media::kInfiniteDuration()) {
|
| + DCHECK(last_timestamp_ != media::kNoTimestamp());
|
| + GenerateFakeAudioFrames(audio_frames);
|
| + last_timestamp_ = media::kNoTimestamp();
|
| + last_duration_ = media::kInfiniteDuration();
|
| + return cdm::kSuccess;
|
| + }
|
| +
|
| + last_timestamp_ = media::kNoTimestamp();
|
| + return cdm::kNeedMoreData;
|
| + }
|
| +
|
| + base::TimeDelta cur_timestamp = buffer->GetTimestamp();
|
| + DCHECK(cur_timestamp != media::kNoTimestamp());
|
| +
|
| + // Return kNeedMoreData for the first frame because duration is unknown.
|
| + if (last_timestamp_ == media::kNoTimestamp()) {
|
| + last_timestamp_ = cur_timestamp;
|
| + return cdm::kNeedMoreData;
|
| + }
|
| +
|
| + DCHECK(cur_timestamp > last_timestamp_);
|
| + last_duration_ = cur_timestamp - last_timestamp_;
|
| + last_timestamp_ = cur_timestamp;
|
| +
|
| + GenerateFakeAudioFrames(audio_frames);
|
| + return cdm::kSuccess;
|
| +#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
|
| +}
|
| +
|
| cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
|
| const cdm::InputBuffer& encrypted_buffer,
|
| scoped_refptr<media::DecoderBuffer>* decrypted_buffer) {
|
| @@ -363,6 +471,28 @@ cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
|
| return cdm::kSuccess;
|
| }
|
|
|
| +#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
|
| +void ClearKeyCdm::GenerateFakeAudioFrames(cdm::AudioFrames* audio_frames) {
|
| + DCHECK(last_duration_ != media::kInfiniteDuration());
|
| + int64 duration_in_microseconds = last_duration_.InMicroseconds();
|
| + DCHECK_GT(duration_in_microseconds, 0);
|
| +
|
| + int64 timestamp = last_timestamp_.InMicroseconds();
|
| + int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8;
|
| + int64 frame_size = bytes_per_sample * samples_per_second_ *
|
| + duration_in_microseconds / base::Time::kMicrosecondsPerSecond;
|
| +
|
| + const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
|
| + audio_frames->set_buffer(allocator_->Allocate(kHeaderSize + frame_size));
|
| + int64* data = reinterpret_cast<int64*>(audio_frames->buffer()->data());
|
| + *(data++) = timestamp;
|
| + *(data++) = frame_size;
|
| + // You won't hear anything because we have all zeros here. But the video
|
| + // should play just fine!
|
| + memset(data, 0, frame_size);
|
| +}
|
| +#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
|
| +
|
| #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
|
| void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp,
|
| cdm::VideoFrame* video_frame) {
|
| @@ -405,11 +535,4 @@ void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp,
|
| }
|
| #endif // CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER
|
|
|
| -cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
|
| - const cdm::InputBuffer& encrypted_buffer,
|
| - cdm::Buffer* sample_buffer) {
|
| - NOTIMPLEMENTED();
|
| - return cdm::kDecryptError;
|
| -}
|
| -
|
| } // namespace webkit_media
|
|
|