webrtc_m130/video/buffered_frame_decryptor.h
Benjamin Wright a556448138 Don't recreate the VideoReceiveStream on SetFrameDecryptor in the MediaEngine.
This change introduces new logic to allow the injection of the FrameDecryptor
into an arbitrary already running VideoReceiveStream without resetting it. It
does this by taking advantage of the BufferedFrameDecryptor which will
forcefully be created regardless of whether a FrameDecryptor is passed in
during construction of the VideoReceiver if the
crypto_option.require_frame_encryption is true. By allowing the
BufferedFrameDecryptor to swap out which FrameDecryptor it uses this allows the
Receiver to switch decryptors without resetting the stream.

This is intended to mostly be used when you set your FrameDecryptor at a point
post creation for the first time.

Bug: webrtc:10416
Change-Id: If656b2acc447e2e77537cfa394729e5c3a8b660a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/130361
Commit-Queue: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27458}
2019-04-05 07:58:05 +00:00

104 lines
4.3 KiB
C++

/*
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef VIDEO_BUFFERED_FRAME_DECRYPTOR_H_
#define VIDEO_BUFFERED_FRAME_DECRYPTOR_H_
#include <deque>
#include <memory>
#include "api/crypto/crypto_options.h"
#include "api/crypto/frame_decryptor_interface.h"
#include "modules/include/module_common_types.h"
#include "modules/video_coding/frame_object.h"
namespace webrtc {
// This callback is provided during the construction of the
// BufferedFrameDecryptor and is called each time a frame is sucessfully
// decrypted by the buffer.
class OnDecryptedFrameCallback {
public:
virtual ~OnDecryptedFrameCallback() = default;
// Called each time a decrypted frame is returned.
virtual void OnDecryptedFrame(
std::unique_ptr<video_coding::RtpFrameObject> frame) = 0;
};
// This callback is called each time there is a status change in the decryption
// stream. For example going from a none state to a first decryption or going
// frome a decryptable state to a non decryptable state.
class OnDecryptionStatusChangeCallback {
public:
virtual ~OnDecryptionStatusChangeCallback() = default;
// Called each time the decryption stream status changes. This call is
// blocking so the caller must relinquish the callback quickly. This status
// must match what is specified in the FrameDecryptorInterface file. Notably
// 0 must indicate success and any positive integer is a failure.
virtual void OnDecryptionStatusChange(int status) = 0;
};
// The BufferedFrameDecryptor is responsible for deciding when to pass
// decrypted received frames onto the OnDecryptedFrameCallback. Frames can be
// delayed when frame encryption is enabled but the key hasn't arrived yet. In
// this case we stash about 1 second of encrypted frames instead of dropping
// them to prevent re-requesting the key frame. This optimization is
// particularly important on low bandwidth networks. Note stashing is only ever
// done if we have never sucessfully decrypted a frame before. After the first
// successful decryption payloads will never be stashed.
class BufferedFrameDecryptor final {
public:
// Constructs a new BufferedFrameDecryptor that can hold
explicit BufferedFrameDecryptor(
OnDecryptedFrameCallback* decrypted_frame_callback,
OnDecryptionStatusChangeCallback* decryption_status_change_callback);
~BufferedFrameDecryptor();
// This object cannot be copied.
BufferedFrameDecryptor(const BufferedFrameDecryptor&) = delete;
BufferedFrameDecryptor& operator=(const BufferedFrameDecryptor&) = delete;
// Sets a new frame decryptor as the decryptor for the buffered frame
// decryptor. This allows the decryptor to be switched out without resetting
// the video stream.
void SetFrameDecryptor(
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor);
// Determines whether the frame should be stashed, dropped or handed off to
// the OnDecryptedFrameCallback.
void ManageEncryptedFrame(
std::unique_ptr<video_coding::RtpFrameObject> encrypted_frame);
private:
// Represents what should be done with a given frame.
enum class FrameDecision { kStash, kDecrypted, kDrop };
// Attempts to decrypt the frame, if it fails and no prior frames have been
// decrypted it will return kStash. Otherwise fail to decrypts will return
// kDrop. Successful decryptions will always return kDecrypted.
FrameDecision DecryptFrame(video_coding::RtpFrameObject* frame);
// Retries all the stashed frames this is triggered each time a kDecrypted
// event occurs.
void RetryStashedFrames();
static const size_t kMaxStashedFrames = 24;
const bool generic_descriptor_auth_experiment_;
bool first_frame_decrypted_ = false;
int last_status_ = -1;
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
OnDecryptedFrameCallback* const decrypted_frame_callback_;
OnDecryptionStatusChangeCallback* const decryption_status_change_callback_;
std::deque<std::unique_ptr<video_coding::RtpFrameObject>> stashed_frames_;
};
} // namespace webrtc
#endif // VIDEO_BUFFERED_FRAME_DECRYPTOR_H_