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

Unified Diff: webkit/media/crypto/ppapi/clear_key_cdm.cc

Issue 11260007: Add FFmpeg audio decoder for the clear key CDM. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased on 11242005 and 11189082 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 side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698