summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc')
-rw-r--r--third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc266
1 files changed, 266 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
new file mode 100644
index 0000000000..9d7c58d19a
--- /dev/null
+++ b/third_party/libwebrtc/modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.cc
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2020 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 "modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "api/sequence_checker.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/event.h"
+
+namespace webrtc {
+namespace {
+
+class TransformableVideoSenderFrame : public TransformableVideoFrameInterface {
+ public:
+ TransformableVideoSenderFrame(const EncodedImage& encoded_image,
+ const RTPVideoHeader& video_header,
+ int payload_type,
+ absl::optional<VideoCodecType> codec_type,
+ uint32_t rtp_timestamp,
+ TimeDelta expected_retransmission_time,
+ uint32_t ssrc,
+ std::vector<uint32_t> csrcs,
+ const std::string& rid)
+ : encoded_data_(encoded_image.GetEncodedData()),
+ pre_transform_payload_size_(encoded_image.size()),
+ header_(video_header),
+ frame_type_(encoded_image._frameType),
+ payload_type_(payload_type),
+ codec_type_(codec_type),
+ timestamp_(rtp_timestamp),
+ capture_time_(encoded_image.CaptureTime()),
+ capture_time_identifier_(encoded_image.CaptureTimeIdentifier()),
+ expected_retransmission_time_(expected_retransmission_time),
+ ssrc_(ssrc),
+ csrcs_(csrcs),
+ rid_(rid) {
+ RTC_DCHECK_GE(payload_type_, 0);
+ RTC_DCHECK_LE(payload_type_, 127);
+ }
+
+ ~TransformableVideoSenderFrame() override = default;
+
+ // Implements TransformableVideoFrameInterface.
+ rtc::ArrayView<const uint8_t> GetData() const override {
+ return *encoded_data_;
+ }
+
+ void SetData(rtc::ArrayView<const uint8_t> data) override {
+ encoded_data_ = EncodedImageBuffer::Create(data.data(), data.size());
+ }
+
+ size_t GetPreTransformPayloadSize() const {
+ return pre_transform_payload_size_;
+ }
+
+ uint32_t GetTimestamp() const override { return timestamp_; }
+ void SetRTPTimestamp(uint32_t timestamp) override { timestamp_ = timestamp; }
+
+ uint32_t GetSsrc() const override { return ssrc_; }
+
+ bool IsKeyFrame() const override {
+ return frame_type_ == VideoFrameType::kVideoFrameKey;
+ }
+
+ VideoFrameMetadata Metadata() const override {
+ VideoFrameMetadata metadata = header_.GetAsMetadata();
+ metadata.SetSsrc(ssrc_);
+ metadata.SetCsrcs(csrcs_);
+ return metadata;
+ }
+
+ void SetMetadata(const VideoFrameMetadata& metadata) override {
+ header_.SetFromMetadata(metadata);
+ ssrc_ = metadata.GetSsrc();
+ csrcs_ = metadata.GetCsrcs();
+ }
+
+ const RTPVideoHeader& GetHeader() const { return header_; }
+ uint8_t GetPayloadType() const override { return payload_type_; }
+ absl::optional<VideoCodecType> GetCodecType() const { return codec_type_; }
+ Timestamp GetCaptureTime() const { return capture_time_; }
+ absl::optional<Timestamp> GetCaptureTimeIdentifier() const override {
+ return capture_time_identifier_;
+ }
+
+ TimeDelta GetExpectedRetransmissionTime() const {
+ return expected_retransmission_time_;
+ }
+
+ Direction GetDirection() const override { return Direction::kSender; }
+ std::string GetMimeType() const override {
+ if (!codec_type_.has_value()) {
+ return "video/x-unknown";
+ }
+ std::string mime_type = "video/";
+ return mime_type + CodecTypeToPayloadString(*codec_type_);
+ }
+
+ const std::string& GetRid() const override { return rid_; }
+
+ private:
+ rtc::scoped_refptr<EncodedImageBufferInterface> encoded_data_;
+ const size_t pre_transform_payload_size_;
+ RTPVideoHeader header_;
+ const VideoFrameType frame_type_;
+ const uint8_t payload_type_;
+ const absl::optional<VideoCodecType> codec_type_ = absl::nullopt;
+ uint32_t timestamp_;
+ const Timestamp capture_time_;
+ const absl::optional<Timestamp> capture_time_identifier_;
+ const TimeDelta expected_retransmission_time_;
+
+ uint32_t ssrc_;
+ std::vector<uint32_t> csrcs_;
+ const std::string rid_;
+};
+} // namespace
+
+RTPSenderVideoFrameTransformerDelegate::RTPSenderVideoFrameTransformerDelegate(
+ RTPVideoFrameSenderInterface* sender,
+ rtc::scoped_refptr<FrameTransformerInterface> frame_transformer,
+ uint32_t ssrc,
+ const std::string& rid,
+ TaskQueueFactory* task_queue_factory)
+ : sender_(sender),
+ frame_transformer_(std::move(frame_transformer)),
+ ssrc_(ssrc),
+ rid_(rid),
+ transformation_queue_(task_queue_factory->CreateTaskQueue(
+ "video_frame_transformer",
+ TaskQueueFactory::Priority::NORMAL)) {}
+
+void RTPSenderVideoFrameTransformerDelegate::Init() {
+ frame_transformer_->RegisterTransformedFrameSinkCallback(
+ rtc::scoped_refptr<TransformedFrameCallback>(this), ssrc_);
+}
+
+bool RTPSenderVideoFrameTransformerDelegate::TransformFrame(
+ int payload_type,
+ absl::optional<VideoCodecType> codec_type,
+ uint32_t rtp_timestamp,
+ const EncodedImage& encoded_image,
+ RTPVideoHeader video_header,
+ TimeDelta expected_retransmission_time) {
+ frame_transformer_->Transform(std::make_unique<TransformableVideoSenderFrame>(
+ encoded_image, video_header, payload_type, codec_type, rtp_timestamp,
+ expected_retransmission_time, ssrc_,
+ /*csrcs=*/std::vector<uint32_t>(), rid_));
+ return true;
+}
+
+void RTPSenderVideoFrameTransformerDelegate::OnTransformedFrame(
+ std::unique_ptr<TransformableFrameInterface> frame) {
+ MutexLock lock(&sender_lock_);
+
+ if (!sender_) {
+ return;
+ }
+ rtc::scoped_refptr<RTPSenderVideoFrameTransformerDelegate> delegate(this);
+ transformation_queue_->PostTask(
+ [delegate = std::move(delegate), frame = std::move(frame)]() mutable {
+ RTC_DCHECK_RUN_ON(delegate->transformation_queue_.get());
+ delegate->SendVideo(std::move(frame));
+ });
+}
+
+void RTPSenderVideoFrameTransformerDelegate::SendVideo(
+ std::unique_ptr<TransformableFrameInterface> transformed_frame) const {
+ RTC_DCHECK_RUN_ON(transformation_queue_.get());
+ MutexLock lock(&sender_lock_);
+ if (!sender_)
+ return;
+ if (transformed_frame->GetDirection() ==
+ TransformableFrameInterface::Direction::kSender) {
+ auto* transformed_video_frame =
+ static_cast<TransformableVideoSenderFrame*>(transformed_frame.get());
+ sender_->SendVideo(transformed_video_frame->GetPayloadType(),
+ transformed_video_frame->GetCodecType(),
+ transformed_video_frame->GetTimestamp(),
+ transformed_video_frame->GetCaptureTime(),
+ transformed_video_frame->GetData(),
+ transformed_video_frame->GetPreTransformPayloadSize(),
+ transformed_video_frame->GetHeader(),
+ transformed_video_frame->GetExpectedRetransmissionTime(),
+ transformed_video_frame->Metadata().GetCsrcs());
+ } else {
+ auto* transformed_video_frame =
+ static_cast<TransformableVideoFrameInterface*>(transformed_frame.get());
+ VideoFrameMetadata metadata = transformed_video_frame->Metadata();
+ sender_->SendVideo(
+ transformed_video_frame->GetPayloadType(), metadata.GetCodec(),
+ transformed_video_frame->GetTimestamp(),
+ /*capture_time=*/Timestamp::MinusInfinity(),
+ transformed_video_frame->GetData(),
+ transformed_video_frame->GetData().size(),
+ RTPVideoHeader::FromMetadata(metadata),
+ /*expected_retransmission_time=*/TimeDelta::PlusInfinity(),
+ metadata.GetCsrcs());
+ }
+}
+
+void RTPSenderVideoFrameTransformerDelegate::SetVideoStructureUnderLock(
+ const FrameDependencyStructure* video_structure) {
+ MutexLock lock(&sender_lock_);
+ RTC_CHECK(sender_);
+ sender_->SetVideoStructureAfterTransformation(video_structure);
+}
+
+void RTPSenderVideoFrameTransformerDelegate::SetVideoLayersAllocationUnderLock(
+ VideoLayersAllocation allocation) {
+ MutexLock lock(&sender_lock_);
+ RTC_CHECK(sender_);
+ sender_->SetVideoLayersAllocationAfterTransformation(std::move(allocation));
+}
+
+void RTPSenderVideoFrameTransformerDelegate::Reset() {
+ frame_transformer_->UnregisterTransformedFrameSinkCallback(ssrc_);
+ frame_transformer_ = nullptr;
+ {
+ MutexLock lock(&sender_lock_);
+ sender_ = nullptr;
+ }
+ // Wait until all pending tasks are executed, to ensure that the last ref
+ // standing is not on the transformation queue.
+ rtc::Event flush;
+ transformation_queue_->PostTask([this, &flush]() {
+ RTC_DCHECK_RUN_ON(transformation_queue_.get());
+ flush.Set();
+ });
+ flush.Wait(rtc::Event::kForever);
+}
+
+std::unique_ptr<TransformableVideoFrameInterface> CloneSenderVideoFrame(
+ TransformableVideoFrameInterface* original) {
+ auto encoded_image_buffer = EncodedImageBuffer::Create(
+ original->GetData().data(), original->GetData().size());
+ EncodedImage encoded_image;
+ encoded_image.SetEncodedData(encoded_image_buffer);
+ encoded_image._frameType = original->IsKeyFrame()
+ ? VideoFrameType::kVideoFrameKey
+ : VideoFrameType::kVideoFrameDelta;
+ // TODO(bugs.webrtc.org/14708): Fill in other EncodedImage parameters
+
+ VideoFrameMetadata metadata = original->Metadata();
+ RTPVideoHeader new_header = RTPVideoHeader::FromMetadata(metadata);
+ return std::make_unique<TransformableVideoSenderFrame>(
+ encoded_image, new_header, original->GetPayloadType(), new_header.codec,
+ original->GetTimestamp(),
+ /*expected_retransmission_time=*/TimeDelta::PlusInfinity(),
+ original->GetSsrc(), metadata.GetCsrcs(), original->GetRid());
+}
+
+} // namespace webrtc