Files
platform-external-webrtc/video/buffered_frame_decryptor.cc
Benjamin Wright 2af5dcbe9e Reland "Refactor FrameDecryptorInterface::Decrypt to use new API."
This reverts commit 7dd83e2bf73a7f1746c5ee976939bf52e19fa8be.

Reason for revert: This wasn't the cause of the break. 

Original change's description:
> Revert "Refactor FrameDecryptorInterface::Decrypt to use new API."
> 
> This reverts commit 642aa81f7d5cc55d5b99e2abc51327eed9d40195.
> 
> Reason for revert: Speculative revert. The chromium roll is failing:
> https://ci.chromium.org/p/chromium/builders/try/linux-rel/64388
> But I can't figure out exactly what is failing, this looks suspecious.
> 
> Original change's description:
> > Refactor FrameDecryptorInterface::Decrypt to use new API.
> > 
> > This change refactors the FrameDecryptorInterface to use the new API. The new
> > API surface simply moves bytes_written to the return type and implements a
> > simple Status type.
> > 
> > Bug: webrtc:10512
> > Change-Id: I622c5d344d58e618853c94c2f691cf7c8fb73a36
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131460
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
> > Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
> > Reviewed-by: Stefan Holmer <stefan@webrtc.org>
> > Commit-Queue: Benjamin Wright <benwright@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#27497}
> 
> TBR=brandtr@webrtc.org,steveanton@webrtc.org,solenberg@webrtc.org,ossu@webrtc.org,stefan@webrtc.org,benwright@webrtc.org
> 
> Change-Id: Ia9ec70263762c34671af13f0d519e636eb8473cd
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: webrtc:10512
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132013
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27510}

TBR=brandtr@webrtc.org,steveanton@webrtc.org,solenberg@webrtc.org,hbos@webrtc.org,ossu@webrtc.org,stefan@webrtc.org,benwright@webrtc.org

Change-Id: I8e4b7965cf1d1a1554c3b46e6245f5ad0d2dcbb4
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:10512
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131982
Reviewed-by: Benjamin Wright <benwright@webrtc.org>
Commit-Queue: Benjamin Wright <benwright@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27529}
2019-04-09 20:08:56 +00:00

128 lines
4.8 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.
*/
#include "video/buffered_frame_decryptor.h"
#include <utility>
#include "rtc_base/logging.h"
#include "rtc_base/system/fallthrough.h"
#include "system_wrappers/include/field_trial.h"
namespace webrtc {
BufferedFrameDecryptor::BufferedFrameDecryptor(
OnDecryptedFrameCallback* decrypted_frame_callback,
OnDecryptionStatusChangeCallback* decryption_status_change_callback)
: generic_descriptor_auth_experiment_(
field_trial::IsEnabled("WebRTC-GenericDescriptorAuth")),
decrypted_frame_callback_(decrypted_frame_callback),
decryption_status_change_callback_(decryption_status_change_callback) {}
BufferedFrameDecryptor::~BufferedFrameDecryptor() {}
void BufferedFrameDecryptor::SetFrameDecryptor(
rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
frame_decryptor_ = std::move(frame_decryptor);
}
void BufferedFrameDecryptor::ManageEncryptedFrame(
std::unique_ptr<video_coding::RtpFrameObject> encrypted_frame) {
switch (DecryptFrame(encrypted_frame.get())) {
case FrameDecision::kStash:
if (stashed_frames_.size() >= kMaxStashedFrames) {
RTC_LOG(LS_WARNING) << "Encrypted frame stash full poping oldest item.";
stashed_frames_.pop_front();
}
stashed_frames_.push_back(std::move(encrypted_frame));
break;
case FrameDecision::kDecrypted:
RetryStashedFrames();
decrypted_frame_callback_->OnDecryptedFrame(std::move(encrypted_frame));
break;
case FrameDecision::kDrop:
break;
}
}
BufferedFrameDecryptor::FrameDecision BufferedFrameDecryptor::DecryptFrame(
video_coding::RtpFrameObject* frame) {
// Optionally attempt to decrypt the raw video frame if it was provided.
if (frame_decryptor_ == nullptr) {
RTC_LOG(LS_INFO) << "Frame decryption required but not attached to this "
"stream. Stashing frame.";
return FrameDecision::kStash;
}
// When using encryption we expect the frame to have the generic descriptor.
absl::optional<RtpGenericFrameDescriptor> descriptor =
frame->GetGenericFrameDescriptor();
if (!descriptor) {
RTC_LOG(LS_ERROR) << "No generic frame descriptor found dropping frame.";
return FrameDecision::kDrop;
}
// Retrieve the maximum possible size of the decrypted payload.
const size_t max_plaintext_byte_size =
frame_decryptor_->GetMaxPlaintextByteSize(cricket::MEDIA_TYPE_VIDEO,
frame->size());
RTC_CHECK_LE(max_plaintext_byte_size, frame->size());
// Place the decrypted frame inline into the existing frame.
rtc::ArrayView<uint8_t> inline_decrypted_bitstream(frame->data(),
max_plaintext_byte_size);
// Only enable authenticating the header if the field trial is enabled.
rtc::ArrayView<const uint8_t> additional_data;
if (generic_descriptor_auth_experiment_) {
additional_data = descriptor->GetByteRepresentation();
}
// Attempt to decrypt the video frame.
const FrameDecryptorInterface::Result decrypt_result =
frame_decryptor_->Decrypt(cricket::MEDIA_TYPE_VIDEO, /*csrcs=*/{},
additional_data, *frame,
inline_decrypted_bitstream);
// Optionally call the callback if there was a change in status
if (decrypt_result.status != last_status_) {
last_status_ = decrypt_result.status;
decryption_status_change_callback_->OnDecryptionStatusChange(
decrypt_result.status);
}
if (!decrypt_result.IsOk()) {
// Only stash frames if we have never decrypted a frame before.
return first_frame_decrypted_ ? FrameDecision::kDrop
: FrameDecision::kStash;
}
RTC_CHECK_LE(decrypt_result.bytes_written, max_plaintext_byte_size);
// Update the frame to contain just the written bytes.
frame->set_size(decrypt_result.bytes_written);
// Indicate that all future fail to decrypt frames should be dropped.
if (!first_frame_decrypted_) {
first_frame_decrypted_ = true;
}
return FrameDecision::kDecrypted;
}
void BufferedFrameDecryptor::RetryStashedFrames() {
if (!stashed_frames_.empty()) {
RTC_LOG(LS_INFO) << "Retrying stashed encrypted frames. Count: "
<< stashed_frames_.size();
}
for (auto& frame : stashed_frames_) {
if (DecryptFrame(frame.get()) == FrameDecision::kDecrypted) {
decrypted_frame_callback_->OnDecryptedFrame(std::move(frame));
}
}
stashed_frames_.clear();
}
} // namespace webrtc