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
3// found in the LICENSE file.
4
5#ifndef MEDIA_CDM_PPAPI_EXTERNAL_CLEAR_KEY_CLEAR_KEY_CDM_H_
6#define MEDIA_CDM_PPAPI_EXTERNAL_CLEAR_KEY_CLEAR_KEY_CDM_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "base/compiler_specific.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/synchronization/lock.h"
16#include "media/cdm/aes_decryptor.h"
17#include "media/cdm/ppapi/external_clear_key/clear_key_cdm_common.h"
18
19// Enable this to use the fake decoder for testing.
20// TODO(tomfinegan): Move fake audio decoder into a separate class.
21#if 0
22#define CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
23#endif
24
25namespace media {
26class FileIOTestRunner;
27class CdmVideoDecoder;
28class DecoderBuffer;
29class FFmpegCdmAudioDecoder;
30
31// Clear key implementation of the cdm::ContentDecryptionModule interface.
32class ClearKeyCdm : public ClearKeyCdmInterface {
33 public:
34  ClearKeyCdm(Host* host, const std::string& key_system);
35  virtual ~ClearKeyCdm();
36
37  // ContentDecryptionModule implementation.
38  virtual void CreateSession(uint32 promise_id,
39                             const char* init_data_type,
40                             uint32 init_data_type_size,
41                             const uint8* init_data,
42                             uint32 init_data_size,
43                             cdm::SessionType session_type) OVERRIDE;
44  virtual void LoadSession(uint32 promise_id,
45                           const char* web_session_id,
46                           uint32_t web_session_id_length) OVERRIDE;
47  virtual void UpdateSession(uint32 promise_id,
48                             const char* web_session_id,
49                             uint32_t web_session_id_length,
50                             const uint8* response,
51                             uint32 response_size) OVERRIDE;
52  virtual void CloseSession(uint32 promise_id,
53                            const char* web_session_id,
54                            uint32_t web_session_id_length) OVERRIDE;
55  virtual void RemoveSession(uint32 promise_id,
56                             const char* web_session_id,
57                             uint32_t web_session_id_length) OVERRIDE;
58  virtual void GetUsableKeyIds(uint32_t promise_id,
59                               const char* web_session_id,
60                               uint32_t web_session_id_length) OVERRIDE;
61  virtual void SetServerCertificate(
62      uint32 promise_id,
63      const uint8_t* server_certificate_data,
64      uint32_t server_certificate_data_size) OVERRIDE;
65  virtual void TimerExpired(void* context) OVERRIDE;
66  virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
67                              cdm::DecryptedBlock* decrypted_block) OVERRIDE;
68  virtual cdm::Status InitializeAudioDecoder(
69      const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE;
70  virtual cdm::Status InitializeVideoDecoder(
71      const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE;
72  virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE;
73  virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE;
74  virtual cdm::Status DecryptAndDecodeFrame(
75      const cdm::InputBuffer& encrypted_buffer,
76      cdm::VideoFrame* video_frame) OVERRIDE;
77  virtual cdm::Status DecryptAndDecodeSamples(
78      const cdm::InputBuffer& encrypted_buffer,
79      cdm::AudioFrames* audio_frames) OVERRIDE;
80  virtual void Destroy() OVERRIDE;
81  virtual void OnPlatformChallengeResponse(
82      const cdm::PlatformChallengeResponse& response) OVERRIDE;
83  virtual void OnQueryOutputProtectionStatus(
84      uint32_t link_mask, uint32_t output_protection_mask) OVERRIDE;
85
86 private:
87  // Emulates a session stored for |session_id_for_emulated_loadsession_|. This
88  // is necessary since aes_decryptor.cc does not support storing sessions.
89  void LoadLoadableSession();
90
91  // ContentDecryptionModule callbacks.
92  void OnSessionMessage(const std::string& web_session_id,
93                        const std::vector<uint8>& message,
94                        const GURL& destination_url);
95  void OnSessionKeysChange(const std::string& web_session_id,
96                           bool has_additional_usable_key);
97  void OnSessionClosed(const std::string& web_session_id);
98
99  // Handle the success/failure of a promise. These methods are responsible for
100  // calling |host_| to resolve or reject the promise.
101  void OnSessionCreated(uint32 promise_id, const std::string& web_session_id);
102  void OnSessionLoaded(uint32 promise_id, const std::string& web_session_id);
103  void OnSessionUpdated(uint32 promise_id, const std::string& web_session_id);
104  void OnUsableKeyIdsObtained(uint32 promise_id, const KeyIdsVector& key_ids);
105  void OnPromiseResolved(uint32 promise_id);
106  void OnPromiseFailed(uint32 promise_id,
107                       MediaKeys::Exception exception_code,
108                       uint32 system_code,
109                       const std::string& error_message);
110
111  // Prepares next heartbeat message and sets a timer for it.
112  void ScheduleNextHeartBeat();
113
114  // Decrypts the |encrypted_buffer| and puts the result in |decrypted_buffer|.
115  // Returns cdm::kSuccess if decryption succeeded. The decrypted result is
116  // put in |decrypted_buffer|. If |encrypted_buffer| is empty, the
117  // |decrypted_buffer| is set to an empty (EOS) buffer.
118  // Returns cdm::kNoKey if no decryption key was available. In this case
119  // |decrypted_buffer| should be ignored by the caller.
120  // Returns cdm::kDecryptError if any decryption error occurred. In this case
121  // |decrypted_buffer| should be ignored by the caller.
122  cdm::Status DecryptToMediaDecoderBuffer(
123      const cdm::InputBuffer& encrypted_buffer,
124      scoped_refptr<DecoderBuffer>* decrypted_buffer);
125
126#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
127  int64 CurrentTimeStampInMicroseconds() const;
128
129  // Generates fake video frames with |duration_in_microseconds|.
130  // Returns the number of samples generated in the |audio_frames|.
131  int GenerateFakeAudioFramesFromDuration(int64 duration_in_microseconds,
132                                          cdm::AudioFrames* audio_frames) const;
133
134  // Generates fake video frames given |input_timestamp|.
135  // Returns cdm::kSuccess if any audio frame is successfully generated.
136  cdm::Status GenerateFakeAudioFrames(int64 timestamp_in_microseconds,
137                                      cdm::AudioFrames* audio_frames);
138#endif  // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
139
140  void StartFileIOTest();
141
142  // Callback for CDM File IO test.
143  void OnFileIOTestComplete(bool success);
144
145  // Keep track of the last session created.
146  void SetSessionId(const std::string& web_session_id);
147
148  AesDecryptor decryptor_;
149
150  ClearKeyCdmHost* host_;
151
152  const std::string key_system_;
153
154  std::string last_session_id_;
155  std::string next_heartbeat_message_;
156
157  // In order to simulate LoadSession(), CreateSession() and then
158  // UpdateSession() will be called to create a session with known keys.
159  // |session_id_for_emulated_loadsession_| is used to keep track of the
160  // session_id allocated by aes_decryptor, as the session_id will be returned
161  // as |kLoadableWebSessionId|. Future requests for this simulated session
162  // need to use |session_id_for_emulated_loadsession_| for all calls
163  // to aes_decryptor.
164  // |promise_id_for_emulated_loadsession_| is used to keep track of the
165  // original LoadSession() promise, as it is not resolved until the
166  // UpdateSession() call succeeds.
167  // TODO(xhwang): Extract testing code from main implementation.
168  // See http://crbug.com/341751
169  std::string session_id_for_emulated_loadsession_;
170  uint32_t promise_id_for_emulated_loadsession_;
171
172  // Timer delay in milliseconds for the next host_->SetTimer() call.
173  int64 timer_delay_ms_;
174
175  // Indicates whether a heartbeat timer has been set to prevent multiple timers
176  // from running.
177  bool heartbeat_timer_set_;
178
179#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
180  int channel_count_;
181  int bits_per_channel_;
182  int samples_per_second_;
183  int64 output_timestamp_base_in_microseconds_;
184  int total_samples_generated_;
185#endif  // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
186
187#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
188  scoped_ptr<FFmpegCdmAudioDecoder> audio_decoder_;
189#endif  // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
190
191  scoped_ptr<CdmVideoDecoder> video_decoder_;
192
193  scoped_ptr<FileIOTestRunner> file_io_test_runner_;
194
195  DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm);
196};
197
198}  // namespace media
199
200#endif  // MEDIA_CDM_PPAPI_EXTERNAL_CLEAR_KEY_CLEAR_KEY_CDM_H_
201