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

Side by Side Diff: webkit/media/crypto/clear_key_cdm.cc

Issue 10837252: Update CDM interface and add clear key CDM. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Resolve ddorwin's comments. Created 8 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/media/crypto/clear_key_cdm.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/time.h"
12 #include "media/base/decoder_buffer.h"
13
14 static const char kClearKeyCdmVersion[] = "0.1.0.0";
15
16 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom(
17 const cdm::InputBuffer& input_buffer) {
18 scoped_refptr<media::DecoderBuffer> output_buffer =
19 media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size);
20
21 std::vector<media::SubsampleEntry> subsamples;
22 for (uint32_t i = 0; i < input_buffer.num_subsamples; ++i) {
23 media::SubsampleEntry subsample;
24 subsample.clear_bytes = input_buffer.subsamples[i].clear_bytes;
25 subsample.cypher_bytes = input_buffer.subsamples[i].cipher_bytes;
26 subsamples.push_back(subsample);
27 }
28
29 scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig(
30 std::string(reinterpret_cast<const char*>(input_buffer.key_id),
31 input_buffer.key_id_size),
32 std::string(reinterpret_cast<const char*>(input_buffer.iv),
33 input_buffer.key_id_size),
34 std::string(reinterpret_cast<const char*>(input_buffer.checksum),
35 input_buffer.checksum_size),
36 input_buffer.data_offset,
37 subsamples));
38
39 output_buffer->SetDecryptConfig(decrypt_config.Pass());
40 output_buffer->SetTimestamp(
41 base::TimeDelta::FromMilliseconds(input_buffer.timestamp));
42 output_buffer->SetDuration(
43 base::TimeDelta::FromMilliseconds(input_buffer.duration));
44
45 return output_buffer;
46 }
47
48 template<typename Type>
49 class ScopedResetter {
50 public:
51 explicit ScopedResetter(Type* object) : object_(object) {}
52 ~ScopedResetter() {
53 object_->Reset();
54 }
55
56 private:
57 Type* const object_;
58 };
59
60 template<typename Type>
61 static Type* AllocateAndCopy(const Type* data, int size) {
62 COMPILE_ASSERT(sizeof(Type) == 1, type_size_is_not_one);
63 Type* copy = new Type[size];
64 memcpy(copy, data, size);
65 return copy;
66 }
67
68 cdm::ContentDecryptionModule* CreateCdmInstance() {
69 return new webkit_media::ClearKeyCdm();
70 }
71
72 void DestroyCdmInstance(cdm::ContentDecryptionModule* instance) {
73 delete instance;
74 }
75
76 const char* GetCdmVersion() {
77 return kClearKeyCdmVersion;
78 }
79
80 namespace webkit_media {
81
82 ClearKeyCdm::Client::Client() : status_(kKeyError), key_message_length_(0) {}
83
84 ClearKeyCdm::Client::~Client() {}
85
86 void ClearKeyCdm::Client::Reset() {
87 status_ = kKeyError;
88 session_id_.clear();
89 key_message_.reset();
90 key_message_length_ = 0;
91 default_url_.clear();
92 }
93
94 void ClearKeyCdm::Client::KeyAdded(const std::string& key_system,
95 const std::string& session_id) {
96 status_ = kKeyAdded;
97 session_id_ = session_id;
98 }
99
100 void ClearKeyCdm::Client::KeyError(const std::string& key_system,
101 const std::string& session_id,
102 media::Decryptor::KeyError error_code,
103 int system_code) {
104 status_ = kKeyError;
105 session_id_ = session_id;
106 }
107
108 void ClearKeyCdm::Client::KeyMessage(const std::string& key_system,
109 const std::string& session_id,
110 scoped_array<uint8> message,
111 int message_length,
112 const std::string& default_url) {
113 status_ = kKeyMessage;
114 session_id_ = session_id;
115 key_message_ = message.Pass();
116 key_message_length_ = message_length;
117 }
118
119 void ClearKeyCdm::Client::NeedKey(const std::string& key_system,
120 const std::string& session_id,
121 scoped_array<uint8> init_data,
122 int init_data_length) {
123 // In the current implementation of AesDecryptor, NeedKey is not used.
124 // If no key is available to decrypt an input buffer, it returns kNoKey to
125 // the caller instead of firing NeedKey.
126 NOTREACHED();
127 }
128
129 ClearKeyCdm::ClearKeyCdm() : decryptor_(&client_) {}
130
131 ClearKeyCdm::~ClearKeyCdm() {}
132
133 ClearKeyCdm::Status ClearKeyCdm::GenerateKeyRequest(const uint8_t* init_data,
134 int init_data_size,
135 char** session_id,
136 int* session_id_size,
137 uint8_t** key_request,
138 int* key_request_size,
139 char** default_url,
140 int* default_url_size) {
141 base::AutoLock auto_lock(lock_);
142 ScopedResetter<Client> auto_resetter(&client_);
143 decryptor_.GenerateKeyRequest("", init_data, init_data_size);
144
145 if (client_.status() != Client::kKeyMessage)
146 return kErrorUnknown;
147
148 // Client methods are called synchronously, so we can use client variables
149 // here.
150 *session_id_size = client_.session_id().size();
151 *session_id = AllocateAndCopy(client_.session_id().data(), *session_id_size);
152 *key_request_size = client_.key_message_length();
153 *key_request = AllocateAndCopy(client_.key_message(), *key_request_size);
154 *default_url_size = client_.default_url().size();
155 *default_url = AllocateAndCopy(client_.default_url().data(),
156 *default_url_size);
157 return kSuccess;
158 }
159
160 ClearKeyCdm::Status ClearKeyCdm::AddKey(const char* session_id,
161 int session_id_size,
162 const uint8_t* key,
163 int key_size,
164 const uint8_t* key_id,
165 int key_id_size) {
166 base::AutoLock auto_lock(lock_);
167 ScopedResetter<Client> auto_resetter(&client_);
168 decryptor_.AddKey("", key, key_size, key_id, key_id_size,
169 std::string(session_id, session_id_size));
170
171 // Client methods are called synchronously, so we can use client variables
ddorwin 2012/08/16 17:36:50 Not sure what this is trying to say (that isn't al
xhwang 2012/08/20 21:09:45 Done.
172 // here.
173 if (client_.status() != Client::kKeyAdded)
174 return kErrorUnknown;
175
176 return kSuccess;
177 }
178
179 ClearKeyCdm::Status ClearKeyCdm::CancelKeyRequest(const char* session_id,
180 int session_id_size) {
181 base::AutoLock auto_lock(lock_);
182 ScopedResetter<Client> auto_resetter(&client_);
183 decryptor_.CancelKeyRequest("", std::string(session_id, session_id_size));
184 return kSuccess;
185 }
186
187 static void CopyDecryptResults(
188 media::Decryptor::Status* status_copy,
189 scoped_refptr<media::DecoderBuffer>* buffer_copy,
190 media::Decryptor::Status status,
191 const scoped_refptr<media::DecoderBuffer>& buffer) {
192 *status_copy = status;
193 *buffer_copy = buffer;
194 }
195
196 ClearKeyCdm::Status ClearKeyCdm::Decrypt(
197 const char* session_id,
198 int session_id_size,
199 const cdm::InputBuffer& encrypted_buffer,
200 cdm::OutputBuffer* decrypted_buffer) {
201 scoped_refptr<media::DecoderBuffer> decoder_buffer =
202 CopyDecoderBufferFrom(encrypted_buffer);
203
204 // Callback is called synchronously, so we can use variables on the stack.
205 media::Decryptor::Status status;
206 scoped_refptr<media::DecoderBuffer> buffer;
207 decryptor_.Decrypt(decoder_buffer,
208 base::Bind(&CopyDecryptResults, &status, &buffer));
209
210 if (status == media::Decryptor::kError)
211 return kErrorUnknown;
212
213 if (status == media::Decryptor::kNoKey)
214 return kErrorNoKey;
215
216 DCHECK(buffer);
217 int data_size = buffer->GetDataSize();
218 decrypted_buffer->data = AllocateAndCopy(buffer->GetData(), data_size);
219 decrypted_buffer->data_size = data_size;
220 decrypted_buffer->timestamp = buffer->GetTimestamp().InMilliseconds();
221 decrypted_buffer->duration = buffer->GetDuration().InMilliseconds();
222 return kSuccess;
223 }
224
225 } // namespace webkit_media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698