blob: 9c7fa56775d437efcf6bdfea338ff69bdd5bd86b [file] [log] [blame]
[email protected]e5aeef02012-08-17 00:18:431// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[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]e5aeef02012-08-17 00:18:4313#include "ppapi/c/pp_errors.h"
14#include "ppapi/c/pp_stdint.h"
[email protected]98ad9782012-08-22 04:06:2215#include "ppapi/c/private/pp_content_decryptor.h"
[email protected]e5aeef02012-08-17 00:18:4316#include "ppapi/cpp/completion_callback.h"
17#include "ppapi/cpp/core.h"
18#include "ppapi/cpp/instance.h"
19#include "ppapi/cpp/logging.h"
20#include "ppapi/cpp/module.h"
21#include "ppapi/cpp/pass_ref.h"
22#include "ppapi/cpp/resource.h"
23#include "ppapi/cpp/var.h"
24#include "ppapi/cpp/var_array_buffer.h"
25#include "ppapi/cpp/dev/buffer_dev.h"
26#include "ppapi/cpp/private/content_decryptor_private.h"
27#include "ppapi/utility/completion_callback_factory.h"
[email protected]6e0c87802012-12-18 07:08:3228#include "webkit/media/crypto/ppapi/cdm/content_decryption_module.h"
[email protected]bf5f1682012-10-23 04:31:4329#include "webkit/media/crypto/ppapi/linked_ptr.h"
[email protected]e5aeef02012-08-17 00:18:4330
31namespace {
32
[email protected]98ad9782012-08-22 04:06:2233bool IsMainThread() {
34 return pp::Module::Get()->core()->IsMainThread();
35}
36
[email protected]8f1be472012-12-15 19:06:3337// Posts a task to run |cb| on the main thread. The task is posted even if the
38// current thread is the main thread.
39void PostOnMain(pp::CompletionCallback cb) {
40 pp::Module::Get()->core()->CallOnMainThread(0, cb, PP_OK);
41}
42
43// Ensures |cb| is called on the main thread, either because the current thread
44// is the main thread or by posting it to the main thread.
[email protected]e5aeef02012-08-17 00:18:4345void CallOnMain(pp::CompletionCallback cb) {
[email protected]98ad9782012-08-22 04:06:2246 // TODO(tomfinegan): This is only necessary because PPAPI doesn't allow calls
47 // off the main thread yet. Remove this once the change lands.
48 if (IsMainThread())
49 cb.Run(PP_OK);
50 else
[email protected]8f1be472012-12-15 19:06:3351 PostOnMain(cb);
[email protected]e5aeef02012-08-17 00:18:4352}
53
[email protected]181d9c12012-10-03 22:53:4854// Configures a cdm::InputBuffer. |subsamples| must exist as long as
55// |input_buffer| is in use.
56void ConfigureInputBuffer(
57 const pp::Buffer_Dev& encrypted_buffer,
58 const PP_EncryptedBlockInfo& encrypted_block_info,
59 std::vector<cdm::SubsampleEntry>* subsamples,
60 cdm::InputBuffer* input_buffer) {
61 PP_DCHECK(subsamples);
[email protected]741c28f2012-10-18 07:02:2562 PP_DCHECK(!encrypted_buffer.is_null());
63
[email protected]3b274b42012-10-26 20:41:2664 input_buffer->data = static_cast<uint8_t*>(encrypted_buffer.data());
[email protected]2468aae2012-11-21 19:53:1665 input_buffer->data_size = encrypted_block_info.data_size;
66 PP_DCHECK(encrypted_buffer.size() >=
67 static_cast<uint32_t>(input_buffer->data_size));
[email protected]181d9c12012-10-03 22:53:4868 input_buffer->data_offset = encrypted_block_info.data_offset;
[email protected]181d9c12012-10-03 22:53:4869
[email protected]f3fffa22013-01-25 22:16:0370 PP_DCHECK(encrypted_block_info.key_id_size <=
71 arraysize(encrypted_block_info.key_id));
72 input_buffer->key_id_size = encrypted_block_info.key_id_size;
73 input_buffer->key_id = input_buffer->key_id_size > 0 ?
74 encrypted_block_info.key_id : NULL;
75
76 PP_DCHECK(encrypted_block_info.iv_size <= arraysize(encrypted_block_info.iv));
77 input_buffer->iv_size = encrypted_block_info.iv_size;
78 input_buffer->iv = encrypted_block_info.iv_size > 0 ?
79 encrypted_block_info.iv : NULL;
80
81 input_buffer->num_subsamples = encrypted_block_info.num_subsamples;
[email protected]181d9c12012-10-03 22:53:4882 if (encrypted_block_info.num_subsamples > 0) {
83 subsamples->reserve(encrypted_block_info.num_subsamples);
84
85 for (uint32_t i = 0; i < encrypted_block_info.num_subsamples; ++i) {
86 subsamples->push_back(cdm::SubsampleEntry(
87 encrypted_block_info.subsamples[i].clear_bytes,
88 encrypted_block_info.subsamples[i].cipher_bytes));
89 }
90
91 input_buffer->subsamples = &(*subsamples)[0];
92 }
93
94 input_buffer->timestamp = encrypted_block_info.tracking_info.timestamp;
95}
96
[email protected]8f5a9a52012-10-23 20:49:2097PP_DecryptResult CdmStatusToPpDecryptResult(cdm::Status status) {
98 switch (status) {
99 case cdm::kSuccess:
100 return PP_DECRYPTRESULT_SUCCESS;
101 case cdm::kNoKey:
102 return PP_DECRYPTRESULT_DECRYPT_NOKEY;
103 case cdm::kNeedMoreData:
104 return PP_DECRYPTRESULT_NEEDMOREDATA;
105 case cdm::kDecryptError:
106 return PP_DECRYPTRESULT_DECRYPT_ERROR;
107 case cdm::kDecodeError:
108 return PP_DECRYPTRESULT_DECODE_ERROR;
109 default:
110 PP_NOTREACHED();
111 return PP_DECRYPTRESULT_DECODE_ERROR;
112 }
113}
114
[email protected]e9d3a1022012-10-11 23:43:55115PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
[email protected]181d9c12012-10-03 22:53:48116 cdm::VideoFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20117 switch (format) {
118 case cdm::kYv12:
119 return PP_DECRYPTEDFRAMEFORMAT_YV12;
120 case cdm::kI420:
121 return PP_DECRYPTEDFRAMEFORMAT_I420;
122 default:
123 return PP_DECRYPTEDFRAMEFORMAT_UNKNOWN;
124 }
[email protected]e9d3a1022012-10-11 23:43:55125}
126
[email protected]c999b3b72012-10-19 22:33:46127cdm::AudioDecoderConfig::AudioCodec PpAudioCodecToCdmAudioCodec(
128 PP_AudioCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20129 switch (codec) {
130 case PP_AUDIOCODEC_VORBIS:
131 return cdm::AudioDecoderConfig::kCodecVorbis;
[email protected]4967628d2012-10-27 02:08:48132 case PP_AUDIOCODEC_AAC:
133 return cdm::AudioDecoderConfig::kCodecAac;
[email protected]8f5a9a52012-10-23 20:49:20134 default:
135 return cdm::AudioDecoderConfig::kUnknownAudioCodec;
136 }
[email protected]c999b3b72012-10-19 22:33:46137}
138
[email protected]e9d3a1022012-10-11 23:43:55139cdm::VideoDecoderConfig::VideoCodec PpVideoCodecToCdmVideoCodec(
140 PP_VideoCodec codec) {
[email protected]8f5a9a52012-10-23 20:49:20141 switch (codec) {
142 case PP_VIDEOCODEC_VP8:
[email protected]4967628d2012-10-27 02:08:48143 return cdm::VideoDecoderConfig::kCodecVp8;
144 case PP_VIDEOCODEC_H264:
145 return cdm::VideoDecoderConfig::kCodecH264;
[email protected]8f5a9a52012-10-23 20:49:20146 default:
147 return cdm::VideoDecoderConfig::kUnknownVideoCodec;
148 }
[email protected]e9d3a1022012-10-11 23:43:55149}
150
151cdm::VideoDecoderConfig::VideoCodecProfile PpVCProfileToCdmVCProfile(
152 PP_VideoCodecProfile profile) {
[email protected]8f5a9a52012-10-23 20:49:20153 switch (profile) {
154 case PP_VIDEOCODECPROFILE_VP8_MAIN:
155 return cdm::VideoDecoderConfig::kVp8ProfileMain;
[email protected]4967628d2012-10-27 02:08:48156 case PP_VIDEOCODECPROFILE_H264_BASELINE:
157 return cdm::VideoDecoderConfig::kH264ProfileBaseline;
158 case PP_VIDEOCODECPROFILE_H264_MAIN:
159 return cdm::VideoDecoderConfig::kH264ProfileMain;
160 case PP_VIDEOCODECPROFILE_H264_EXTENDED:
161 return cdm::VideoDecoderConfig::kH264ProfileExtended;
162 case PP_VIDEOCODECPROFILE_H264_HIGH:
163 return cdm::VideoDecoderConfig::kH264ProfileHigh;
164 case PP_VIDEOCODECPROFILE_H264_HIGH_10:
165 return cdm::VideoDecoderConfig::kH264ProfileHigh10;
166 case PP_VIDEOCODECPROFILE_H264_HIGH_422:
167 return cdm::VideoDecoderConfig::kH264ProfileHigh422;
168 case PP_VIDEOCODECPROFILE_H264_HIGH_444_PREDICTIVE:
169 return cdm::VideoDecoderConfig::kH264ProfileHigh444Predictive;
[email protected]8f5a9a52012-10-23 20:49:20170 default:
171 return cdm::VideoDecoderConfig::kUnknownVideoCodecProfile;
172 }
[email protected]e9d3a1022012-10-11 23:43:55173}
174
175cdm::VideoFormat PpDecryptedFrameFormatToCdmVideoFormat(
176 PP_DecryptedFrameFormat format) {
[email protected]8f5a9a52012-10-23 20:49:20177 switch (format) {
178 case PP_DECRYPTEDFRAMEFORMAT_YV12:
179 return cdm::kYv12;
180 case PP_DECRYPTEDFRAMEFORMAT_I420:
181 return cdm::kI420;
182 default:
183 return cdm::kUnknownVideoFormat;
184 }
[email protected]181d9c12012-10-03 22:53:48185}
186
[email protected]bf5f1682012-10-23 04:31:43187cdm::StreamType PpDecryptorStreamTypeToCdmStreamType(
188 PP_DecryptorStreamType stream_type) {
189 switch (stream_type) {
190 case PP_DECRYPTORSTREAMTYPE_AUDIO:
191 return cdm::kStreamTypeAudio;
192 case PP_DECRYPTORSTREAMTYPE_VIDEO:
193 return cdm::kStreamTypeVideo;
194 }
195
196 PP_NOTREACHED();
197 return cdm::kStreamTypeVideo;
198}
199
[email protected]e5aeef02012-08-17 00:18:43200} // namespace
201
[email protected]d341e332012-08-28 18:57:40202namespace webkit_media {
[email protected]e5aeef02012-08-17 00:18:43203
[email protected]ce19e7b52012-12-05 19:47:24204// cdm::Buffer implementation that provides access to memory owned by a
205// pp::Buffer_Dev.
206// This class holds a reference to the Buffer_Dev throughout its lifetime.
207// TODO(xhwang): Find a better name. It's confusing to have PpbBuffer,
208// pp::Buffer_Dev and PPB_Buffer_Dev.
[email protected]9264e1502012-09-18 19:53:01209class PpbBuffer : public cdm::Buffer {
210 public:
[email protected]f75555a2012-12-10 22:35:24211 static PpbBuffer* Create(const pp::Buffer_Dev& buffer, uint32_t buffer_id) {
[email protected]ce19e7b52012-12-05 19:47:24212 PP_DCHECK(buffer.data());
213 PP_DCHECK(buffer.size());
[email protected]f75555a2012-12-10 22:35:24214 PP_DCHECK(buffer_id);
215 return new PpbBuffer(buffer, buffer_id);
[email protected]ce19e7b52012-12-05 19:47:24216 }
217
218 // cdm::Buffer implementation.
[email protected]9264e1502012-09-18 19:53:01219 virtual void Destroy() OVERRIDE { delete this; }
220
[email protected]f75555a2012-12-10 22:35:24221 virtual int32_t Capacity() const OVERRIDE { return buffer_.size(); }
222
223 virtual uint8_t* Data() OVERRIDE {
[email protected]9264e1502012-09-18 19:53:01224 return static_cast<uint8_t*>(buffer_.data());
225 }
226
[email protected]f75555a2012-12-10 22:35:24227 virtual void SetSize(int32_t size) OVERRIDE {
228 PP_DCHECK(size >= 0);
229 PP_DCHECK(size < Capacity());
230 if (size < 0 || size > Capacity()) {
231 size_ = 0;
232 return;
233 }
234
235 size_ = size;
236 }
237
238 virtual int32_t Size() const OVERRIDE { return size_; }
[email protected]9264e1502012-09-18 19:53:01239
240 pp::Buffer_Dev buffer_dev() const { return buffer_; }
241
[email protected]ce19e7b52012-12-05 19:47:24242 uint32_t buffer_id() const { return buffer_id_; }
243
[email protected]9264e1502012-09-18 19:53:01244 private:
[email protected]f75555a2012-12-10 22:35:24245 PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id)
[email protected]ce19e7b52012-12-05 19:47:24246 : buffer_(buffer),
247 buffer_id_(buffer_id),
[email protected]f75555a2012-12-10 22:35:24248 size_(0) {}
[email protected]9264e1502012-09-18 19:53:01249 virtual ~PpbBuffer() {}
250
251 pp::Buffer_Dev buffer_;
[email protected]ce19e7b52012-12-05 19:47:24252 uint32_t buffer_id_;
253 int32_t size_;
[email protected]9264e1502012-09-18 19:53:01254
255 DISALLOW_COPY_AND_ASSIGN(PpbBuffer);
256};
257
258class PpbBufferAllocator : public cdm::Allocator {
259 public:
[email protected]ce19e7b52012-12-05 19:47:24260 explicit PpbBufferAllocator(pp::Instance* instance)
261 : instance_(instance),
262 next_buffer_id_(1) {}
[email protected]3b274b42012-10-26 20:41:26263 virtual ~PpbBufferAllocator() {}
[email protected]9264e1502012-09-18 19:53:01264
[email protected]ce19e7b52012-12-05 19:47:24265 // cdm::Allocator implementation.
[email protected]f75555a2012-12-10 22:35:24266 virtual cdm::Buffer* Allocate(int32_t capacity) OVERRIDE;
[email protected]9264e1502012-09-18 19:53:01267
[email protected]ce19e7b52012-12-05 19:47:24268 // Releases the buffer with |buffer_id|. A buffer can be recycled after
269 // it is released.
270 void Release(uint32_t buffer_id);
271
[email protected]9264e1502012-09-18 19:53:01272 private:
[email protected]ce19e7b52012-12-05 19:47:24273 typedef std::map<uint32_t, pp::Buffer_Dev> AllocatedBufferMap;
274 typedef std::multimap<int, std::pair<uint32_t, pp::Buffer_Dev> >
275 FreeBufferMap;
276
277 // Always pad new allocated buffer so that we don't need to reallocate
278 // buffers frequently if requested sizes fluctuate slightly.
279 static const int kBufferPadding = 512;
280
281 // Maximum number of free buffers we can keep when allocating new buffers.
282 static const int kFreeLimit = 3;
283
[email protected]f75555a2012-12-10 22:35:24284 pp::Buffer_Dev AllocateNewBuffer(int capacity);
[email protected]ce19e7b52012-12-05 19:47:24285
[email protected]9264e1502012-09-18 19:53:01286 pp::Instance* const instance_;
[email protected]ce19e7b52012-12-05 19:47:24287 uint32_t next_buffer_id_;
288 AllocatedBufferMap allocated_buffers_;
289 FreeBufferMap free_buffers_;
[email protected]9264e1502012-09-18 19:53:01290
291 DISALLOW_COPY_AND_ASSIGN(PpbBufferAllocator);
292};
293
[email protected]f75555a2012-12-10 22:35:24294cdm::Buffer* PpbBufferAllocator::Allocate(int32_t capacity) {
[email protected]3b274b42012-10-26 20:41:26295 PP_DCHECK(IsMainThread());
[email protected]7ed56ed2012-10-02 02:43:27296
[email protected]f75555a2012-12-10 22:35:24297 if (capacity <= 0)
298 return NULL;
299
[email protected]ce19e7b52012-12-05 19:47:24300 pp::Buffer_Dev buffer;
301 uint32_t buffer_id = 0;
[email protected]7ed56ed2012-10-02 02:43:27302
[email protected]f75555a2012-12-10 22:35:24303 // Reuse a buffer in the free list if there is one that fits |capacity|.
[email protected]ce19e7b52012-12-05 19:47:24304 // Otherwise, create a new one.
[email protected]f75555a2012-12-10 22:35:24305 FreeBufferMap::iterator found = free_buffers_.lower_bound(capacity);
[email protected]ce19e7b52012-12-05 19:47:24306 if (found == free_buffers_.end()) {
307 // TODO(xhwang): Report statistics about how many new buffers are allocated.
[email protected]f75555a2012-12-10 22:35:24308 buffer = AllocateNewBuffer(capacity);
[email protected]ce19e7b52012-12-05 19:47:24309 if (buffer.is_null())
310 return NULL;
311 buffer_id = next_buffer_id_++;
312 } else {
313 buffer = found->second.second;
314 buffer_id = found->second.first;
315 free_buffers_.erase(found);
316 }
317
318 allocated_buffers_.insert(std::make_pair(buffer_id, buffer));
319
[email protected]f75555a2012-12-10 22:35:24320 return PpbBuffer::Create(buffer, buffer_id);
[email protected]ce19e7b52012-12-05 19:47:24321}
322
323void PpbBufferAllocator::Release(uint32_t buffer_id) {
324 if (!buffer_id)
325 return;
326
327 AllocatedBufferMap::iterator found = allocated_buffers_.find(buffer_id);
328 if (found == allocated_buffers_.end())
329 return;
330
331 pp::Buffer_Dev& buffer = found->second;
332 free_buffers_.insert(
333 std::make_pair(buffer.size(), std::make_pair(buffer_id, buffer)));
334
335 allocated_buffers_.erase(found);
336}
337
[email protected]f75555a2012-12-10 22:35:24338pp::Buffer_Dev PpbBufferAllocator::AllocateNewBuffer(int32_t capacity) {
[email protected]ce19e7b52012-12-05 19:47:24339 // Destroy the smallest buffer before allocating a new bigger buffer if the
340 // number of free buffers exceeds a limit. This mechanism helps avoid ending
341 // up with too many small buffers, which could happen if the size to be
342 // allocated keeps increasing.
343 if (free_buffers_.size() >= static_cast<uint32_t>(kFreeLimit))
344 free_buffers_.erase(free_buffers_.begin());
345
346 // Creation of pp::Buffer_Dev is expensive! It involves synchronous IPC calls.
347 // That's why we try to avoid AllocateNewBuffer() as much as we can.
[email protected]f75555a2012-12-10 22:35:24348 return pp::Buffer_Dev(instance_, capacity + kBufferPadding);
[email protected]3b274b42012-10-26 20:41:26349}
[email protected]7ed56ed2012-10-02 02:43:27350
[email protected]3b274b42012-10-26 20:41:26351class DecryptedBlockImpl : public cdm::DecryptedBlock {
352 public:
353 DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {}
354 virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); }
[email protected]9264e1502012-09-18 19:53:01355
[email protected]f75555a2012-12-10 22:35:24356 virtual void SetDecryptedBuffer(cdm::Buffer* buffer) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26357 buffer_ = static_cast<PpbBuffer*>(buffer);
358 }
[email protected]f75555a2012-12-10 22:35:24359 virtual cdm::Buffer* DecryptedBuffer() OVERRIDE { return buffer_; }
[email protected]9264e1502012-09-18 19:53:01360
[email protected]f75555a2012-12-10 22:35:24361 virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26362 timestamp_ = timestamp;
363 }
[email protected]f75555a2012-12-10 22:35:24364 virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
[email protected]9264e1502012-09-18 19:53:01365
[email protected]3b274b42012-10-26 20:41:26366 private:
367 PpbBuffer* buffer_;
368 int64_t timestamp_;
[email protected]9264e1502012-09-18 19:53:01369
[email protected]3b274b42012-10-26 20:41:26370 DISALLOW_COPY_AND_ASSIGN(DecryptedBlockImpl);
371};
[email protected]9264e1502012-09-18 19:53:01372
[email protected]181d9c12012-10-03 22:53:48373class VideoFrameImpl : public cdm::VideoFrame {
374 public:
375 VideoFrameImpl();
376 virtual ~VideoFrameImpl();
377
[email protected]f75555a2012-12-10 22:35:24378 virtual void SetFormat(cdm::VideoFormat format) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26379 format_ = format;
380 }
[email protected]f75555a2012-12-10 22:35:24381 virtual cdm::VideoFormat Format() const OVERRIDE { return format_; }
[email protected]181d9c12012-10-03 22:53:48382
[email protected]f75555a2012-12-10 22:35:24383 virtual void SetSize(cdm::Size size) OVERRIDE { size_ = size; }
384 virtual cdm::Size Size() const OVERRIDE { return size_; }
[email protected]d0ec47492012-10-13 05:01:46385
[email protected]f75555a2012-12-10 22:35:24386 virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26387 frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer);
388 }
[email protected]f75555a2012-12-10 22:35:24389 virtual cdm::Buffer* FrameBuffer() OVERRIDE { return frame_buffer_; }
[email protected]181d9c12012-10-03 22:53:48390
[email protected]f75555a2012-12-10 22:35:24391 virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane,
392 int32_t offset) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26393 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
394 PP_DCHECK(offset >= 0);
395 plane_offsets_[plane] = offset;
396 }
[email protected]f75555a2012-12-10 22:35:24397 virtual int32_t PlaneOffset(VideoPlane plane) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26398 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
399 return plane_offsets_[plane];
400 }
[email protected]181d9c12012-10-03 22:53:48401
[email protected]f75555a2012-12-10 22:35:24402 virtual void SetStride(VideoPlane plane, int32_t stride) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26403 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
404 strides_[plane] = stride;
405 }
[email protected]f75555a2012-12-10 22:35:24406 virtual int32_t Stride(VideoPlane plane) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26407 PP_DCHECK(0 <= plane && plane < kMaxPlanes);
408 return strides_[plane];
409 }
[email protected]181d9c12012-10-03 22:53:48410
[email protected]f75555a2012-12-10 22:35:24411 virtual void SetTimestamp(int64_t timestamp) OVERRIDE {
[email protected]3b274b42012-10-26 20:41:26412 timestamp_ = timestamp;
413 }
[email protected]f75555a2012-12-10 22:35:24414 virtual int64_t Timestamp() const OVERRIDE { return timestamp_; }
[email protected]181d9c12012-10-03 22:53:48415
416 private:
417 // The video buffer format.
418 cdm::VideoFormat format_;
419
[email protected]d0ec47492012-10-13 05:01:46420 // Width and height of the video frame.
421 cdm::Size size_;
422
[email protected]181d9c12012-10-03 22:53:48423 // The video frame buffer.
424 PpbBuffer* frame_buffer_;
425
426 // Array of data pointers to each plane in the video frame buffer.
427 int32_t plane_offsets_[kMaxPlanes];
428
429 // Array of strides for each plane, typically greater or equal to the width
430 // of the surface divided by the horizontal sampling period. Note that
431 // strides can be negative.
432 int32_t strides_[kMaxPlanes];
433
434 // Presentation timestamp in microseconds.
435 int64_t timestamp_;
[email protected]3b274b42012-10-26 20:41:26436
437 DISALLOW_COPY_AND_ASSIGN(VideoFrameImpl);
[email protected]181d9c12012-10-03 22:53:48438};
439
[email protected]181d9c12012-10-03 22:53:48440VideoFrameImpl::VideoFrameImpl()
441 : format_(cdm::kUnknownVideoFormat),
442 frame_buffer_(NULL),
443 timestamp_(0) {
444 for (int32_t i = 0; i < kMaxPlanes; ++i) {
445 plane_offsets_[i] = 0;
446 strides_[i] = 0;
447 }
448}
449
450VideoFrameImpl::~VideoFrameImpl() {
451 if (frame_buffer_)
452 frame_buffer_->Destroy();
453}
454
[email protected]ecbb97682012-10-24 22:33:54455class AudioFramesImpl : public cdm::AudioFrames {
456 public:
457 AudioFramesImpl() : buffer_(NULL) {}
458 virtual ~AudioFramesImpl() {
459 if (buffer_)
460 buffer_->Destroy();
461 }
462
463 // AudioFrames implementation.
[email protected]f75555a2012-12-10 22:35:24464 virtual void SetFrameBuffer(cdm::Buffer* buffer) OVERRIDE {
[email protected]ecbb97682012-10-24 22:33:54465 buffer_ = static_cast<PpbBuffer*>(buffer);
466 }
[email protected]f75555a2012-12-10 22:35:24467 virtual cdm::Buffer* FrameBuffer() OVERRIDE {
[email protected]ecbb97682012-10-24 22:33:54468 return buffer_;
469 }
470
471 private:
472 PpbBuffer* buffer_;
473
474 DISALLOW_COPY_AND_ASSIGN(AudioFramesImpl);
475};
476
[email protected]e5aeef02012-08-17 00:18:43477// A wrapper class for abstracting away PPAPI interaction and threading for a
478// Content Decryption Module (CDM).
[email protected]d341e332012-08-28 18:57:40479class CdmWrapper : public pp::Instance,
[email protected]f5c9b938e2012-10-10 12:24:07480 public pp::ContentDecryptor_Private,
[email protected]f75555a2012-12-10 22:35:24481 public cdm::Host {
[email protected]e5aeef02012-08-17 00:18:43482 public:
[email protected]d341e332012-08-28 18:57:40483 CdmWrapper(PP_Instance instance, pp::Module* module);
484 virtual ~CdmWrapper();
[email protected]3b274b42012-10-26 20:41:26485
486 // pp::Instance implementation.
[email protected]d341e332012-08-28 18:57:40487 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
488 return true;
489 }
[email protected]e5aeef02012-08-17 00:18:43490
[email protected]3b274b42012-10-26 20:41:26491 // PPP_ContentDecryptor_Private implementation.
[email protected]d40797c2012-10-04 04:36:14492 // Note: Results of calls to these methods must be reported through the
493 // PPB_ContentDecryptor_Private interface.
[email protected]ea4ff802012-09-13 01:36:44494 virtual void GenerateKeyRequest(const std::string& key_system,
[email protected]f1b1db02012-10-29 22:50:23495 const std::string& type,
[email protected]e5aeef02012-08-17 00:18:43496 pp::VarArrayBuffer init_data) OVERRIDE;
[email protected]ea4ff802012-09-13 01:36:44497 virtual void AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22498 pp::VarArrayBuffer key,
499 pp::VarArrayBuffer init_data) OVERRIDE;
[email protected]ea4ff802012-09-13 01:36:44500 virtual void CancelKeyRequest(const std::string& session_id) OVERRIDE;
501 virtual void Decrypt(
[email protected]98ad9782012-08-22 04:06:22502 pp::Buffer_Dev encrypted_buffer,
503 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
[email protected]c999b3b72012-10-19 22:33:46504 virtual void InitializeAudioDecoder(
505 const PP_AudioDecoderConfig& decoder_config,
506 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
[email protected]e9d3a1022012-10-11 23:43:55507 virtual void InitializeVideoDecoder(
508 const PP_VideoDecoderConfig& decoder_config,
509 pp::Buffer_Dev extra_data_buffer) OVERRIDE;
[email protected]23de87452012-10-12 07:03:09510 virtual void DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
511 uint32_t request_id) OVERRIDE;
512 virtual void ResetDecoder(PP_DecryptorStreamType decoder_type,
513 uint32_t request_id) OVERRIDE;
[email protected]467434d2012-10-12 10:48:53514 virtual void DecryptAndDecode(
515 PP_DecryptorStreamType decoder_type,
516 pp::Buffer_Dev encrypted_buffer,
517 const PP_EncryptedBlockInfo& encrypted_block_info) OVERRIDE;
[email protected]e5aeef02012-08-17 00:18:43518
[email protected]f75555a2012-12-10 22:35:24519 // cdm::Host implementation.
520 virtual void SetTimer(int64_t delay_ms, void* context) OVERRIDE;
[email protected]cc3c56b2012-11-01 17:35:32521 virtual double GetCurrentWallTimeInSeconds() OVERRIDE;
[email protected]f75555a2012-12-10 22:35:24522 virtual void SendKeyMessage(
523 const char* session_id, int32_t session_id_length,
524 const char* message, int32_t message_length,
525 const char* default_url, int32_t default_url_length) OVERRIDE;
526 virtual void SendKeyError(const char* session_id,
527 int32_t session_id_length,
528 cdm::MediaKeyError error_code,
529 uint32_t system_code) OVERRIDE;
[email protected]f5c9b938e2012-10-10 12:24:07530
[email protected]e5aeef02012-08-17 00:18:43531 private:
[email protected]6cb006c2013-01-10 21:39:18532 struct SessionInfo {
533 SessionInfo(const std::string& key_system_in,
534 const std::string& session_id_in)
535 : key_system(key_system_in),
536 session_id(session_id_in) {}
537 const std::string key_system;
538 const std::string session_id;
539 };
540
[email protected]7ed56ed2012-10-02 02:43:27541 typedef linked_ptr<DecryptedBlockImpl> LinkedDecryptedBlock;
[email protected]181d9c12012-10-03 22:53:48542 typedef linked_ptr<VideoFrameImpl> LinkedVideoFrame;
[email protected]ecbb97682012-10-24 22:33:54543 typedef linked_ptr<AudioFramesImpl> LinkedAudioFrames;
[email protected]e5aeef02012-08-17 00:18:43544
[email protected]6cb006c2013-01-10 21:39:18545 void SendUnknownKeyError(const std::string& key_system,
546 const std::string& session_id);
[email protected]8f1be472012-12-15 19:06:33547
[email protected]6cb006c2013-01-10 21:39:18548 void SendKeyAdded(const std::string& key_system,
549 const std::string& session_id);
550
551 void SendKeyErrorInternal(const std::string& key_system,
552 const std::string& session_id,
553 cdm::MediaKeyError error_code,
554 uint32_t system_code);
[email protected]8f1be472012-12-15 19:06:33555
[email protected]e5aeef02012-08-17 00:18:43556 // <code>PPB_ContentDecryptor_Private</code> dispatchers. These are passed to
557 // <code>callback_factory_</code> to ensure that calls into
558 // <code>PPP_ContentDecryptor_Private</code> are asynchronous.
[email protected]6cb006c2013-01-10 21:39:18559 void KeyAdded(int32_t result, const SessionInfo& session_info);
[email protected]f75555a2012-12-10 22:35:24560 void KeyMessage(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18561 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:24562 const std::string& message,
563 const std::string& default_url);
564 void KeyError(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18565 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:24566 cdm::MediaKeyError error_code,
567 uint32_t system_code);
[email protected]d341e332012-08-28 18:57:40568 void DeliverBlock(int32_t result,
569 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:27570 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:40571 const PP_DecryptTrackingInfo& tracking_info);
[email protected]c999b3b72012-10-19 22:33:46572 void DecoderInitializeDone(int32_t result,
573 PP_DecryptorStreamType decoder_type,
574 uint32_t request_id,
575 bool success);
[email protected]23de87452012-10-12 07:03:09576 void DecoderDeinitializeDone(int32_t result,
577 PP_DecryptorStreamType decoder_type,
578 uint32_t request_id);
579 void DecoderResetDone(int32_t result,
580 PP_DecryptorStreamType decoder_type,
581 uint32_t request_id);
[email protected]181d9c12012-10-03 22:53:48582 void DeliverFrame(int32_t result,
583 const cdm::Status& status,
584 const LinkedVideoFrame& video_frame,
585 const PP_DecryptTrackingInfo& tracking_info);
[email protected]ecbb97682012-10-24 22:33:54586 void DeliverSamples(int32_t result,
587 const cdm::Status& status,
588 const LinkedAudioFrames& audio_frames,
589 const PP_DecryptTrackingInfo& tracking_info);
[email protected]e5aeef02012-08-17 00:18:43590
[email protected]f5c9b938e2012-10-10 12:24:07591 // Helper for SetTimer().
[email protected]f75555a2012-12-10 22:35:24592 void TimerExpired(int32_t result, void* context);
[email protected]f5c9b938e2012-10-10 12:24:07593
[email protected]ce19e7b52012-12-05 19:47:24594 bool IsValidVideoFrame(const LinkedVideoFrame& video_frame);
595
[email protected]9264e1502012-09-18 19:53:01596 PpbBufferAllocator allocator_;
[email protected]d341e332012-08-28 18:57:40597 pp::CompletionCallbackFactory<CdmWrapper> callback_factory_;
598 cdm::ContentDecryptionModule* cdm_;
599 std::string key_system_;
[email protected]3b274b42012-10-26 20:41:26600
601 DISALLOW_COPY_AND_ASSIGN(CdmWrapper);
[email protected]e5aeef02012-08-17 00:18:43602};
603
[email protected]d341e332012-08-28 18:57:40604CdmWrapper::CdmWrapper(PP_Instance instance, pp::Module* module)
[email protected]e5aeef02012-08-17 00:18:43605 : pp::Instance(instance),
[email protected]d341e332012-08-28 18:57:40606 pp::ContentDecryptor_Private(this),
[email protected]9264e1502012-09-18 19:53:01607 allocator_(this),
[email protected]d341e332012-08-28 18:57:40608 cdm_(NULL) {
[email protected]e5aeef02012-08-17 00:18:43609 callback_factory_.Initialize(this);
610}
611
[email protected]d341e332012-08-28 18:57:40612CdmWrapper::~CdmWrapper() {
613 if (cdm_)
614 DestroyCdmInstance(cdm_);
615}
616
[email protected]ea4ff802012-09-13 01:36:44617void CdmWrapper::GenerateKeyRequest(const std::string& key_system,
[email protected]f1b1db02012-10-29 22:50:23618 const std::string& type,
[email protected]e5aeef02012-08-17 00:18:43619 pp::VarArrayBuffer init_data) {
[email protected]6cb006c2013-01-10 21:39:18620 PP_DCHECK(!key_system.empty());
[email protected]f75555a2012-12-10 22:35:24621 PP_DCHECK(key_system_.empty() || key_system_ == key_system);
[email protected]e5aeef02012-08-17 00:18:43622
[email protected]d341e332012-08-28 18:57:40623 if (!cdm_) {
[email protected]f1b1db02012-10-29 22:50:23624 cdm_ = CreateCdmInstance(key_system.data(), key_system.size(),
625 &allocator_, this);
[email protected]3b274b42012-10-26 20:41:26626 PP_DCHECK(cdm_);
627 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18628 SendUnknownKeyError(key_system, "");
[email protected]ea4ff802012-09-13 01:36:44629 return;
[email protected]3b274b42012-10-26 20:41:26630 }
[email protected]d341e332012-08-28 18:57:40631 }
[email protected]e5aeef02012-08-17 00:18:43632
[email protected]6cb006c2013-01-10 21:39:18633 // Must be set here in case the CDM synchronously calls a cdm::Host method.
634 // Clear below on error.
635 // TODO(ddorwin): Remove this when key_system is added to cdm::Host methods.
636 key_system_ = key_system;
[email protected]d341e332012-08-28 18:57:40637 cdm::Status status = cdm_->GenerateKeyRequest(
[email protected]f1b1db02012-10-29 22:50:23638 type.data(), type.size(),
[email protected]3b274b42012-10-26 20:41:26639 static_cast<const uint8_t*>(init_data.Map()),
[email protected]f75555a2012-12-10 22:35:24640 init_data.ByteLength());
[email protected]0b959582012-10-01 23:13:27641 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]6cb006c2013-01-10 21:39:18642 if (status != cdm::kSuccess) {
643 key_system_.clear(); // See comment above.
[email protected]ea4ff802012-09-13 01:36:44644 return;
[email protected]6cb006c2013-01-10 21:39:18645 }
[email protected]d341e332012-08-28 18:57:40646
[email protected]d341e332012-08-28 18:57:40647 key_system_ = key_system;
[email protected]e5aeef02012-08-17 00:18:43648}
649
[email protected]ea4ff802012-09-13 01:36:44650void CdmWrapper::AddKey(const std::string& session_id,
[email protected]98ad9782012-08-22 04:06:22651 pp::VarArrayBuffer key,
652 pp::VarArrayBuffer init_data) {
[email protected]3b274b42012-10-26 20:41:26653 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
654 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18655 SendUnknownKeyError(key_system_, session_id);
[email protected]3b274b42012-10-26 20:41:26656 return;
657 }
658
659 const uint8_t* key_ptr = static_cast<const uint8_t*>(key.Map());
[email protected]d341e332012-08-28 18:57:40660 int key_size = key.ByteLength();
[email protected]3b274b42012-10-26 20:41:26661 const uint8_t* init_data_ptr = static_cast<const uint8_t*>(init_data.Map());
[email protected]d341e332012-08-28 18:57:40662 int init_data_size = init_data.ByteLength();
[email protected]26b200102013-01-30 05:24:23663 PP_DCHECK(!init_data_ptr == !init_data_size);
[email protected]e5aeef02012-08-17 00:18:43664
[email protected]26b200102013-01-30 05:24:23665 if (!key_ptr || key_size <= 0) {
[email protected]6cb006c2013-01-10 21:39:18666 SendUnknownKeyError(key_system_, session_id);
[email protected]ea4ff802012-09-13 01:36:44667 return;
[email protected]3b274b42012-10-26 20:41:26668 }
[email protected]e5aeef02012-08-17 00:18:43669
[email protected]d341e332012-08-28 18:57:40670 cdm::Status status = cdm_->AddKey(session_id.data(), session_id.size(),
671 key_ptr, key_size,
672 init_data_ptr, init_data_size);
[email protected]0b959582012-10-01 23:13:27673 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]d341e332012-08-28 18:57:40674 if (status != cdm::kSuccess) {
[email protected]6cb006c2013-01-10 21:39:18675 SendUnknownKeyError(key_system_, session_id);
[email protected]ea4ff802012-09-13 01:36:44676 return;
[email protected]d341e332012-08-28 18:57:40677 }
678
[email protected]6cb006c2013-01-10 21:39:18679 SendKeyAdded(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43680}
681
[email protected]ea4ff802012-09-13 01:36:44682void CdmWrapper::CancelKeyRequest(const std::string& session_id) {
[email protected]3b274b42012-10-26 20:41:26683 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
684 if (!cdm_) {
[email protected]6cb006c2013-01-10 21:39:18685 SendUnknownKeyError(key_system_, session_id);
[email protected]3b274b42012-10-26 20:41:26686 return;
687 }
688
[email protected]d341e332012-08-28 18:57:40689 cdm::Status status = cdm_->CancelKeyRequest(session_id.data(),
690 session_id.size());
[email protected]0b959582012-10-01 23:13:27691 PP_DCHECK(status == cdm::kSuccess || status == cdm::kSessionError);
[email protected]3b274b42012-10-26 20:41:26692 if (status != cdm::kSuccess)
[email protected]6cb006c2013-01-10 21:39:18693 SendUnknownKeyError(key_system_, session_id);
[email protected]e5aeef02012-08-17 00:18:43694}
695
[email protected]3b274b42012-10-26 20:41:26696// Note: In the following decryption/decoding related functions, errors are NOT
697// reported via KeyError, but are reported via corresponding PPB calls.
698
[email protected]ea4ff802012-09-13 01:36:44699void CdmWrapper::Decrypt(pp::Buffer_Dev encrypted_buffer,
[email protected]98ad9782012-08-22 04:06:22700 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]3b274b42012-10-26 20:41:26701 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
[email protected]e5aeef02012-08-17 00:18:43702 PP_DCHECK(!encrypted_buffer.is_null());
703
[email protected]ce19e7b52012-12-05 19:47:24704 // Release a buffer that the caller indicated it is finished with.
705 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
706
[email protected]3b274b42012-10-26 20:41:26707 cdm::Status status = cdm::kDecryptError;
[email protected]7ed56ed2012-10-02 02:43:27708 LinkedDecryptedBlock decrypted_block(new DecryptedBlockImpl());
[email protected]3b274b42012-10-26 20:41:26709
710 if (cdm_) {
711 cdm::InputBuffer input_buffer;
712 std::vector<cdm::SubsampleEntry> subsamples;
713 ConfigureInputBuffer(encrypted_buffer, encrypted_block_info, &subsamples,
714 &input_buffer);
715 status = cdm_->Decrypt(input_buffer, decrypted_block.get());
[email protected]f75555a2012-12-10 22:35:24716 PP_DCHECK(status != cdm::kSuccess ||
717 (decrypted_block->DecryptedBuffer() &&
718 decrypted_block->DecryptedBuffer()->Size()));
[email protected]3b274b42012-10-26 20:41:26719 }
[email protected]d341e332012-08-28 18:57:40720
721 CallOnMain(callback_factory_.NewCallback(
722 &CdmWrapper::DeliverBlock,
723 status,
[email protected]7ed56ed2012-10-02 02:43:27724 decrypted_block,
[email protected]d341e332012-08-28 18:57:40725 encrypted_block_info.tracking_info));
[email protected]e5aeef02012-08-17 00:18:43726}
727
[email protected]c999b3b72012-10-19 22:33:46728void CdmWrapper::InitializeAudioDecoder(
729 const PP_AudioDecoderConfig& decoder_config,
730 pp::Buffer_Dev extra_data_buffer) {
[email protected]3b274b42012-10-26 20:41:26731 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
732
733 cdm::Status status = cdm::kSessionError;
734 if (cdm_) {
735 cdm::AudioDecoderConfig cdm_decoder_config;
736 cdm_decoder_config.codec =
737 PpAudioCodecToCdmAudioCodec(decoder_config.codec);
738 cdm_decoder_config.channel_count = decoder_config.channel_count;
739 cdm_decoder_config.bits_per_channel = decoder_config.bits_per_channel;
740 cdm_decoder_config.samples_per_second = decoder_config.samples_per_second;
741 cdm_decoder_config.extra_data =
742 static_cast<uint8_t*>(extra_data_buffer.data());
743 cdm_decoder_config.extra_data_size =
744 static_cast<int32_t>(extra_data_buffer.size());
745 status = cdm_->InitializeAudioDecoder(cdm_decoder_config);
746 }
[email protected]c999b3b72012-10-19 22:33:46747
748 CallOnMain(callback_factory_.NewCallback(
749 &CdmWrapper::DecoderInitializeDone,
750 PP_DECRYPTORSTREAMTYPE_AUDIO,
751 decoder_config.request_id,
752 status == cdm::kSuccess));
753}
754
[email protected]e9d3a1022012-10-11 23:43:55755void CdmWrapper::InitializeVideoDecoder(
756 const PP_VideoDecoderConfig& decoder_config,
757 pp::Buffer_Dev extra_data_buffer) {
[email protected]3b274b42012-10-26 20:41:26758 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
759
760 cdm::Status status = cdm::kSessionError;
761 if (cdm_) {
762 cdm::VideoDecoderConfig cdm_decoder_config;
763 cdm_decoder_config.codec =
764 PpVideoCodecToCdmVideoCodec(decoder_config.codec);
765 cdm_decoder_config.profile =
766 PpVCProfileToCdmVCProfile(decoder_config.profile);
767 cdm_decoder_config.format =
768 PpDecryptedFrameFormatToCdmVideoFormat(decoder_config.format);
769 cdm_decoder_config.coded_size.width = decoder_config.width;
770 cdm_decoder_config.coded_size.height = decoder_config.height;
771 cdm_decoder_config.extra_data =
772 static_cast<uint8_t*>(extra_data_buffer.data());
773 cdm_decoder_config.extra_data_size =
774 static_cast<int32_t>(extra_data_buffer.size());
775 status = cdm_->InitializeVideoDecoder(cdm_decoder_config);
776 }
[email protected]e9d3a1022012-10-11 23:43:55777
778 CallOnMain(callback_factory_.NewCallback(
[email protected]c999b3b72012-10-19 22:33:46779 &CdmWrapper::DecoderInitializeDone,
780 PP_DECRYPTORSTREAMTYPE_VIDEO,
781 decoder_config.request_id,
782 status == cdm::kSuccess));
[email protected]e9d3a1022012-10-11 23:43:55783}
784
[email protected]23de87452012-10-12 07:03:09785void CdmWrapper::DeinitializeDecoder(PP_DecryptorStreamType decoder_type,
786 uint32_t request_id) {
[email protected]3b274b42012-10-26 20:41:26787 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
788 if (cdm_) {
789 cdm_->DeinitializeDecoder(
790 PpDecryptorStreamTypeToCdmStreamType(decoder_type));
791 }
792
[email protected]23de87452012-10-12 07:03:09793 CallOnMain(callback_factory_.NewCallback(
794 &CdmWrapper::DecoderDeinitializeDone,
795 decoder_type,
796 request_id));
797}
798
799void CdmWrapper::ResetDecoder(PP_DecryptorStreamType decoder_type,
800 uint32_t request_id) {
[email protected]3b274b42012-10-26 20:41:26801 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
802 if (cdm_)
803 cdm_->ResetDecoder(PpDecryptorStreamTypeToCdmStreamType(decoder_type));
804
[email protected]23de87452012-10-12 07:03:09805 CallOnMain(callback_factory_.NewCallback(&CdmWrapper::DecoderResetDone,
806 decoder_type,
807 request_id));
808}
809
[email protected]467434d2012-10-12 10:48:53810void CdmWrapper::DecryptAndDecode(
811 PP_DecryptorStreamType decoder_type,
812 pp::Buffer_Dev encrypted_buffer,
813 const PP_EncryptedBlockInfo& encrypted_block_info) {
[email protected]3b274b42012-10-26 20:41:26814 PP_DCHECK(cdm_); // GenerateKeyRequest() should have succeeded.
[email protected]181d9c12012-10-03 22:53:48815
[email protected]ce19e7b52012-12-05 19:47:24816 // Release a buffer that the caller indicated it is finished with.
817 allocator_.Release(encrypted_block_info.tracking_info.buffer_id);
818
[email protected]181d9c12012-10-03 22:53:48819 cdm::InputBuffer input_buffer;
820 std::vector<cdm::SubsampleEntry> subsamples;
[email protected]3b274b42012-10-26 20:41:26821 if (cdm_ && !encrypted_buffer.is_null()) {
[email protected]741c28f2012-10-18 07:02:25822 ConfigureInputBuffer(encrypted_buffer,
823 encrypted_block_info,
824 &subsamples,
825 &input_buffer);
826 }
[email protected]181d9c12012-10-03 22:53:48827
[email protected]ecbb97682012-10-24 22:33:54828 cdm::Status status = cdm::kDecodeError;
[email protected]3b274b42012-10-26 20:41:26829
[email protected]ecbb97682012-10-24 22:33:54830 switch (decoder_type) {
831 case PP_DECRYPTORSTREAMTYPE_VIDEO: {
832 LinkedVideoFrame video_frame(new VideoFrameImpl());
[email protected]3b274b42012-10-26 20:41:26833 if (cdm_)
834 status = cdm_->DecryptAndDecodeFrame(input_buffer, video_frame.get());
[email protected]ecbb97682012-10-24 22:33:54835 CallOnMain(callback_factory_.NewCallback(
836 &CdmWrapper::DeliverFrame,
837 status,
838 video_frame,
839 encrypted_block_info.tracking_info));
840 return;
841 }
842
843 case PP_DECRYPTORSTREAMTYPE_AUDIO: {
844 LinkedAudioFrames audio_frames(new AudioFramesImpl());
[email protected]3b274b42012-10-26 20:41:26845 if (cdm_) {
846 status = cdm_->DecryptAndDecodeSamples(input_buffer,
847 audio_frames.get());
848 }
[email protected]ecbb97682012-10-24 22:33:54849 CallOnMain(callback_factory_.NewCallback(
850 &CdmWrapper::DeliverSamples,
851 status,
852 audio_frames,
853 encrypted_block_info.tracking_info));
854 return;
855 }
856
857 default:
858 PP_NOTREACHED();
859 return;
860 }
[email protected]d341e332012-08-28 18:57:40861}
862
[email protected]f75555a2012-12-10 22:35:24863void CdmWrapper::SetTimer(int64_t delay_ms, void* context) {
[email protected]f5c9b938e2012-10-10 12:24:07864 // NOTE: doesn't really need to run on the main thread; could just as well run
865 // on a helper thread if |cdm_| were thread-friendly and care was taken. We
866 // only use CallOnMainThread() here to get delayed-execution behavior.
867 pp::Module::Get()->core()->CallOnMainThread(
868 delay_ms,
[email protected]f75555a2012-12-10 22:35:24869 callback_factory_.NewCallback(&CdmWrapper::TimerExpired, context),
[email protected]f5c9b938e2012-10-10 12:24:07870 PP_OK);
871}
872
[email protected]f75555a2012-12-10 22:35:24873void CdmWrapper::TimerExpired(int32_t result, void* context) {
[email protected]f5c9b938e2012-10-10 12:24:07874 PP_DCHECK(result == PP_OK);
[email protected]f75555a2012-12-10 22:35:24875 cdm_->TimerExpired(context);
[email protected]f5c9b938e2012-10-10 12:24:07876}
877
[email protected]cc3c56b2012-11-01 17:35:32878double CdmWrapper::GetCurrentWallTimeInSeconds() {
[email protected]f5c9b938e2012-10-10 12:24:07879 return pp::Module::Get()->core()->GetTime();
880}
881
[email protected]f75555a2012-12-10 22:35:24882void CdmWrapper::SendKeyMessage(
883 const char* session_id, int32_t session_id_length,
884 const char* message, int32_t message_length,
885 const char* default_url, int32_t default_url_length) {
[email protected]6cb006c2013-01-10 21:39:18886 PP_DCHECK(!key_system_.empty());
[email protected]8f1be472012-12-15 19:06:33887 PostOnMain(callback_factory_.NewCallback(
[email protected]f75555a2012-12-10 22:35:24888 &CdmWrapper::KeyMessage,
[email protected]6cb006c2013-01-10 21:39:18889 SessionInfo(key_system_,
890 std::string(session_id, session_id_length)),
[email protected]f75555a2012-12-10 22:35:24891 std::string(message, message_length),
892 std::string(default_url, default_url_length)));
893}
894
895void CdmWrapper::SendKeyError(const char* session_id,
896 int32_t session_id_length,
897 cdm::MediaKeyError error_code,
898 uint32_t system_code) {
[email protected]6cb006c2013-01-10 21:39:18899 SendKeyErrorInternal(key_system_,
900 std::string(session_id, session_id_length),
901 error_code,
902 system_code);
903}
904
905void CdmWrapper::SendUnknownKeyError(const std::string& key_system,
906 const std::string& session_id) {
907 SendKeyErrorInternal(key_system, session_id, cdm::kUnknownError, 0);
908}
909
910
911void CdmWrapper::SendKeyAdded(const std::string& key_system,
912 const std::string& session_id) {
[email protected]8f1be472012-12-15 19:06:33913 PostOnMain(callback_factory_.NewCallback(
[email protected]6cb006c2013-01-10 21:39:18914 &CdmWrapper::KeyAdded,
915 SessionInfo(key_system_, session_id)));
[email protected]f75555a2012-12-10 22:35:24916}
917
[email protected]6cb006c2013-01-10 21:39:18918void CdmWrapper::SendKeyErrorInternal(const std::string& key_system,
919 const std::string& session_id,
920 cdm::MediaKeyError error_code,
921 uint32_t system_code) {
922 PP_DCHECK(!key_system.empty());
923 PostOnMain(callback_factory_.NewCallback(&CdmWrapper::KeyError,
924 SessionInfo(key_system_, session_id),
925 error_code,
926 system_code));
[email protected]8f1be472012-12-15 19:06:33927}
928
[email protected]6cb006c2013-01-10 21:39:18929void CdmWrapper::KeyAdded(int32_t result, const SessionInfo& session_info) {
[email protected]f5c9b938e2012-10-10 12:24:07930 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:18931 PP_DCHECK(!session_info.key_system.empty());
932 pp::ContentDecryptor_Private::KeyAdded(session_info.key_system,
933 session_info.session_id);
[email protected]e5aeef02012-08-17 00:18:43934}
935
[email protected]d341e332012-08-28 18:57:40936void CdmWrapper::KeyMessage(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18937 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:24938 const std::string& message,
939 const std::string& default_url) {
[email protected]f5c9b938e2012-10-10 12:24:07940 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:18941 PP_DCHECK(!session_info.key_system.empty());
[email protected]6d613d62012-12-04 23:39:00942
[email protected]a6e4fbf2012-12-12 05:25:00943 pp::VarArrayBuffer message_array_buffer(message.size());
944 if (message.size() > 0) {
945 memcpy(message_array_buffer.Map(), message.data(), message.size());
[email protected]6d613d62012-12-04 23:39:00946 }
947
[email protected]d341e332012-08-28 18:57:40948 pp::ContentDecryptor_Private::KeyMessage(
[email protected]6cb006c2013-01-10 21:39:18949 session_info.key_system, session_info.session_id,
950 message_array_buffer, default_url);
[email protected]e5aeef02012-08-17 00:18:43951}
952
[email protected]f75555a2012-12-10 22:35:24953void CdmWrapper::KeyError(int32_t result,
[email protected]6cb006c2013-01-10 21:39:18954 const SessionInfo& session_info,
[email protected]f75555a2012-12-10 22:35:24955 cdm::MediaKeyError error_code,
956 uint32_t system_code) {
[email protected]f5c9b938e2012-10-10 12:24:07957 PP_DCHECK(result == PP_OK);
[email protected]6cb006c2013-01-10 21:39:18958 PP_DCHECK(!session_info.key_system.empty());
[email protected]f75555a2012-12-10 22:35:24959 pp::ContentDecryptor_Private::KeyError(
[email protected]6cb006c2013-01-10 21:39:18960 session_info.key_system, session_info.session_id,
961 error_code, system_code);
[email protected]e5aeef02012-08-17 00:18:43962}
963
[email protected]d341e332012-08-28 18:57:40964void CdmWrapper::DeliverBlock(int32_t result,
965 const cdm::Status& status,
[email protected]7ed56ed2012-10-02 02:43:27966 const LinkedDecryptedBlock& decrypted_block,
[email protected]d341e332012-08-28 18:57:40967 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:07968 PP_DCHECK(result == PP_OK);
[email protected]d341e332012-08-28 18:57:40969 PP_DecryptedBlockInfo decrypted_block_info;
[email protected]181d9c12012-10-03 22:53:48970 decrypted_block_info.tracking_info = tracking_info;
[email protected]f75555a2012-12-10 22:35:24971 decrypted_block_info.tracking_info.timestamp = decrypted_block->Timestamp();
[email protected]ce19e7b52012-12-05 19:47:24972 decrypted_block_info.tracking_info.buffer_id = 0;
973 decrypted_block_info.data_size = 0;
[email protected]8f5a9a52012-10-23 20:49:20974 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
[email protected]d341e332012-08-28 18:57:40975
[email protected]8f5a9a52012-10-23 20:49:20976 pp::Buffer_Dev buffer;
977
978 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]f75555a2012-12-10 22:35:24979 PP_DCHECK(decrypted_block.get() && decrypted_block->DecryptedBuffer());
980 if (!decrypted_block.get() || !decrypted_block->DecryptedBuffer()) {
[email protected]ecbb97682012-10-24 22:33:54981 PP_NOTREACHED();
[email protected]d341e332012-08-28 18:57:40982 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
[email protected]8f5a9a52012-10-23 20:49:20983 } else {
[email protected]ce19e7b52012-12-05 19:47:24984 PpbBuffer* ppb_buffer =
[email protected]f75555a2012-12-10 22:35:24985 static_cast<PpbBuffer*>(decrypted_block->DecryptedBuffer());
[email protected]ce19e7b52012-12-05 19:47:24986 buffer = ppb_buffer->buffer_dev();
987 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
[email protected]f75555a2012-12-10 22:35:24988 decrypted_block_info.data_size = ppb_buffer->Size();
[email protected]8f5a9a52012-10-23 20:49:20989 }
[email protected]d341e332012-08-28 18:57:40990 }
991
[email protected]4bc37112012-09-21 19:49:25992 pp::ContentDecryptor_Private::DeliverBlock(buffer, decrypted_block_info);
[email protected]e5aeef02012-08-17 00:18:43993}
994
[email protected]c999b3b72012-10-19 22:33:46995void CdmWrapper::DecoderInitializeDone(int32_t result,
996 PP_DecryptorStreamType decoder_type,
997 uint32_t request_id,
998 bool success) {
999 PP_DCHECK(result == PP_OK);
1000 pp::ContentDecryptor_Private::DecoderInitializeDone(decoder_type,
1001 request_id,
1002 success);
[email protected]e9d3a1022012-10-11 23:43:551003}
1004
[email protected]23de87452012-10-12 07:03:091005void CdmWrapper::DecoderDeinitializeDone(int32_t result,
1006 PP_DecryptorStreamType decoder_type,
1007 uint32_t request_id) {
1008 pp::ContentDecryptor_Private::DecoderDeinitializeDone(decoder_type,
1009 request_id);
1010}
1011
1012void CdmWrapper::DecoderResetDone(int32_t result,
1013 PP_DecryptorStreamType decoder_type,
1014 uint32_t request_id) {
1015 pp::ContentDecryptor_Private::DecoderResetDone(decoder_type, request_id);
1016}
1017
[email protected]181d9c12012-10-03 22:53:481018void CdmWrapper::DeliverFrame(
1019 int32_t result,
1020 const cdm::Status& status,
1021 const LinkedVideoFrame& video_frame,
1022 const PP_DecryptTrackingInfo& tracking_info) {
[email protected]f5c9b938e2012-10-10 12:24:071023 PP_DCHECK(result == PP_OK);
[email protected]181d9c12012-10-03 22:53:481024 PP_DecryptedFrameInfo decrypted_frame_info;
[email protected]749576ff2012-10-30 05:10:481025 decrypted_frame_info.tracking_info.request_id = tracking_info.request_id;
[email protected]ce19e7b52012-12-05 19:47:241026 decrypted_frame_info.tracking_info.buffer_id = 0;
[email protected]8f5a9a52012-10-23 20:49:201027 decrypted_frame_info.result = CdmStatusToPpDecryptResult(status);
[email protected]181d9c12012-10-03 22:53:481028
[email protected]8f5a9a52012-10-23 20:49:201029 pp::Buffer_Dev buffer;
[email protected]741c28f2012-10-18 07:02:251030
[email protected]8f5a9a52012-10-23 20:49:201031 if (decrypted_frame_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]ce19e7b52012-12-05 19:47:241032 if (!IsValidVideoFrame(video_frame)) {
[email protected]ecbb97682012-10-24 22:33:541033 PP_NOTREACHED();
[email protected]8f5a9a52012-10-23 20:49:201034 decrypted_frame_info.result = PP_DECRYPTRESULT_DECODE_ERROR;
1035 } else {
[email protected]ce19e7b52012-12-05 19:47:241036 PpbBuffer* ppb_buffer =
[email protected]f75555a2012-12-10 22:35:241037 static_cast<PpbBuffer*>(video_frame->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:241038
1039 buffer = ppb_buffer->buffer_dev();
1040
[email protected]f75555a2012-12-10 22:35:241041 decrypted_frame_info.tracking_info.timestamp = video_frame->Timestamp();
[email protected]ce19e7b52012-12-05 19:47:241042 decrypted_frame_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
1043 decrypted_frame_info.format =
[email protected]f75555a2012-12-10 22:35:241044 CdmVideoFormatToPpDecryptedFrameFormat(video_frame->Format());
1045 decrypted_frame_info.width = video_frame->Size().width;
1046 decrypted_frame_info.height = video_frame->Size().height;
[email protected]181d9c12012-10-03 22:53:481047 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]f75555a2012-12-10 22:35:241048 video_frame->PlaneOffset(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:481049 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]f75555a2012-12-10 22:35:241050 video_frame->PlaneOffset(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:481051 decrypted_frame_info.plane_offsets[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]f75555a2012-12-10 22:35:241052 video_frame->PlaneOffset(cdm::VideoFrame::kVPlane);
[email protected]181d9c12012-10-03 22:53:481053 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_Y] =
[email protected]f75555a2012-12-10 22:35:241054 video_frame->Stride(cdm::VideoFrame::kYPlane);
[email protected]181d9c12012-10-03 22:53:481055 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_U] =
[email protected]f75555a2012-12-10 22:35:241056 video_frame->Stride(cdm::VideoFrame::kUPlane);
[email protected]181d9c12012-10-03 22:53:481057 decrypted_frame_info.strides[PP_DECRYPTEDFRAMEPLANES_V] =
[email protected]f75555a2012-12-10 22:35:241058 video_frame->Stride(cdm::VideoFrame::kVPlane);
[email protected]8f5a9a52012-10-23 20:49:201059 }
[email protected]181d9c12012-10-03 22:53:481060 }
[email protected]181d9c12012-10-03 22:53:481061 pp::ContentDecryptor_Private::DeliverFrame(buffer, decrypted_frame_info);
1062}
1063
[email protected]ecbb97682012-10-24 22:33:541064void CdmWrapper::DeliverSamples(int32_t result,
1065 const cdm::Status& status,
1066 const LinkedAudioFrames& audio_frames,
1067 const PP_DecryptTrackingInfo& tracking_info) {
1068 PP_DCHECK(result == PP_OK);
[email protected]749576ff2012-10-30 05:10:481069
[email protected]ecbb97682012-10-24 22:33:541070 PP_DecryptedBlockInfo decrypted_block_info;
1071 decrypted_block_info.tracking_info = tracking_info;
[email protected]ecbb97682012-10-24 22:33:541072 decrypted_block_info.tracking_info.timestamp = 0;
[email protected]ce19e7b52012-12-05 19:47:241073 decrypted_block_info.tracking_info.buffer_id = 0;
1074 decrypted_block_info.data_size = 0;
[email protected]ecbb97682012-10-24 22:33:541075 decrypted_block_info.result = CdmStatusToPpDecryptResult(status);
1076
1077 pp::Buffer_Dev buffer;
1078
1079 if (decrypted_block_info.result == PP_DECRYPTRESULT_SUCCESS) {
[email protected]f75555a2012-12-10 22:35:241080 PP_DCHECK(audio_frames.get() && audio_frames->FrameBuffer());
1081 if (!audio_frames.get() || !audio_frames->FrameBuffer()) {
[email protected]ecbb97682012-10-24 22:33:541082 PP_NOTREACHED();
1083 decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_ERROR;
1084 } else {
[email protected]f75555a2012-12-10 22:35:241085 PpbBuffer* ppb_buffer =
1086 static_cast<PpbBuffer*>(audio_frames->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:241087 buffer = ppb_buffer->buffer_dev();
1088 decrypted_block_info.tracking_info.buffer_id = ppb_buffer->buffer_id();
[email protected]f75555a2012-12-10 22:35:241089 decrypted_block_info.data_size = ppb_buffer->Size();
[email protected]ecbb97682012-10-24 22:33:541090 }
1091 }
1092
1093 pp::ContentDecryptor_Private::DeliverSamples(buffer, decrypted_block_info);
1094}
[email protected]181d9c12012-10-03 22:53:481095
[email protected]ce19e7b52012-12-05 19:47:241096bool CdmWrapper::IsValidVideoFrame(const LinkedVideoFrame& video_frame) {
1097 if (!video_frame.get() ||
[email protected]f75555a2012-12-10 22:35:241098 !video_frame->FrameBuffer() ||
1099 (video_frame->Format() != cdm::kI420 &&
1100 video_frame->Format() != cdm::kYv12)) {
[email protected]ce19e7b52012-12-05 19:47:241101 return false;
1102 }
1103
[email protected]f75555a2012-12-10 22:35:241104 PpbBuffer* ppb_buffer = static_cast<PpbBuffer*>(video_frame->FrameBuffer());
[email protected]ce19e7b52012-12-05 19:47:241105
1106 for (int i = 0; i < cdm::VideoFrame::kMaxPlanes; ++i) {
1107 int plane_height = (i == cdm::VideoFrame::kYPlane) ?
[email protected]f75555a2012-12-10 22:35:241108 video_frame->Size().height : (video_frame->Size().height + 1) / 2;
[email protected]ce19e7b52012-12-05 19:47:241109 cdm::VideoFrame::VideoPlane plane =
1110 static_cast<cdm::VideoFrame::VideoPlane>(i);
[email protected]f75555a2012-12-10 22:35:241111 if (ppb_buffer->Size() < video_frame->PlaneOffset(plane) +
1112 plane_height * video_frame->Stride(plane)) {
[email protected]ce19e7b52012-12-05 19:47:241113 return false;
1114 }
1115 }
1116
1117 return true;
1118}
1119
[email protected]e5aeef02012-08-17 00:18:431120// This object is the global object representing this plugin library as long
1121// as it is loaded.
[email protected]9264e1502012-09-18 19:53:011122class CdmWrapperModule : public pp::Module {
[email protected]e5aeef02012-08-17 00:18:431123 public:
[email protected]a9c788e2012-10-26 23:54:551124 CdmWrapperModule() : pp::Module() {
1125 // This function blocks the renderer thread (PluginInstance::Initialize()).
1126 // Move this call to other places if this may be a concern in the future.
1127 INITIALIZE_CDM_MODULE();
1128 }
1129 virtual ~CdmWrapperModule() {
[email protected]f75555a2012-12-10 22:35:241130 DeinitializeCdmModule();
[email protected]a9c788e2012-10-26 23:54:551131 }
[email protected]e5aeef02012-08-17 00:18:431132
1133 virtual pp::Instance* CreateInstance(PP_Instance instance) {
[email protected]d341e332012-08-28 18:57:401134 return new CdmWrapper(instance, this);
[email protected]e5aeef02012-08-17 00:18:431135 }
1136};
1137
[email protected]d341e332012-08-28 18:57:401138} // namespace webkit_media
1139
[email protected]e5aeef02012-08-17 00:18:431140namespace pp {
1141
1142// Factory function for your specialization of the Module object.
1143Module* CreateModule() {
[email protected]9264e1502012-09-18 19:53:011144 return new webkit_media::CdmWrapperModule();
[email protected]e5aeef02012-08-17 00:18:431145}
1146
1147} // namespace pp