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

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

Issue 11242005: Fake clear key CDM audio decoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/media/crypto/ppapi/clear_key_cdm.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/media/crypto/ppapi/clear_key_cdm.h" 5 #include "webkit/media/crypto/ppapi/clear_key_cdm.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/time.h" 11 #include "base/time.h"
12 #include "media/base/buffers.h"
12 #include "media/base/decoder_buffer.h" 13 #include "media/base/decoder_buffer.h"
13 14
14 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 15 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
15 #include "base/at_exit.h" 16 #include "base/at_exit.h"
16 #include "base/file_path.h" 17 #include "base/file_path.h"
17 #include "base/path_service.h" 18 #include "base/path_service.h"
18 #include "media/base/media.h" 19 #include "media/base/media.h"
19 #include "webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h" 20 #include "webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
20 21
21 // TODO(tomfinegan): When COMPONENT_BUILD is not defined an AtExitManager must 22 // TODO(tomfinegan): When COMPONENT_BUILD is not defined an AtExitManager must
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 output_buffer->SetTimestamp( 75 output_buffer->SetTimestamp(
75 base::TimeDelta::FromMicroseconds(input_buffer.timestamp)); 76 base::TimeDelta::FromMicroseconds(input_buffer.timestamp));
76 77
77 return output_buffer; 78 return output_buffer;
78 } 79 }
79 80
80 template<typename Type> 81 template<typename Type>
81 class ScopedResetter { 82 class ScopedResetter {
82 public: 83 public:
83 explicit ScopedResetter(Type* object) : object_(object) {} 84 explicit ScopedResetter(Type* object) : object_(object) {}
84 ~ScopedResetter() { 85 ~ScopedResetter() { object_->Reset(); }
85 object_->Reset();
86 }
87 86
88 private: 87 private:
89 Type* const object_; 88 Type* const object_;
90 }; 89 };
91 90
92 template<typename Type> 91 template<typename Type>
93 static Type* AllocateAndCopy(const Type* data, int size) { 92 static Type* AllocateAndCopy(const Type* data, int size) {
94 COMPILE_ASSERT(sizeof(Type) == 1, type_size_is_not_one); 93 COMPILE_ASSERT(sizeof(Type) == 1, type_size_is_not_one);
95 Type* copy = new Type[size]; 94 Type* copy = new Type[size];
96 memcpy(copy, data, size); 95 memcpy(copy, data, size);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 const std::string& session_id, 154 const std::string& session_id,
156 scoped_array<uint8> init_data, 155 scoped_array<uint8> init_data,
157 int init_data_length) { 156 int init_data_length) {
158 // In the current implementation of AesDecryptor, NeedKey is not used. 157 // In the current implementation of AesDecryptor, NeedKey is not used.
159 // If no key is available to decrypt an input buffer, it returns kNoKey to 158 // If no key is available to decrypt an input buffer, it returns kNoKey to
160 // the caller instead of firing NeedKey. 159 // the caller instead of firing NeedKey.
161 NOTREACHED(); 160 NOTREACHED();
162 } 161 }
163 162
164 ClearKeyCdm::ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost*) 163 ClearKeyCdm::ClearKeyCdm(cdm::Allocator* allocator, cdm::CdmHost*)
165 : decryptor_(&client_), allocator_(allocator) { 164 : decryptor_(&client_),
165 allocator_(allocator) {
166 DCHECK(allocator_); 166 DCHECK(allocator_);
167 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
168 channel_count_ = 0;
169 bits_per_channel_ = 0;
170 samples_per_second_ = 0;
171 last_timestamp_ = media::kNoTimestamp();
172 last_duration_ = media::kInfiniteDuration();
173 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
167 } 174 }
168 175
169 ClearKeyCdm::~ClearKeyCdm() {} 176 ClearKeyCdm::~ClearKeyCdm() {}
170 177
171 cdm::Status ClearKeyCdm::GenerateKeyRequest(const uint8_t* init_data, 178 cdm::Status ClearKeyCdm::GenerateKeyRequest(const uint8_t* init_data,
172 int init_data_size, 179 int init_data_size,
173 cdm::KeyMessage* key_request) { 180 cdm::KeyMessage* key_request) {
174 DVLOG(1) << "GenerateKeyRequest()"; 181 DVLOG(1) << "GenerateKeyRequest()";
175 base::AutoLock auto_lock(client_lock_); 182 base::AutoLock auto_lock(client_lock_);
176 ScopedResetter<Client> auto_resetter(&client_); 183 ScopedResetter<Client> auto_resetter(&client_);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 memcpy(reinterpret_cast<void*>(decrypted_block->buffer()->data()), 262 memcpy(reinterpret_cast<void*>(decrypted_block->buffer()->data()),
256 buffer->GetData(), 263 buffer->GetData(),
257 buffer->GetDataSize()); 264 buffer->GetDataSize());
258 decrypted_block->set_timestamp(buffer->GetTimestamp().InMicroseconds()); 265 decrypted_block->set_timestamp(buffer->GetTimestamp().InMicroseconds());
259 266
260 return cdm::kSuccess; 267 return cdm::kSuccess;
261 } 268 }
262 269
263 cdm::Status ClearKeyCdm::InitializeAudioDecoder( 270 cdm::Status ClearKeyCdm::InitializeAudioDecoder(
264 const cdm::AudioDecoderConfig& audio_decoder_config) { 271 const cdm::AudioDecoderConfig& audio_decoder_config) {
272 #if !defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
265 NOTIMPLEMENTED(); 273 NOTIMPLEMENTED();
266 return cdm::kSessionError; 274 return cdm::kSessionError;
275 #else
276 channel_count_ = audio_decoder_config.channel_count;
277 bits_per_channel_ = audio_decoder_config.bits_per_channel;
278 samples_per_second_ = audio_decoder_config.samples_per_second;
279 return cdm::kSuccess;
280 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
267 } 281 }
268 282
269 cdm::Status ClearKeyCdm::InitializeVideoDecoder( 283 cdm::Status ClearKeyCdm::InitializeVideoDecoder(
270 const cdm::VideoDecoderConfig& video_decoder_config) { 284 const cdm::VideoDecoderConfig& video_decoder_config) {
271 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 285 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
272 if (!video_decoder_) 286 if (!video_decoder_)
273 video_decoder_.reset(new webkit_media::FFmpegCdmVideoDecoder(allocator_)); 287 video_decoder_.reset(new webkit_media::FFmpegCdmVideoDecoder(allocator_));
274 288
275 if (!video_decoder_->Initialize(video_decoder_config)) 289 if (!video_decoder_->Initialize(video_decoder_config))
276 return cdm::kSessionError; 290 return cdm::kSessionError;
277 291
278 return cdm::kSuccess; 292 return cdm::kSuccess;
279 #elif defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER) 293 #elif defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
280 video_size_ = video_decoder_config.coded_size; 294 video_size_ = video_decoder_config.coded_size;
281 return cdm::kSuccess; 295 return cdm::kSuccess;
282 #else 296 #else
283 NOTIMPLEMENTED(); 297 NOTIMPLEMENTED();
284 return cdm::kSessionError; 298 return cdm::kSessionError;
285 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 299 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
286 } 300 }
287 301
288 void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) { 302 void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) {
303 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
304 if (decoder_type == cdm::kStreamTypeAudio) {
305 last_timestamp_ = media::kNoTimestamp();
306 last_duration_ = media::kInfiniteDuration();
307 }
308 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
309
289 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 310 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
290 if (decoder_type == cdm::kStreamTypeVideo) 311 if (decoder_type == cdm::kStreamTypeVideo)
291 video_decoder_->Reset(); 312 video_decoder_->Reset();
292 #endif 313 #endif
293 } 314 }
294 315
295 void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) { 316 void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) {
317 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
318 if (decoder_type == cdm::kStreamTypeAudio) {
319 last_timestamp_ = media::kNoTimestamp();
320 last_duration_ = media::kInfiniteDuration();
321 }
322 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
323
296 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 324 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
297 if (decoder_type == cdm::kStreamTypeVideo) 325 if (decoder_type == cdm::kStreamTypeVideo)
298 video_decoder_->Deinitialize(); 326 video_decoder_->Deinitialize();
299 #endif 327 #endif
300 } 328 }
301 329
302 cdm::Status ClearKeyCdm::DecryptAndDecodeFrame( 330 cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
303 const cdm::InputBuffer& encrypted_buffer, 331 const cdm::InputBuffer& encrypted_buffer,
304 cdm::VideoFrame* decoded_frame) { 332 cdm::VideoFrame* decoded_frame) {
305 DVLOG(1) << "DecryptAndDecodeFrame()"; 333 DVLOG(1) << "DecryptAndDecodeFrame()";
(...skipping 18 matching lines...) Expand all
324 return cdm::kNeedMoreData; 352 return cdm::kNeedMoreData;
325 353
326 GenerateFakeVideoFrame(buffer->GetTimestamp(), decoded_frame); 354 GenerateFakeVideoFrame(buffer->GetTimestamp(), decoded_frame);
327 return cdm::kSuccess; 355 return cdm::kSuccess;
328 #else 356 #else
329 NOTIMPLEMENTED(); 357 NOTIMPLEMENTED();
330 return cdm::kDecodeError; 358 return cdm::kDecodeError;
331 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 359 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
332 } 360 }
333 361
362 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
363 const cdm::InputBuffer& encrypted_buffer,
364 cdm::AudioFrames* audio_frames) {
365 DVLOG(1) << "DecryptAndDecodeSamples()";
366
367 scoped_refptr<media::DecoderBuffer> buffer;
368 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);
369
370 if (status != cdm::kSuccess)
371 return status;
372
373 #if !defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
374 NOTIMPLEMENTED();
375 return cdm::kDecodeError;
376 #else
377 if (buffer->IsEndOfStream()) {
378 // Upon the first EOS frame, return a frame with |last_duration_|.
379 if (last_duration_ != media::kInfiniteDuration()) {
380 DCHECK(last_timestamp_ != media::kNoTimestamp());
381 GenerateFakeAudioFrames(audio_frames);
382 last_timestamp_ = media::kNoTimestamp();
383 last_duration_ = media::kInfiniteDuration();
384 return cdm::kSuccess;
385 }
386
387 last_timestamp_ = media::kNoTimestamp();
388 return cdm::kNeedMoreData;
389 }
390
391 base::TimeDelta cur_timestamp = buffer->GetTimestamp();
392 DCHECK(cur_timestamp != media::kNoTimestamp());
393
394 // Return kNeedMoreData for the first frame because duration is unknown.
395 if (last_timestamp_ == media::kNoTimestamp()) {
396 last_timestamp_ = cur_timestamp;
397 return cdm::kNeedMoreData;
398 }
399
400 DCHECK(cur_timestamp > last_timestamp_);
401 last_duration_ = cur_timestamp - last_timestamp_;
402 last_timestamp_ = cur_timestamp;
403
404 GenerateFakeAudioFrames(audio_frames);
405 return cdm::kSuccess;
406 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
407 }
408
334 cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer( 409 cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
335 const cdm::InputBuffer& encrypted_buffer, 410 const cdm::InputBuffer& encrypted_buffer,
336 scoped_refptr<media::DecoderBuffer>* decrypted_buffer) { 411 scoped_refptr<media::DecoderBuffer>* decrypted_buffer) {
337 DCHECK(decrypted_buffer); 412 DCHECK(decrypted_buffer);
338 scoped_refptr<media::DecoderBuffer> buffer = 413 scoped_refptr<media::DecoderBuffer> buffer =
339 CopyDecoderBufferFrom(encrypted_buffer); 414 CopyDecoderBufferFrom(encrypted_buffer);
340 415
341 if (buffer->IsEndOfStream()) { 416 if (buffer->IsEndOfStream()) {
342 *decrypted_buffer = buffer; 417 *decrypted_buffer = buffer;
343 return cdm::kSuccess; 418 return cdm::kSuccess;
(...skipping 11 matching lines...) Expand all
355 if (status == media::Decryptor::kError) 430 if (status == media::Decryptor::kError)
356 return cdm::kDecryptError; 431 return cdm::kDecryptError;
357 432
358 if (status == media::Decryptor::kNoKey) 433 if (status == media::Decryptor::kNoKey)
359 return cdm::kNoKey; 434 return cdm::kNoKey;
360 435
361 DCHECK_EQ(status, media::Decryptor::kSuccess); 436 DCHECK_EQ(status, media::Decryptor::kSuccess);
362 return cdm::kSuccess; 437 return cdm::kSuccess;
363 } 438 }
364 439
440 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
441 void ClearKeyCdm::GenerateFakeAudioFrames(cdm::AudioFrames* audio_frames) {
442 // For now we only generate one audio frame for the whole duration.
443 // TODO(xhwang): Generate multiple audio frames for testing purposes.
444 DCHECK(last_duration_ != media::kInfiniteDuration());
445 int64 duration_in_microseconds = last_duration_.InMicroseconds();
446 DCHECK_GT(duration_in_microseconds, 0);
447
448 int64 timestamp = last_timestamp_.InMicroseconds();
449 int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8;
450 int64 frame_size = bytes_per_sample * samples_per_second_ *
451 duration_in_microseconds / base::Time::kMicrosecondsPerSecond;
452
453 const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
454 audio_frames->set_buffer(allocator_->Allocate(kHeaderSize + frame_size));
455 int64* data = reinterpret_cast<int64*>(audio_frames->buffer()->data());
456 *(data++) = timestamp;
457 *(data++) = frame_size;
458 // You won't hear anything because we have all zeros here. But the video
459 // should play just fine!
460 memset(data, 0, frame_size);
461 }
462 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
463
365 #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER) 464 #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
366 void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp, 465 void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp,
367 cdm::VideoFrame* video_frame) { 466 cdm::VideoFrame* video_frame) {
368 // Choose non-zero alignment and padding on purpose for testing. 467 // Choose non-zero alignment and padding on purpose for testing.
369 const int kAlignment = 8; 468 const int kAlignment = 8;
370 const int kPadding = 16; 469 const int kPadding = 16;
371 const int kPlanePadding = 128; 470 const int kPlanePadding = 128;
372 471
373 int width = video_size_.width; 472 int width = video_size_.width;
374 int height = video_size_.height; 473 int height = video_size_.height;
(...skipping 22 matching lines...) Expand all
397 video_frame->set_timestamp(timestamp.InMicroseconds()); 496 video_frame->set_timestamp(timestamp.InMicroseconds());
398 497
399 static unsigned char color = 0; 498 static unsigned char color = 0;
400 color += 10; 499 color += 10;
401 500
402 memset(reinterpret_cast<void*>(video_frame->frame_buffer()->data()), 501 memset(reinterpret_cast<void*>(video_frame->frame_buffer()->data()),
403 color, frame_size); 502 color, frame_size);
404 } 503 }
405 #endif // CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER 504 #endif // CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER
406 505
407 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
408 const cdm::InputBuffer& encrypted_buffer,
409 cdm::AudioFrames* audio_frames) {
410 NOTIMPLEMENTED();
411 return cdm::kDecryptError;
412 }
413
414 } // namespace webkit_media 506 } // namespace webkit_media
OLDNEW
« no previous file with comments | « webkit/media/crypto/ppapi/clear_key_cdm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698