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

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: remove unused header 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
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
287 } 300 }
288 301
289 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
290 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 310 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
291 if (decoder_type == cdm::kStreamTypeVideo) 311 if (decoder_type == cdm::kStreamTypeVideo)
292 video_decoder_->Reset(); 312 video_decoder_->Reset();
293 #endif 313 #endif
294 } 314 }
295 315
296 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
297 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 324 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
298 if (decoder_type == cdm::kStreamTypeVideo) 325 if (decoder_type == cdm::kStreamTypeVideo)
299 video_decoder_->Deinitialize(); 326 video_decoder_->Deinitialize();
300 #endif 327 #endif
301 } 328 }
302 329
303 cdm::Status ClearKeyCdm::DecryptAndDecodeFrame( 330 cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
304 const cdm::InputBuffer& encrypted_buffer, 331 const cdm::InputBuffer& encrypted_buffer,
305 cdm::VideoFrame* decoded_frame) { 332 cdm::VideoFrame* decoded_frame) {
306 DVLOG(1) << "DecryptAndDecodeFrame()"; 333 DVLOG(1) << "DecryptAndDecodeFrame()";
(...skipping 18 matching lines...) Expand all
325 return cdm::kNeedMoreData; 352 return cdm::kNeedMoreData;
326 353
327 GenerateFakeVideoFrame(buffer->GetTimestamp(), decoded_frame); 354 GenerateFakeVideoFrame(buffer->GetTimestamp(), decoded_frame);
328 return cdm::kSuccess; 355 return cdm::kSuccess;
329 #else 356 #else
330 NOTIMPLEMENTED(); 357 NOTIMPLEMENTED();
331 return cdm::kDecodeError; 358 return cdm::kDecodeError;
332 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 359 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
333 } 360 }
334 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());
ddorwin 2012/10/24 17:59:27 Will this DCHECK if you get EOS buffer in the firs
xhwang 2012/10/24 19:45:57 If the first frame is EOS, then last_duration_ sho
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;
ddorwin 2012/10/24 17:59:27 Should last_duration remain infinite?
xhwang 2012/10/24 19:45:57 I would say yes. We don't have any valid duration
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
335 cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer( 409 cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
336 const cdm::InputBuffer& encrypted_buffer, 410 const cdm::InputBuffer& encrypted_buffer,
337 scoped_refptr<media::DecoderBuffer>* decrypted_buffer) { 411 scoped_refptr<media::DecoderBuffer>* decrypted_buffer) {
338 DCHECK(decrypted_buffer); 412 DCHECK(decrypted_buffer);
339 scoped_refptr<media::DecoderBuffer> buffer = 413 scoped_refptr<media::DecoderBuffer> buffer =
340 CopyDecoderBufferFrom(encrypted_buffer); 414 CopyDecoderBufferFrom(encrypted_buffer);
341 415
342 if (buffer->IsEndOfStream()) { 416 if (buffer->IsEndOfStream()) {
343 *decrypted_buffer = buffer; 417 *decrypted_buffer = buffer;
344 return cdm::kSuccess; 418 return cdm::kSuccess;
(...skipping 11 matching lines...) Expand all
356 if (status == media::Decryptor::kError) 430 if (status == media::Decryptor::kError)
357 return cdm::kDecryptError; 431 return cdm::kDecryptError;
358 432
359 if (status == media::Decryptor::kNoKey) 433 if (status == media::Decryptor::kNoKey)
360 return cdm::kNoKey; 434 return cdm::kNoKey;
361 435
362 DCHECK_EQ(status, media::Decryptor::kSuccess); 436 DCHECK_EQ(status, media::Decryptor::kSuccess);
363 return cdm::kSuccess; 437 return cdm::kSuccess;
364 } 438 }
365 439
440 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
441 void ClearKeyCdm::GenerateFakeAudioFrames(cdm::AudioFrames* audio_frames) {
ddorwin 2012/10/24 17:59:27 // Generates one channel of audio.?
xhwang 2012/10/24 19:45:57 Not sure about "one channel of audio". But updated
442 DCHECK(last_duration_ != media::kInfiniteDuration());
443 int64 duration_in_microseconds = last_duration_.InMicroseconds();
444 DCHECK_GT(duration_in_microseconds, 0);
445
446 int64 timestamp = last_timestamp_.InMicroseconds();
447 int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8;
448 int64 frame_size = bytes_per_sample * samples_per_second_ *
449 duration_in_microseconds / base::Time::kMicrosecondsPerSecond;
450
451 const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size);
452 audio_frames->set_buffer(allocator_->Allocate(kHeaderSize + frame_size));
453 int64* data = reinterpret_cast<int64*>(audio_frames->buffer()->data());
454 *(data++) = timestamp;
455 *(data++) = frame_size;
456 // You won't hear anything because we have all zeros here. But the video
457 // should play just fine!
458 memset(data, 0, frame_size);
459 }
460 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
461
366 #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER) 462 #if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
367 void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp, 463 void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp,
368 cdm::VideoFrame* video_frame) { 464 cdm::VideoFrame* video_frame) {
369 // Choose non-zero alignment and padding on purpose for testing. 465 // Choose non-zero alignment and padding on purpose for testing.
370 const int kAlignment = 8; 466 const int kAlignment = 8;
371 const int kPadding = 16; 467 const int kPadding = 16;
372 const int kPlanePadding = 128; 468 const int kPlanePadding = 128;
373 469
374 int width = video_size_.width; 470 int width = video_size_.width;
375 int height = video_size_.height; 471 int height = video_size_.height;
(...skipping 22 matching lines...) Expand all
398 video_frame->set_timestamp(timestamp.InMicroseconds()); 494 video_frame->set_timestamp(timestamp.InMicroseconds());
399 495
400 static unsigned char color = 0; 496 static unsigned char color = 0;
401 color += 10; 497 color += 10;
402 498
403 memset(reinterpret_cast<void*>(video_frame->frame_buffer()->data()), 499 memset(reinterpret_cast<void*>(video_frame->frame_buffer()->data()),
404 color, frame_size); 500 color, frame_size);
405 } 501 }
406 #endif // CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER 502 #endif // CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER
407 503
408 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples(
409 const cdm::InputBuffer& encrypted_buffer,
410 cdm::AudioFrames* audio_frames) {
411 NOTIMPLEMENTED();
412 return cdm::kDecryptError;
413 }
414
415 } // namespace webkit_media 504 } // namespace webkit_media
OLDNEW
« webkit/media/crypto/ppapi/clear_key_cdm.h ('K') | « 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