1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker #ifndef VIDEO_BUFFERED_FRAME_DECRYPTOR_H_ 12*d9f75844SAndroid Build Coastguard Worker #define VIDEO_BUFFERED_FRAME_DECRYPTOR_H_ 13*d9f75844SAndroid Build Coastguard Worker 14*d9f75844SAndroid Build Coastguard Worker #include <deque> 15*d9f75844SAndroid Build Coastguard Worker #include <memory> 16*d9f75844SAndroid Build Coastguard Worker 17*d9f75844SAndroid Build Coastguard Worker #include "api/crypto/crypto_options.h" 18*d9f75844SAndroid Build Coastguard Worker #include "api/crypto/frame_decryptor_interface.h" 19*d9f75844SAndroid Build Coastguard Worker #include "api/field_trials_view.h" 20*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/frame_object.h" 21*d9f75844SAndroid Build Coastguard Worker 22*d9f75844SAndroid Build Coastguard Worker namespace webrtc { 23*d9f75844SAndroid Build Coastguard Worker 24*d9f75844SAndroid Build Coastguard Worker // This callback is provided during the construction of the 25*d9f75844SAndroid Build Coastguard Worker // BufferedFrameDecryptor and is called each time a frame is sucessfully 26*d9f75844SAndroid Build Coastguard Worker // decrypted by the buffer. 27*d9f75844SAndroid Build Coastguard Worker class OnDecryptedFrameCallback { 28*d9f75844SAndroid Build Coastguard Worker public: 29*d9f75844SAndroid Build Coastguard Worker virtual ~OnDecryptedFrameCallback() = default; 30*d9f75844SAndroid Build Coastguard Worker // Called each time a decrypted frame is returned. 31*d9f75844SAndroid Build Coastguard Worker virtual void OnDecryptedFrame(std::unique_ptr<RtpFrameObject> frame) = 0; 32*d9f75844SAndroid Build Coastguard Worker }; 33*d9f75844SAndroid Build Coastguard Worker 34*d9f75844SAndroid Build Coastguard Worker // This callback is called each time there is a status change in the decryption 35*d9f75844SAndroid Build Coastguard Worker // stream. For example going from a none state to a first decryption or going 36*d9f75844SAndroid Build Coastguard Worker // frome a decryptable state to a non decryptable state. 37*d9f75844SAndroid Build Coastguard Worker class OnDecryptionStatusChangeCallback { 38*d9f75844SAndroid Build Coastguard Worker public: 39*d9f75844SAndroid Build Coastguard Worker virtual ~OnDecryptionStatusChangeCallback() = default; 40*d9f75844SAndroid Build Coastguard Worker // Called each time the decryption stream status changes. This call is 41*d9f75844SAndroid Build Coastguard Worker // blocking so the caller must relinquish the callback quickly. This status 42*d9f75844SAndroid Build Coastguard Worker // must match what is specified in the FrameDecryptorInterface file. Notably 43*d9f75844SAndroid Build Coastguard Worker // 0 must indicate success and any positive integer is a failure. 44*d9f75844SAndroid Build Coastguard Worker virtual void OnDecryptionStatusChange( 45*d9f75844SAndroid Build Coastguard Worker FrameDecryptorInterface::Status status) = 0; 46*d9f75844SAndroid Build Coastguard Worker }; 47*d9f75844SAndroid Build Coastguard Worker 48*d9f75844SAndroid Build Coastguard Worker // The BufferedFrameDecryptor is responsible for deciding when to pass 49*d9f75844SAndroid Build Coastguard Worker // decrypted received frames onto the OnDecryptedFrameCallback. Frames can be 50*d9f75844SAndroid Build Coastguard Worker // delayed when frame encryption is enabled but the key hasn't arrived yet. In 51*d9f75844SAndroid Build Coastguard Worker // this case we stash about 1 second of encrypted frames instead of dropping 52*d9f75844SAndroid Build Coastguard Worker // them to prevent re-requesting the key frame. This optimization is 53*d9f75844SAndroid Build Coastguard Worker // particularly important on low bandwidth networks. Note stashing is only ever 54*d9f75844SAndroid Build Coastguard Worker // done if we have never sucessfully decrypted a frame before. After the first 55*d9f75844SAndroid Build Coastguard Worker // successful decryption payloads will never be stashed. 56*d9f75844SAndroid Build Coastguard Worker class BufferedFrameDecryptor final { 57*d9f75844SAndroid Build Coastguard Worker public: 58*d9f75844SAndroid Build Coastguard Worker // Constructs a new BufferedFrameDecryptor that can hold 59*d9f75844SAndroid Build Coastguard Worker explicit BufferedFrameDecryptor( 60*d9f75844SAndroid Build Coastguard Worker OnDecryptedFrameCallback* decrypted_frame_callback, 61*d9f75844SAndroid Build Coastguard Worker OnDecryptionStatusChangeCallback* decryption_status_change_callback, 62*d9f75844SAndroid Build Coastguard Worker const FieldTrialsView& field_trials); 63*d9f75844SAndroid Build Coastguard Worker 64*d9f75844SAndroid Build Coastguard Worker ~BufferedFrameDecryptor(); 65*d9f75844SAndroid Build Coastguard Worker // This object cannot be copied. 66*d9f75844SAndroid Build Coastguard Worker BufferedFrameDecryptor(const BufferedFrameDecryptor&) = delete; 67*d9f75844SAndroid Build Coastguard Worker BufferedFrameDecryptor& operator=(const BufferedFrameDecryptor&) = delete; 68*d9f75844SAndroid Build Coastguard Worker 69*d9f75844SAndroid Build Coastguard Worker // Sets a new frame decryptor as the decryptor for the buffered frame 70*d9f75844SAndroid Build Coastguard Worker // decryptor. This allows the decryptor to be switched out without resetting 71*d9f75844SAndroid Build Coastguard Worker // the video stream. 72*d9f75844SAndroid Build Coastguard Worker void SetFrameDecryptor( 73*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor); 74*d9f75844SAndroid Build Coastguard Worker 75*d9f75844SAndroid Build Coastguard Worker // Determines whether the frame should be stashed, dropped or handed off to 76*d9f75844SAndroid Build Coastguard Worker // the OnDecryptedFrameCallback. 77*d9f75844SAndroid Build Coastguard Worker void ManageEncryptedFrame(std::unique_ptr<RtpFrameObject> encrypted_frame); 78*d9f75844SAndroid Build Coastguard Worker 79*d9f75844SAndroid Build Coastguard Worker private: 80*d9f75844SAndroid Build Coastguard Worker // Represents what should be done with a given frame. 81*d9f75844SAndroid Build Coastguard Worker enum class FrameDecision { kStash, kDecrypted, kDrop }; 82*d9f75844SAndroid Build Coastguard Worker 83*d9f75844SAndroid Build Coastguard Worker // Attempts to decrypt the frame, if it fails and no prior frames have been 84*d9f75844SAndroid Build Coastguard Worker // decrypted it will return kStash. Otherwise fail to decrypts will return 85*d9f75844SAndroid Build Coastguard Worker // kDrop. Successful decryptions will always return kDecrypted. 86*d9f75844SAndroid Build Coastguard Worker FrameDecision DecryptFrame(RtpFrameObject* frame); 87*d9f75844SAndroid Build Coastguard Worker // Retries all the stashed frames this is triggered each time a kDecrypted 88*d9f75844SAndroid Build Coastguard Worker // event occurs. 89*d9f75844SAndroid Build Coastguard Worker void RetryStashedFrames(); 90*d9f75844SAndroid Build Coastguard Worker 91*d9f75844SAndroid Build Coastguard Worker static const size_t kMaxStashedFrames = 24; 92*d9f75844SAndroid Build Coastguard Worker 93*d9f75844SAndroid Build Coastguard Worker const bool generic_descriptor_auth_experiment_; 94*d9f75844SAndroid Build Coastguard Worker bool first_frame_decrypted_ = false; 95*d9f75844SAndroid Build Coastguard Worker FrameDecryptorInterface::Status last_status_ = 96*d9f75844SAndroid Build Coastguard Worker FrameDecryptorInterface::Status::kUnknown; 97*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_; 98*d9f75844SAndroid Build Coastguard Worker OnDecryptedFrameCallback* const decrypted_frame_callback_; 99*d9f75844SAndroid Build Coastguard Worker OnDecryptionStatusChangeCallback* const decryption_status_change_callback_; 100*d9f75844SAndroid Build Coastguard Worker std::deque<std::unique_ptr<RtpFrameObject>> stashed_frames_; 101*d9f75844SAndroid Build Coastguard Worker }; 102*d9f75844SAndroid Build Coastguard Worker 103*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc 104*d9f75844SAndroid Build Coastguard Worker 105*d9f75844SAndroid Build Coastguard Worker #endif // VIDEO_BUFFERED_FRAME_DECRYPTOR_H_ 106