Allow feeding a Sender encoded videoframe into a Receiver Transform
Instead of crashing with a CHECK fail when an insertable stream of a Video RTPReceiver is given a frame from an RTPSender's insertable stream, construct a reasonable analogous receive frame and pass it through to be decoded. A small step towards removing the split we have between Sender and Receiver implementations of TransformableFrameInterface which just confuses users of the API. Bug: chromium:1250638 Change-Id: I02e0f1d9d35c16dc12718927c5200ff7cf4407e3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/301181 Reviewed-by: Palak Agarwal <agpalak@google.com> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Commit-Queue: Tony Herre <herre@google.com> Cr-Commit-Position: refs/heads/main@{#39888}
This commit is contained in:
parent
95e7a0398c
commit
580b0f944b
@ -638,6 +638,7 @@ if (rtc_include_tests) {
|
||||
"../../api:frame_transformer_factory",
|
||||
"../../api:libjingle_peerconnection_api",
|
||||
"../../api:mock_frame_encryptor",
|
||||
"../../api:mock_transformable_video_frame",
|
||||
"../../api:rtp_headers",
|
||||
"../../api:rtp_packet_info",
|
||||
"../../api:rtp_parameters",
|
||||
|
||||
@ -115,13 +115,44 @@ void RtpVideoStreamReceiverFrameTransformerDelegate::OnTransformedFrame(
|
||||
void RtpVideoStreamReceiverFrameTransformerDelegate::ManageFrame(
|
||||
std::unique_ptr<TransformableFrameInterface> frame) {
|
||||
RTC_DCHECK_RUN_ON(&network_sequence_checker_);
|
||||
RTC_CHECK_EQ(frame->GetDirection(),
|
||||
TransformableFrameInterface::Direction::kReceiver);
|
||||
if (!receiver_)
|
||||
return;
|
||||
auto transformed_frame = absl::WrapUnique(
|
||||
static_cast<TransformableVideoReceiverFrame*>(frame.release()));
|
||||
receiver_->ManageFrame(std::move(*transformed_frame).ExtractFrame());
|
||||
if (frame->GetDirection() ==
|
||||
TransformableFrameInterface::Direction::kReceiver) {
|
||||
auto transformed_frame = absl::WrapUnique(
|
||||
static_cast<TransformableVideoReceiverFrame*>(frame.release()));
|
||||
receiver_->ManageFrame(std::move(*transformed_frame).ExtractFrame());
|
||||
} else {
|
||||
RTC_CHECK_EQ(frame->GetDirection(),
|
||||
TransformableFrameInterface::Direction::kSender);
|
||||
// This frame is actually an frame encoded locally, to be sent, but has been
|
||||
// fed back into this receiver's insertable stream writer.
|
||||
// Create a reasonable RtpFrameObject as if this frame had been received
|
||||
// over RTP, reusing the frameId as an analog for the RTP sequence number,
|
||||
// and handle it as if it had been received.
|
||||
// TODO(https://crbug.com/1250638): Rewrite the receiver's codepaths after
|
||||
// this transform to be transport-agnostic and not need a faked rtp
|
||||
// sequence number.
|
||||
|
||||
auto transformed_frame = absl::WrapUnique(
|
||||
static_cast<TransformableVideoFrameInterface*>(frame.release()));
|
||||
VideoFrameMetadata metadata = transformed_frame->Metadata();
|
||||
RTPVideoHeader video_header = RTPVideoHeader::FromMetadata(metadata);
|
||||
VideoSendTiming timing;
|
||||
rtc::ArrayView<const uint8_t> data = transformed_frame->GetData();
|
||||
receiver_->ManageFrame(std::make_unique<RtpFrameObject>(
|
||||
/*first_seq_num=*/metadata.GetFrameId().value_or(0),
|
||||
/*last_seq_num=*/metadata.GetFrameId().value_or(0),
|
||||
/*markerBit=*/video_header.is_last_frame_in_picture,
|
||||
/*times_nacked=*/0,
|
||||
/*first_packet_received_time=*/0,
|
||||
/*last_packet_received_time=*/0,
|
||||
/*rtp_timestamp=*/transformed_frame->GetTimestamp(),
|
||||
/*ntp_time_ms=*/0, timing, transformed_frame->GetPayloadType(),
|
||||
metadata.GetCodec(), metadata.GetRotation(), metadata.GetContentType(),
|
||||
video_header, video_header.color_space, RtpPacketInfos(),
|
||||
EncodedImageBuffer::Create(data.data(), data.size())));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "api/call/transport.h"
|
||||
#include "api/test/mock_transformable_video_frame.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "call/video_receive_stream.h"
|
||||
#include "modules/rtp_rtcp/source/rtp_descriptor_authentication.h"
|
||||
@ -31,6 +32,7 @@ namespace {
|
||||
using ::testing::_;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
using ::testing::SaveArg;
|
||||
|
||||
std::unique_ptr<RtpFrameObject> CreateRtpFrameObject(
|
||||
@ -175,5 +177,43 @@ TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
|
||||
delegate->TransformFrame(CreateRtpFrameObject(video_header, csrcs));
|
||||
}
|
||||
|
||||
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
|
||||
SenderFramesAreConvertedToReceiverFrames) {
|
||||
rtc::AutoThread main_thread_;
|
||||
TestRtpVideoFrameReceiver receiver;
|
||||
auto mock_frame_transformer =
|
||||
rtc::make_ref_counted<NiceMock<MockFrameTransformer>>();
|
||||
auto delegate =
|
||||
rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
|
||||
&receiver, mock_frame_transformer, rtc::Thread::Current(),
|
||||
/*remote_ssrc*/ 1111);
|
||||
|
||||
auto mock_sender_frame =
|
||||
std::make_unique<NiceMock<MockTransformableVideoFrame>>();
|
||||
ON_CALL(*mock_sender_frame, GetDirection)
|
||||
.WillByDefault(Return(TransformableFrameInterface::Direction::kSender));
|
||||
VideoFrameMetadata metadata;
|
||||
metadata.SetCodec(kVideoCodecVP8);
|
||||
metadata.SetRTPVideoHeaderCodecSpecifics(RTPVideoHeaderVP8());
|
||||
ON_CALL(*mock_sender_frame, Metadata).WillByDefault(Return(metadata));
|
||||
rtc::scoped_refptr<EncodedImageBufferInterface> buffer =
|
||||
EncodedImageBuffer::Create(1);
|
||||
ON_CALL(*mock_sender_frame, GetData)
|
||||
.WillByDefault(Return(rtc::ArrayView<const uint8_t>(*buffer)));
|
||||
|
||||
rtc::scoped_refptr<TransformedFrameCallback> callback;
|
||||
EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameSinkCallback)
|
||||
.WillOnce(SaveArg<0>(&callback));
|
||||
delegate->Init();
|
||||
ASSERT_TRUE(callback);
|
||||
|
||||
EXPECT_CALL(receiver, ManageFrame)
|
||||
.WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
|
||||
EXPECT_EQ(frame->codec_type(), metadata.GetCodec());
|
||||
});
|
||||
callback->OnTransformedFrame(std::move(mock_sender_frame));
|
||||
rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user