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