Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "media/cdm/ppapi/clear_key_cdm.h" | 5 #include "media/cdm/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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 const int64 kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; | 66 const int64 kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; |
| 67 // Heart beat message header. If a key message starts with |kHeartBeatHeader|, | 67 // Heart beat message header. If a key message starts with |kHeartBeatHeader|, |
| 68 // it's a heart beat message. Otherwise, it's a key request. | 68 // it's a heart beat message. Otherwise, it's a key request. |
| 69 const char kHeartBeatHeader[] = "HEARTBEAT"; | 69 const char kHeartBeatHeader[] = "HEARTBEAT"; |
| 70 | 70 |
| 71 // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is | 71 // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is |
| 72 // empty, an empty (end-of-stream) media::DecoderBuffer is returned. | 72 // empty, an empty (end-of-stream) media::DecoderBuffer is returned. |
| 73 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( | 73 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( |
| 74 const cdm::InputBuffer& input_buffer) { | 74 const cdm::InputBuffer& input_buffer) { |
| 75 if (!input_buffer.data) { | 75 if (!input_buffer.data) { |
| 76 DCHECK_EQ(input_buffer.data_size, 0); | 76 DCHECK_EQ(input_buffer.data_size, 0u); |
| 77 return media::DecoderBuffer::CreateEOSBuffer(); | 77 return media::DecoderBuffer::CreateEOSBuffer(); |
| 78 } | 78 } |
| 79 | 79 |
| 80 // TODO(tomfinegan): Get rid of this copy. | 80 // TODO(tomfinegan): Get rid of this copy. |
| 81 scoped_refptr<media::DecoderBuffer> output_buffer = | 81 scoped_refptr<media::DecoderBuffer> output_buffer = |
| 82 media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size); | 82 media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size); |
| 83 | 83 |
| 84 std::vector<media::SubsampleEntry> subsamples; | 84 std::vector<media::SubsampleEntry> subsamples; |
| 85 for (int32_t i = 0; i < input_buffer.num_subsamples; ++i) { | 85 for (uint32_t i = 0; i < input_buffer.num_subsamples; ++i) { |
| 86 media::SubsampleEntry subsample; | 86 media::SubsampleEntry subsample; |
| 87 subsample.clear_bytes = input_buffer.subsamples[i].clear_bytes; | 87 subsample.clear_bytes = input_buffer.subsamples[i].clear_bytes; |
| 88 subsample.cypher_bytes = input_buffer.subsamples[i].cipher_bytes; | 88 subsample.cypher_bytes = input_buffer.subsamples[i].cipher_bytes; |
| 89 subsamples.push_back(subsample); | 89 subsamples.push_back(subsample); |
| 90 } | 90 } |
| 91 | 91 |
| 92 scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig( | 92 scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig( |
| 93 std::string(reinterpret_cast<const char*>(input_buffer.key_id), | 93 std::string(reinterpret_cast<const char*>(input_buffer.key_id), |
| 94 input_buffer.key_id_size), | 94 input_buffer.key_id_size), |
| 95 std::string(reinterpret_cast<const char*>(input_buffer.iv), | 95 std::string(reinterpret_cast<const char*>(input_buffer.iv), |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 119 DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; | 119 DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; |
| 120 av_register_all(); | 120 av_register_all(); |
| 121 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 121 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
| 122 } | 122 } |
| 123 | 123 |
| 124 void DeinitializeCdmModule() { | 124 void DeinitializeCdmModule() { |
| 125 } | 125 } |
| 126 | 126 |
| 127 void* CreateCdmInstance( | 127 void* CreateCdmInstance( |
| 128 int cdm_interface_version, | 128 int cdm_interface_version, |
| 129 const char* key_system, int key_system_size, | 129 const char* key_system, uint32_t key_system_size, |
| 130 GetCdmHostFunc get_cdm_host_func, void* user_data) { | 130 GetCdmHostFunc get_cdm_host_func, void* user_data) { |
| 131 DVLOG(1) << "CreateCdmInstance()"; | 131 DVLOG(1) << "CreateCdmInstance()"; |
| 132 | 132 |
| 133 if (cdm_interface_version != cdm::kCdmInterfaceVersion) | 133 if (cdm_interface_version != cdm::kCdmInterfaceVersion) |
| 134 return NULL; | 134 return NULL; |
| 135 | 135 |
| 136 cdm::Host* host = static_cast<cdm::Host*>( | 136 cdm::Host* host = static_cast<cdm::Host*>( |
| 137 get_cdm_host_func(cdm::kHostInterfaceVersion, user_data)); | 137 get_cdm_host_func(cdm::kHostInterfaceVersion, user_data)); |
| 138 if (!host) | 138 if (!host) |
| 139 return NULL; | 139 return NULL; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 channel_count_ = 0; | 191 channel_count_ = 0; |
| 192 bits_per_channel_ = 0; | 192 bits_per_channel_ = 0; |
| 193 samples_per_second_ = 0; | 193 samples_per_second_ = 0; |
| 194 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 194 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
| 195 total_samples_generated_ = 0; | 195 total_samples_generated_ = 0; |
| 196 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 196 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
| 197 } | 197 } |
| 198 | 198 |
| 199 ClearKeyCdm::~ClearKeyCdm() {} | 199 ClearKeyCdm::~ClearKeyCdm() {} |
| 200 | 200 |
| 201 cdm::Status ClearKeyCdm::GenerateKeyRequest(const char* type, int type_size, | 201 cdm::Status ClearKeyCdm::GenerateKeyRequest(const char* type, |
| 202 uint32_t type_size, | |
| 202 const uint8_t* init_data, | 203 const uint8_t* init_data, |
| 203 int init_data_size) { | 204 uint32_t init_data_size) { |
| 204 DVLOG(1) << "GenerateKeyRequest()"; | 205 DVLOG(1) << "GenerateKeyRequest()"; |
| 205 base::AutoLock auto_lock(client_lock_); | 206 base::AutoLock auto_lock(client_lock_); |
| 206 ScopedResetter<Client> auto_resetter(&client_); | 207 ScopedResetter<Client> auto_resetter(&client_); |
| 207 decryptor_.GenerateKeyRequest(std::string(type, type_size), | 208 decryptor_.GenerateKeyRequest(std::string(type, type_size), |
| 208 init_data, init_data_size); | 209 init_data, init_data_size); |
| 209 | 210 |
| 210 if (client_.status() != Client::kKeyMessage) { | 211 if (client_.status() != Client::kKeyMessage) { |
| 211 host_->SendKeyError(NULL, 0, cdm::kUnknownError, 0); | 212 host_->SendKeyError(NULL, 0, cdm::kUnknownError, 0); |
| 212 return cdm::kSessionError; | 213 return cdm::kSessionError; |
| 213 } | 214 } |
| 214 | 215 |
| 215 host_->SendKeyMessage( | 216 host_->SendKeyMessage( |
| 216 client_.session_id().data(), client_.session_id().size(), | 217 client_.session_id().data(), client_.session_id().size(), |
| 217 reinterpret_cast<const char*>(&client_.key_message()[0]), | 218 reinterpret_cast<const char*>(&client_.key_message()[0]), |
| 218 client_.key_message().size(), | 219 client_.key_message().size(), |
| 219 client_.default_url().data(), client_.default_url().size()); | 220 client_.default_url().data(), client_.default_url().size()); |
| 220 | 221 |
| 221 // Only save the latest session ID for heartbeat messages. | 222 // Only save the latest session ID for heartbeat messages. |
| 222 heartbeat_session_id_ = client_.session_id(); | 223 heartbeat_session_id_ = client_.session_id(); |
| 223 | 224 |
| 224 return cdm::kSuccess; | 225 return cdm::kSuccess; |
| 225 } | 226 } |
| 226 | 227 |
| 227 cdm::Status ClearKeyCdm::AddKey(const char* session_id, | 228 cdm::Status ClearKeyCdm::AddKey(const char* session_id, |
| 228 int session_id_size, | 229 uint32_t session_id_size, |
| 229 const uint8_t* key, | 230 const uint8_t* key, |
| 230 int key_size, | 231 uint32_t key_size, |
| 231 const uint8_t* key_id, | 232 const uint8_t* key_id, |
| 232 int key_id_size) { | 233 uint32_t key_id_size) { |
| 233 DVLOG(1) << "AddKey()"; | 234 DVLOG(1) << "AddKey()"; |
| 234 base::AutoLock auto_lock(client_lock_); | 235 base::AutoLock auto_lock(client_lock_); |
| 235 ScopedResetter<Client> auto_resetter(&client_); | 236 ScopedResetter<Client> auto_resetter(&client_); |
| 236 decryptor_.AddKey(key, key_size, key_id, key_id_size, | 237 decryptor_.AddKey(key, key_size, key_id, key_id_size, |
| 237 std::string(session_id, session_id_size)); | 238 std::string(session_id, session_id_size)); |
| 238 | 239 |
| 239 if (client_.status() != Client::kKeyAdded) | 240 if (client_.status() != Client::kKeyAdded) |
| 240 return cdm::kSessionError; | 241 return cdm::kSessionError; |
| 241 | 242 |
| 242 if (!timer_set_) { | 243 if (!timer_set_) { |
| 243 ScheduleNextHeartBeat(); | 244 ScheduleNextHeartBeat(); |
| 244 timer_set_ = true; | 245 timer_set_ = true; |
| 245 } | 246 } |
| 246 | 247 |
| 247 return cdm::kSuccess; | 248 return cdm::kSuccess; |
| 248 } | 249 } |
| 249 | 250 |
| 250 cdm::Status ClearKeyCdm::CancelKeyRequest(const char* session_id, | 251 cdm::Status ClearKeyCdm::CancelKeyRequest(const char* session_id, |
| 251 int session_id_size) { | 252 uint32_t session_id_size) { |
| 252 DVLOG(1) << "CancelKeyRequest()"; | 253 DVLOG(1) << "CancelKeyRequest()"; |
| 253 base::AutoLock auto_lock(client_lock_); | 254 base::AutoLock auto_lock(client_lock_); |
| 254 ScopedResetter<Client> auto_resetter(&client_); | 255 ScopedResetter<Client> auto_resetter(&client_); |
| 255 decryptor_.CancelKeyRequest(std::string(session_id, session_id_size)); | 256 decryptor_.CancelKeyRequest(std::string(session_id, session_id_size)); |
| 256 return cdm::kSuccess; | 257 return cdm::kSuccess; |
| 257 } | 258 } |
| 258 | 259 |
| 259 void ClearKeyCdm::TimerExpired(void* context) { | 260 void ClearKeyCdm::TimerExpired(void* context) { |
| 260 std::string heartbeat_message; | 261 std::string heartbeat_message; |
| 261 if (!next_heartbeat_message_.empty() && | 262 if (!next_heartbeat_message_.empty() && |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 DVLOG(1) << "DecryptAndDecodeFrame()"; | 393 DVLOG(1) << "DecryptAndDecodeFrame()"; |
| 393 TRACE_EVENT0("eme", "ClearKeyCdm::DecryptAndDecodeFrame"); | 394 TRACE_EVENT0("eme", "ClearKeyCdm::DecryptAndDecodeFrame"); |
| 394 | 395 |
| 395 scoped_refptr<media::DecoderBuffer> buffer; | 396 scoped_refptr<media::DecoderBuffer> buffer; |
| 396 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); | 397 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); |
| 397 | 398 |
| 398 if (status != cdm::kSuccess) | 399 if (status != cdm::kSuccess) |
| 399 return status; | 400 return status; |
| 400 | 401 |
| 401 const uint8_t* data = NULL; | 402 const uint8_t* data = NULL; |
| 402 int32_t size = 0; | 403 uint32_t size = 0; |
| 403 int64_t timestamp = 0; | 404 int64_t timestamp = 0; |
| 404 if (!buffer->end_of_stream()) { | 405 if (!buffer->end_of_stream()) { |
| 405 data = buffer->data(); | 406 data = buffer->data(); |
| 406 size = buffer->data_size(); | 407 size = buffer->data_size(); |
| 407 timestamp = encrypted_buffer.timestamp; | 408 timestamp = encrypted_buffer.timestamp; |
| 408 } | 409 } |
| 409 | 410 |
| 410 return video_decoder_->DecodeFrame(data, size, timestamp, decoded_frame); | 411 return video_decoder_->DecodeFrame(data, size, timestamp, decoded_frame); |
| 411 } | 412 } |
| 412 | 413 |
| 413 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples( | 414 cdm::Status ClearKeyCdm::DecryptAndDecodeSamples( |
| 414 const cdm::InputBuffer& encrypted_buffer, | 415 const cdm::InputBuffer& encrypted_buffer, |
| 415 cdm::AudioFrames* audio_frames) { | 416 cdm::AudioFrames* audio_frames) { |
| 416 DVLOG(1) << "DecryptAndDecodeSamples()"; | 417 DVLOG(1) << "DecryptAndDecodeSamples()"; |
| 417 | 418 |
| 418 scoped_refptr<media::DecoderBuffer> buffer; | 419 scoped_refptr<media::DecoderBuffer> buffer; |
| 419 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); | 420 cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); |
| 420 | 421 |
| 421 if (status != cdm::kSuccess) | 422 if (status != cdm::kSuccess) |
| 422 return status; | 423 return status; |
| 423 | 424 |
| 424 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 425 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
| 425 const uint8_t* data = NULL; | 426 const uint8_t* data = NULL; |
| 426 int32_t size = 0; | 427 uint32_t size = 0; |
| 427 int64_t timestamp = 0; | 428 int64_t timestamp = 0; |
| 428 if (!buffer->end_of_stream()) { | 429 if (!buffer->end_of_stream()) { |
| 429 data = buffer->data(); | 430 data = buffer->data(); |
| 430 size = buffer->data_size(); | 431 size = buffer->data_size(); |
| 431 timestamp = encrypted_buffer.timestamp; | 432 timestamp = encrypted_buffer.timestamp; |
| 432 } | 433 } |
| 433 | 434 |
| 434 return audio_decoder_->DecodeBuffer(data, size, timestamp, audio_frames); | 435 return audio_decoder_->DecodeBuffer(data, size, timestamp, audio_frames); |
| 435 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 436 #elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
| 436 int64 timestamp_in_microseconds = kNoTimestamp; | 437 int64 timestamp_in_microseconds = kNoTimestamp; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 509 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
| 509 int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { | 510 int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { |
| 510 return output_timestamp_base_in_microseconds_ + | 511 return output_timestamp_base_in_microseconds_ + |
| 511 base::Time::kMicrosecondsPerSecond * | 512 base::Time::kMicrosecondsPerSecond * |
| 512 total_samples_generated_ / samples_per_second_; | 513 total_samples_generated_ / samples_per_second_; |
| 513 } | 514 } |
| 514 | 515 |
| 515 int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( | 516 int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( |
| 516 int64 duration_in_microseconds, | 517 int64 duration_in_microseconds, |
| 517 cdm::AudioFrames* audio_frames) const { | 518 cdm::AudioFrames* audio_frames) const { |
| 518 int64 samples_to_generate = static_cast<double>(samples_per_second_) * | 519 int samples_to_generate = static_cast<double>(samples_per_second_) * |
|
ddorwin
2013/10/08 23:53:20
should we do the calculation, check <= MAX_UINT, t
| |
| 519 duration_in_microseconds / base::Time::kMicrosecondsPerSecond + 0.5; | 520 duration_in_microseconds / base::Time::kMicrosecondsPerSecond + 0.5; |
| 520 if (samples_to_generate <= 0) | 521 if (samples_to_generate <= 0) |
| 521 return 0; | 522 return 0; |
| 522 | 523 |
| 523 int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8; | 524 uint32_t bytes_per_sample = channel_count_ * bits_per_channel_ / 8; |
| 524 // |frame_size| must be a multiple of |bytes_per_sample|. | 525 // |frame_size| must be a multiple of |bytes_per_sample|. |
| 525 int64 frame_size = bytes_per_sample * samples_to_generate; | 526 uint32_t frame_size = bytes_per_sample * samples_to_generate; |
| 526 | 527 |
| 527 int64 timestamp = CurrentTimeStampInMicroseconds(); | 528 int64 timestamp = CurrentTimeStampInMicroseconds(); |
| 528 | 529 |
| 529 const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size); | 530 const uint32_t kHeaderSize = sizeof(timestamp) + sizeof(frame_size); |
| 530 audio_frames->SetFrameBuffer(host_->Allocate(kHeaderSize + frame_size)); | 531 audio_frames->SetFrameBuffer(host_->Allocate(kHeaderSize + frame_size)); |
| 531 uint8_t* data = audio_frames->FrameBuffer()->Data(); | 532 uint8_t* data = audio_frames->FrameBuffer()->Data(); |
| 532 | 533 |
| 533 memcpy(data, ×tamp, sizeof(timestamp)); | 534 memcpy(data, ×tamp, sizeof(timestamp)); |
| 534 data += sizeof(timestamp); | 535 data += sizeof(timestamp); |
| 535 memcpy(data, &frame_size, sizeof(frame_size)); | 536 memcpy(data, &frame_size, sizeof(frame_size)); |
| 536 data += sizeof(frame_size); | 537 data += sizeof(frame_size); |
| 537 // You won't hear anything because we have all zeros here. But the video | 538 // You won't hear anything because we have all zeros here. But the video |
| 538 // should play just fine! | 539 // should play just fine! |
| 539 memset(data, 0, frame_size); | 540 memset(data, 0, frame_size); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 558 int samples_generated = GenerateFakeAudioFramesFromDuration( | 559 int samples_generated = GenerateFakeAudioFramesFromDuration( |
| 559 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), | 560 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), |
| 560 audio_frames); | 561 audio_frames); |
| 561 total_samples_generated_ += samples_generated; | 562 total_samples_generated_ += samples_generated; |
| 562 | 563 |
| 563 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; | 564 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; |
| 564 } | 565 } |
| 565 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 566 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
| 566 | 567 |
| 567 } // namespace media | 568 } // namespace media |
| OLD | NEW |