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 |