Index: webkit/media/crypto/clear_key_cdm.cc |
diff --git a/webkit/media/crypto/clear_key_cdm.cc b/webkit/media/crypto/clear_key_cdm.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7b73979f7bf18e1c246f8126753d85e978308f9f |
--- /dev/null |
+++ b/webkit/media/crypto/clear_key_cdm.cc |
@@ -0,0 +1,212 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "webkit/media/crypto/clear_key_cdm.h" |
+ |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "base/time.h" |
+#include "media/base/decoder_buffer.h" |
+ |
+static const char kClearKeyCdmVersion[] = "0.1.0.0"; |
+ |
+static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( |
+ const InputBuffer& input_buffer) { |
+ scoped_refptr<media::DecoderBuffer> output_buffer = |
+ media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size); |
+ |
+ std::vector<media::SubsampleEntry> subsamples; |
+ for (int i = 0; i < input_buffer.num_subsamples; ++i) { |
+ media::SubsampleEntry subsample; |
+ subsample.clear_bytes = input_buffer.subsamples[i].clear_bytes; |
+ subsample.cypher_bytes = input_buffer.subsamples[i].cypher_bytes; |
+ subsamples.push_back(subsample); |
+ } |
+ |
+ scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig( |
+ std::string(reinterpret_cast<const char*>(input_buffer.key_id), |
+ input_buffer.key_id_size), |
+ std::string(reinterpret_cast<const char*>(input_buffer.iv), |
+ input_buffer.key_id_size), |
+ std::string(reinterpret_cast<const char*>(input_buffer.checksum), |
+ input_buffer.checksum_size), |
+ input_buffer.data_offset, |
+ subsamples)); |
+ |
+ output_buffer->SetDecryptConfig(decrypt_config.Pass()); |
+ output_buffer->SetTimestamp( |
+ base::TimeDelta::FromMilliseconds(input_buffer.timestamp)); |
+ output_buffer->SetDuration( |
+ base::TimeDelta::FromMilliseconds(input_buffer.duration)); |
+ |
+ return output_buffer; |
+} |
+ |
+template<typename Type> |
+class ScopedResetter { |
+ public: |
+ explicit ScopedResetter(Type* object) : object_(object) {} |
+ ~ScopedResetter() { |
+ object_->Reset(); |
+ } |
+ |
+ private: |
+ Type* object_; |
ddorwin
2012/08/15 20:15:00
*const
xhwang
2012/08/16 02:32:40
Done.
|
+}; |
+ |
+template<typename Type> |
+static Type* AllocateAndCopy(const Type* data, int size) { |
+ COMPILE_ASSERT(sizeof(Type) == 1, type_size_is_not_one); |
+ Type* copy = new Type[size]; |
+ memcpy(copy, data, size); |
+ return copy; |
+} |
+ |
+ContentDecryptionModule* CdmCreateInstance() { |
+ return new ClearKeyCdm(); |
+} |
+ |
+const char* CdmGetVersion() { |
+ return kClearKeyCdmVersion; |
+} |
+ |
+ClearKeyCdm::Client::Client() : status_(kKeyError), key_message_length_(0) {} |
+ |
+ClearKeyCdm::Client::~Client() {} |
+ |
+void ClearKeyCdm::Client::Reset() { |
+ status_ = kKeyError; |
+ session_id_.clear(); |
+ key_message_.reset(); |
+ key_message_length_ = 0; |
+ default_url_.clear(); |
+} |
+ |
+void ClearKeyCdm::Client::KeyAdded(const std::string& key_system, |
+ const std::string& session_id) { |
+ status_ = kKeyAdded; |
+ session_id_ = session_id; |
+} |
+ |
+void ClearKeyCdm::Client::KeyError(const std::string& key_system, |
+ const std::string& session_id, |
+ media::Decryptor::KeyError error_code, |
+ int system_code) { |
+ status_ = kKeyError; |
+ session_id_ = session_id; |
+} |
+ |
+void ClearKeyCdm::Client::KeyMessage(const std::string& key_system, |
+ const std::string& session_id, |
+ scoped_array<uint8> message, |
+ int message_length, |
+ const std::string& default_url) { |
+ status_ = kKeyMessage; |
+ session_id_ = session_id; |
+ key_message_ = message.Pass(); |
+ key_message_length_ = message_length; |
+} |
+ |
+void ClearKeyCdm::Client::NeedKey(const std::string& key_system, |
+ const std::string& session_id, |
+ scoped_array<uint8> init_data, |
+ int init_data_length) { |
+ NOTREACHED(); |
+} |
+ |
+ClearKeyCdm::ClearKeyCdm() |
+ : decryptor_(&client_), |
ddorwin
2012/08/15 21:03:07
Re-using the client means we cannot parallelize an
xhwang
2012/08/16 02:32:40
Yes, we cannot parallelize these calls. Added comm
|
+ decryption_status_(media::Decryptor::kError) { |
+} |
+ |
+ClearKeyCdm::~ClearKeyCdm() {} |
+ |
+void ClearKeyCdm::Reset() { |
ddorwin
2012/08/15 20:15:00
This doesn't reset the whole class, so I think thi
xhwang
2012/08/16 02:32:40
Removed this method and made decryption_status_ an
|
+ decryption_status_ = media::Decryptor::kError; |
+ decrypted_buffer_ = NULL; |
+} |
+ |
+CdmStatus ClearKeyCdm::GenerateKeyRequest(const uint8_t* init_data, |
+ int init_data_size, |
+ char** session_id, |
+ int* session_id_size, |
+ uint8_t** key_request, |
+ int* key_request_size, |
+ char** default_url, |
+ int* default_url_size) { |
+ ScopedResetter<Client> _(&client_); |
Tom Finegan
2012/08/15 20:02:42
How about s/_(/resetter(/? :)
xhwang
2012/08/16 02:32:40
Replaced with auto_resetter.
|
+ decryptor_.GenerateKeyRequest("", init_data, init_data_size); |
Tom Finegan
2012/08/15 20:02:42
Don't we have a placeholder key system name we can
Tom Finegan
2012/08/15 20:22:24
Err- disregard this, meant to remove it.
|
+ |
+ if (client_.status() != Client::kKeyMessage) |
+ return kCdmStatusErrorUnknown; |
+ |
+ *session_id_size = client_.session_id().size(); |
+ *session_id = AllocateAndCopy(client_.session_id().data(), *session_id_size); |
+ *key_request_size = client_.key_message_length(); |
+ *key_request = AllocateAndCopy(client_.key_message(), *key_request_size); |
+ *default_url_size = client_.default_url().size(); |
+ *default_url = AllocateAndCopy(client_.default_url().data(), |
+ *default_url_size); |
+ |
Tom Finegan
2012/08/15 20:02:42
nit: can probably remove this empty line
xhwang
2012/08/16 02:32:40
Done.
|
+ return kCdmStatusSuccess; |
+} |
+ |
+CdmStatus ClearKeyCdm::AddKey(const char* session_id, |
+ int session_id_size, |
+ const uint8_t* key, |
+ int key_size) { |
+ ScopedResetter<Client> _(&client_); |
Tom Finegan
2012/08/15 20:02:42
Ditto on all of these. :)
xhwang
2012/08/16 02:32:40
Done.
|
+ decryptor_.AddKey("", key, key_size, NULL, 0, |
+ std::string(session_id, session_id_size)); |
+ if (client_.status() != Client::kKeyAdded) |
+ return kCdmStatusErrorUnknown; |
+ |
+ return kCdmStatusSuccess; |
+} |
+ |
+CdmStatus ClearKeyCdm::CancelKeyRequest(const char* session_id, |
+ int session_id_size) { |
+ ScopedResetter<Client> _(&client_); |
+ decryptor_.CancelKeyRequest("", std::string(session_id, session_id_size)); |
+ |
+ return kCdmStatusSuccess; |
+} |
+ |
+CdmStatus ClearKeyCdm::Decrypt(const char* session_id, |
+ int session_id_size, |
+ const InputBuffer &encrypted_buffer, |
+ OutputBuffer* decrypted_buffer) { |
+ ScopedResetter<ClearKeyCdm> _(this); |
+ scoped_refptr<media::DecoderBuffer> decoder_buffer = |
+ CopyDecoderBufferFrom(encrypted_buffer); |
+ |
+ decryptor_.Decrypt(decoder_buffer, base::Bind(&ClearKeyCdm::OnBufferDecrpted, |
+ base::Unretained(this))); |
+ if (decryption_status_ == media::Decryptor::kError) |
+ return kCdmStatusErrorUnknown; |
+ |
+ if (decryption_status_ == media::Decryptor::kNoKey) |
+ return kCdmStatusErrorNoKey; |
+ |
+ DCHECK(decrypted_buffer_); |
+ int data_size = decrypted_buffer_->GetDataSize(); |
+ decrypted_buffer->data = AllocateAndCopy(decrypted_buffer_->GetData(), |
+ data_size); |
+ decrypted_buffer->data_size = data_size; |
+ decrypted_buffer->timestamp = |
+ decrypted_buffer_->GetTimestamp().InMilliseconds(); |
+ decrypted_buffer->duration = |
+ decrypted_buffer_->GetDuration().InMilliseconds(); |
+ |
+ return kCdmStatusSuccess; |
+} |
+ |
+void ClearKeyCdm::OnBufferDecrpted( |
Tom Finegan
2012/08/15 20:02:42
s/Decrpted/Decrypted/
xhwang
2012/08/16 02:32:40
This function is removed, but thanks for catching
|
+ media::Decryptor::Status status, |
+ const scoped_refptr<media::DecoderBuffer>& buffer) { |
+ decryption_status_ = status; |
+ decrypted_buffer_ = buffer; |
+} |