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> |
11 | 11 |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "media/base/decoder_buffer.h" | 16 #include "media/base/decoder_buffer.h" |
17 #include "media/base/decrypt_config.h" | 17 #include "media/base/decrypt_config.h" |
| 18 #include "media/cdm/ppapi/cdm_file_io_test.h" |
18 #include "media/cdm/ppapi/cdm_video_decoder.h" | 19 #include "media/cdm/ppapi/cdm_video_decoder.h" |
19 | 20 |
20 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 21 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
21 #include "base/basictypes.h" | 22 #include "base/basictypes.h" |
22 const int64 kNoTimestamp = kint64min; | 23 const int64 kNoTimestamp = kint64min; |
23 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 24 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
24 | 25 |
25 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 26 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
26 #include "base/at_exit.h" | 27 #include "base/at_exit.h" |
27 #include "base/files/file_path.h" | 28 #include "base/files/file_path.h" |
(...skipping 28 matching lines...) Expand all Loading... |
56 return true; | 57 return true; |
57 } | 58 } |
58 | 59 |
59 static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries(); | 60 static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries(); |
60 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 61 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
61 | 62 |
62 const char kClearKeyCdmVersion[] = "0.1.0.1"; | 63 const char kClearKeyCdmVersion[] = "0.1.0.1"; |
63 const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; | 64 const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; |
64 const char kExternalClearKeyDecryptOnlyKeySystem[] = | 65 const char kExternalClearKeyDecryptOnlyKeySystem[] = |
65 "org.chromium.externalclearkey.decryptonly"; | 66 "org.chromium.externalclearkey.decryptonly"; |
| 67 const char kExternalClearKeyFileIOTestKeySystem[] = |
| 68 "org.chromium.externalclearkey.fileiotest"; |
66 const int64 kSecondsPerMinute = 60; | 69 const int64 kSecondsPerMinute = 60; |
67 const int64 kMsPerSecond = 1000; | 70 const int64 kMsPerSecond = 1000; |
68 const int64 kInitialTimerDelayMs = 200; | 71 const int64 kInitialTimerDelayMs = 200; |
69 const int64 kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; | 72 const int64 kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; |
70 // Heart beat message header. If a key message starts with |kHeartBeatHeader|, | 73 // Heart beat message header. If a key message starts with |kHeartBeatHeader|, |
71 // it's a heart beat message. Otherwise, it's a key request. | 74 // it's a heart beat message. Otherwise, it's a key request. |
72 const char kHeartBeatHeader[] = "HEARTBEAT"; | 75 const char kHeartBeatHeader[] = "HEARTBEAT"; |
| 76 // CDM file IO test result header. |
| 77 const char kFileIOTestResultHeader[] = "FILEIOTESTRESULT"; |
73 | 78 |
74 // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is | 79 // Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is |
75 // empty, an empty (end-of-stream) media::DecoderBuffer is returned. | 80 // empty, an empty (end-of-stream) media::DecoderBuffer is returned. |
76 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( | 81 static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( |
77 const cdm::InputBuffer& input_buffer) { | 82 const cdm::InputBuffer& input_buffer) { |
78 if (!input_buffer.data) { | 83 if (!input_buffer.data) { |
79 DCHECK(!input_buffer.data_size); | 84 DCHECK(!input_buffer.data_size); |
80 return media::DecoderBuffer::CreateEOSBuffer(); | 85 return media::DecoderBuffer::CreateEOSBuffer(); |
81 } | 86 } |
82 | 87 |
(...skipping 17 matching lines...) Expand all Loading... |
100 input_buffer.data_offset, | 105 input_buffer.data_offset, |
101 subsamples)); | 106 subsamples)); |
102 | 107 |
103 output_buffer->set_decrypt_config(decrypt_config.Pass()); | 108 output_buffer->set_decrypt_config(decrypt_config.Pass()); |
104 output_buffer->set_timestamp( | 109 output_buffer->set_timestamp( |
105 base::TimeDelta::FromMicroseconds(input_buffer.timestamp)); | 110 base::TimeDelta::FromMicroseconds(input_buffer.timestamp)); |
106 | 111 |
107 return output_buffer; | 112 return output_buffer; |
108 } | 113 } |
109 | 114 |
| 115 static std::string GetFileIOTestResultMessage(bool success) { |
| 116 std::string message(kFileIOTestResultHeader); |
| 117 message += success ? '1' : '0'; |
| 118 return message; |
| 119 } |
| 120 |
110 template<typename Type> | 121 template<typename Type> |
111 class ScopedResetter { | 122 class ScopedResetter { |
112 public: | 123 public: |
113 explicit ScopedResetter(Type* object) : object_(object) {} | 124 explicit ScopedResetter(Type* object) : object_(object) {} |
114 ~ScopedResetter() { object_->Reset(); } | 125 ~ScopedResetter() { object_->Reset(); } |
115 | 126 |
116 private: | 127 private: |
117 Type* const object_; | 128 Type* const object_; |
118 }; | 129 }; |
119 | 130 |
120 void INITIALIZE_CDM_MODULE() { | 131 void INITIALIZE_CDM_MODULE() { |
121 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) | 132 #if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) |
122 DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; | 133 DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; |
123 av_register_all(); | 134 av_register_all(); |
124 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER | 135 #endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER |
125 } | 136 } |
126 | 137 |
127 void DeinitializeCdmModule() { | 138 void DeinitializeCdmModule() { |
128 } | 139 } |
129 | 140 |
130 void* CreateCdmInstance(int cdm_interface_version, | 141 void* CreateCdmInstance(int cdm_interface_version, |
131 const char* key_system, uint32_t key_system_size, | 142 const char* key_system, uint32_t key_system_size, |
132 GetCdmHostFunc get_cdm_host_func, | 143 GetCdmHostFunc get_cdm_host_func, |
133 void* user_data) { | 144 void* user_data) { |
134 DVLOG(1) << "CreateCdmInstance()"; | 145 DVLOG(1) << "CreateCdmInstance()"; |
135 | 146 |
136 std::string key_system_string(key_system, key_system_size); | 147 std::string key_system_string(key_system, key_system_size); |
137 if (key_system_string != kExternalClearKeyKeySystem && | 148 if (key_system_string != kExternalClearKeyKeySystem && |
138 key_system_string != kExternalClearKeyDecryptOnlyKeySystem) { | 149 key_system_string != kExternalClearKeyDecryptOnlyKeySystem && |
| 150 key_system_string != kExternalClearKeyFileIOTestKeySystem) { |
139 DVLOG(1) << "Unsupported key system:" << key_system_string; | 151 DVLOG(1) << "Unsupported key system:" << key_system_string; |
140 return NULL; | 152 return NULL; |
141 } | 153 } |
142 | 154 |
143 if (cdm_interface_version != media::ClearKeyCdmInterface::kVersion) | 155 if (cdm_interface_version != media::ClearKeyCdmInterface::kVersion) |
144 return NULL; | 156 return NULL; |
145 | 157 |
146 media::ClearKeyCdmHost* host = static_cast<media::ClearKeyCdmHost*>( | 158 media::ClearKeyCdmHost* host = static_cast<media::ClearKeyCdmHost*>( |
147 get_cdm_host_func(media::ClearKeyCdmHost::kVersion, user_data)); | 159 get_cdm_host_func(media::ClearKeyCdmHost::kVersion, user_data)); |
148 if (!host) | 160 if (!host) |
149 return NULL; | 161 return NULL; |
150 | 162 |
151 return new media::ClearKeyCdm( | 163 return new media::ClearKeyCdm( |
152 host, key_system_string == kExternalClearKeyDecryptOnlyKeySystem); | 164 host, |
| 165 key_system_string == kExternalClearKeyDecryptOnlyKeySystem, |
| 166 key_system_string == kExternalClearKeyFileIOTestKeySystem); |
153 } | 167 } |
154 | 168 |
155 const char* GetCdmVersion() { | 169 const char* GetCdmVersion() { |
156 return kClearKeyCdmVersion; | 170 return kClearKeyCdmVersion; |
157 } | 171 } |
158 | 172 |
159 namespace media { | 173 namespace media { |
160 | 174 |
161 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, bool is_decrypt_only) | 175 ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, |
| 176 bool is_decrypt_only, |
| 177 bool should_test_file_io) |
162 : decryptor_( | 178 : decryptor_( |
163 base::Bind(&ClearKeyCdm::OnSessionCreated, base::Unretained(this)), | 179 base::Bind(&ClearKeyCdm::OnSessionCreated, base::Unretained(this)), |
164 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), | 180 base::Bind(&ClearKeyCdm::OnSessionMessage, base::Unretained(this)), |
165 base::Bind(&ClearKeyCdm::OnSessionReady, base::Unretained(this)), | 181 base::Bind(&ClearKeyCdm::OnSessionReady, base::Unretained(this)), |
166 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), | 182 base::Bind(&ClearKeyCdm::OnSessionClosed, base::Unretained(this)), |
167 base::Bind(&ClearKeyCdm::OnSessionError, base::Unretained(this))), | 183 base::Bind(&ClearKeyCdm::OnSessionError, base::Unretained(this))), |
168 host_(host), | 184 host_(host), |
169 is_decrypt_only_(is_decrypt_only), | 185 is_decrypt_only_(is_decrypt_only), |
170 heartbeat_session_id_(0), | 186 should_test_file_io_(should_test_file_io), |
| 187 last_session_id_(MediaKeys::kInvalidSessionId), |
171 timer_delay_ms_(kInitialTimerDelayMs), | 188 timer_delay_ms_(kInitialTimerDelayMs), |
172 timer_set_(false) { | 189 timer_set_(false) { |
173 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) | 190 #if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) |
174 channel_count_ = 0; | 191 channel_count_ = 0; |
175 bits_per_channel_ = 0; | 192 bits_per_channel_ = 0; |
176 samples_per_second_ = 0; | 193 samples_per_second_ = 0; |
177 output_timestamp_base_in_microseconds_ = kNoTimestamp; | 194 output_timestamp_base_in_microseconds_ = kNoTimestamp; |
178 total_samples_generated_ = 0; | 195 total_samples_generated_ = 0; |
179 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 196 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
180 } | 197 } |
181 | 198 |
182 ClearKeyCdm::~ClearKeyCdm() {} | 199 ClearKeyCdm::~ClearKeyCdm() {} |
183 | 200 |
184 void ClearKeyCdm::CreateSession(uint32 session_id, | 201 void ClearKeyCdm::CreateSession(uint32 session_id, |
185 const char* type, | 202 const char* type, |
186 uint32 type_size, | 203 uint32 type_size, |
187 const uint8* init_data, | 204 const uint8* init_data, |
188 uint32 init_data_size) { | 205 uint32 init_data_size) { |
189 DVLOG(1) << __FUNCTION__; | 206 DVLOG(1) << __FUNCTION__; |
190 decryptor_.CreateSession( | 207 decryptor_.CreateSession( |
191 session_id, std::string(type, type_size), init_data, init_data_size); | 208 session_id, std::string(type, type_size), init_data, init_data_size); |
192 | 209 |
193 // Only save the latest session ID for heartbeat messages. | 210 // Save the latest session ID for heartbeat and file IO test messages. |
194 heartbeat_session_id_ = session_id; | 211 last_session_id_ = session_id; |
| 212 |
| 213 if (should_test_file_io_) |
| 214 StartFileIOTest(); |
195 } | 215 } |
196 | 216 |
197 void ClearKeyCdm::UpdateSession(uint32 session_id, | 217 void ClearKeyCdm::UpdateSession(uint32 session_id, |
198 const uint8* response, | 218 const uint8* response, |
199 uint32 response_size) { | 219 uint32 response_size) { |
200 DVLOG(1) << __FUNCTION__; | 220 DVLOG(1) << __FUNCTION__; |
201 decryptor_.UpdateSession(session_id, response, response_size); | 221 decryptor_.UpdateSession(session_id, response, response_size); |
202 | 222 |
203 if (!timer_set_) { | 223 if (!timer_set_) { |
204 ScheduleNextHeartBeat(); | 224 ScheduleNextHeartBeat(); |
(...skipping 12 matching lines...) Expand all Loading... |
217 context == &next_heartbeat_message_[0]) { | 237 context == &next_heartbeat_message_[0]) { |
218 heartbeat_message = next_heartbeat_message_; | 238 heartbeat_message = next_heartbeat_message_; |
219 } else { | 239 } else { |
220 heartbeat_message = "ERROR: Invalid timer context found!"; | 240 heartbeat_message = "ERROR: Invalid timer context found!"; |
221 } | 241 } |
222 | 242 |
223 // This URL is only used for testing the code path for defaultURL. | 243 // This URL is only used for testing the code path for defaultURL. |
224 // There is no service at this URL, so applications should ignore it. | 244 // There is no service at this URL, so applications should ignore it. |
225 const char url[] = "http://test.externalclearkey.chromium.org"; | 245 const char url[] = "http://test.externalclearkey.chromium.org"; |
226 | 246 |
227 host_->OnSessionMessage(heartbeat_session_id_, | 247 host_->OnSessionMessage(last_session_id_, |
228 heartbeat_message.data(), | 248 heartbeat_message.data(), |
229 heartbeat_message.size(), | 249 heartbeat_message.size(), |
230 url, | 250 url, |
231 arraysize(url) - 1); | 251 arraysize(url) - 1); |
232 | 252 |
233 ScheduleNextHeartBeat(); | 253 ScheduleNextHeartBeat(); |
234 } | 254 } |
235 | 255 |
236 static void CopyDecryptResults( | 256 static void CopyDecryptResults( |
237 media::Decryptor::Status* status_copy, | 257 media::Decryptor::Status* status_copy, |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 | 569 |
550 int samples_generated = GenerateFakeAudioFramesFromDuration( | 570 int samples_generated = GenerateFakeAudioFramesFromDuration( |
551 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), | 571 timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), |
552 audio_frames); | 572 audio_frames); |
553 total_samples_generated_ += samples_generated; | 573 total_samples_generated_ += samples_generated; |
554 | 574 |
555 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; | 575 return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; |
556 } | 576 } |
557 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER | 577 #endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER |
558 | 578 |
| 579 void ClearKeyCdm::StartFileIOTest() { |
| 580 file_io_test_runner_.reset(new FileIOTestRunner( |
| 581 base::Bind(&ClearKeyCdmHost::CreateFileIO, base::Unretained(host_)))); |
| 582 file_io_test_runner_->RunAllTests( |
| 583 base::Bind(&ClearKeyCdm::OnFileIOTestComplete, base::Unretained(this))); |
| 584 } |
| 585 |
| 586 void ClearKeyCdm::OnFileIOTestComplete(bool success) { |
| 587 DVLOG(1) << __FUNCTION__ << ": " << success; |
| 588 std::string message = GetFileIOTestResultMessage(success); |
| 589 host_->OnSessionMessage( |
| 590 last_session_id_, message.data(), message.size(), NULL, 0); |
| 591 file_io_test_runner_.reset(); |
| 592 } |
| 593 |
559 } // namespace media | 594 } // namespace media |
OLD | NEW |