blob: 60a8e441f6c723499bc8ad215f1e9663e5512a91 [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]9264e1502012-09-18 19:53:015#include <cstring>
[email protected]ce19e7b52012-12-05 19:47:246#include <map>
[email protected]9264e1502012-09-18 19:53:017#include <string>
[email protected]ce19e7b52012-12-05 19:47:248#include <utility>
[email protected]d341e332012-08-28 18:57:409#include <vector>
[email protected]e5aeef02012-08-17 00:18:4310
[email protected]9264e1502012-09-18 19:53:0111#include "base/basictypes.h"
12#include "base/compiler_specific.h"
[email protected]ae9754e2013-10-08 22:52:2513#include "build/build_config.h"
[email protected]177bcf82013-08-10 08:21:1614#include "media/cdm/ppapi/api/content_decryption_module.h"
15#include "media/cdm/ppapi/linked_ptr.h"
[email protected]ae9754e2013-10-08 22:52:2516#include "ppapi/c/pp_completion_callback.h"
[email protected]e5aeef02012-08-17 00:18:4317#include "ppapi/c/pp_errors.h"
18#include "ppapi/c/pp_stdint.h"
[email protected]98ad9782012-08-22 04:06:2219#include "ppapi/c/private/pp_content_decryptor.h"
[email protected]e5aeef02012-08-17 00:18:4320#include "ppapi/cpp/completion_callback.h"
21#include "ppapi/cpp/core.h"
[email protected]85a37afd2013-05-30 22:51:1522#include "ppapi/cpp/dev/buffer_dev.h"
[email protected]e5aeef02012-08-17 00:18:4323#include "ppapi/cpp/instance.h"
24#include "ppapi/cpp/logging.h"
25#include "ppapi/cpp/module.h"
26#include "ppapi/cpp/pass_ref.h"
[email protected]85a37afd2013-05-30 22:51:1527#include "ppapi/cpp/private/content_decryptor_private.h"
[email protected]e5aeef02012-08-17 00:18:4328#include "ppapi/cpp/resource.h"
29#include "ppapi/cpp/var.h"
30#include "ppapi/cpp/var_array_buffer.h"
[email protected]e5aeef02012-08-17 00:18:4331#include "ppapi/utility/completion_callback_factory.h"
32
[email protected]76ee293e2013-05-22 18:10:4733#if defined(CHECK_DOCUMENT_URL)
34#include "ppapi/cpp/dev/url_util_dev.h"
35#include "ppapi/cpp/instance_handle.h"
36#endif // defined(CHECK_DOCUMENT_URL)
[email protected]799eace2013-03-11 20:28:2237
[email protected]ae9754e2013-10-08 22:52:2538#if defined(OS_CHROMEOS)
39#include "ppapi/cpp/private/output_protection_private.h"
40#include "ppapi/cpp/private/platform_verification.h"
41#endif
42
[email protected]e5aeef02012-08-17 00:18:4343namespace {
44
[email protected]98ad9782012-08-22 04:06:2245bool IsMainThread() {
46 return pp::Module::Get()->core()->IsMainThread();
47}
48
[email protected]8f1be472012-12-15 19:06:3349// Posts a task to run |cb| on the main thread. The task is posted even if the
50// current thread is the main thread.
51void PostOnMain(pp::CompletionCallback cb) {
52 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
53}
54
55// Ensures |cb| is called on the main thread, either because the current thread
56// is the main thread or by posting it to the main thread.
[email protected]e5aeef02012-08-17 00:18:4357void CallOnMain(pp::CompletionCallback cb) {
[email protected]98ad9782012-08-22 04:06:2258 // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
59 // off the main thread yet. Remove this once the change lands.
60 if (IsMainThread())
61 cb.Run(PP_OK);
62 else
[email protected]8f1be472012-12-15 19:06:3363 PostOnMain(cb);
[email protected]e5aeef02012-08-17 00:18:4364}
65
[email protected]181d9c12012-10-03 22:53:4866// Configures a cdm::InputBuffer. |subsamples| must exist as long as
67// |input_buffer| is in use.
68void ConfigureInputBuffer(
69 const pp::Buffer_Dev& encrypted_buffer,
70 const PP_EncryptedBlockInfo& encrypted_block_info,
71 std::vector<cdm::SubsampleEntry>* subsamples,
72 cdm::InputBuffer* input_buffer) {
73 PP_DCHECK(subsamples);
[email protected]741c28f2012-10-18 07:02:2574 PP_DCHECK(!encrypted_buffer.is_null());
75
[email protected]3b274b42012-10-26 20:41:2676 input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
[email protected]2468aae2012-11-21 19:53:1677 input_buffer->data_size = encrypted_block_info.data_size;
78 PP_DCHECK(encrypted_buffer.size() >=
79 static_cast<uint32_t>(input_buffer->data_size));
[email protected]181d9c12012-10-03 22:53:4880 input_buffer->data_offset = encrypted_block_info.data_offset;
[email protected]181d9c12012-10-03 22:53:4881
[email protected]f3fffa22013-01-25 22:16:0382 PP_DCHECK(encrypted_block_info.key_id_size <=
83 arraysize(encrypted_block_info.key_id));
84 input_buffer->key_id_size = encrypted_block_info.key_id_size;
85 input_buffer->key_id = input_buffer->key_id_size > 0 ?
86 encrypted_block_info.key_id : NULL;
87
88 PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
89 input_buffer->iv_size = encrypted_block_info.iv_size;
90 input_buffer->iv = encrypted_block_info.iv_size > 0 ?
91 encrypted_block_info.iv : NULL;
92
93 input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
[email protected]181d9c12012-10-03 22:53:4894 if (encrypted_block_info.num_subsamples > 0) {
95 subsamples->reserve(encrypted_block_info.num_subsamples);
96
97 for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
98 subsamples->push_back(cdm::SubsampleEntry(
99 encrypted_block_info.subsamples[i].clear_bytes,
100 encrypted_block_info.subsamples[i].cipher_bytes));
101 }
102
103 input_buffer->subsamples = &(*subsamples)[0];
104 }
105
106 input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
107}
108
[email protected]8f5a9a52012-10-23 20:49:20109PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
110 switch (status) {
111 case cdm::kSuccess:
112 return PP_DECRYPTRESULT_SUCCESS;
113 case cdm::kNoKey:
114 return PP_DECRYPTRESULT_DECRYPT_NOKEY;
115 case cdm::kNeedMoreData:
116 return PP_DECRYPTRESULT_NEEDMOREDATA;
117 case cdm::kDecryptError:
118 return PP_DECRYPTRESULT_DECRYPT_ERROR;
119 case cdm::kDecodeError:
120 return PP_DECRYPTRESULT_DECODE_ERROR;
121 default:
122 PP_NOTREACHED();
123 return PP_DECRYPTRESULT_DECODE_ERROR;
124 }
125}
126
[email protected]e9d3a1022012-10-11 23:43:55127PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
[email protected]181d9c12012-10-03 22:53:48128 cdm::VideoFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20129 switch (format) {
130 case cdm::kYv12:
131 return PP_DECRYPTEDFRAMEFORMAT_YV12;
132 case cdm::kI420:
133 return PP_DECRYPTEDFRAMEFORMAT_I420;
134 default:
135 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
136 }
[email protected]e9d3a1022012-10-11 23:43:55137}
138
[email protected]c999b3b72012-10-19 22:33:46139cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
140 PP_AudioCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20141 switch (codec) {
142 case PP_AUDIOCODEC_VORBIS:
143 return cdm::AudioDecoderConfig::kCodecVorbis;
[email protected]4967628d2012-10-27 02:08:48144 case PP_AUDIOCODEC_AAC:
145 return cdm::AudioDecoderConfig::kCodecAac;
[email protected]8f5a9a52012-10-23 20:49:20146 default:
147 return cdm::AudioDecoderConfig::kUnknownAudioCodec;
148 }
[email protected]c999b3b72012-10-19 22:33:46149}
150
[email protected]e9d3a1022012-10-11 23:43:55151cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
152 PP_VideoCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20153 switch (codec) {
154 case PP_VIDEOCODEC_VP8:
[email protected]4967628d2012-10-27 02:08:48155 return cdm::VideoDecoderConfig::kCodecVp8;
156 case PP_VIDEOCODEC_H264:
157 return cdm::VideoDecoderConfig::kCodecH264;
[email protected]8f5a9a52012-10-23 20:49:20158 default:
159 return cdm::VideoDecoderConfig::kUnknownVideoCodec;
160 }
[email protected]e9d3a1022012-10-11 23:43:55161}
162
163cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
164 PP_VideoCodecProfile profile) {
[email protected]8f5a9a52012-10-23 20:49:20165 switch (profile) {
166 case PP_VIDEOCODECPROFILE_VP8_MAIN:
167 return cdm::VideoDecoderConfig::kVp8ProfileMain;
[email protected]4967628d2012-10-27 02:08:48168 case PP_VIDEOCODECPROFILE_H264_BASELINE:
169 return cdm::VideoDecoderConfig::kH264ProfileBaseline;
170 case PP_VIDEOCODECPROFILE_H264_MAIN:
171 return cdm::VideoDecoderConfig::kH264ProfileMain;
172 case PP_VIDEOCODECPROFILE_H264_EXTENDED:
173 return cdm::VideoDecoderConfig::kH264ProfileExtended;
174 case PP_VIDEOCODECPROFILE_H264_HIGH:
175 return cdm::VideoDecoderConfig::kH264ProfileHigh;
176 case PP_VIDEOCODECPROFILE_H264_HIGH_10:
177 return cdm::VideoDecoderConfig::kH264ProfileHigh10;
178 case PP_VIDEOCODECPROFILE_H264_HIGH_422:
179 return cdm::VideoDecoderConfig::kH264ProfileHigh422;
180 case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
181 return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
[email protected]8f5a9a52012-10-23 20:49:20182 default:
183 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
184 }
[email protected]e9d3a1022012-10-11 23:43:55185}
186
187cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
188 PP_DecryptedFrameFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20189 switch (format) {
190 case PP_DECRYPTEDFRAMEFORMAT_YV12:
191 return cdm::kYv12;
192 case PP_DECRYPTEDFRAMEFORMAT_I420:
193 return cdm::kI420;
194 default:
195 return cdm::kUnknownVideoFormat;
196 }
[email protected]181d9c12012-10-03 22:53:48197}
198
[email protected]bf5f1682012-10-23 04:31:43199cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
200 PP_DecryptorStreamType stream_type) {
201 switch (stream_type) {
202 case PP_DECRYPTORSTREAMTYPE_AUDIO:
203 return cdm::kStreamTypeAudio;
204 case PP_DECRYPTORSTREAMTYPE_VIDEO:
205 return cdm::kStreamTypeVideo;
206 }
207
208 PP_NOTREACHED();
209 return cdm::kStreamTypeVideo;
210}
211
[email protected]e5aeef02012-08-17 00:18:43212} // namespace
213
[email protected]177bcf82013-08-10 08:21:16214namespace media {
[email protected]e5aeef02012-08-17 00:18:43215
[email protected]ce19e7b52012-12-05 19:47:24216// cdm::Buffer implementation that provides access to memory owned by a
217// pp::Buffer_Dev.
218// This class holds a reference to the Buffer_Dev throughout its lifetime.
219// TODO(xhwang): Find a better name. It's confusing to have PpbBuffer,
220// pp::Buffer_Dev and PPB_Buffer_Dev.
[email protected]9264e1502012-09-18 19:53:01221class PpbBuffer : public cdm::Buffer {
222 public:
[email protected]f75555a2012-12-10 22:35:24223 static PpbBuffer* Create(const pp::Buffer_Dev& buffer, uint32_t buffer_id) {
[email protected]ce19e7b52012-12-05 19:47:24224 PP_DCHECK(buffer.data());
225 PP_DCHECK(buffer.size());
[email protected]f75555a2012-12-10 22:35:24226 PP_DCHECK(buffer_id);
227 return new PpbBuffer(buffer, buffer_id);
[email protected]ce19e7b52012-12-05 19:47:24228 }
229
230 // cdm::Buffer implementation.
[email protected]9264e1502012-09-18 19:53:01231 virtual void Destroy() OVERRIDE { delete this; }
232
[email protected]f75555a2012-12-10 22:35:24233 virtual int32_t Capacity() const OVERRIDE { return buffer_.size(); }
234
235 virtual uint8_t* Data() OVERRIDE {
[email protected]9264e1502012-09-18 19:53:01236 return static_cast<uint8_t*>(buffer_.data());
237 }
238
[email protected]f75555a2012-12-10 22:35:24239 virtual void SetSize(int32_t size) OVERRIDE {
240 PP_DCHECK(size >= 0);
241 PP_DCHECK(size < Capacity());
242 if (size < 0 || size > Capacity()) {
243 size_ = 0;
244 return;
245 }
246
247 size_ = size;
248 }
249
250 virtual int32_t Size() const OVERRIDE { return size_; }
[email protected]9264e1502012-09-18 19:53:01251
252 pp::Buffer_Dev buffer_dev() const { return buffer_; }
253
[email protected]ce19e7b52012-12-05 19:47:24254 uint32_t buffer_id() const { return buffer_id_; }
255
[email protected]9264e1502012-09-18 19:53:01256 private:
[email protected]f75555a2012-12-10 22:35:24257 PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id)
[email protected]ce19e7b52012-12-05 19:47:24258 : buffer_(buffer),
259 buffer_id_(buffer_id),
[email protected]f75555a2012-12-10 22:35:24260 size_(0) {}
[email protected]9264e1502012-09-18 19:53:01261 virtual ~PpbBuffer() {}
262
263 pp::Buffer_Dev buffer_;
[email protected]ce19e7b52012-12-05 19:47:24264 uint32_t buffer_id_;
265 int32_t size_;
[email protected]9264e1502012-09-18 19:53:01266
267 DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
268};
269
[email protected]b68e1442013-02-12 04:46:11270class PpbBufferAllocator {
[email protected]9264e1502012-09-18 19:53:01271 public:
[email protected]ce19e7b52012-12-05 19:47:24272 explicit PpbBufferAllocator(pp::Instance* instance)
273 : instance_(instance),
274 next_buffer_id_(1) {}
[email protected]b68e1442013-02-12 04:46:11275 ~PpbBufferAllocator() {}
[email protected]9264e1502012-09-18 19:53:01276
[email protected]b68e1442013-02-12 04:46:11277 cdm::Buffer* Allocate(int32_t capacity);
[email protected]9264e1502012-09-18 19:53:01278
[email protected]ce19e7b52012-12-05 19:47:24279 // Releases the buffer with |buffer_id|. A buffer can be recycled after
280 // it is released.
281 void Release(uint32_t buffer_id);
282
[email protected]9264e1502012-09-18 19:53:01283 private:
[email protected]ce19e7b52012-12-05 19:47:24284 typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap;
285 typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> >
286 FreeBufferMap;
287
288 // Always pad new allocated buffer so that we don't need to reallocate
289 // buffers frequently if requested sizes fluctuate slightly.
290 static const int kBufferPadding = 512;
291
292 // Maximum number of free buffers we can keep when allocating new buffers.
293 static const int kFreeLimit = 3;
294
[email protected]f75555a2012-12-10 22:35:24295 pp::Buffer_Dev AllocateNewBuffer(int capacity);
[email protected]ce19e7b52012-12-05 19:47:24296
[email protected]9264e1502012-09-18 19:53:01297 pp::Instance* const instance_;
[email protected]ce19e7b52012-12-05 19:47:24298 uint32_t next_buffer_id_;
299 AllocatedBufferMap allocated_buffers_;
300 FreeBufferMap free_buffers_;
[email protected]9264e1502012-09-18 19:53:01301
302 DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
303};
304
[email protected]f75555a2012-12-10 22:35:24305cdm::Buffer* PpbBufferAllocator::Allocate(int32_t capacity) {
[email protected]3b274b42012-10-26 20:41:26306 PP_DCHECK(IsMainThread());
[email protected]7ed56ed2012-10-02 02:43:27307
[email protected]f75555a2012-12-10 22:35:24308 if (capacity <= 0)
309 return NULL;
310
[email protected]ce19e7b52012-12-05 19:47:24311 pp::Buffer_Dev buffer;
312 uint32_t buffer_id = 0;
[email protected]7ed56ed2012-10-02 02:43:27313
[email protected]f75555a2012-12-10 22:35:24314 // Reuse a buffer in the free list if there is one that fits |capacity|.
[email protected]ce19e7b52012-12-05 19:47:24315 // Otherwise, create a new one.
[email protected]f75555a2012-12-10 22:35:24316 FreeBufferMap::iterator found = free_buffers_.lower_bound(capacity);
[email protected]ce19e7b52012-12-05 19:47:24317 if (found == free_buffers_.end()) {
318 // TODO(xhwang): Report statistics about how many new buffers are allocated.
[email protected]f75555a2012-12-10 22:35:24319 buffer = AllocateNewBuffer(capacity);
[email protected]ce19e7b52012-12-05 19:47:24320 if (buffer.is_null())
321 return NULL;
322 buffer_id = next_buffer_id_++;
323 } else {
324 buffer = found->second.second;
325 buffer_id = found->second.first;
326 free_buffers_.erase(found);
327 }
328
329 allocated_buffers_.insert(std::make_pair(buffer_id, buffer));
330
[email protected]f75555a2012-12-10 22:35:24331 return PpbBuffer::Create(buffer, buffer_id);
[email protected]ce19e7b52012-12-05 19:47:24332}
333
334void PpbBufferAllocator::Release(uint32_t buffer_id) {
335 if (!buffer_id)
336 return;
337
338 AllocatedBufferMap::iterator found = allocated_buffers_.find(buffer_id);
339 if (found == allocated_buffers_.end())
340 return;
341
342 pp::Buffer_Dev& buffer = found->second;
343 free_buffers_.insert(
344 std::make_pair(buffer.size(), std::make_pair(buffer_id, buffer)));
345
346 allocated_buffers_.erase(found);
347}
348
[email protected]f75555a2012-12-10 22:35:24349pp::Buffer_Dev PpbBufferAllocator::AllocateNewBuffer(int32_t capacity) {
[email protected]ce19e7b52012-12-05 19:47:24350 // Destroy the smallest buffer before allocating a new bigger buffer if the
351 // number of free buffers exceeds a limit. This mechanism helps avoid ending
352 // up with too many small buffers, which could happen if the size to be
353 // allocated keeps increasing.
354 if (free_buffers_.size() >= static_cast<uint32_t>(kFreeLimit))
355 free_buffers_.erase(free_buffers_.begin());
356
357 // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
358 // That's why we try to avoid AllocateNewBuffer() as much as we can.
[email protected]f75555a2012-12-10 22:35:24359 return pp::Buffer_Dev(instance_, capacity + kBufferPadding);
[email protected]3b274b42012-10-26 20:41:26360}
[email protected]7ed56ed2012-10-02 02:43:27361
[email protected]3b274b42012-10-26 20:41:26362class DecryptedBlockImpl : public cdm::DecryptedBlock {
363 public:
364 DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
365 virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); }
[email protected]9264e1502012-09-18 19:53:01366
[email protected]f75555a2012-12-10 22:35:24367 virtual void SetDecryptedBuffer(cdm::Buffer* buffer) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26368 buffer_ = static_cast<PpbBuffer*>(buffer);
369 }
[email protected]f75555a2012-12-10 22:35:24370 virtual cdm::Buffer* DecryptedBuffer() OVERRIDE { return buffer_; }
[email protected]9264e1502012-09-18 19:53:01371
[email protected]f75555a2012-12-10 22:35:24372 virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26373 timestamp_ = timestamp;
374 }
[email protected]f75555a2012-12-10 22:35:24375 virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
[email protected]9264e1502012-09-18 19:53:01376
[email protected]3b274b42012-10-26 20:41:26377 private:
378 PpbBuffer* buffer_;
379 int64_t timestamp_;
[email protected]9264e1502012-09-18 19:53:01380
[email protected]3b274b42012-10-26 20:41:26381 DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
382};
[email protected]9264e1502012-09-18 19:53:01383
[email protected]181d9c12012-10-03 22:53:48384class VideoFrameImpl : public cdm::VideoFrame {
385 public:
386 VideoFrameImpl();
387 virtual ~VideoFrameImpl();
388
[email protected]f75555a2012-12-10 22:35:24389 virtual void SetFormat(cdm::VideoFormat format) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26390 format_ = format;
391 }
[email protected]f75555a2012-12-10 22:35:24392 virtual cdm::VideoFormat Format() const OVERRIDE { return format_; }
[email protected]181d9c12012-10-03 22:53:48393
[email protected]f75555a2012-12-10 22:35:24394 virtual void SetSize(cdm::Size size) OVERRIDE { size_ = size; }
395 virtual cdm::Size Size() const OVERRIDE { return size_; }
[email protected]d0ec47492012-10-13 05:01:46396
[email protected]f75555a2012-12-10 22:35:24397 virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26398 frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
399 }
[email protected]f75555a2012-12-10 22:35:24400 virtual cdm::Buffer* FrameBuffer() OVERRIDE { return frame_buffer_; }
[email protected]181d9c12012-10-03 22:53:48401
[email protected]f75555a2012-12-10 22:35:24402 virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
403 int32_t offset) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26404 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
405 PP_DCHECK(offset >= 0);
406 plane_offsets_[plane] = offset;
407 }
[email protected]f75555a2012-12-10 22:35:24408 virtual int32_t PlaneOffset(VideoPlane plane) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26409 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
410 return plane_offsets_[plane];
411 }
[email protected]181d9c12012-10-03 22:53:48412
[email protected]f75555a2012-12-10 22:35:24413 virtual void SetStride(VideoPlane plane, int32_t stride) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26414 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
415 strides_[plane] = stride;
416 }
[email protected]f75555a2012-12-10 22:35:24417 virtual int32_t Stride(VideoPlane plane) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26418 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
419 return strides_[plane];
420 }
[email protected]181d9c12012-10-03 22:53:48421
[email protected]f75555a2012-12-10 22:35:24422 virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26423 timestamp_ = timestamp;
424 }
[email protected]f75555a2012-12-10 22:35:24425 virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
[email protected]181d9c12012-10-03 22:53:48426
427 private:
428 // The video buffer format.
429 cdm::VideoFormat format_;
430
[email protected]d0ec47492012-10-13 05:01:46431 // Width and height of the video frame.
432 cdm::Size size_;
433
[email protected]181d9c12012-10-03 22:53:48434 // The video frame buffer.
435 PpbBuffer* frame_buffer_;
436
437 // Array of data pointers to each plane in the video frame buffer.
438 int32_t plane_offsets_[kMaxPlanes];
439
440 // Array of strides for each plane, typically greater or equal to the width
441 // of the surface divided by the horizontal sampling period. Note that
442 // strides can be negative.
443 int32_t strides_[kMaxPlanes];
444
445 // Presentation timestamp in microseconds.
446 int64_t timestamp_;
[email protected]3b274b42012-10-26 20:41:26447
448 DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
[email protected]181d9c12012-10-03 22:53:48449};
450
[email protected]181d9c12012-10-03 22:53:48451VideoFrameImpl::VideoFrameImpl()
452 : format_(cdm::kUnknownVideoFormat),
453 frame_buffer_(NULL),
454 timestamp_(0) {
455 for (int32_t i = 0; i < kMaxPlanes; ++i) {
456 plane_offsets_[i] = 0;
457 strides_[i] = 0;
458 }
459}
460
461VideoFrameImpl::~VideoFrameImpl() {
462 if (frame_buffer_)
463 frame_buffer_->Destroy();
464}
465
[email protected]ae9754e2013-10-08 22:52:25466class AudioFramesImpl : public cdm::AudioFrames_1,
467 public cdm::AudioFrames_2 {
[email protected]ecbb97682012-10-24 22:33:54468 public:
[email protected]ae9754e2013-10-08 22:52:25469 AudioFramesImpl() : buffer_(NULL), format_(cdm::kAudioFormatS16) {}
[email protected]ecbb97682012-10-24 22:33:54470 virtual ~AudioFramesImpl() {
471 if (buffer_)
472 buffer_->Destroy();
473 }
474
475 // AudioFrames implementation.
[email protected]f75555a2012-12-10 22:35:24476 virtual void SetFrameBuffer(cdm::Buffer* buffer) OVERRIDE {
[email protected]ecbb97682012-10-24 22:33:54477 buffer_ = static_cast<PpbBuffer*>(buffer);
478 }
[email protected]f75555a2012-12-10 22:35:24479 virtual cdm::Buffer* FrameBuffer() OVERRIDE {
[email protected]ecbb97682012-10-24 22:33:54480 return buffer_;
481 }
[email protected]ae9754e2013-10-08 22:52:25482 virtual void SetFormat(cdm::AudioFormat format) OVERRIDE {
483 format_ = format;
484 }
485 virtual cdm::AudioFormat Format() const OVERRIDE {
486 return format_;
487 }
[email protected]ecbb97682012-10-24 22:33:54488
489 private:
490 PpbBuffer* buffer_;
[email protected]ae9754e2013-10-08 22:52:25491 cdm::AudioFormat format_;
[email protected]ecbb97682012-10-24 22:33:54492
493 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
494};
495
[email protected]b68e1442013-02-12 04:46:11496// GetCdmHostFunc implementation.
497void* GetCdmHost(int host_interface_version, void* user_data);
498
[email protected]e5aeef02012-08-17 00:18:43499// A wrapper class for abstracting away PPAPI interaction and threading for a
500// Content Decryption Module (CDM).
[email protected]d341e332012-08-28 18:57:40501class CdmWrapper : public pp::Instance,
[email protected]f5c9b938e2012-10-10 12:24:07502 public pp::ContentDecryptor_Private,
[email protected]ae9754e2013-10-08 22:52:25503 public cdm::Host_1,
504 public cdm::Host_2 {
[email protected]e5aeef02012-08-17 00:18:43505 public:
[email protected]d341e332012-08-28 18:57:40506 CdmWrapper(PP_Instance instance, pp::Module* module);
507 virtual ~CdmWrapper();
[email protected]3b274b42012-10-26 20:41:26508
509 // pp::Instance implementation.
[email protected]d341e332012-08-28 18:57:40510 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
511 return true;
512 }
[email protected]e5aeef02012-08-17 00:18:43513
[email protected]3b274b42012-10-26 20:41:26514 // PPP_ContentDecryptor_Private implementation.
[email protected]d40797c2012-10-04 04:36:14515 // Note: Results of calls to these methods must be reported through the
516 // PPB_ContentDecryptor_Private interface.
[email protected]38a995d92013-09-20 06:34:51517 virtual void Initialize(const std::string& key_system,
518 bool can_challenge_platform) OVERRIDE;
519 virtual void GenerateKeyRequest(const std::string& type,
[email protected]e5aeef02012-08-17 00:18:43520 pp::VarArrayBuffer init_data) OVERRIDE;
[email protected]ea4ff802012-09-13 01:36:44521 virtual void AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22522 pp::VarArrayBuffer key,
523 pp::VarArrayBuffer init_data) OVERRIDE;
[email protected]ea4ff802012-09-13 01:36:44524 virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
525 virtual void Decrypt(
[email protected]98ad9782012-08-22 04:06:22526 pp::Buffer_Dev encrypted_buffer,
527 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
[email protected]c999b3b72012-10-19 22:33:46528 virtual void InitializeAudioDecoder(
529 const PP_AudioDecoderConfig& decoder_config,
530 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
[email protected]e9d3a1022012-10-11 23:43:55531 virtual void InitializeVideoDecoder(
532 const PP_VideoDecoderConfig& decoder_config,
533 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
[email protected]23de87452012-10-12 07:03:09534 virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
535 uint32_t request_id) OVERRIDE;
536 virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
537 uint32_t request_id) OVERRIDE;
[email protected]467434d2012-10-12 10:48:53538 virtual void DecryptAndDecode(
539 PP_DecryptorStreamType decoder_type,
540 pp::Buffer_Dev encrypted_buffer,
541 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
[email protected]e5aeef02012-08-17 00:18:43542
[email protected]ae9754e2013-10-08 22:52:25543 // cdm::Host_1 implementation.
[email protected]b68e1442013-02-12 04:46:11544 virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE;
[email protected]f75555a2012-12-10 22:35:24545 virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
[email protected]cc3c56b2012-11-01 17:35:32546 virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
[email protected]f75555a2012-12-10 22:35:24547 virtual void SendKeyMessage(
548 const char* session_id, int32_t session_id_length,
549 const char* message, int32_t message_length,
550 const char* default_url, int32_t default_url_length) OVERRIDE;
551 virtual void SendKeyError(const char* session_id,
552 int32_t session_id_length,
553 cdm::MediaKeyError error_code,
554 uint32_t system_code) OVERRIDE;
[email protected]b68e1442013-02-12 04:46:11555 virtual void GetPrivateData(int32_t* instance,
556 GetPrivateInterface* get_interface) OVERRIDE;
[email protected]f5c9b938e2012-10-10 12:24:07557
[email protected]ae9754e2013-10-08 22:52:25558 // cdm::Host_2 implementation.
559 virtual bool CanChallengePlatform() OVERRIDE;
560 virtual void SendPlatformChallenge(
561 const char* service_id, int32_t service_id_length,
562 const char* challenge, int32_t challenge_length) OVERRIDE;
563 virtual void EnableOutputProtection(
564 uint32_t desired_protection_mask) OVERRIDE;
565 virtual void QueryOutputProtectionStatus() OVERRIDE;
566
[email protected]e5aeef02012-08-17 00:18:43567 private:
[email protected]6cb006c2013-01-10 21:39:18568 struct SessionInfo {
569 SessionInfo(const std::string& key_system_in,
570 const std::string& session_id_in)
571 : key_system(key_system_in),
572 session_id(session_id_in) {}
573 const std::string key_system;
574 const std::string session_id;
575 };
576
[email protected]7ed56ed2012-10-02 02:43:27577 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
[email protected]181d9c12012-10-03 22:53:48578 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
[email protected]ecbb97682012-10-24 22:33:54579 typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;
[email protected]e5aeef02012-08-17 00:18:43580
[email protected]b68e1442013-02-12 04:46:11581 bool CreateCdmInstance(const std::string& key_system);
582
[email protected]6cb006c2013-01-10 21:39:18583 void SendUnknownKeyError(const std::string& key_system,
584 const std::string& session_id);
[email protected]8f1be472012-12-15 19:06:33585
[email protected]6cb006c2013-01-10 21:39:18586 void SendKeyAdded(const std::string& key_system,
587 const std::string& session_id);
588
[email protected]a941d4e572013-10-14 21:22:05589 // TODO(jrummell): Drop the |key_system| parameter.
[email protected]6cb006c2013-01-10 21:39:18590 void SendKeyErrorInternal(const std::string& key_system,
591 const std::string& session_id,
592 cdm::MediaKeyError error_code,
593 uint32_t system_code);
[email protected]8f1be472012-12-15 19:06:33594
[email protected]e5aeef02012-08-17 00:18:43595 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
596 // <code>callback_factory_</code> to ensure that calls into
597 // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
[email protected]6cb006c2013-01-10 21:39:18598 void KeyAdded(int32_t result, const SessionInfo& session_info);
[email protected]f75555a2012-12-10 22:35:24599 void KeyMessage(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18600 const SessionInfo& session_info,
[email protected]0a81bdb2013-06-29 23:18:06601 const std::vector<uint8>& message,
[email protected]f75555a2012-12-10 22:35:24602 const std::string& default_url);
603 void KeyError(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18604 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:24605 cdm::MediaKeyError error_code,
606 uint32_t system_code);
[email protected]d341e332012-08-28 18:57:40607 void DeliverBlock(int32_t result,
608 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:27609 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:40610 const PP_DecryptTrackingInfo& tracking_info);
[email protected]c999b3b72012-10-19 22:33:46611 void DecoderInitializeDone(int32_t result,
612 PP_DecryptorStreamType decoder_type,
613 uint32_t request_id,
614 bool success);
[email protected]23de87452012-10-12 07:03:09615 void DecoderDeinitializeDone(int32_t result,
616 PP_DecryptorStreamType decoder_type,
617 uint32_t request_id);
618 void DecoderResetDone(int32_t result,
619 PP_DecryptorStreamType decoder_type,
620 uint32_t request_id);
[email protected]181d9c12012-10-03 22:53:48621 void DeliverFrame(int32_t result,
622 const cdm::Status& status,
623 const LinkedVideoFrame& video_frame,
624 const PP_DecryptTrackingInfo& tracking_info);
[email protected]ecbb97682012-10-24 22:33:54625 void DeliverSamples(int32_t result,
626 const cdm::Status& status,
627 const LinkedAudioFrames& audio_frames,
628 const PP_DecryptTrackingInfo& tracking_info);
[email protected]e5aeef02012-08-17 00:18:43629
[email protected]f5c9b938e2012-10-10 12:24:07630 // Helper for SetTimer().
[email protected]f75555a2012-12-10 22:35:24631 void TimerExpired(int32_t result, void* context);
[email protected]f5c9b938e2012-10-10 12:24:07632
[email protected]ce19e7b52012-12-05 19:47:24633 bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
634
[email protected]ae9754e2013-10-08 22:52:25635#if defined(OS_CHROMEOS)
636 void CanChallengePlatformDone(int32_t result, bool can_challenge_platform);
637 void SendPlatformChallengeDone(int32_t result);
638 void EnableProtectionDone(int32_t result);
639 void QueryOutputProtectionStatusDone(int32_t result);
640
641 pp::OutputProtection_Private output_protection_;
642 pp::PlatformVerification platform_verification_;
643
644 // |can_challenge_platform_| is currently set asynchronously, return the value
645 // if we have it, otherwise guess "true" for the most common case...
646 // TODO(jrummell): This stinks. The value should be delivered via the
647 // Initialize() method once plumbed.
648 bool can_challenge_platform_;
649
650 // Since PPAPI doesn't provide handlers for CompletionCallbacks w/ more than
651 // one output we need to manage our own. These values are only read by
652 // SendPlatformChallengeDone().
653 pp::Var signed_data_output_;
654 pp::Var signed_data_signature_output_;
655 pp::Var platform_key_certificate_output_;
656 bool challenge_in_progress_;
657
658 // Same as above, these are only read by QueryOutputProtectionStatusDone().
659 uint32_t output_link_mask_;
660 uint32_t output_protection_mask_;
661 bool query_output_protection_in_progress_;
662#endif
663
[email protected]9264e1502012-09-18 19:53:01664 PpbBufferAllocator allocator_;
[email protected]d341e332012-08-28 18:57:40665 pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
666 cdm::ContentDecryptionModule* cdm_;
667 std::string key_system_;
[email protected]3b274b42012-10-26 20:41:26668
669 DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
[email protected]e5aeef02012-08-17 00:18:43670};
671
[email protected]d341e332012-08-28 18:57:40672CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
[email protected]e5aeef02012-08-17 00:18:43673 : pp::Instance(instance),
[email protected]d341e332012-08-28 18:57:40674 pp::ContentDecryptor_Private(this),
[email protected]ae9754e2013-10-08 22:52:25675#if defined(OS_CHROMEOS)
676 output_protection_(this),
677 platform_verification_(this),
678 // Err on the side of the most common case...
679 can_challenge_platform_(true),
680 challenge_in_progress_(false),
681 output_link_mask_(0),
682 output_protection_mask_(0),
683 query_output_protection_in_progress_(false),
684#endif
[email protected]9264e1502012-09-18 19:53:01685 allocator_(this),
[email protected]d341e332012-08-28 18:57:40686 cdm_(NULL) {
[email protected]e5aeef02012-08-17 00:18:43687 callback_factory_.Initialize(this);
[email protected]ae9754e2013-10-08 22:52:25688#if defined(OS_CHROMEOS)
689 // Preemptively retrieve the platform challenge status. It will not change.
690 platform_verification_.CanChallengePlatform(
691 callback_factory_.NewCallbackWithOutput(
692 &CdmWrapper::CanChallengePlatformDone));
693#endif
[email protected]e5aeef02012-08-17 00:18:43694}
695
[email protected]d341e332012-08-28 18:57:40696CdmWrapper::~CdmWrapper() {
697 if (cdm_)
[email protected]b68e1442013-02-12 04:46:11698 cdm_->Destroy();
699}
700
701bool CdmWrapper::CreateCdmInstance(const std::string& key_system) {
702 PP_DCHECK(!cdm_);
703 cdm_ = static_cast<cdm::ContentDecryptionModule*>(
704 ::CreateCdmInstance(cdm::kCdmInterfaceVersion,
705 key_system.data(), key_system.size(),
706 GetCdmHost, this));
707
708 return (cdm_ != NULL);
[email protected]d341e332012-08-28 18:57:40709}
710
[email protected]a941d4e572013-10-14 21:22:05711// No KeyErrors should be reported in this function because they cannot be
712// bubbled up in the WD EME API. Those errors will be reported during session
713// creation (aka GenerateKeyRequest).
[email protected]38a995d92013-09-20 06:34:51714void CdmWrapper::Initialize(const std::string& key_system,
715 bool can_challenge_platform) {
[email protected]6cb006c2013-01-10 21:39:18716 PP_DCHECK(!key_system.empty());
[email protected]38a995d92013-09-20 06:34:51717 PP_DCHECK(key_system_.empty() || (key_system_ == key_system && cdm_));
718
[email protected]a941d4e572013-10-14 21:22:05719 if (!cdm_ && !CreateCdmInstance(key_system))
720 return;
721
[email protected]38a995d92013-09-20 06:34:51722 PP_DCHECK(cdm_);
723 key_system_ = key_system;
724}
725
726void CdmWrapper::GenerateKeyRequest(const std::string& type,
727 pp::VarArrayBuffer init_data) {
[email protected]a941d4e572013-10-14 21:22:05728 // Initialize() doesn't report an error, so GenerateKeyRequest() can be called
729 // even if Initialize() failed.
730 if (!cdm_) {
731 SendUnknownKeyError(key_system_, std::string());
732 return;
733 }
[email protected]e5aeef02012-08-17 00:18:43734
[email protected]76ee293e2013-05-22 18:10:47735#if defined(CHECK_DOCUMENT_URL)
736 PP_URLComponents_Dev url_components = {};
737 pp::Var href = pp::URLUtil_Dev::Get()->GetDocumentURL(
738 pp::InstanceHandle(pp_instance()), &url_components);
739 PP_DCHECK(href.is_string());
740 PP_DCHECK(!href.AsString().empty());
741 PP_DCHECK(url_components.host.begin);
742 PP_DCHECK(0 < url_components.host.len);
743#endif // defined(CHECK_DOCUMENT_URL)
[email protected]799eace2013-03-11 20:28:22744
[email protected]d341e332012-08-28 18:57:40745 cdm::Status status = cdm_->GenerateKeyRequest(
[email protected]f1b1db02012-10-29 22:50:23746 type.data(), type.size(),
[email protected]3b274b42012-10-26 20:41:26747 static_cast<const uint8_t*>(init_data.Map()),
[email protected]f75555a2012-12-10 22:35:24748 init_data.ByteLength());
[email protected]0b959582012-10-01 23:13:27749 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]38a995d92013-09-20 06:34:51750 if (status != cdm::kSuccess)
751 SendUnknownKeyError(key_system_, std::string());
[email protected]e5aeef02012-08-17 00:18:43752}
753
[email protected]ea4ff802012-09-13 01:36:44754void CdmWrapper::AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22755 pp::VarArrayBuffer key,
756 pp::VarArrayBuffer init_data) {
[email protected]a941d4e572013-10-14 21:22:05757 // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
758 // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
[email protected]3b274b42012-10-26 20:41:26759 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18760 SendUnknownKeyError(key_system_, session_id);
[email protected]3b274b42012-10-26 20:41:26761 return;
762 }
763
764 const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
[email protected]d341e332012-08-28 18:57:40765 int key_size = key.ByteLength();
[email protected]3b274b42012-10-26 20:41:26766 const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
[email protected]d341e332012-08-28 18:57:40767 int init_data_size = init_data.ByteLength();
[email protected]26b200102013-01-30 05:24:23768 PP_DCHECK(!init_data_ptr == !init_data_size);
[email protected]e5aeef02012-08-17 00:18:43769
[email protected]26b200102013-01-30 05:24:23770 if (!key_ptr || key_size <= 0) {
[email protected]6cb006c2013-01-10 21:39:18771 SendUnknownKeyError(key_system_, session_id);
[email protected]ea4ff802012-09-13 01:36:44772 return;
[email protected]3b274b42012-10-26 20:41:26773 }
[email protected]e5aeef02012-08-17 00:18:43774
[email protected]d341e332012-08-28 18:57:40775 cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
776 key_ptr, key_size,
777 init_data_ptr, init_data_size);
[email protected]0b959582012-10-01 23:13:27778 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]d341e332012-08-28 18:57:40779 if (status != cdm::kSuccess) {
[email protected]6cb006c2013-01-10 21:39:18780 SendUnknownKeyError(key_system_, session_id);
[email protected]ea4ff802012-09-13 01:36:44781 return;
[email protected]d341e332012-08-28 18:57:40782 }
783
[email protected]6cb006c2013-01-10 21:39:18784 SendKeyAdded(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43785}
786
[email protected]ea4ff802012-09-13 01:36:44787void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
[email protected]a941d4e572013-10-14 21:22:05788 // TODO(jrummell): In EME WD, AddKey() can only be called on valid sessions.
789 // We should be able to DCHECK(cdm_) when addressing http://crbug.com/249976.
[email protected]3b274b42012-10-26 20:41:26790 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18791 SendUnknownKeyError(key_system_, session_id);
[email protected]3b274b42012-10-26 20:41:26792 return;
793 }
794
[email protected]d341e332012-08-28 18:57:40795 cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
796 session_id.size());
[email protected]0b959582012-10-01 23:13:27797 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]3b274b42012-10-26 20:41:26798 if (status != cdm::kSuccess)
[email protected]6cb006c2013-01-10 21:39:18799 SendUnknownKeyError(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43800}
801
[email protected]3b274b42012-10-26 20:41:26802// Note: In the following decryption/decoding related functions, errors are NOT
803// reported via KeyError, but are reported via corresponding PPB calls.
804
[email protected]ea4ff802012-09-13 01:36:44805void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
[email protected]98ad9782012-08-22 04:06:22806 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]e5aeef02012-08-17 00:18:43807 PP_DCHECK(!encrypted_buffer.is_null());
808
[email protected]ce19e7b52012-12-05 19:47:24809 // Release a buffer that the caller indicated it is finished with.
810 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
811
[email protected]3b274b42012-10-26 20:41:26812 cdm::Status status = cdm::kDecryptError;
[email protected]7ed56ed2012-10-02 02:43:27813 LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
[email protected]3b274b42012-10-26 20:41:26814
815 if (cdm_) {
816 cdm::InputBuffer input_buffer;
817 std::vector<cdm::SubsampleEntry> subsamples;
818 ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
819 &input_buffer);
820 status = cdm_->Decrypt(input_buffer, decrypted_block.get());
[email protected]f75555a2012-12-10 22:35:24821 PP_DCHECK(status != cdm::kSuccess ||
822 (decrypted_block->DecryptedBuffer() &&
823 decrypted_block->DecryptedBuffer()->Size()));
[email protected]3b274b42012-10-26 20:41:26824 }
[email protected]d341e332012-08-28 18:57:40825
826 CallOnMain(callback_factory_.NewCallback(
827 &CdmWrapper::DeliverBlock,
828 status,
[email protected]7ed56ed2012-10-02 02:43:27829 decrypted_block,
[email protected]d341e332012-08-28 18:57:40830 encrypted_block_info.tracking_info));
[email protected]e5aeef02012-08-17 00:18:43831}
832
[email protected]c999b3b72012-10-19 22:33:46833void CdmWrapper::InitializeAudioDecoder(
834 const PP_AudioDecoderConfig& decoder_config,
835 pp::Buffer_Dev extra_data_buffer) {
[email protected]3b274b42012-10-26 20:41:26836 cdm::Status status = cdm::kSessionError;
837 if (cdm_) {
838 cdm::AudioDecoderConfig cdm_decoder_config;
839 cdm_decoder_config.codec =
840 PpAudioCodecToCdmAudioCodec(decoder_config.codec);
841 cdm_decoder_config.channel_count = decoder_config.channel_count;
842 cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
843 cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
844 cdm_decoder_config.extra_data =
845 static_cast<uint8_t*>(extra_data_buffer.data());
846 cdm_decoder_config.extra_data_size =
847 static_cast<int32_t>(extra_data_buffer.size());
848 status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
849 }
[email protected]c999b3b72012-10-19 22:33:46850
851 CallOnMain(callback_factory_.NewCallback(
852 &CdmWrapper::DecoderInitializeDone,
853 PP_DECRYPTORSTREAMTYPE_AUDIO,
854 decoder_config.request_id,
855 status == cdm::kSuccess));
856}
857
[email protected]e9d3a1022012-10-11 23:43:55858void CdmWrapper::InitializeVideoDecoder(
859 const PP_VideoDecoderConfig& decoder_config,
860 pp::Buffer_Dev extra_data_buffer) {
[email protected]3b274b42012-10-26 20:41:26861 cdm::Status status = cdm::kSessionError;
862 if (cdm_) {
863 cdm::VideoDecoderConfig cdm_decoder_config;
864 cdm_decoder_config.codec =
865 PpVideoCodecToCdmVideoCodec(decoder_config.codec);
866 cdm_decoder_config.profile =
867 PpVCProfileToCdmVCProfile(decoder_config.profile);
868 cdm_decoder_config.format =
869 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
870 cdm_decoder_config.coded_size.width = decoder_config.width;
871 cdm_decoder_config.coded_size.height = decoder_config.height;
872 cdm_decoder_config.extra_data =
873 static_cast<uint8_t*>(extra_data_buffer.data());
874 cdm_decoder_config.extra_data_size =
875 static_cast<int32_t>(extra_data_buffer.size());
876 status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
877 }
[email protected]e9d3a1022012-10-11 23:43:55878
879 CallOnMain(callback_factory_.NewCallback(
[email protected]c999b3b72012-10-19 22:33:46880 &CdmWrapper::DecoderInitializeDone,
881 PP_DECRYPTORSTREAMTYPE_VIDEO,
882 decoder_config.request_id,
883 status == cdm::kSuccess));
[email protected]e9d3a1022012-10-11 23:43:55884}
885
[email protected]23de87452012-10-12 07:03:09886void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
887 uint32_t request_id) {
[email protected]a941d4e572013-10-14 21:22:05888 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
[email protected]3b274b42012-10-26 20:41:26889 if (cdm_) {
890 cdm_->DeinitializeDecoder(
891 PpDecryptorStreamTypeToCdmStreamType(decoder_type));
892 }
893
[email protected]23de87452012-10-12 07:03:09894 CallOnMain(callback_factory_.NewCallback(
895 &CdmWrapper::DecoderDeinitializeDone,
896 decoder_type,
897 request_id));
898}
899
900void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
901 uint32_t request_id) {
[email protected]a941d4e572013-10-14 21:22:05902 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
[email protected]3b274b42012-10-26 20:41:26903 if (cdm_)
904 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
905
[email protected]23de87452012-10-12 07:03:09906 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone,
907 decoder_type,
908 request_id));
909}
910
[email protected]467434d2012-10-12 10:48:53911void CdmWrapper::DecryptAndDecode(
912 PP_DecryptorStreamType decoder_type,
913 pp::Buffer_Dev encrypted_buffer,
914 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]a941d4e572013-10-14 21:22:05915 PP_DCHECK(cdm_); // InitializeXxxxxDecoder should have succeeded.
[email protected]ce19e7b52012-12-05 19:47:24916 // Release a buffer that the caller indicated it is finished with.
917 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
918
[email protected]181d9c12012-10-03 22:53:48919 cdm::InputBuffer input_buffer;
920 std::vector<cdm::SubsampleEntry> subsamples;
[email protected]3b274b42012-10-26 20:41:26921 if (cdm_ && !encrypted_buffer.is_null()) {
[email protected]741c28f2012-10-18 07:02:25922 ConfigureInputBuffer(encrypted_buffer,
923 encrypted_block_info,
924 &subsamples,
925 &input_buffer);
926 }
[email protected]181d9c12012-10-03 22:53:48927
[email protected]ecbb97682012-10-24 22:33:54928 cdm::Status status = cdm::kDecodeError;
[email protected]3b274b42012-10-26 20:41:26929
[email protected]ecbb97682012-10-24 22:33:54930 switch (decoder_type) {
931 case PP_DECRYPTORSTREAMTYPE_VIDEO: {
932 LinkedVideoFrame video_frame(new VideoFrameImpl());
[email protected]3b274b42012-10-26 20:41:26933 if (cdm_)
934 status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
[email protected]ecbb97682012-10-24 22:33:54935 CallOnMain(callback_factory_.NewCallback(
936 &CdmWrapper::DeliverFrame,
937 status,
938 video_frame,
939 encrypted_block_info.tracking_info));
940 return;
941 }
942
943 case PP_DECRYPTORSTREAMTYPE_AUDIO: {
944 LinkedAudioFrames audio_frames(new AudioFramesImpl());
[email protected]3b274b42012-10-26 20:41:26945 if (cdm_) {
946 status = cdm_->DecryptAndDecodeSamples(input_buffer,
947 audio_frames.get());
948 }
[email protected]ecbb97682012-10-24 22:33:54949 CallOnMain(callback_factory_.NewCallback(
950 &CdmWrapper::DeliverSamples,
951 status,
952 audio_frames,
953 encrypted_block_info.tracking_info));
954 return;
955 }
956
957 default:
958 PP_NOTREACHED();
959 return;
960 }
[email protected]d341e332012-08-28 18:57:40961}
962
[email protected]b68e1442013-02-12 04:46:11963cdm::Buffer* CdmWrapper::Allocate(int32_t capacity) {
964 return allocator_.Allocate(capacity);
965}
966
[email protected]f75555a2012-12-10 22:35:24967void CdmWrapper::SetTimer(int64_t delay_ms, void* context) {
[email protected]f5c9b938e2012-10-10 12:24:07968 // NOTE: doesn't really need to run on the main thread; could just as well run
969 // on a helper thread if |cdm_| were thread-friendly and care was taken. We
970 // only use CallOnMainThread() here to get delayed-execution behavior.
971 pp::Module::Get()->core()->CallOnMainThread(
972 delay_ms,
[email protected]f75555a2012-12-10 22:35:24973 callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context),
[email protected]f5c9b938e2012-10-10 12:24:07974 PP_OK);
975}
976
[email protected]f75555a2012-12-10 22:35:24977void CdmWrapper::TimerExpired(int32_t result, void* context) {
[email protected]f5c9b938e2012-10-10 12:24:07978 PP_DCHECK(result == PP_OK);
[email protected]f75555a2012-12-10 22:35:24979 cdm_->TimerExpired(context);
[email protected]f5c9b938e2012-10-10 12:24:07980}
981
[email protected]cc3c56b2012-11-01 17:35:32982double CdmWrapper::GetCurrentWallTimeInSeconds() {
[email protected]f5c9b938e2012-10-10 12:24:07983 return pp::Module::Get()->core()->GetTime();
984}
985
[email protected]f75555a2012-12-10 22:35:24986void CdmWrapper::SendKeyMessage(
987 const char* session_id, int32_t session_id_length,
988 const char* message, int32_t message_length,
989 const char* default_url, int32_t default_url_length) {
[email protected]6cb006c2013-01-10 21:39:18990 PP_DCHECK(!key_system_.empty());
[email protected]8f1be472012-12-15 19:06:33991 PostOnMain(callback_factory_.NewCallback(
[email protected]f75555a2012-12-10 22:35:24992 &CdmWrapper::KeyMessage,
[email protected]6cb006c2013-01-10 21:39:18993 SessionInfo(key_system_,
994 std::string(session_id, session_id_length)),
[email protected]0a81bdb2013-06-29 23:18:06995 std::vector<uint8>(message, message + message_length),
[email protected]f75555a2012-12-10 22:35:24996 std::string(default_url, default_url_length)));
997}
998
999void CdmWrapper::SendKeyError(const char* session_id,
1000 int32_t session_id_length,
1001 cdm::MediaKeyError error_code,
1002 uint32_t system_code) {
[email protected]6cb006c2013-01-10 21:39:181003 SendKeyErrorInternal(key_system_,
1004 std::string(session_id, session_id_length),
1005 error_code,
1006 system_code);
1007}
1008
[email protected]b68e1442013-02-12 04:46:111009void CdmWrapper::GetPrivateData(int32_t* instance,
[email protected]ae9754e2013-10-08 22:52:251010 GetPrivateInterface* get_interface) {
[email protected]b68e1442013-02-12 04:46:111011 *instance = pp_instance();
1012 *get_interface = pp::Module::Get()->get_browser_interface();
1013}
1014
[email protected]6cb006c2013-01-10 21:39:181015void CdmWrapper::SendUnknownKeyError(const std::string& key_system,
1016 const std::string& session_id) {
1017 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0);
1018}
1019
[email protected]6cb006c2013-01-10 21:39:181020void CdmWrapper::SendKeyAdded(const std::string& key_system,
1021 const std::string& session_id) {
[email protected]8f1be472012-12-15 19:06:331022 PostOnMain(callback_factory_.NewCallback(
[email protected]6cb006c2013-01-10 21:39:181023 &CdmWrapper::KeyAdded,
1024 SessionInfo(key_system_, session_id)));
[email protected]f75555a2012-12-10 22:35:241025}
1026
[email protected]6cb006c2013-01-10 21:39:181027void CdmWrapper::SendKeyErrorInternal(const std::string& key_system,
1028 const std::string& session_id,
1029 cdm::MediaKeyError error_code,
1030 uint32_t system_code) {
[email protected]6cb006c2013-01-10 21:39:181031 PostOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
1032 SessionInfo(key_system_, session_id),
1033 error_code,
1034 system_code));
[email protected]8f1be472012-12-15 19:06:331035}
1036
[email protected]6cb006c2013-01-10 21:39:181037void CdmWrapper::KeyAdded(int32_t result, const SessionInfo& session_info) {
[email protected]f5c9b938e2012-10-10 12:24:071038 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:181039 PP_DCHECK(!session_info.key_system.empty());
1040 pp::ContentDecryptor_Private::KeyAdded(session_info.key_system,
1041 session_info.session_id);
[email protected]e5aeef02012-08-17 00:18:431042}
1043
[email protected]d341e332012-08-28 18:57:401044void CdmWrapper::KeyMessage(int32_t result,
[email protected]6cb006c2013-01-10 21:39:181045 const SessionInfo& session_info,
[email protected]0a81bdb2013-06-29 23:18:061046 const std::vector<uint8>& message,
[email protected]f75555a2012-12-10 22:35:241047 const std::string& default_url) {
[email protected]f5c9b938e2012-10-10 12:24:071048 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:181049 PP_DCHECK(!session_info.key_system.empty());
[email protected]6d613d62012-12-04 23:39:001050
[email protected]a6e4fbf2012-12-12 05:25:001051 pp::VarArrayBuffer message_array_buffer(message.size());
1052 if (message.size() > 0) {
1053 memcpy(message_array_buffer.Map(), message.data(), message.size());
[email protected]6d613d62012-12-04 23:39:001054 }
1055
[email protected]d341e332012-08-28 18:57:401056 pp::ContentDecryptor_Private::KeyMessage(
[email protected]6cb006c2013-01-10 21:39:181057 session_info.key_system, session_info.session_id,
1058 message_array_buffer, default_url);
[email protected]e5aeef02012-08-17 00:18:431059}
1060
[email protected]f75555a2012-12-10 22:35:241061void CdmWrapper::KeyError(int32_t result,
[email protected]6cb006c2013-01-10 21:39:181062 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:241063 cdm::MediaKeyError error_code,
1064 uint32_t system_code) {
[email protected]f5c9b938e2012-10-10 12:24:071065 PP_DCHECK(result == PP_OK);
[email protected]f75555a2012-12-10 22:35:241066 pp::ContentDecryptor_Private::KeyError(
[email protected]6cb006c2013-01-10 21:39:181067 session_info.key_system, session_info.session_id,
1068 error_code, system_code);
[email protected]e5aeef02012-08-17 00:18:431069}
1070
[email protected]d341e332012-08-28 18:57:401071void CdmWrapper::DeliverBlock(int32_t result,
1072 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:271073 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:401074 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:071075 PP_DCHECK(result == PP_OK);
[email protected]d341e332012-08-28 18:57:401076 PP_DecryptedBlockInfo decrypted_block_info;
[email protected]181d9c12012-10-03 22:53:481077 decrypted_block_info.tracking_info = tracking_info;
[email protected]f75555a2012-12-10 22:35:241078 decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
[email protected]ce19e7b52012-12-05 19:47:241079 decrypted_block_info.tracking_info.buffer_id = 0;
1080 decrypted_block_info.data_size = 0;
[email protected]8f5a9a52012-10-23 20:49:201081 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
[email protected]d341e332012-08-28 18:57:401082
[email protected]8f5a9a52012-10-23 20:49:201083 pp::Buffer_Dev buffer;
1084
1085 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]f75555a2012-12-10 22:35:241086 PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
1087 if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
[email protected]ecbb97682012-10-24 22:33:541088 PP_NOTREACHED();
[email protected]d341e332012-08-28 18:57:401089 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
[email protected]8f5a9a52012-10-23 20:49:201090 } else {
[email protected]ce19e7b52012-12-05 19:47:241091 PpbBuffer* ppb_buffer =
[email protected]f75555a2012-12-10 22:35:241092 static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
[email protected]ce19e7b52012-12-05 19:47:241093 buffer = ppb_buffer->buffer_dev();
1094 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
[email protected]f75555a2012-12-10 22:35:241095 decrypted_block_info.data_size = ppb_buffer->Size();
[email protected]8f5a9a52012-10-23 20:49:201096 }
[email protected]d341e332012-08-28 18:57:401097 }
1098
[email protected]4bc37112012-09-21 19:49:251099 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
[email protected]e5aeef02012-08-17 00:18:431100}
1101
[email protected]c999b3b72012-10-19 22:33:461102void CdmWrapper::DecoderInitializeDone(int32_t result,
1103 PP_DecryptorStreamType decoder_type,
1104 uint32_t request_id,
1105 bool success) {
1106 PP_DCHECK(result == PP_OK);
1107 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
1108 request_id,
1109 success);
[email protected]e9d3a1022012-10-11 23:43:551110}
1111
[email protected]23de87452012-10-12 07:03:091112void CdmWrapper::DecoderDeinitializeDone(int32_t result,
1113 PP_DecryptorStreamType decoder_type,
1114 uint32_t request_id) {
1115 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
1116 request_id);
1117}
1118
1119void CdmWrapper::DecoderResetDone(int32_t result,
1120 PP_DecryptorStreamType decoder_type,
1121 uint32_t request_id) {
1122 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
1123}
1124
[email protected]181d9c12012-10-03 22:53:481125void CdmWrapper::DeliverFrame(
1126 int32_t result,
1127 const cdm::Status& status,
1128 const LinkedVideoFrame& video_frame,
1129 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:071130 PP_DCHECK(result == PP_OK);
[email protected]181d9c12012-10-03 22:53:481131 PP_DecryptedFrameInfo decrypted_frame_info;
[email protected]749576ff2012-10-30 05:10:481132 decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
[email protected]ce19e7b52012-12-05 19:47:241133 decrypted_frame_info.tracking_info.buffer_id = 0;
[email protected]8f5a9a52012-10-23 20:49:201134 decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
[email protected]181d9c12012-10-03 22:53:481135
[email protected]8f5a9a52012-10-23 20:49:201136 pp::Buffer_Dev buffer;
[email protected]741c28f2012-10-18 07:02:251137
[email protected]8f5a9a52012-10-23 20:49:201138 if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]ce19e7b52012-12-05 19:47:241139 if (!IsValidVideoFrame(video_frame)) {
[email protected]ecbb97682012-10-24 22:33:541140 PP_NOTREACHED();
[email protected]8f5a9a52012-10-23 20:49:201141 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
1142 } else {
[email protected]ce19e7b52012-12-05 19:47:241143 PpbBuffer* ppb_buffer =
[email protected]f75555a2012-12-10 22:35:241144 static_cast<PpbBuffer*>(video_frame->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:241145
1146 buffer = ppb_buffer->buffer_dev();
1147
[email protected]f75555a2012-12-10 22:35:241148 decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
[email protected]ce19e7b52012-12-05 19:47:241149 decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
1150 decrypted_frame_info.format =
[email protected]f75555a2012-12-10 22:35:241151 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
1152 decrypted_frame_info.width = video_frame->Size().width;
1153 decrypted_frame_info.height = video_frame->Size().height;
[email protected]181d9c12012-10-03 22:53:481154 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]f75555a2012-12-10 22:35:241155 video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:481156 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]f75555a2012-12-10 22:35:241157 video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:481158 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]f75555a2012-12-10 22:35:241159 video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
[email protected]181d9c12012-10-03 22:53:481160 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]f75555a2012-12-10 22:35:241161 video_frame->Stride(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:481162 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]f75555a2012-12-10 22:35:241163 video_frame->Stride(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:481164 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]f75555a2012-12-10 22:35:241165 video_frame->Stride(cdm::VideoFrame::kVPlane);
[email protected]8f5a9a52012-10-23 20:49:201166 }
[email protected]181d9c12012-10-03 22:53:481167 }
[email protected]181d9c12012-10-03 22:53:481168 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
1169}
1170
[email protected]ecbb97682012-10-24 22:33:541171void CdmWrapper::DeliverSamples(int32_t result,
1172 const cdm::Status& status,
1173 const LinkedAudioFrames& audio_frames,
1174 const PP_DecryptTrackingInfo& tracking_info) {
1175 PP_DCHECK(result == PP_OK);
[email protected]749576ff2012-10-30 05:10:481176
[email protected]ecbb97682012-10-24 22:33:541177 PP_DecryptedBlockInfo decrypted_block_info;
1178 decrypted_block_info.tracking_info = tracking_info;
[email protected]ecbb97682012-10-24 22:33:541179 decrypted_block_info.tracking_info.timestamp = 0;
[email protected]ce19e7b52012-12-05 19:47:241180 decrypted_block_info.tracking_info.buffer_id = 0;
1181 decrypted_block_info.data_size = 0;
[email protected]ecbb97682012-10-24 22:33:541182 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
1183
1184 pp::Buffer_Dev buffer;
1185
1186 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]f75555a2012-12-10 22:35:241187 PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
1188 if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
[email protected]ecbb97682012-10-24 22:33:541189 PP_NOTREACHED();
1190 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
1191 } else {
[email protected]f75555a2012-12-10 22:35:241192 PpbBuffer* ppb_buffer =
1193 static_cast<PpbBuffer*>(audio_frames->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:241194 buffer = ppb_buffer->buffer_dev();
1195 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
[email protected]f75555a2012-12-10 22:35:241196 decrypted_block_info.data_size = ppb_buffer->Size();
[email protected]ecbb97682012-10-24 22:33:541197 }
1198 }
1199
1200 pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_block_info);
1201}
[email protected]181d9c12012-10-03 22:53:481202
[email protected]ce19e7b52012-12-05 19:47:241203bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
1204 if (!video_frame.get() ||
[email protected]f75555a2012-12-10 22:35:241205 !video_frame->FrameBuffer() ||
1206 (video_frame->Format() != cdm::kI420 &&
1207 video_frame->Format() != cdm::kYv12)) {
[email protected]ce19e7b52012-12-05 19:47:241208 return false;
1209 }
1210
[email protected]f75555a2012-12-10 22:35:241211 PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:241212
1213 for (int i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
1214 int plane_height = (i == cdm::VideoFrame::kYPlane) ?
[email protected]f75555a2012-12-10 22:35:241215 video_frame->Size().height : (video_frame->Size().height + 1) / 2;
[email protected]ce19e7b52012-12-05 19:47:241216 cdm::VideoFrame::VideoPlane plane =
1217 static_cast<cdm::VideoFrame::VideoPlane>(i);
[email protected]f75555a2012-12-10 22:35:241218 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
1219 plane_height * video_frame->Stride(plane)) {
[email protected]ce19e7b52012-12-05 19:47:241220 return false;
1221 }
1222 }
1223
1224 return true;
1225}
1226
[email protected]ae9754e2013-10-08 22:52:251227bool CdmWrapper::CanChallengePlatform() {
1228#if defined(OS_CHROMEOS)
1229 return can_challenge_platform_;
1230#else
1231 return false;
1232#endif
1233}
1234
1235void CdmWrapper::SendPlatformChallenge(
1236 const char* service_id, int32_t service_id_length,
1237 const char* challenge, int32_t challenge_length) {
1238#if defined(OS_CHROMEOS)
1239 PP_DCHECK(!challenge_in_progress_);
1240
1241 // Ensure member variables set by the callback are in a clean state.
1242 signed_data_output_ = pp::Var();
1243 signed_data_signature_output_ = pp::Var();
1244 platform_key_certificate_output_ = pp::Var();
1245
1246 pp::VarArrayBuffer challenge_var(challenge_length);
1247 uint8_t* var_data = static_cast<uint8_t*>(challenge_var.Map());
1248 memcpy(var_data, challenge, challenge_length);
1249
1250 std::string service_id_str(service_id, service_id_length);
1251 int32_t result = platform_verification_.ChallengePlatform(
1252 pp::Var(service_id_str), challenge_var, &signed_data_output_,
1253 &signed_data_signature_output_, &platform_key_certificate_output_,
1254 callback_factory_.NewCallback(&CdmWrapper::SendPlatformChallengeDone));
1255 challenge_var.Unmap();
1256 if (result == PP_OK_COMPLETIONPENDING) {
1257 challenge_in_progress_ = true;
1258 return;
1259 }
1260
1261 // Fall through on error and issue an empty OnPlatformChallengeResponse().
1262 PP_DCHECK(result != PP_OK);
1263#endif
1264
1265 cdm::PlatformChallengeResponse response = {};
1266 cdm_->OnPlatformChallengeResponse(response);
1267}
1268
1269void CdmWrapper::EnableOutputProtection(uint32_t desired_protection_mask) {
1270#if defined(OS_CHROMEOS)
1271 output_protection_.EnableProtection(
1272 desired_protection_mask, callback_factory_.NewCallback(
1273 &CdmWrapper::EnableProtectionDone));
1274
1275 // Errors are ignored since clients must call QueryOutputProtectionStatus() to
1276 // inspect the protection status on a regular basis.
1277 // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here...
1278#endif
1279}
1280
1281void CdmWrapper::QueryOutputProtectionStatus() {
1282#if defined(OS_CHROMEOS)
1283 PP_DCHECK(!query_output_protection_in_progress_);
1284
1285 output_link_mask_ = output_protection_mask_ = 0;
1286 const int32_t result = output_protection_.QueryStatus(
1287 &output_link_mask_,
1288 &output_protection_mask_,
1289 callback_factory_.NewCallback(
1290 &CdmWrapper::QueryOutputProtectionStatusDone));
1291 if (result == PP_OK_COMPLETIONPENDING) {
1292 query_output_protection_in_progress_ = true;
1293 return;
1294 }
1295
1296 // Fall through on error and issue an empty OnQueryOutputProtectionStatus().
1297 PP_DCHECK(result != PP_OK);
1298#endif
1299
1300 cdm_->OnQueryOutputProtectionStatus(0, 0);
1301}
1302
1303#if defined(OS_CHROMEOS)
1304void CdmWrapper::CanChallengePlatformDone(int32_t result,
1305 bool can_challenge_platform) {
1306 can_challenge_platform_ = (result == PP_OK) ? can_challenge_platform : false;
1307}
1308
1309void CdmWrapper::SendPlatformChallengeDone(int32_t result) {
1310 challenge_in_progress_ = false;
1311
1312 if (result != PP_OK) {
1313 cdm::PlatformChallengeResponse response = {};
1314 cdm_->OnPlatformChallengeResponse(response);
1315 return;
1316 }
1317
1318 pp::VarArrayBuffer signed_data_var(signed_data_output_);
1319 pp::VarArrayBuffer signed_data_signature_var(signed_data_signature_output_);
1320 std::string platform_key_certificate_string =
1321 platform_key_certificate_output_.AsString();
1322
1323 cdm::PlatformChallengeResponse response = {
1324 static_cast<uint8_t*>(signed_data_var.Map()),
1325 static_cast<int32_t>(signed_data_var.ByteLength()),
1326
1327 static_cast<uint8_t*>(signed_data_signature_var.Map()),
1328 static_cast<int32_t>(signed_data_signature_var.ByteLength()),
1329
1330 reinterpret_cast<const uint8_t*>(platform_key_certificate_string.c_str()),
1331 static_cast<int32_t>(platform_key_certificate_string.length())
1332 };
1333 cdm_->OnPlatformChallengeResponse(response);
1334
1335 signed_data_var.Unmap();
1336 signed_data_signature_var.Unmap();
1337}
1338
1339void CdmWrapper::EnableProtectionDone(int32_t result) {
1340 // Does nothing since clients must call QueryOutputProtectionStatus() to
1341 // inspect the protection status on a regular basis.
1342 // TODO(dalecurtis): It'd be nice to log a message or non-fatal error here...
1343}
1344
1345void CdmWrapper::QueryOutputProtectionStatusDone(int32_t result) {
1346 PP_DCHECK(query_output_protection_in_progress_);
1347 query_output_protection_in_progress_ = false;
1348
1349 // Return a protection status of none on error.
1350 if (result != PP_OK)
1351 output_link_mask_ = output_protection_mask_ = 0;
1352
1353 cdm_->OnQueryOutputProtectionStatus(output_link_mask_,
1354 output_protection_mask_);
1355}
1356#endif
1357
[email protected]b68e1442013-02-12 04:46:111358void* GetCdmHost(int host_interface_version, void* user_data) {
1359 if (!host_interface_version || !user_data)
1360 return NULL;
1361
[email protected]b68e1442013-02-12 04:46:111362 CdmWrapper* cdm_wrapper = static_cast<CdmWrapper*>(user_data);
[email protected]ae9754e2013-10-08 22:52:251363 switch (host_interface_version) {
1364 case cdm::kHostInterfaceVersion_1:
1365 return static_cast<cdm::Host_1*>(cdm_wrapper);
1366 case cdm::kHostInterfaceVersion_2:
1367 return static_cast<cdm::Host_2*>(cdm_wrapper);
1368 default:
1369 PP_NOTREACHED();
1370 return NULL;
1371 }
[email protected]b68e1442013-02-12 04:46:111372}
1373
[email protected]e5aeef02012-08-17 00:18:431374// This object is the global object representing this plugin library as long
1375// as it is loaded.
[email protected]9264e1502012-09-18 19:53:011376class CdmWrapperModule : public pp::Module {
[email protected]e5aeef02012-08-17 00:18:431377 public:
[email protected]a9c788e2012-10-26 23:54:551378 CdmWrapperModule() : pp::Module() {
1379 // This function blocks the renderer thread (PluginInstance::Initialize()).
1380 // Move this call to other places if this may be a concern in the future.
1381 INITIALIZE_CDM_MODULE();
1382 }
1383 virtual ~CdmWrapperModule() {
[email protected]f75555a2012-12-10 22:35:241384 DeinitializeCdmModule();
[email protected]a9c788e2012-10-26 23:54:551385 }
[email protected]e5aeef02012-08-17 00:18:431386
1387 virtual pp::Instance* CreateInstance(PP_Instance instance) {
[email protected]d341e332012-08-28 18:57:401388 return new CdmWrapper(instance, this);
[email protected]e5aeef02012-08-17 00:18:431389 }
1390};
1391
[email protected]177bcf82013-08-10 08:21:161392} // namespace media
[email protected]d341e332012-08-28 18:57:401393
[email protected]e5aeef02012-08-17 00:18:431394namespace pp {
1395
1396// Factory function for your specialization of the Module object.
1397Module* CreateModule() {
[email protected]177bcf82013-08-10 08:21:161398 return new media::CdmWrapperModule();
[email protected]e5aeef02012-08-17 00:18:431399}
1400
1401} // namespace pp