| OLD | NEW |
| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 void INITIALIZE_CDM_MODULE() { | 118 void INITIALIZE_CDM_MODULE() { |
| 119 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 119 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
| 120 DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; | 120 DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; |
| 121 av_register_all(); | 121 av_register_all(); |
| 122 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 122 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
| 123 } | 123 } |
| 124 | 124 |
| 125 void DeinitializeCdmModule() { | 125 void DeinitializeCdmModule() { |
| 126 } | 126 } |
| 127 | 127 |
| 128 cdm::ContentDecryptionModule* CreateCdmInstance(const char* key_system_arg, | 128 void* CreateCdmInstance( |
| 129 int key_system_size, | 129 int cdm_interface_version, |
| 130 cdm::Allocator* allocator, | 130 const char* key_system, int key_system_size, |
| 131 cdm::Host* host) { | 131 GetCdmHostFunc get_cdm_host_func, void* user_data) { |
| 132 DVLOG(1) << "CreateCdmInstance()"; | 132 DVLOG(1) << "CreateCdmInstance()"; |
| 133 DCHECK_EQ(std::string(key_system_arg, key_system_size), kExternalClearKey); | |
| 134 return new webkit_media::ClearKeyCdm(allocator, host); | |
| 135 } | |
| 136 | 133 |
| 137 void DestroyCdmInstance(cdm::ContentDecryptionModule* instance) { | 134 if (cdm_interface_version != cdm::kCdmInterfaceVersion) |
| 138 DVLOG(1) << "DestroyCdmInstance()"; | 135 return NULL; |
| 139 delete instance; | 136 |
| 137 cdm::Host* host = reinterpret_cast<cdm::Host*>( |
| 138 get_cdm_host_func(cdm::kHostInterfaceVersion, user_data)); |
| 139 if (!host) |
| 140 return NULL; |
| 141 |
| 142 return new webkit_media::ClearKeyCdm(host); |
| 140 } | 143 } |
| 141 | 144 |
| 142 const char* GetCdmVersion() { | 145 const char* GetCdmVersion() { |
| 143 return kClearKeyCdmVersion; | 146 return kClearKeyCdmVersion; |
| 144 } | 147 } |
| 145 | 148 |
| 146 namespace webkit_media { | 149 namespace webkit_media { |
| 147 | 150 |
| 148 ClearKeyCdm::Client::Client() : status_(kKeyError) {} | 151 ClearKeyCdm::Client::Client() : status_(kKeyError) {} |
| 149 | 152 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 const std::string& session_id, | 187 const std::string& session_id, |
| 185 const std::string& type, | 188 const std::string& type, |
| 186 scoped_array<uint8> init_data, | 189 scoped_array<uint8> init_data, |
| 187 int init_data_length) { | 190 int init_data_length) { |
| 188 // In the current implementation of AesDecryptor, NeedKey is not used. | 191 // In the current implementation of AesDecryptor, NeedKey is not used. |
| 189 // If no key is available to decrypt an input buffer, it returns kNoKey to | 192 // If no key is available to decrypt an input buffer, it returns kNoKey to |
| 190 // the caller instead of firing NeedKey. | 193 // the caller instead of firing NeedKey. |
| 191 NOTREACHED(); | 194 NOTREACHED(); |
| 192 } | 195 } |
| 193 | 196 |
| 194 ClearKeyCdm::ClearKeyCdm(cdm::Allocator* allocator, cdm::Host* host) | 197 ClearKeyCdm::ClearKeyCdm(cdm::Host* host) |
| 195 : decryptor_(base::Bind(&Client::KeyAdded, base::Unretained(&client_)), | 198 : decryptor_(base::Bind(&Client::KeyAdded, base::Unretained(&client_)), |
| 196 base::Bind(&Client::KeyError, base::Unretained(&client_)), | 199 base::Bind(&Client::KeyError, base::Unretained(&client_)), |
| 197 base::Bind(&Client::KeyMessage, base::Unretained(&client_)), | 200 base::Bind(&Client::KeyMessage, base::Unretained(&client_)), |
| 198 base::Bind(&Client::NeedKey, base::Unretained(&client_))), | 201 base::Bind(&Client::NeedKey, base::Unretained(&client_))), |
| 199 allocator_(allocator), | |
| 200 host_(host), | 202 host_(host), |
| 201 timer_delay_ms_(kInitialTimerDelayMs), | 203 timer_delay_ms_(kInitialTimerDelayMs), |
| 202 timer_set_(false) { | 204 timer_set_(false) { |
| 203 DCHECK(allocator_); | |
| 204 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 205 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
| 205 channel_count_ = 0; | 206 channel_count_ = 0; |
| 206 bits_per_channel_ = 0; | 207 bits_per_channel_ = 0; |
| 207 samples_per_second_ = 0; | 208 samples_per_second_ = 0; |
| 208 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 209 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
| 209 total_samples_generated_ = 0; | 210 total_samples_generated_ = 0; |
| 210 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 211 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
| 211 } | 212 } |
| 212 | 213 |
| 213 ClearKeyCdm::~ClearKeyCdm() {} | 214 ClearKeyCdm::~ClearKeyCdm() {} |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 DCHECK(encrypted_buffer.data); | 308 DCHECK(encrypted_buffer.data); |
| 308 | 309 |
| 309 scoped_refptr<media::DecoderBuffer> buffer; | 310 scoped_refptr<media::DecoderBuffer> buffer; |
| 310 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); | 311 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); |
| 311 | 312 |
| 312 if (status != cdm::kSuccess) | 313 if (status != cdm::kSuccess) |
| 313 return status; | 314 return status; |
| 314 | 315 |
| 315 DCHECK(buffer->GetData()); | 316 DCHECK(buffer->GetData()); |
| 316 decrypted_block->SetDecryptedBuffer( | 317 decrypted_block->SetDecryptedBuffer( |
| 317 allocator_->Allocate(buffer->GetDataSize())); | 318 host_->Allocate(buffer->GetDataSize())); |
| 318 memcpy(reinterpret_cast<void*>(decrypted_block->DecryptedBuffer()->Data()), | 319 memcpy(reinterpret_cast<void*>(decrypted_block->DecryptedBuffer()->Data()), |
| 319 buffer->GetData(), | 320 buffer->GetData(), |
| 320 buffer->GetDataSize()); | 321 buffer->GetDataSize()); |
| 321 decrypted_block->DecryptedBuffer()->SetSize(buffer->GetDataSize()); | 322 decrypted_block->DecryptedBuffer()->SetSize(buffer->GetDataSize()); |
| 322 decrypted_block->SetTimestamp(buffer->GetTimestamp().InMicroseconds()); | 323 decrypted_block->SetTimestamp(buffer->GetTimestamp().InMicroseconds()); |
| 323 | 324 |
| 324 return cdm::kSuccess; | 325 return cdm::kSuccess; |
| 325 } | 326 } |
| 326 | 327 |
| 327 cdm::Status ClearKeyCdm::InitializeAudioDecoder( | 328 cdm::Status ClearKeyCdm::InitializeAudioDecoder( |
| 328 const cdm::AudioDecoderConfig& audio_decoder_config) { | 329 const cdm::AudioDecoderConfig& audio_decoder_config) { |
| 329 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 330 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
| 330 if (!audio_decoder_) | 331 if (!audio_decoder_) |
| 331 audio_decoder_.reset(new webkit_media::FFmpegCdmAudioDecoder(allocator_)); | 332 audio_decoder_.reset(new webkit_media::FFmpegCdmAudioDecoder(host_)); |
| 332 | 333 |
| 333 if (!audio_decoder_->Initialize(audio_decoder_config)) | 334 if (!audio_decoder_->Initialize(audio_decoder_config)) |
| 334 return cdm::kSessionError; | 335 return cdm::kSessionError; |
| 335 | 336 |
| 336 return cdm::kSuccess; | 337 return cdm::kSuccess; |
| 337 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 338 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
| 338 channel_count_ = audio_decoder_config.channel_count; | 339 channel_count_ = audio_decoder_config.channel_count; |
| 339 bits_per_channel_ = audio_decoder_config.bits_per_channel; | 340 bits_per_channel_ = audio_decoder_config.bits_per_channel; |
| 340 samples_per_second_ = audio_decoder_config.samples_per_second; | 341 samples_per_second_ = audio_decoder_config.samples_per_second; |
| 341 return cdm::kSuccess; | 342 return cdm::kSuccess; |
| 342 #else | 343 #else |
| 343 NOTIMPLEMENTED(); | 344 NOTIMPLEMENTED(); |
| 344 return cdm::kSessionError; | 345 return cdm::kSessionError; |
| 345 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 346 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
| 346 } | 347 } |
| 347 | 348 |
| 348 cdm::Status ClearKeyCdm::InitializeVideoDecoder( | 349 cdm::Status ClearKeyCdm::InitializeVideoDecoder( |
| 349 const cdm::VideoDecoderConfig& video_decoder_config) { | 350 const cdm::VideoDecoderConfig& video_decoder_config) { |
| 350 if (video_decoder_ && video_decoder_->is_initialized()) { | 351 if (video_decoder_ && video_decoder_->is_initialized()) { |
| 351 DCHECK(!video_decoder_->is_initialized()); | 352 DCHECK(!video_decoder_->is_initialized()); |
| 352 return cdm::kSessionError; | 353 return cdm::kSessionError; |
| 353 } | 354 } |
| 354 | 355 |
| 355 // Any uninitialized decoder will be replaced. | 356 // Any uninitialized decoder will be replaced. |
| 356 video_decoder_ = CreateVideoDecoder(allocator_, video_decoder_config); | 357 video_decoder_ = CreateVideoDecoder(host_, video_decoder_config); |
| 357 if (!video_decoder_) | 358 if (!video_decoder_) |
| 358 return cdm::kSessionError; | 359 return cdm::kSessionError; |
| 359 | 360 |
| 360 return cdm::kSuccess; | 361 return cdm::kSuccess; |
| 361 } | 362 } |
| 362 | 363 |
| 363 void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) { | 364 void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) { |
| 364 DVLOG(1) << "ResetDecoder()"; | 365 DVLOG(1) << "ResetDecoder()"; |
| 365 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 366 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
| 366 switch (decoder_type) { | 367 switch (decoder_type) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 if (!buffer->IsEndOfStream()) { | 444 if (!buffer->IsEndOfStream()) { |
| 444 timestamp_in_microseconds = buffer->GetTimestamp().InMicroseconds(); | 445 timestamp_in_microseconds = buffer->GetTimestamp().InMicroseconds(); |
| 445 DCHECK(timestamp_in_microseconds != kNoTimestamp); | 446 DCHECK(timestamp_in_microseconds != kNoTimestamp); |
| 446 } | 447 } |
| 447 return GenerateFakeAudioFrames(timestamp_in_microseconds, audio_frames); | 448 return GenerateFakeAudioFrames(timestamp_in_microseconds, audio_frames); |
| 448 #else | 449 #else |
| 449 return cdm::kSuccess; | 450 return cdm::kSuccess; |
| 450 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 451 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
| 451 } | 452 } |
| 452 | 453 |
| 454 void ClearKeyCdm::Destroy() { |
| 455 DVLOG(1) << "Destroy()"; |
| 456 delete this; |
| 457 } |
| 458 |
| 453 void ClearKeyCdm::ScheduleNextHeartBeat() { | 459 void ClearKeyCdm::ScheduleNextHeartBeat() { |
| 454 // Prepare the next heartbeat message and set timer. | 460 // Prepare the next heartbeat message and set timer. |
| 455 std::ostringstream msg_stream; | 461 std::ostringstream msg_stream; |
| 456 msg_stream << kHeartBeatHeader << " from ClearKey CDM set at time " | 462 msg_stream << kHeartBeatHeader << " from ClearKey CDM set at time " |
| 457 << host_->GetCurrentWallTimeInSeconds() << "."; | 463 << host_->GetCurrentWallTimeInSeconds() << "."; |
| 458 next_heartbeat_message_ = msg_stream.str(); | 464 next_heartbeat_message_ = msg_stream.str(); |
| 459 | 465 |
| 460 host_->SetTimer(timer_delay_ms_, &next_heartbeat_message_[0]); | 466 host_->SetTimer(timer_delay_ms_, &next_heartbeat_message_[0]); |
| 461 | 467 |
| 462 // Use a smaller timer delay at start-up to facilitate testing. Increase the | 468 // Use a smaller timer delay at start-up to facilitate testing. Increase the |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 if (samples_to_generate <= 0) | 517 if (samples_to_generate <= 0) |
| 512 return 0; | 518 return 0; |
| 513 | 519 |
| 514 int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8; | 520 int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8; |
| 515 // |frame_size| must be a multiple of |bytes_per_sample|. | 521 // |frame_size| must be a multiple of |bytes_per_sample|. |
| 516 int64 frame_size = bytes_per_sample * samples_to_generate; | 522 int64 frame_size = bytes_per_sample * samples_to_generate; |
| 517 | 523 |
| 518 int64 timestamp = CurrentTimeStampInMicroseconds(); | 524 int64 timestamp = CurrentTimeStampInMicroseconds(); |
| 519 | 525 |
| 520 const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size); | 526 const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size); |
| 521 audio_frames->SetFrameBuffer(allocator_->Allocate(kHeaderSize + frame_size)); | 527 audio_frames->SetFrameBuffer(host_->Allocate(kHeaderSize + frame_size)); |
| 522 uint8_t* data = audio_frames->FrameBuffer()->Data(); | 528 uint8_t* data = audio_frames->FrameBuffer()->Data(); |
| 523 | 529 |
| 524 memcpy(data, ×tamp, sizeof(timestamp)); | 530 memcpy(data, ×tamp, sizeof(timestamp)); |
| 525 data += sizeof(timestamp); | 531 data += sizeof(timestamp); |
| 526 memcpy(data, &frame_size, sizeof(frame_size)); | 532 memcpy(data, &frame_size, sizeof(frame_size)); |
| 527 data += sizeof(frame_size); | 533 data += sizeof(frame_size); |
| 528 // You won't hear anything because we have all zeros here. But the video | 534 // You won't hear anything because we have all zeros here. But the video |
| 529 // should play just fine! | 535 // should play just fine! |
| 530 memset(data, 0, frame_size); | 536 memset(data, 0, frame_size); |
| 531 | 537 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 549 int samples_generated = GenerateFakeAudioFramesFromDuration( | 555 int samples_generated = GenerateFakeAudioFramesFromDuration( |
| 550 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), | 556 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), |
| 551 audio_frames); | 557 audio_frames); |
| 552 total_samples_generated_ += samples_generated; | 558 total_samples_generated_ += samples_generated; |
| 553 | 559 |
| 554 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; | 560 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; |
| 555 } | 561 } |
| 556 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 562 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
| 557 | 563 |
| 558 } // namespace webkit_media | 564 } // namespace webkit_media |
| OLD | NEW |