summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/test/data/media/encrypted_media_utils.js25
-rw-r--r--webkit/media/crypto/ppapi/clear_key_cdm.cc52
-rw-r--r--webkit/media/crypto/ppapi/clear_key_cdm.h12
3 files changed, 77 insertions, 12 deletions
diff --git a/content/test/data/media/encrypted_media_utils.js b/content/test/data/media/encrypted_media_utils.js
index 40fbde6..16ab4b7 100644
--- a/content/test/data/media/encrypted_media_utils.js
+++ b/content/test/data/media/encrypted_media_utils.js
@@ -28,6 +28,20 @@ var KEY = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b,
0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]);
// Stores a failure message that is read by the browser test when it fails.
var failMessage = '';
+// Heart beat message header.
+var HEART_BEAT_HEADER = 'HEARTBEAT';
+
+function isHeartBeatMessage(msg) {
+ if (msg.length < HEART_BEAT_HEADER.length)
+ return false;
+
+ for (var i = 0; i < HEART_BEAT_HEADER.length; ++i) {
+ if (HEART_BEAT_HEADER[i] != String.fromCharCode(msg[i]))
+ return false;
+ }
+
+ return true;
+}
function failTest(msg) {
if (msg instanceof Event)
@@ -95,17 +109,24 @@ function loadEncryptedMedia(video, mediaFile, keySystem, key) {
}
function onKeyMessage(e) {
- console.log('onKeyMessage', e);
+ if (isHeartBeatMessage(e.message)) {
+ console.log('onKeyMessage - heart beat', e);
+ return;
+ }
+
+ console.log('onKeyMessage - key request', e);
video.webkitAddKey(keySystem, key, e.message);
}
var mediaSource = new WebKitMediaSource();
- video.src = window.URL.createObjectURL(mediaSource);
+
mediaSource.addEventListener('webkitsourceopen', onSourceOpen);
video.addEventListener('webkitneedkey', onNeedKey);
video.addEventListener('webkitkeymessage', onKeyMessage);
video.addEventListener('webkitkeyerror', failTest);
video.addEventListener('webkitkeyadded', onKeyAdded);
installTitleEventHandler(video, 'error');
+
+ video.src = window.URL.createObjectURL(mediaSource);
return mediaSource;
}
diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.cc b/webkit/media/crypto/ppapi/clear_key_cdm.cc
index 7930646..3c3ce77 100644
--- a/webkit/media/crypto/ppapi/clear_key_cdm.cc
+++ b/webkit/media/crypto/ppapi/clear_key_cdm.cc
@@ -4,6 +4,9 @@
#include "webkit/media/crypto/ppapi/clear_key_cdm.h"
+#include <algorithm>
+#include <sstream>
+#include <string>
#include <vector>
#include "base/bind.h"
@@ -54,8 +57,15 @@ static bool InitializeFFmpegLibraries() {
static bool g_cdm_module_initialized = InitializeFFmpegLibraries();
#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
-static const char kClearKeyCdmVersion[] = "0.1.0.0";
+static const char kClearKeyCdmVersion[] = "0.1.0.1";
static const char kExternalClearKey[] = "org.chromium.externalclearkey";
+static const int64 kSecondsPerMinute = 60;
+static const int64 kMsPerSecond = 1000;
+static const int64 kInitialTimerDelayMs = 200;
+static const int64 kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond;
+// Heart beat message header. If a key message starts with |kHeartBeatHeader|,
+// it's a heart beat message. Otherwise, it's a key request.
+static const char kHeartBeatHeader[] = "HEARTBEAT";
// Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is
// empty, an empty (end-of-stream) media::DecoderBuffer is returned.
@@ -188,9 +198,12 @@ void ClearKeyCdm::Client::NeedKey(const std::string& key_system,
NOTREACHED();
}
-ClearKeyCdm::ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost*)
+ClearKeyCdm::ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost* cdm_host)
: decryptor_(&client_),
- allocator_(allocator) {
+ allocator_(allocator),
+ cdm_host_(cdm_host),
+ timer_delay_ms_(kInitialTimerDelayMs),
+ timer_set_(false) {
DCHECK(allocator_);
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
channel_count_ = 0;
@@ -220,18 +233,18 @@ cdm::Status ClearKeyCdm::GenerateKeyRequest(const char* type, int type_size,
DCHECK(key_request);
key_request->set_session_id(client_.session_id().data(),
client_.session_id().size());
+ latest_session_id_ = client_.session_id();
// TODO(tomfinegan): Get rid of this copy.
key_request->set_message(allocator_->Allocate(client_.key_message_length()));
-
DCHECK(key_request->message());
DCHECK_EQ(key_request->message()->size(), client_.key_message_length());
- memcpy(reinterpret_cast<void*>(key_request->message()->data()),
- reinterpret_cast<const void*>(client_.key_message()),
- client_.key_message_length());
+ memcpy(key_request->message()->data(),
+ client_.key_message(), client_.key_message_length());
key_request->set_default_url(client_.default_url().data(),
client_.default_url().size());
+
return cdm::kSuccess;
}
@@ -250,6 +263,11 @@ cdm::Status ClearKeyCdm::AddKey(const char* session_id,
if (client_.status() != Client::kKeyAdded)
return cdm::kSessionError;
+ if (!timer_set_) {
+ cdm_host_->SetTimer(timer_delay_ms_);
+ timer_set_ = true;
+ }
+
return cdm::kSuccess;
}
@@ -263,8 +281,24 @@ cdm::Status ClearKeyCdm::CancelKeyRequest(const char* session_id,
}
void ClearKeyCdm::TimerExpired(cdm::KeyMessage* msg, bool* populated) {
- // TODO(xhwang): do something with this?
- NOTREACHED() << "Wouldn't it be nice if CdmHost::SetTimer() was used?";
+ std::ostringstream msg_stream;
+ msg_stream << kHeartBeatHeader << " from ClearKey CDM at time "
+ << cdm_host_->GetCurrentWallTimeInSeconds() << ".";
+ std::string msg_string = msg_stream.str();
+
+ msg->set_message(allocator_->Allocate(msg_string.length()));
+ memcpy(msg->message()->data(), msg_string.data(), msg_string.length());
+ msg->set_session_id(latest_session_id_.data(), latest_session_id_.length());
+ msg->set_default_url(NULL, 0);
+
+ *populated = true;
+
+ cdm_host_->SetTimer(timer_delay_ms_);
+
+ // Use a smaller timer delay at start-up to facilitate testing. Increase the
+ // timer delay up to a limit to avoid message spam.
+ if (timer_delay_ms_ < kMaxTimerDelayMs)
+ timer_delay_ms_ = std::min(2 * timer_delay_ms_, kMaxTimerDelayMs);
}
static void CopyDecryptResults(
diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.h b/webkit/media/crypto/ppapi/clear_key_cdm.h
index e3056be..691e1df 100644
--- a/webkit/media/crypto/ppapi/clear_key_cdm.h
+++ b/webkit/media/crypto/ppapi/clear_key_cdm.h
@@ -42,7 +42,7 @@ class FFmpegCdmVideoDecoder;
// Clear key implementation of the cdm::ContentDecryptionModule interface.
class ClearKeyCdm : public cdm::ContentDecryptionModule {
public:
- explicit ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost*);
+ ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost* cdm_host);
virtual ~ClearKeyCdm();
// ContentDecryptionModule implementation.
@@ -159,6 +159,16 @@ class ClearKeyCdm : public cdm::ContentDecryptionModule {
base::Lock client_lock_;
cdm::Allocator* const allocator_;
+ cdm::CdmHost* cdm_host_;
+
+ std::string latest_session_id_;
+
+ // Timer delay in milliseconds for the next cdm_host_->SetTimer() call.
+ int64 timer_delay_ms_;
+
+ // Indicates whether a timer has been set to prevent multiple timers from
+ // running.
+ bool timer_set_;
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
int channel_count_;