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 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_RENDERER_PEPPER_CONTENT_DECRYPTOR_DELEGATE_H_ 6 #define CONTENT_RENDERER_PEPPER_CONTENT_DECRYPTOR_DELEGATE_H_ 7 8 #include <map> 9 #include <queue> 10 #include <string> 11 12 #include "base/basictypes.h" 13 #include "base/callback_helpers.h" 14 #include "base/compiler_specific.h" 15 #include "base/containers/scoped_ptr_hash_map.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/memory/weak_ptr.h" 18 #include "media/base/cdm_promise.h" 19 #include "media/base/channel_layout.h" 20 #include "media/base/decryptor.h" 21 #include "media/base/media_keys.h" 22 #include "media/base/sample_format.h" 23 #include "ppapi/c/pp_time.h" 24 #include "ppapi/c/private/pp_content_decryptor.h" 25 #include "ppapi/c/private/ppp_content_decryptor_private.h" 26 #include "ui/gfx/size.h" 27 28 namespace media { 29 class AudioDecoderConfig; 30 class DecoderBuffer; 31 class VideoDecoderConfig; 32 } 33 34 namespace content { 35 36 class PPB_Buffer_Impl; 37 38 class ContentDecryptorDelegate { 39 public: 40 // ContentDecryptorDelegate does not take ownership of 41 // |plugin_decryption_interface|. Therefore |plugin_decryption_interface| 42 // must outlive this object. 43 ContentDecryptorDelegate( 44 PP_Instance pp_instance, 45 const PPP_ContentDecryptor_Private* plugin_decryption_interface); 46 ~ContentDecryptorDelegate(); 47 48 // This object should not be accessed after |fatal_plugin_error_cb| is called. 49 void Initialize( 50 const std::string& key_system, 51 const media::SessionMessageCB& session_message_cb, 52 const media::SessionReadyCB& session_ready_cb, 53 const media::SessionClosedCB& session_closed_cb, 54 const media::SessionErrorCB& session_error_cb, 55 const media::SessionKeysChangeCB& session_keys_change_cb, 56 const media::SessionExpirationUpdateCB& session_expiration_update_cb, 57 const base::Closure& fatal_plugin_error_cb); 58 59 void InstanceCrashed(); 60 61 // Provides access to PPP_ContentDecryptor_Private. 62 void SetServerCertificate(const uint8_t* certificate, 63 uint32_t certificate_length, 64 scoped_ptr<media::SimpleCdmPromise> promise); 65 void CreateSession(const std::string& init_data_type, 66 const uint8* init_data, 67 int init_data_length, 68 media::MediaKeys::SessionType session_type, 69 scoped_ptr<media::NewSessionCdmPromise> promise); 70 void LoadSession(const std::string& web_session_id, 71 scoped_ptr<media::NewSessionCdmPromise> promise); 72 void UpdateSession(const std::string& web_session_id, 73 const uint8* response, 74 int response_length, 75 scoped_ptr<media::SimpleCdmPromise> promise); 76 void CloseSession(const std::string& web_session_id, 77 scoped_ptr<media::SimpleCdmPromise> promise); 78 void RemoveSession(const std::string& web_session_id, 79 scoped_ptr<media::SimpleCdmPromise> promise); 80 void GetUsableKeyIds(const std::string& web_session_id, 81 scoped_ptr<media::KeyIdsPromise> promise); 82 bool Decrypt(media::Decryptor::StreamType stream_type, 83 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 84 const media::Decryptor::DecryptCB& decrypt_cb); 85 bool CancelDecrypt(media::Decryptor::StreamType stream_type); 86 bool InitializeAudioDecoder( 87 const media::AudioDecoderConfig& decoder_config, 88 const media::Decryptor::DecoderInitCB& decoder_init_cb); 89 bool InitializeVideoDecoder( 90 const media::VideoDecoderConfig& decoder_config, 91 const media::Decryptor::DecoderInitCB& decoder_init_cb); 92 // TODO(tomfinegan): Add callback args for DeinitializeDecoder() and 93 // ResetDecoder() 94 bool DeinitializeDecoder(media::Decryptor::StreamType stream_type); 95 bool ResetDecoder(media::Decryptor::StreamType stream_type); 96 // Note: These methods can be used with unencrypted data. 97 bool DecryptAndDecodeAudio( 98 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 99 const media::Decryptor::AudioDecodeCB& audio_decode_cb); 100 bool DecryptAndDecodeVideo( 101 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 102 const media::Decryptor::VideoDecodeCB& video_decode_cb); 103 104 // PPB_ContentDecryptor_Private dispatching methods. 105 void OnPromiseResolved(uint32 promise_id); 106 void OnPromiseResolvedWithSession(uint32 promise_id, PP_Var web_session_id); 107 void OnPromiseResolvedWithKeyIds(uint32 promise_id, PP_Var key_ids_array); 108 void OnPromiseRejected(uint32 promise_id, 109 PP_CdmExceptionCode exception_code, 110 uint32 system_code, 111 PP_Var error_description); 112 void OnSessionMessage(PP_Var web_session_id, 113 PP_Var message, 114 PP_Var destination_url); 115 void OnSessionKeysChange(PP_Var web_session_id, 116 PP_Bool has_additional_usable_key); 117 void OnSessionExpirationChange(PP_Var web_session_id, 118 PP_Time new_expiry_time); 119 void OnSessionReady(PP_Var web_session_id); 120 void OnSessionClosed(PP_Var web_session_id); 121 void OnSessionError(PP_Var web_session_id, 122 PP_CdmExceptionCode exception_code, 123 uint32 system_code, 124 PP_Var error_description); 125 void DeliverBlock(PP_Resource decrypted_block, 126 const PP_DecryptedBlockInfo* block_info); 127 void DecoderInitializeDone(PP_DecryptorStreamType decoder_type, 128 uint32_t request_id, 129 PP_Bool success); 130 void DecoderDeinitializeDone(PP_DecryptorStreamType decoder_type, 131 uint32_t request_id); 132 void DecoderResetDone(PP_DecryptorStreamType decoder_type, 133 uint32_t request_id); 134 void DeliverFrame(PP_Resource decrypted_frame, 135 const PP_DecryptedFrameInfo* frame_info); 136 void DeliverSamples(PP_Resource audio_frames, 137 const PP_DecryptedSampleInfo* sample_info); 138 139 private: 140 // The following types keep track of Promises. The index is the promise_id, 141 // so that returning results can be matched to the corresponding promise. 142 typedef base::ScopedPtrHashMap<uint32_t, media::CdmPromise> PromiseMap; 143 144 template <typename Callback> 145 class TrackableCallback { 146 public: 147 TrackableCallback() : id_(0u) {} 148 ~TrackableCallback() { 149 // Callbacks must be satisfied. 150 DCHECK_EQ(id_, 0u); 151 DCHECK(is_null()); 152 }; 153 154 bool Matches(uint32_t id) const { return id == id_; } 155 156 bool is_null() const { return cb_.is_null(); } 157 158 void Set(uint32_t id, const Callback& cb) { 159 DCHECK_EQ(id_, 0u); 160 DCHECK(cb_.is_null()); 161 id_ = id; 162 cb_ = cb; 163 } 164 165 Callback ResetAndReturn() { 166 id_ = 0; 167 return base::ResetAndReturn(&cb_); 168 } 169 170 private: 171 uint32_t id_; 172 Callback cb_; 173 }; 174 175 // Cancels the pending decrypt-and-decode callback for |stream_type|. 176 void CancelDecode(media::Decryptor::StreamType stream_type); 177 178 // Fills |resource| with a PPB_Buffer_Impl and copies the data from 179 // |encrypted_buffer| into the buffer resource. This method reuses 180 // |audio_input_resource_| and |video_input_resource_| to reduce the latency 181 // in requesting new PPB_Buffer_Impl resources. The caller must make sure that 182 // |audio_input_resource_| or |video_input_resource_| is available before 183 // calling this method. 184 // 185 // An end of stream |encrypted_buffer| is represented as a null |resource|. 186 // 187 // Returns true upon success and false if any error happened. 188 bool MakeMediaBufferResource( 189 media::Decryptor::StreamType stream_type, 190 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, 191 scoped_refptr<PPB_Buffer_Impl>* resource); 192 193 void FreeBuffer(uint32_t buffer_id); 194 195 void SetBufferToFreeInTrackingInfo(PP_DecryptTrackingInfo* tracking_info); 196 197 // Deserializes audio data stored in |audio_frames| into individual audio 198 // buffers in |frames|. Returns true upon success. 199 bool DeserializeAudioFrames(PP_Resource audio_frames, 200 size_t data_size, 201 media::SampleFormat sample_format, 202 media::Decryptor::AudioBuffers* frames); 203 204 void SatisfyAllPendingCallbacksOnError(); 205 206 // Takes ownership of |promise| and returns an identifier to be passed via 207 // Pepper. 208 uint32_t SavePromise(scoped_ptr<media::CdmPromise> promise); 209 210 // Find the promise for a specified |promise_id|. Caller is responsible to 211 // delete the CdmPromise<> once done with it. 212 scoped_ptr<media::CdmPromise> TakePromise(uint32_t promise_id); 213 214 const PP_Instance pp_instance_; 215 const PPP_ContentDecryptor_Private* const plugin_decryption_interface_; 216 217 // TODO(ddorwin): Remove after updating the Pepper API to not use key system. 218 std::string key_system_; 219 220 // Callbacks for firing session events. 221 media::SessionMessageCB session_message_cb_; 222 media::SessionReadyCB session_ready_cb_; 223 media::SessionClosedCB session_closed_cb_; 224 media::SessionErrorCB session_error_cb_; 225 media::SessionKeysChangeCB session_keys_change_cb_; 226 media::SessionExpirationUpdateCB session_expiration_update_cb_; 227 228 // Callback to notify that unexpected error happened and |this| should not 229 // be used anymore. 230 base::Closure fatal_plugin_error_cb_; 231 232 gfx::Size natural_size_; 233 234 // Request ID for tracking pending content decryption callbacks. 235 // Note that zero indicates an invalid request ID. 236 // TODO(xhwang): Add completion callbacks for Reset/Stop and remove the use 237 // of request IDs. 238 uint32_t next_decryption_request_id_; 239 240 TrackableCallback<media::Decryptor::DecryptCB> audio_decrypt_cb_; 241 TrackableCallback<media::Decryptor::DecryptCB> video_decrypt_cb_; 242 TrackableCallback<media::Decryptor::DecoderInitCB> audio_decoder_init_cb_; 243 TrackableCallback<media::Decryptor::DecoderInitCB> video_decoder_init_cb_; 244 TrackableCallback<media::Decryptor::AudioDecodeCB> audio_decode_cb_; 245 TrackableCallback<media::Decryptor::VideoDecodeCB> video_decode_cb_; 246 247 // Cached audio and video input buffers. See MakeMediaBufferResource. 248 scoped_refptr<PPB_Buffer_Impl> audio_input_resource_; 249 scoped_refptr<PPB_Buffer_Impl> video_input_resource_; 250 251 std::queue<uint32_t> free_buffers_; 252 253 // Keep track of audio parameters. 254 int audio_samples_per_second_; 255 int audio_channel_count_; 256 media::ChannelLayout audio_channel_layout_; 257 258 // Keep track of outstanding promises. Maps have ownership of the promises. 259 uint32_t next_promise_id_; 260 PromiseMap promises_; 261 262 base::WeakPtr<ContentDecryptorDelegate> weak_this_; 263 base::WeakPtrFactory<ContentDecryptorDelegate> weak_ptr_factory_; 264 265 DISALLOW_COPY_AND_ASSIGN(ContentDecryptorDelegate); 266 }; 267 268 } // namespace content 269 270 #endif // CONTENT_RENDERER_PEPPER_CONTENT_DECRYPTOR_DELEGATE_H_ 271