Chromium Code Reviews| 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; |
| +} |