blob: a60f402ccb178bc0ae7c3096d08864fd4d085d8d [file] [log] [blame]
[email protected]85a37afd2013-05-30 22:51:151// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]e5aeef02012-08-17 00:18:432// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]6cae92e2013-10-19 00:12:145#include "media/cdm/ppapi/cdm_adapter.h"
6
[email protected]6cae92e2013-10-19 00:12:147#include "media/cdm/ppapi/cdm_helpers.h"
[email protected]e5aeef02012-08-17 00:18:438
[email protected]76ee293e2013-05-22 18:10:479#if defined(CHECK_DOCUMENT_URL)
10#include "ppapi/cpp/dev/url_util_dev.h"
11#include "ppapi/cpp/instance_handle.h"
12#endif // defined(CHECK_DOCUMENT_URL)
[email protected]799eace2013-03-11 20:28:2213
[email protected]e5aeef02012-08-17 00:18:4314namespace {
15
[email protected]98ad9782012-08-22 04:06:2216bool IsMainThread() {
17 return pp::Module::Get()->core()->IsMainThread();
18}
19
[email protected]8f1be472012-12-15 19:06:3320// Posts a task to run |cb| on the main thread. The task is posted even if the
21// current thread is the main thread.
22void PostOnMain(pp::CompletionCallback cb) {
23 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
24}
25
26// Ensures |cb| is called on the main thread, either because the current thread
27// is the main thread or by posting it to the main thread.
[email protected]e5aeef02012-08-17 00:18:4328void CallOnMain(pp::CompletionCallback cb) {
[email protected]98ad9782012-08-22 04:06:2229 // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
30 // off the main thread yet. Remove this once the change lands.
31 if (IsMainThread())
32 cb.Run(PP_OK);
33 else
[email protected]8f1be472012-12-15 19:06:3334 PostOnMain(cb);
[email protected]e5aeef02012-08-17 00:18:4335}
36
[email protected]181d9c12012-10-03 22:53:4837// Configures a cdm::InputBuffer. |subsamples| must exist as long as
38// |input_buffer| is in use.
39void ConfigureInputBuffer(
40 const pp::Buffer_Dev& encrypted_buffer,
41 const PP_EncryptedBlockInfo& encrypted_block_info,
42 std::vector<cdm::SubsampleEntry>* subsamples,
43 cdm::InputBuffer* input_buffer) {
44 PP_DCHECK(subsamples);
[email protected]741c28f2012-10-18 07:02:2545 PP_DCHECK(!encrypted_buffer.is_null());
46
[email protected]3b274b42012-10-26 20:41:2647 input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
[email protected]2468aae2012-11-21 19:53:1648 input_buffer->data_size = encrypted_block_info.data_size;
[email protected]03481182013-10-23 09:51:4349 PP_DCHECK(encrypted_buffer.size() >= input_buffer->data_size);
[email protected]181d9c12012-10-03 22:53:4850 input_buffer->data_offset = encrypted_block_info.data_offset;
[email protected]181d9c12012-10-03 22:53:4851
[email protected]f3fffa22013-01-25 22:16:0352 PP_DCHECK(encrypted_block_info.key_id_size <=
53 arraysize(encrypted_block_info.key_id));
54 input_buffer->key_id_size = encrypted_block_info.key_id_size;
55 input_buffer->key_id = input_buffer->key_id_size > 0 ?
56 encrypted_block_info.key_id : NULL;
57
58 PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
59 input_buffer->iv_size = encrypted_block_info.iv_size;
60 input_buffer->iv = encrypted_block_info.iv_size > 0 ?
61 encrypted_block_info.iv : NULL;
62
63 input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
[email protected]181d9c12012-10-03 22:53:4864 if (encrypted_block_info.num_subsamples > 0) {
65 subsamples->reserve(encrypted_block_info.num_subsamples);
66
67 for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
68 subsamples->push_back(cdm::SubsampleEntry(
69 encrypted_block_info.subsamples[i].clear_bytes,
70 encrypted_block_info.subsamples[i].cipher_bytes));
71 }
72
73 input_buffer->subsamples = &(*subsamples)[0];
74 }
75
76 input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
77}
78
[email protected]8f5a9a52012-10-23 20:49:2079PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
80 switch (status) {
81 case cdm::kSuccess:
82 return PP_DECRYPTRESULT_SUCCESS;
83 case cdm::kNoKey:
84 return PP_DECRYPTRESULT_DECRYPT_NOKEY;
85 case cdm::kNeedMoreData:
86 return PP_DECRYPTRESULT_NEEDMOREDATA;
87 case cdm::kDecryptError:
88 return PP_DECRYPTRESULT_DECRYPT_ERROR;
89 case cdm::kDecodeError:
90 return PP_DECRYPTRESULT_DECODE_ERROR;
91 default:
92 PP_NOTREACHED();
93 return PP_DECRYPTRESULT_DECODE_ERROR;
94 }
95}
96
[email protected]e9d3a1022012-10-11 23:43:5597PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
[email protected]181d9c12012-10-03 22:53:4898 cdm::VideoFormat format) {
[email protected]8f5a9a52012-10-23 20:49:2099 switch (format) {
100 case cdm::kYv12:
101 return PP_DECRYPTEDFRAMEFORMAT_YV12;
102 case cdm::kI420:
103 return PP_DECRYPTEDFRAMEFORMAT_I420;
104 default:
105 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
106 }
[email protected]e9d3a1022012-10-11 23:43:55107}
108
[email protected]455e7d842013-10-22 23:19:39109PP_DecryptedSampleFormat CdmAudioFormatToPpDecryptedSampleFormat(
110 cdm::AudioFormat format) {
111 switch (format) {
112 case cdm::kAudioFormatU8:
113 return PP_DECRYPTEDSAMPLEFORMAT_U8;
114 case cdm::kAudioFormatS16:
115 return PP_DECRYPTEDSAMPLEFORMAT_S16;
116 case cdm::kAudioFormatS32:
117 return PP_DECRYPTEDSAMPLEFORMAT_S32;
118 case cdm::kAudioFormatF32:
119 return PP_DECRYPTEDSAMPLEFORMAT_F32;
120 case cdm::kAudioFormatPlanarS16:
121 return PP_DECRYPTEDSAMPLEFORMAT_PLANAR_S16;
122 case cdm::kAudioFormatPlanarF32:
123 return PP_DECRYPTEDSAMPLEFORMAT_PLANAR_F32;
124 default:
125 return PP_DECRYPTEDSAMPLEFORMAT_UNKNOWN;
126 }
127}
128
[email protected]c999b3b72012-10-19 22:33:46129cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
130 PP_AudioCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20131 switch (codec) {
132 case PP_AUDIOCODEC_VORBIS:
133 return cdm::AudioDecoderConfig::kCodecVorbis;
[email protected]4967628d2012-10-27 02:08:48134 case PP_AUDIOCODEC_AAC:
135 return cdm::AudioDecoderConfig::kCodecAac;
[email protected]8f5a9a52012-10-23 20:49:20136 default:
137 return cdm::AudioDecoderConfig::kUnknownAudioCodec;
138 }
[email protected]c999b3b72012-10-19 22:33:46139}
140
[email protected]e9d3a1022012-10-11 23:43:55141cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
142 PP_VideoCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20143 switch (codec) {
144 case PP_VIDEOCODEC_VP8:
[email protected]4967628d2012-10-27 02:08:48145 return cdm::VideoDecoderConfig::kCodecVp8;
146 case PP_VIDEOCODEC_H264:
147 return cdm::VideoDecoderConfig::kCodecH264;
[email protected]8f5a9a52012-10-23 20:49:20148 default:
149 return cdm::VideoDecoderConfig::kUnknownVideoCodec;
150 }
[email protected]e9d3a1022012-10-11 23:43:55151}
152
153cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
154 PP_VideoCodecProfile profile) {
[email protected]8f5a9a52012-10-23 20:49:20155 switch (profile) {
156 case PP_VIDEOCODECPROFILE_VP8_MAIN:
157 return cdm::VideoDecoderConfig::kVp8ProfileMain;
[email protected]4967628d2012-10-27 02:08:48158 case PP_VIDEOCODECPROFILE_H264_BASELINE:
159 return cdm::VideoDecoderConfig::kH264ProfileBaseline;
160 case PP_VIDEOCODECPROFILE_H264_MAIN:
161 return cdm::VideoDecoderConfig::kH264ProfileMain;
162 case PP_VIDEOCODECPROFILE_H264_EXTENDED:
163 return cdm::VideoDecoderConfig::kH264ProfileExtended;
164 case PP_VIDEOCODECPROFILE_H264_HIGH:
165 return cdm::VideoDecoderConfig::kH264ProfileHigh;
166 case PP_VIDEOCODECPROFILE_H264_HIGH_10:
167 return cdm::VideoDecoderConfig::kH264ProfileHigh10;
168 case PP_VIDEOCODECPROFILE_H264_HIGH_422:
169 return cdm::VideoDecoderConfig::kH264ProfileHigh422;
170 case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
171 return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
[email protected]8f5a9a52012-10-23 20:49:20172 default:
173 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
174 }
[email protected]e9d3a1022012-10-11 23:43:55175}
176
177cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
178 PP_DecryptedFrameFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20179 switch (format) {
180 case PP_DECRYPTEDFRAMEFORMAT_YV12:
181 return cdm::kYv12;
182 case PP_DECRYPTEDFRAMEFORMAT_I420:
183 return cdm::kI420;
184 default:
185 return cdm::kUnknownVideoFormat;
186 }
[email protected]181d9c12012-10-03 22:53:48187}
188
[email protected]bf5f1682012-10-23 04:31:43189cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
190 PP_DecryptorStreamType stream_type) {
191 switch (stream_type) {
192 case PP_DECRYPTORSTREAMTYPE_AUDIO:
193 return cdm::kStreamTypeAudio;
194 case PP_DECRYPTORSTREAMTYPE_VIDEO:
195 return cdm::kStreamTypeVideo;
196 }
197
198 PP_NOTREACHED();
199 return cdm::kStreamTypeVideo;
200}
201
[email protected]e5aeef02012-08-17 00:18:43202} // namespace
203
[email protected]177bcf82013-08-10 08:21:16204namespace media {
[email protected]e5aeef02012-08-17 00:18:43205
[email protected]6cae92e2013-10-19 00:12:14206CdmAdapter::CdmAdapter(PP_Instance instance, pp::Module* module)
[email protected]e5aeef02012-08-17 00:18:43207 : pp::Instance(instance),
[email protected]d341e332012-08-28 18:57:40208 pp::ContentDecryptor_Private(this),
[email protected]0f6882e2013-10-21 21:26:07209#if defined(OS_CHROMEOS)
210 output_protection_(this),
211 platform_verification_(this),
212 challenge_in_progress_(false),
213 output_link_mask_(0),
214 output_protection_mask_(0),
215 query_output_protection_in_progress_(false),
216#endif
[email protected]9264e1502012-09-18 19:53:01217 allocator_(this),
[email protected]d341e332012-08-28 18:57:40218 cdm_(NULL) {
[email protected]e5aeef02012-08-17 00:18:43219 callback_factory_.Initialize(this);
220}
221
[email protected]580237362013-10-19 15:49:37222CdmAdapter::~CdmAdapter() {}
[email protected]b68e1442013-02-12 04:46:11223
[email protected]6cae92e2013-10-19 00:12:14224bool CdmAdapter::CreateCdmInstance(const std::string& key_system) {
[email protected]b68e1442013-02-12 04:46:11225 PP_DCHECK(!cdm_);
[email protected]580237362013-10-19 15:49:37226 cdm_ = make_linked_ptr(CdmWrapper::Create(
227 key_system.data(), key_system.size(), GetCdmHost, this));
[email protected]b68e1442013-02-12 04:46:11228 return (cdm_ != NULL);
[email protected]d341e332012-08-28 18:57:40229}
230
[email protected]a941d4e572013-10-14 21:22:05231// No KeyErrors should be reported in this function because they cannot be
232// bubbled up in the WD EME API. Those errors will be reported during session
233// creation (aka GenerateKeyRequest).
[email protected]6cae92e2013-10-19 00:12:14234void CdmAdapter::Initialize(const std::string& key_system,
[email protected]38a995d92013-09-20 06:34:51235 bool can_challenge_platform) {
[email protected]6cb006c2013-01-10 21:39:18236 PP_DCHECK(!key_system.empty());
[email protected]38a995d92013-09-20 06:34:51237 PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_));
238
[email protected]a941d4e572013-10-14 21:22:05239 if (!cdm_ && !CreateCdmInstance(key_system))
240 return;
241
[email protected]38a995d92013-09-20 06:34:51242 PP_DCHECK(cdm_);
243 key_system_ = key_system;
244}
245
[email protected]6cae92e2013-10-19 00:12:14246void CdmAdapter::GenerateKeyRequest(const std::string& type,
[email protected]38a995d92013-09-20 06:34:51247 pp::VarArrayBuffer init_data) {
[email protected]a941d4e572013-10-14 21:22:05248 // Initialize() doesn't report an error, so GenerateKeyRequest() can be called
249 // even if Initialize() failed.
250 if (!cdm_) {
251 SendUnknownKeyError(key_system_, std::string());
252 return;
253 }
[email protected]e5aeef02012-08-17 00:18:43254
[email protected]76ee293e2013-05-22 18:10:47255#if defined(CHECK_DOCUMENT_URL)
256 PP_URLComponents_Dev url_components = {};
257 pp::Var href = pp::URLUtil_Dev::Get()->GetDocumentURL(
258 pp::InstanceHandle(pp_instance()), &url_components);
259 PP_DCHECK(href.is_string());
260 PP_DCHECK(!href.AsString().empty());
261 PP_DCHECK(url_components.host.begin);
262 PP_DCHECK(0 < url_components.host.len);
263#endif // defined(CHECK_DOCUMENT_URL)
[email protected]799eace2013-03-11 20:28:22264
[email protected]d341e332012-08-28 18:57:40265 cdm::Status status = cdm_->GenerateKeyRequest(
[email protected]f1b1db02012-10-29 22:50:23266 type.data(), type.size(),
[email protected]3b274b42012-10-26 20:41:26267 static_cast<const uint8_t*>(init_data.Map()),
[email protected]f75555a2012-12-10 22:35:24268 init_data.ByteLength());
[email protected]0b959582012-10-01 23:13:27269 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]38a995d92013-09-20 06:34:51270 if (status != cdm::kSuccess)
271 SendUnknownKeyError(key_system_, std::string());
[email protected]e5aeef02012-08-17 00:18:43272}
273
[email protected]6cae92e2013-10-19 00:12:14274void CdmAdapter::AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22275 pp::VarArrayBuffer key,
276 pp::VarArrayBuffer init_data) {
[email protected]a941d4e572013-10-14 21:22:05277 // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
278 // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
[email protected]3b274b42012-10-26 20:41:26279 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18280 SendUnknownKeyError(key_system_, session_id);
[email protected]3b274b42012-10-26 20:41:26281 return;
282 }
283
284 const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
[email protected]03481182013-10-23 09:51:43285 const uint32_t key_size = key.ByteLength();
[email protected]3b274b42012-10-26 20:41:26286 const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
[email protected]03481182013-10-23 09:51:43287 const uint32_t init_data_size = init_data.ByteLength();
[email protected]26b200102013-01-30 05:24:23288 PP_DCHECK(!init_data_ptr == !init_data_size);
[email protected]e5aeef02012-08-17 00:18:43289
[email protected]03481182013-10-23 09:51:43290 if (!key_ptr || !key_size) {
[email protected]6cb006c2013-01-10 21:39:18291 SendUnknownKeyError(key_system_, session_id);
[email protected]ea4ff802012-09-13 01:36:44292 return;
[email protected]3b274b42012-10-26 20:41:26293 }
[email protected]e5aeef02012-08-17 00:18:43294
[email protected]d341e332012-08-28 18:57:40295 cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
296 key_ptr, key_size,
297 init_data_ptr, init_data_size);
[email protected]0b959582012-10-01 23:13:27298 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]d341e332012-08-28 18:57:40299 if (status != cdm::kSuccess) {
[email protected]6cb006c2013-01-10 21:39:18300 SendUnknownKeyError(key_system_, session_id);
[email protected]ea4ff802012-09-13 01:36:44301 return;
[email protected]d341e332012-08-28 18:57:40302 }
303
[email protected]6cb006c2013-01-10 21:39:18304 SendKeyAdded(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43305}
306
[email protected]6cae92e2013-10-19 00:12:14307void CdmAdapter::CancelKeyRequest(const std::string& session_id) {
[email protected]a941d4e572013-10-14 21:22:05308 // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
309 // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
[email protected]3b274b42012-10-26 20:41:26310 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18311 SendUnknownKeyError(key_system_, session_id);
[email protected]3b274b42012-10-26 20:41:26312 return;
313 }
314
[email protected]d341e332012-08-28 18:57:40315 cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
316 session_id.size());
[email protected]0b959582012-10-01 23:13:27317 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]3b274b42012-10-26 20:41:26318 if (status != cdm::kSuccess)
[email protected]6cb006c2013-01-10 21:39:18319 SendUnknownKeyError(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43320}
321
[email protected]3b274b42012-10-26 20:41:26322// Note: In the following decryption/decoding related functions, errors are NOT
323// reported via KeyError, but are reported via corresponding PPB calls.
324
[email protected]6cae92e2013-10-19 00:12:14325void CdmAdapter::Decrypt(pp::Buffer_Dev encrypted_buffer,
[email protected]98ad9782012-08-22 04:06:22326 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]e5aeef02012-08-17 00:18:43327 PP_DCHECK(!encrypted_buffer.is_null());
328
[email protected]ce19e7b52012-12-05 19:47:24329 // Release a buffer that the caller indicated it is finished with.
330 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
331
[email protected]3b274b42012-10-26 20:41:26332 cdm::Status status = cdm::kDecryptError;
[email protected]7ed56ed2012-10-02 02:43:27333 LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
[email protected]3b274b42012-10-26 20:41:26334
335 if (cdm_) {
336 cdm::InputBuffer input_buffer;
337 std::vector<cdm::SubsampleEntry> subsamples;
338 ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
339 &input_buffer);
340 status = cdm_->Decrypt(input_buffer, decrypted_block.get());
[email protected]f75555a2012-12-10 22:35:24341 PP_DCHECK(status != cdm::kSuccess ||
342 (decrypted_block->DecryptedBuffer() &&
343 decrypted_block->DecryptedBuffer()->Size()));
[email protected]3b274b42012-10-26 20:41:26344 }
[email protected]d341e332012-08-28 18:57:40345
346 CallOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14347 &CdmAdapter::DeliverBlock,
[email protected]d341e332012-08-28 18:57:40348 status,
[email protected]7ed56ed2012-10-02 02:43:27349 decrypted_block,
[email protected]d341e332012-08-28 18:57:40350 encrypted_block_info.tracking_info));
[email protected]e5aeef02012-08-17 00:18:43351}
352
[email protected]6cae92e2013-10-19 00:12:14353void CdmAdapter::InitializeAudioDecoder(
[email protected]c999b3b72012-10-19 22:33:46354 const PP_AudioDecoderConfig& decoder_config,
355 pp::Buffer_Dev extra_data_buffer) {
[email protected]3b274b42012-10-26 20:41:26356 cdm::Status status = cdm::kSessionError;
357 if (cdm_) {
358 cdm::AudioDecoderConfig cdm_decoder_config;
359 cdm_decoder_config.codec =
360 PpAudioCodecToCdmAudioCodec(decoder_config.codec);
361 cdm_decoder_config.channel_count = decoder_config.channel_count;
362 cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
363 cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
364 cdm_decoder_config.extra_data =
365 static_cast<uint8_t*>(extra_data_buffer.data());
[email protected]03481182013-10-23 09:51:43366 cdm_decoder_config.extra_data_size = extra_data_buffer.size();
[email protected]3b274b42012-10-26 20:41:26367 status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
368 }
[email protected]c999b3b72012-10-19 22:33:46369
370 CallOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14371 &CdmAdapter::DecoderInitializeDone,
[email protected]c999b3b72012-10-19 22:33:46372 PP_DECRYPTORSTREAMTYPE_AUDIO,
373 decoder_config.request_id,
374 status == cdm::kSuccess));
375}
376
[email protected]6cae92e2013-10-19 00:12:14377void CdmAdapter::InitializeVideoDecoder(
[email protected]e9d3a1022012-10-11 23:43:55378 const PP_VideoDecoderConfig& decoder_config,
379 pp::Buffer_Dev extra_data_buffer) {
[email protected]3b274b42012-10-26 20:41:26380 cdm::Status status = cdm::kSessionError;
381 if (cdm_) {
382 cdm::VideoDecoderConfig cdm_decoder_config;
383 cdm_decoder_config.codec =
384 PpVideoCodecToCdmVideoCodec(decoder_config.codec);
385 cdm_decoder_config.profile =
386 PpVCProfileToCdmVCProfile(decoder_config.profile);
387 cdm_decoder_config.format =
388 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
389 cdm_decoder_config.coded_size.width = decoder_config.width;
390 cdm_decoder_config.coded_size.height = decoder_config.height;
391 cdm_decoder_config.extra_data =
392 static_cast<uint8_t*>(extra_data_buffer.data());
[email protected]03481182013-10-23 09:51:43393 cdm_decoder_config.extra_data_size = extra_data_buffer.size();
[email protected]3b274b42012-10-26 20:41:26394 status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
395 }
[email protected]e9d3a1022012-10-11 23:43:55396
397 CallOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14398 &CdmAdapter::DecoderInitializeDone,
[email protected]c999b3b72012-10-19 22:33:46399 PP_DECRYPTORSTREAMTYPE_VIDEO,
400 decoder_config.request_id,
401 status == cdm::kSuccess));
[email protected]e9d3a1022012-10-11 23:43:55402}
403
[email protected]6cae92e2013-10-19 00:12:14404void CdmAdapter::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
[email protected]23de87452012-10-12 07:03:09405 uint32_t request_id) {
[email protected]a941d4e572013-10-14 21:22:05406 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
[email protected]3b274b42012-10-26 20:41:26407 if (cdm_) {
408 cdm_->DeinitializeDecoder(
409 PpDecryptorStreamTypeToCdmStreamType(decoder_type));
410 }
411
[email protected]23de87452012-10-12 07:03:09412 CallOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14413 &CdmAdapter::DecoderDeinitializeDone,
[email protected]23de87452012-10-12 07:03:09414 decoder_type,
415 request_id));
416}
417
[email protected]6cae92e2013-10-19 00:12:14418void CdmAdapter::ResetDecoder(PP_DecryptorStreamType decoder_type,
[email protected]23de87452012-10-12 07:03:09419 uint32_t request_id) {
[email protected]a941d4e572013-10-14 21:22:05420 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
[email protected]3b274b42012-10-26 20:41:26421 if (cdm_)
422 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
423
[email protected]6cae92e2013-10-19 00:12:14424 CallOnMain(callback_factory_.NewCallback(&CdmAdapter::DecoderResetDone,
[email protected]23de87452012-10-12 07:03:09425 decoder_type,
426 request_id));
427}
428
[email protected]6cae92e2013-10-19 00:12:14429void CdmAdapter::DecryptAndDecode(
[email protected]467434d2012-10-12 10:48:53430 PP_DecryptorStreamType decoder_type,
431 pp::Buffer_Dev encrypted_buffer,
432 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]a941d4e572013-10-14 21:22:05433 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
[email protected]ce19e7b52012-12-05 19:47:24434 // Release a buffer that the caller indicated it is finished with.
435 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
436
[email protected]181d9c12012-10-03 22:53:48437 cdm::InputBuffer input_buffer;
438 std::vector<cdm::SubsampleEntry> subsamples;
[email protected]3b274b42012-10-26 20:41:26439 if (cdm_ && !encrypted_buffer.is_null()) {
[email protected]741c28f2012-10-18 07:02:25440 ConfigureInputBuffer(encrypted_buffer,
441 encrypted_block_info,
442 &subsamples,
443 &input_buffer);
444 }
[email protected]181d9c12012-10-03 22:53:48445
[email protected]ecbb97682012-10-24 22:33:54446 cdm::Status status = cdm::kDecodeError;
[email protected]3b274b42012-10-26 20:41:26447
[email protected]ecbb97682012-10-24 22:33:54448 switch (decoder_type) {
449 case PP_DECRYPTORSTREAMTYPE_VIDEO: {
450 LinkedVideoFrame video_frame(new VideoFrameImpl());
[email protected]3b274b42012-10-26 20:41:26451 if (cdm_)
452 status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
[email protected]ecbb97682012-10-24 22:33:54453 CallOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14454 &CdmAdapter::DeliverFrame,
[email protected]ecbb97682012-10-24 22:33:54455 status,
456 video_frame,
457 encrypted_block_info.tracking_info));
458 return;
459 }
460
461 case PP_DECRYPTORSTREAMTYPE_AUDIO: {
462 LinkedAudioFrames audio_frames(new AudioFramesImpl());
[email protected]3b274b42012-10-26 20:41:26463 if (cdm_) {
464 status = cdm_->DecryptAndDecodeSamples(input_buffer,
465 audio_frames.get());
466 }
[email protected]ecbb97682012-10-24 22:33:54467 CallOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14468 &CdmAdapter::DeliverSamples,
[email protected]ecbb97682012-10-24 22:33:54469 status,
470 audio_frames,
471 encrypted_block_info.tracking_info));
472 return;
473 }
474
475 default:
476 PP_NOTREACHED();
477 return;
478 }
[email protected]d341e332012-08-28 18:57:40479}
480
[email protected]03481182013-10-23 09:51:43481cdm::Buffer* CdmAdapter::Allocate(uint32_t capacity) {
[email protected]b68e1442013-02-12 04:46:11482 return allocator_.Allocate(capacity);
483}
484
[email protected]6cae92e2013-10-19 00:12:14485void CdmAdapter::SetTimer(int64_t delay_ms, void* context) {
[email protected]f5c9b938e2012-10-10 12:24:07486 // NOTE: doesn't really need to run on the main thread; could just as well run
487 // on a helper thread if |cdm_| were thread-friendly and care was taken. We
488 // only use CallOnMainThread() here to get delayed-execution behavior.
489 pp::Module::Get()->core()->CallOnMainThread(
490 delay_ms,
[email protected]6cae92e2013-10-19 00:12:14491 callback_factory_.NewCallback(&CdmAdapter::TimerExpired, context),
[email protected]f5c9b938e2012-10-10 12:24:07492 PP_OK);
493}
494
[email protected]6cae92e2013-10-19 00:12:14495void CdmAdapter::TimerExpired(int32_t result, void* context) {
[email protected]f5c9b938e2012-10-10 12:24:07496 PP_DCHECK(result == PP_OK);
[email protected]f75555a2012-12-10 22:35:24497 cdm_->TimerExpired(context);
[email protected]f5c9b938e2012-10-10 12:24:07498}
499
[email protected]6cae92e2013-10-19 00:12:14500double CdmAdapter::GetCurrentWallTimeInSeconds() {
[email protected]f5c9b938e2012-10-10 12:24:07501 return pp::Module::Get()->core()->GetTime();
502}
503
[email protected]6cae92e2013-10-19 00:12:14504void CdmAdapter::SendKeyMessage(
[email protected]03481182013-10-23 09:51:43505 const char* session_id, uint32_t session_id_length,
506 const char* message, uint32_t message_length,
507 const char* default_url, uint32_t default_url_length) {
[email protected]6cb006c2013-01-10 21:39:18508 PP_DCHECK(!key_system_.empty());
[email protected]8f1be472012-12-15 19:06:33509 PostOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14510 &CdmAdapter::KeyMessage,
[email protected]6cb006c2013-01-10 21:39:18511 SessionInfo(key_system_,
512 std::string(session_id, session_id_length)),
[email protected]0a81bdb2013-06-29 23:18:06513 std::vector<uint8>(message, message + message_length),
[email protected]f75555a2012-12-10 22:35:24514 std::string(default_url, default_url_length)));
515}
516
[email protected]6cae92e2013-10-19 00:12:14517void CdmAdapter::SendKeyError(const char* session_id,
[email protected]03481182013-10-23 09:51:43518 uint32_t session_id_length,
[email protected]f75555a2012-12-10 22:35:24519 cdm::MediaKeyError error_code,
520 uint32_t system_code) {
[email protected]6cb006c2013-01-10 21:39:18521 SendKeyErrorInternal(key_system_,
522 std::string(session_id, session_id_length),
523 error_code,
524 system_code);
525}
526
[email protected]6cae92e2013-10-19 00:12:14527void CdmAdapter::GetPrivateData(int32_t* instance,
[email protected]0f6882e2013-10-21 21:26:07528 GetPrivateInterface* get_interface) {
[email protected]b68e1442013-02-12 04:46:11529 *instance = pp_instance();
530 *get_interface = pp::Module::Get()->get_browser_interface();
531}
532
[email protected]6cae92e2013-10-19 00:12:14533void CdmAdapter::SendUnknownKeyError(const std::string& key_system,
[email protected]6cb006c2013-01-10 21:39:18534 const std::string& session_id) {
535 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0);
536}
537
[email protected]6cae92e2013-10-19 00:12:14538void CdmAdapter::SendKeyAdded(const std::string& key_system,
[email protected]6cb006c2013-01-10 21:39:18539 const std::string& session_id) {
[email protected]8f1be472012-12-15 19:06:33540 PostOnMain(callback_factory_.NewCallback(
[email protected]6cae92e2013-10-19 00:12:14541 &CdmAdapter::KeyAdded,
[email protected]6cb006c2013-01-10 21:39:18542 SessionInfo(key_system_, session_id)));
[email protected]f75555a2012-12-10 22:35:24543}
544
[email protected]6cae92e2013-10-19 00:12:14545void CdmAdapter::SendKeyErrorInternal(const std::string& key_system,
[email protected]6cb006c2013-01-10 21:39:18546 const std::string& session_id,
547 cdm::MediaKeyError error_code,
548 uint32_t system_code) {
[email protected]6cae92e2013-10-19 00:12:14549 PostOnMain(callback_factory_.NewCallback(&CdmAdapter::KeyError,
[email protected]6cb006c2013-01-10 21:39:18550 SessionInfo(key_system_, session_id),
551 error_code,
552 system_code));
[email protected]8f1be472012-12-15 19:06:33553}
554
[email protected]6cae92e2013-10-19 00:12:14555void CdmAdapter::KeyAdded(int32_t result, const SessionInfo& session_info) {
[email protected]f5c9b938e2012-10-10 12:24:07556 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:18557 PP_DCHECK(!session_info.key_system.empty());
558 pp::ContentDecryptor_Private::KeyAdded(session_info.key_system,
559 session_info.session_id);
[email protected]e5aeef02012-08-17 00:18:43560}
561
[email protected]6cae92e2013-10-19 00:12:14562void CdmAdapter::KeyMessage(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18563 const SessionInfo& session_info,
[email protected]0a81bdb2013-06-29 23:18:06564 const std::vector<uint8>& message,
[email protected]f75555a2012-12-10 22:35:24565 const std::string& default_url) {
[email protected]f5c9b938e2012-10-10 12:24:07566 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:18567 PP_DCHECK(!session_info.key_system.empty());
[email protected]6d613d62012-12-04 23:39:00568
[email protected]a6e4fbf2012-12-12 05:25:00569 pp::VarArrayBuffer message_array_buffer(message.size());
570 if (message.size() > 0) {
571 memcpy(message_array_buffer.Map(), message.data(), message.size());
[email protected]6d613d62012-12-04 23:39:00572 }
573
[email protected]d341e332012-08-28 18:57:40574 pp::ContentDecryptor_Private::KeyMessage(
[email protected]6cb006c2013-01-10 21:39:18575 session_info.key_system, session_info.session_id,
576 message_array_buffer, default_url);
[email protected]e5aeef02012-08-17 00:18:43577}
578
[email protected]6cae92e2013-10-19 00:12:14579void CdmAdapter::KeyError(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18580 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:24581 cdm::MediaKeyError error_code,
582 uint32_t system_code) {
[email protected]f5c9b938e2012-10-10 12:24:07583 PP_DCHECK(result == PP_OK);
[email protected]f75555a2012-12-10 22:35:24584 pp::ContentDecryptor_Private::KeyError(
[email protected]6cb006c2013-01-10 21:39:18585 session_info.key_system, session_info.session_id,
586 error_code, system_code);
[email protected]e5aeef02012-08-17 00:18:43587}
588
[email protected]6cae92e2013-10-19 00:12:14589void CdmAdapter::DeliverBlock(int32_t result,
[email protected]d341e332012-08-28 18:57:40590 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:27591 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:40592 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:07593 PP_DCHECK(result == PP_OK);
[email protected]d341e332012-08-28 18:57:40594 PP_DecryptedBlockInfo decrypted_block_info;
[email protected]181d9c12012-10-03 22:53:48595 decrypted_block_info.tracking_info = tracking_info;
[email protected]f75555a2012-12-10 22:35:24596 decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
[email protected]ce19e7b52012-12-05 19:47:24597 decrypted_block_info.tracking_info.buffer_id = 0;
598 decrypted_block_info.data_size = 0;
[email protected]8f5a9a52012-10-23 20:49:20599 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
[email protected]d341e332012-08-28 18:57:40600
[email protected]8f5a9a52012-10-23 20:49:20601 pp::Buffer_Dev buffer;
602
603 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]f75555a2012-12-10 22:35:24604 PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
605 if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
[email protected]ecbb97682012-10-24 22:33:54606 PP_NOTREACHED();
[email protected]d341e332012-08-28 18:57:40607 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
[email protected]8f5a9a52012-10-23 20:49:20608 } else {
[email protected]ce19e7b52012-12-05 19:47:24609 PpbBuffer* ppb_buffer =
[email protected]f75555a2012-12-10 22:35:24610 static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
[email protected]ce19e7b52012-12-05 19:47:24611 buffer = ppb_buffer->buffer_dev();
612 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
[email protected]f75555a2012-12-10 22:35:24613 decrypted_block_info.data_size = ppb_buffer->Size();
[email protected]8f5a9a52012-10-23 20:49:20614 }
[email protected]d341e332012-08-28 18:57:40615 }
616
[email protected]4bc37112012-09-21 19:49:25617 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
[email protected]e5aeef02012-08-17 00:18:43618}
619
[email protected]6cae92e2013-10-19 00:12:14620void CdmAdapter::DecoderInitializeDone(int32_t result,
[email protected]c999b3b72012-10-19 22:33:46621 PP_DecryptorStreamType decoder_type,
622 uint32_t request_id,
623 bool success) {
624 PP_DCHECK(result == PP_OK);
625 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
626 request_id,
627 success);
[email protected]e9d3a1022012-10-11 23:43:55628}
629
[email protected]6cae92e2013-10-19 00:12:14630void CdmAdapter::DecoderDeinitializeDone(int32_t result,
[email protected]23de87452012-10-12 07:03:09631 PP_DecryptorStreamType decoder_type,
632 uint32_t request_id) {
633 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
634 request_id);
635}
636
[email protected]6cae92e2013-10-19 00:12:14637void CdmAdapter::DecoderResetDone(int32_t result,
[email protected]23de87452012-10-12 07:03:09638 PP_DecryptorStreamType decoder_type,
639 uint32_t request_id) {
640 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
641}
642
[email protected]6cae92e2013-10-19 00:12:14643void CdmAdapter::DeliverFrame(
[email protected]181d9c12012-10-03 22:53:48644 int32_t result,
645 const cdm::Status& status,
646 const LinkedVideoFrame& video_frame,
647 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:07648 PP_DCHECK(result == PP_OK);
[email protected]181d9c12012-10-03 22:53:48649 PP_DecryptedFrameInfo decrypted_frame_info;
[email protected]749576ff2012-10-30 05:10:48650 decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
[email protected]ce19e7b52012-12-05 19:47:24651 decrypted_frame_info.tracking_info.buffer_id = 0;
[email protected]8f5a9a52012-10-23 20:49:20652 decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
[email protected]181d9c12012-10-03 22:53:48653
[email protected]8f5a9a52012-10-23 20:49:20654 pp::Buffer_Dev buffer;
[email protected]741c28f2012-10-18 07:02:25655
[email protected]8f5a9a52012-10-23 20:49:20656 if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]ce19e7b52012-12-05 19:47:24657 if (!IsValidVideoFrame(video_frame)) {
[email protected]ecbb97682012-10-24 22:33:54658 PP_NOTREACHED();
[email protected]8f5a9a52012-10-23 20:49:20659 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
660 } else {
[email protected]ce19e7b52012-12-05 19:47:24661 PpbBuffer* ppb_buffer =
[email protected]f75555a2012-12-10 22:35:24662 static_cast<PpbBuffer*>(video_frame->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:24663
664 buffer = ppb_buffer->buffer_dev();
665
[email protected]f75555a2012-12-10 22:35:24666 decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
[email protected]ce19e7b52012-12-05 19:47:24667 decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
668 decrypted_frame_info.format =
[email protected]f75555a2012-12-10 22:35:24669 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
670 decrypted_frame_info.width = video_frame->Size().width;
671 decrypted_frame_info.height = video_frame->Size().height;
[email protected]181d9c12012-10-03 22:53:48672 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]f75555a2012-12-10 22:35:24673 video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:48674 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]f75555a2012-12-10 22:35:24675 video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:48676 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]f75555a2012-12-10 22:35:24677 video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
[email protected]181d9c12012-10-03 22:53:48678 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]f75555a2012-12-10 22:35:24679 video_frame->Stride(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:48680 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]f75555a2012-12-10 22:35:24681 video_frame->Stride(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:48682 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]f75555a2012-12-10 22:35:24683 video_frame->Stride(cdm::VideoFrame::kVPlane);
[email protected]8f5a9a52012-10-23 20:49:20684 }
[email protected]181d9c12012-10-03 22:53:48685 }
[email protected]181d9c12012-10-03 22:53:48686 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
687}
688
[email protected]6cae92e2013-10-19 00:12:14689void CdmAdapter::DeliverSamples(int32_t result,
[email protected]ecbb97682012-10-24 22:33:54690 const cdm::Status& status,
691 const LinkedAudioFrames& audio_frames,
692 const PP_DecryptTrackingInfo& tracking_info) {
693 PP_DCHECK(result == PP_OK);
[email protected]749576ff2012-10-30 05:10:48694
[email protected]455e7d842013-10-22 23:19:39695 PP_DecryptedSampleInfo decrypted_sample_info;
696 decrypted_sample_info.tracking_info = tracking_info;
697 decrypted_sample_info.tracking_info.timestamp = 0;
698 decrypted_sample_info.tracking_info.buffer_id = 0;
699 decrypted_sample_info.data_size = 0;
700 decrypted_sample_info.result = CdmStatusToPpDecryptResult(status);
[email protected]ecbb97682012-10-24 22:33:54701
702 pp::Buffer_Dev buffer;
703
[email protected]455e7d842013-10-22 23:19:39704 if (decrypted_sample_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]f75555a2012-12-10 22:35:24705 PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
706 if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
[email protected]ecbb97682012-10-24 22:33:54707 PP_NOTREACHED();
[email protected]455e7d842013-10-22 23:19:39708 decrypted_sample_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
[email protected]ecbb97682012-10-24 22:33:54709 } else {
[email protected]f75555a2012-12-10 22:35:24710 PpbBuffer* ppb_buffer =
711 static_cast<PpbBuffer*>(audio_frames->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:24712 buffer = ppb_buffer->buffer_dev();
[email protected]455e7d842013-10-22 23:19:39713 decrypted_sample_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
714 decrypted_sample_info.data_size = ppb_buffer->Size();
715 decrypted_sample_info.format =
716 CdmAudioFormatToPpDecryptedSampleFormat(audio_frames->Format());
[email protected]ecbb97682012-10-24 22:33:54717 }
718 }
719
[email protected]455e7d842013-10-22 23:19:39720 pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_sample_info);
[email protected]ecbb97682012-10-24 22:33:54721}
[email protected]181d9c12012-10-03 22:53:48722
[email protected]6cae92e2013-10-19 00:12:14723bool CdmAdapter::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
[email protected]ce19e7b52012-12-05 19:47:24724 if (!video_frame.get() ||
[email protected]f75555a2012-12-10 22:35:24725 !video_frame->FrameBuffer() ||
726 (video_frame->Format() != cdm::kI420 &&
727 video_frame->Format() != cdm::kYv12)) {
[email protected]ce19e7b52012-12-05 19:47:24728 return false;
729 }
730
[email protected]f75555a2012-12-10 22:35:24731 PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:24732
[email protected]03481182013-10-23 09:51:43733 for (uint32_t i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
[email protected]ce19e7b52012-12-05 19:47:24734 int plane_height = (i == cdm::VideoFrame::kYPlane) ?
[email protected]f75555a2012-12-10 22:35:24735 video_frame->Size().height : (video_frame->Size().height + 1) / 2;
[email protected]ce19e7b52012-12-05 19:47:24736 cdm::VideoFrame::VideoPlane plane =
737 static_cast<cdm::VideoFrame::VideoPlane>(i);
[email protected]f75555a2012-12-10 22:35:24738 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
739 plane_height * video_frame->Stride(plane)) {
[email protected]ce19e7b52012-12-05 19:47:24740 return false;
741 }
742 }
743
744 return true;
745}
746
[email protected]03481182013-10-23 09:51:43747void CdmAdapter::OnDeferredInitializationDone(cdm::StreamType stream_type,
748 cdm::Status decoder_status) {
749 PP_NOTREACHED();
750}
751
[email protected]0f6882e2013-10-21 21:26:07752void CdmAdapter::SendPlatformChallenge(
[email protected]03481182013-10-23 09:51:43753 const char* service_id, uint32_t service_id_length,
754 const char* challenge, uint32_t challenge_length) {
[email protected]0f6882e2013-10-21 21:26:07755#if defined(OS_CHROMEOS)
756 PP_DCHECK(!challenge_in_progress_);
757
758 // Ensure member variables set by the callback are in a clean state.
759 signed_data_output_ = pp::Var();
760 signed_data_signature_output_ = pp::Var();
761 platform_key_certificate_output_ = pp::Var();
762
763 pp::VarArrayBuffer challenge_var(challenge_length);
764 uint8_t* var_data = static_cast<uint8_t*>(challenge_var.Map());
765 memcpy(var_data, challenge, challenge_length);
766
767 std::string service_id_str(service_id, service_id_length);
768 int32_t result = platform_verification_.ChallengePlatform(
769 pp::Var(service_id_str), challenge_var, &signed_data_output_,
770 &signed_data_signature_output_, &platform_key_certificate_output_,
771 callback_factory_.NewCallback(&CdmAdapter::SendPlatformChallengeDone));
772 challenge_var.Unmap();
773 if (result == PP_OK_COMPLETIONPENDING) {
774 challenge_in_progress_ = true;
775 return;
776 }
777
778 // Fall through on error and issue an empty OnPlatformChallengeResponse().
779 PP_DCHECK(result != PP_OK);
780#endif
781
782 cdm::PlatformChallengeResponse response = {};
783 cdm_->OnPlatformChallengeResponse(response);
784}
785
786void CdmAdapter::EnableOutputProtection(uint32_t desired_protection_mask) {
787#if defined(OS_CHROMEOS)
788 output_protection_.EnableProtection(
789 desired_protection_mask, callback_factory_.NewCallback(
790 &CdmAdapter::EnableProtectionDone));
791
792 // Errors are ignored since clients must call QueryOutputProtectionStatus() to
793 // inspect the protection status on a regular basis.
794 // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here...
795#endif
796}
797
798void CdmAdapter::QueryOutputProtectionStatus() {
799#if defined(OS_CHROMEOS)
800 PP_DCHECK(!query_output_protection_in_progress_);
801
802 output_link_mask_ = output_protection_mask_ = 0;
803 const int32_t result = output_protection_.QueryStatus(
804 &output_link_mask_,
805 &output_protection_mask_,
806 callback_factory_.NewCallback(
807 &CdmAdapter::QueryOutputProtectionStatusDone));
808 if (result == PP_OK_COMPLETIONPENDING) {
809 query_output_protection_in_progress_ = true;
810 return;
811 }
812
813 // Fall through on error and issue an empty OnQueryOutputProtectionStatus().
814 PP_DCHECK(result != PP_OK);
815#endif
816
817 cdm_->OnQueryOutputProtectionStatus(0, 0);
818}
819
820#if defined(OS_CHROMEOS)
821void CdmAdapter::SendPlatformChallengeDone(int32_t result) {
822 challenge_in_progress_ = false;
823
824 if (result != PP_OK) {
825 cdm::PlatformChallengeResponse response = {};
826 cdm_->OnPlatformChallengeResponse(response);
827 return;
828 }
829
830 pp::VarArrayBuffer signed_data_var(signed_data_output_);
831 pp::VarArrayBuffer signed_data_signature_var(signed_data_signature_output_);
832 std::string platform_key_certificate_string =
833 platform_key_certificate_output_.AsString();
834
835 cdm::PlatformChallengeResponse response = {
836 static_cast<uint8_t*>(signed_data_var.Map()),
[email protected]03481182013-10-23 09:51:43837 signed_data_var.ByteLength(),
[email protected]0f6882e2013-10-21 21:26:07838
839 static_cast<uint8_t*>(signed_data_signature_var.Map()),
[email protected]03481182013-10-23 09:51:43840 signed_data_signature_var.ByteLength(),
[email protected]0f6882e2013-10-21 21:26:07841
842 reinterpret_cast<const uint8_t*>(platform_key_certificate_string.c_str()),
[email protected]03481182013-10-23 09:51:43843 static_cast<uint32_t>(platform_key_certificate_string.length())
[email protected]0f6882e2013-10-21 21:26:07844 };
845 cdm_->OnPlatformChallengeResponse(response);
846
847 signed_data_var.Unmap();
848 signed_data_signature_var.Unmap();
849}
850
851void CdmAdapter::EnableProtectionDone(int32_t result) {
852 // Does nothing since clients must call QueryOutputProtectionStatus() to
853 // inspect the protection status on a regular basis.
854 // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here...
855}
856
857void CdmAdapter::QueryOutputProtectionStatusDone(int32_t result) {
858 PP_DCHECK(query_output_protection_in_progress_);
859 query_output_protection_in_progress_ = false;
860
861 // Return a protection status of none on error.
862 if (result != PP_OK)
863 output_link_mask_ = output_protection_mask_ = 0;
864
865 cdm_->OnQueryOutputProtectionStatus(output_link_mask_,
866 output_protection_mask_);
867}
868#endif
869
[email protected]b68e1442013-02-12 04:46:11870void* GetCdmHost(int host_interface_version, void* user_data) {
871 if (!host_interface_version || !user_data)
872 return NULL;
873
[email protected]6cae92e2013-10-19 00:12:14874 CdmAdapter* cdm_adapter = static_cast<CdmAdapter*>(user_data);
[email protected]0f6882e2013-10-21 21:26:07875 switch (host_interface_version) {
876 case cdm::kHostInterfaceVersion_1:
877 return static_cast<cdm::Host_1*>(cdm_adapter);
878 case cdm::kHostInterfaceVersion_2:
879 return static_cast<cdm::Host_2*>(cdm_adapter);
880 default:
881 PP_NOTREACHED();
882 return NULL;
883 }
[email protected]b68e1442013-02-12 04:46:11884}
885
[email protected]e5aeef02012-08-17 00:18:43886// This object is the global object representing this plugin library as long
887// as it is loaded.
[email protected]6cae92e2013-10-19 00:12:14888class CdmAdapterModule : public pp::Module {
[email protected]e5aeef02012-08-17 00:18:43889 public:
[email protected]6cae92e2013-10-19 00:12:14890 CdmAdapterModule() : pp::Module() {
[email protected]a9c788e2012-10-26 23:54:55891 // This function blocks the renderer thread (PluginInstance::Initialize()).
892 // Move this call to other places if this may be a concern in the future.
893 INITIALIZE_CDM_MODULE();
894 }
[email protected]6cae92e2013-10-19 00:12:14895 virtual ~CdmAdapterModule() {
[email protected]f75555a2012-12-10 22:35:24896 DeinitializeCdmModule();
[email protected]a9c788e2012-10-26 23:54:55897 }
[email protected]e5aeef02012-08-17 00:18:43898
899 virtual pp::Instance* CreateInstance(PP_Instance instance) {
[email protected]6cae92e2013-10-19 00:12:14900 return new CdmAdapter(instance, this);
[email protected]e5aeef02012-08-17 00:18:43901 }
902};
903
[email protected]177bcf82013-08-10 08:21:16904} // namespace media
[email protected]d341e332012-08-28 18:57:40905
[email protected]e5aeef02012-08-17 00:18:43906namespace pp {
907
908// Factory function for your specialization of the Module object.
909Module* CreateModule() {
[email protected]6cae92e2013-10-19 00:12:14910 return new media::CdmAdapterModule();
[email protected]e5aeef02012-08-17 00:18:43911}
912
913} // namespace pp