Overwrite frame seq nums when piping encoded frames between RTPReceivers
This allows encoded frames to be written to any encoded insertable streams writer without needing to somehow set valid RTP sequence numbers. Assumes streams are using the Dependency Descriptor header ext. A short term fix while we discuss whether we can remove the sequence number check in RtpFrameReferenceFinder::ManageFrame. Bug: chromium:1439799 Change-Id: I3c1d83793cd8b6cae2a8ad2129b3b6daab1d11c4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/302301 Reviewed-by: Stefan Holmer <stefan@webrtc.org> Commit-Queue: Tony Herre <herre@google.com> Cr-Commit-Position: refs/heads/main@{#39966}
This commit is contained in:
parent
cf95dd13a2
commit
096427e494
@ -53,6 +53,11 @@ class RtpFrameObject : public EncodedFrame {
|
||||
|
||||
const std::vector<uint32_t>& Csrcs() const { return csrcs_; }
|
||||
|
||||
void SetFirstSeqNum(uint16_t first_seq_num) {
|
||||
first_seq_num_ = first_seq_num;
|
||||
}
|
||||
void SetLastSeqNum(uint16_t last_seq_num) { last_seq_num_ = last_seq_num; }
|
||||
|
||||
private:
|
||||
// Reference for mutable access.
|
||||
rtc::scoped_refptr<EncodedImageBuffer> image_buffer_;
|
||||
|
||||
@ -25,9 +25,11 @@ class TransformableVideoReceiverFrame
|
||||
: public TransformableVideoFrameInterface {
|
||||
public:
|
||||
TransformableVideoReceiverFrame(std::unique_ptr<RtpFrameObject> frame,
|
||||
uint32_t ssrc)
|
||||
uint32_t ssrc,
|
||||
RtpVideoFrameReceiver* receiver)
|
||||
: frame_(std::move(frame)),
|
||||
metadata_(frame_->GetRtpVideoHeader().GetAsMetadata()) {
|
||||
metadata_(frame_->GetRtpVideoHeader().GetAsMetadata()),
|
||||
receiver_(receiver) {
|
||||
metadata_.SetSsrc(ssrc);
|
||||
metadata_.SetCsrcs(frame_->Csrcs());
|
||||
}
|
||||
@ -64,9 +66,12 @@ class TransformableVideoReceiverFrame
|
||||
|
||||
Direction GetDirection() const override { return Direction::kReceiver; }
|
||||
|
||||
const RtpVideoFrameReceiver* Receiver() { return receiver_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<RtpFrameObject> frame_;
|
||||
VideoFrameMetadata metadata_;
|
||||
RtpVideoFrameReceiver* receiver_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@ -98,8 +103,8 @@ void RtpVideoStreamReceiverFrameTransformerDelegate::TransformFrame(
|
||||
std::unique_ptr<RtpFrameObject> frame) {
|
||||
RTC_DCHECK_RUN_ON(&network_sequence_checker_);
|
||||
frame_transformer_->Transform(
|
||||
std::make_unique<TransformableVideoReceiverFrame>(std::move(frame),
|
||||
ssrc_));
|
||||
std::make_unique<TransformableVideoReceiverFrame>(std::move(frame), ssrc_,
|
||||
receiver_));
|
||||
}
|
||||
|
||||
void RtpVideoStreamReceiverFrameTransformerDelegate::OnTransformedFrame(
|
||||
@ -121,7 +126,21 @@ void RtpVideoStreamReceiverFrameTransformerDelegate::ManageFrame(
|
||||
TransformableFrameInterface::Direction::kReceiver) {
|
||||
auto transformed_frame = absl::WrapUnique(
|
||||
static_cast<TransformableVideoReceiverFrame*>(frame.release()));
|
||||
receiver_->ManageFrame(std::move(*transformed_frame).ExtractFrame());
|
||||
auto frame_receiver = transformed_frame->Receiver();
|
||||
std::unique_ptr<RtpFrameObject> frame_object =
|
||||
std::move(*transformed_frame).ExtractFrame();
|
||||
if (frame_receiver != receiver_) {
|
||||
// This frame was received by a different RtpReceiver instance, so has
|
||||
// first and last sequence numbers which will be meaningless to our
|
||||
// receiver_. Work around this by using the frame id as a surrogate value,
|
||||
// same as when given a Sender frame below.
|
||||
|
||||
// TODO(https://crbug.com/1250638): Change what happens after the encoded
|
||||
// insertable stream insertion to not require RTP data.
|
||||
frame_object->SetFirstSeqNum(frame_object->Id());
|
||||
frame_object->SetLastSeqNum(frame_object->Id());
|
||||
}
|
||||
receiver_->ManageFrame(std::move(frame_object));
|
||||
} else {
|
||||
RTC_CHECK_EQ(frame->GetDirection(),
|
||||
TransformableFrameInterface::Direction::kSender);
|
||||
|
||||
@ -35,13 +35,19 @@ using ::testing::NiceMock;
|
||||
using ::testing::Return;
|
||||
using ::testing::SaveArg;
|
||||
|
||||
const int kFirstSeqNum = 1;
|
||||
const int kLastSeqNum = 2;
|
||||
|
||||
std::unique_ptr<RtpFrameObject> CreateRtpFrameObject(
|
||||
const RTPVideoHeader& video_header,
|
||||
std::vector<uint32_t> csrcs) {
|
||||
RtpPacketInfo packet_info(/*ssrc=*/123, csrcs, /*rtc_timestamp=*/0,
|
||||
/*receive_time=*/Timestamp::Seconds(123456));
|
||||
return std::make_unique<RtpFrameObject>(
|
||||
0, 0, true, 0, 0, 0, 0, 0, VideoSendTiming(), 0, video_header.codec,
|
||||
kFirstSeqNum, kLastSeqNum, /*markerBit=*/true,
|
||||
/*times_nacked=*/3, /*first_packet_received_time=*/4,
|
||||
/*last_packet_received_time=*/5, /*rtp_timestamp=*/6, /*ntp_time_ms=*/7,
|
||||
VideoSendTiming(), /*payload_type=*/8, video_header.codec,
|
||||
kVideoRotation_0, VideoContentType::UNSPECIFIED, video_header,
|
||||
absl::nullopt, RtpPacketInfos({packet_info}),
|
||||
EncodedImageBuffer::Create(0));
|
||||
@ -121,6 +127,8 @@ TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
|
||||
EXPECT_CALL(receiver, ManageFrame)
|
||||
.WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
|
||||
EXPECT_EQ(frame->Csrcs(), csrcs);
|
||||
EXPECT_EQ(frame->first_seq_num(), kFirstSeqNum);
|
||||
EXPECT_EQ(frame->last_seq_num(), kLastSeqNum);
|
||||
});
|
||||
ON_CALL(*mock_frame_transformer, Transform)
|
||||
.WillByDefault(
|
||||
@ -215,5 +223,56 @@ TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
|
||||
rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
|
||||
}
|
||||
|
||||
TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest,
|
||||
ManageFrameFromDifferentReceiver) {
|
||||
rtc::AutoThread main_thread_;
|
||||
std::vector<uint32_t> csrcs = {234, 345, 456};
|
||||
const int frame_id = 11;
|
||||
|
||||
TestRtpVideoFrameReceiver receiver1;
|
||||
auto mock_frame_transformer1(
|
||||
rtc::make_ref_counted<NiceMock<MockFrameTransformer>>());
|
||||
auto delegate1 =
|
||||
rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
|
||||
&receiver1, mock_frame_transformer1, rtc::Thread::Current(),
|
||||
/*remote_ssrc*/ 1111);
|
||||
|
||||
TestRtpVideoFrameReceiver receiver2;
|
||||
auto mock_frame_transformer2(
|
||||
rtc::make_ref_counted<NiceMock<MockFrameTransformer>>());
|
||||
auto delegate2 =
|
||||
rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
|
||||
&receiver2, mock_frame_transformer2, rtc::Thread::Current(),
|
||||
/*remote_ssrc*/ 1111);
|
||||
|
||||
delegate1->Init();
|
||||
rtc::scoped_refptr<TransformedFrameCallback> callback_for_2;
|
||||
EXPECT_CALL(*mock_frame_transformer2, RegisterTransformedFrameSinkCallback)
|
||||
.WillOnce(SaveArg<0>(&callback_for_2));
|
||||
delegate2->Init();
|
||||
ASSERT_TRUE(callback_for_2);
|
||||
|
||||
// Expect a call on receiver2's ManageFrame with sequence numbers overwritten
|
||||
// with the frame's ID.
|
||||
EXPECT_CALL(receiver2, ManageFrame)
|
||||
.WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
|
||||
EXPECT_EQ(frame->Csrcs(), csrcs);
|
||||
EXPECT_EQ(frame->first_seq_num(), frame_id);
|
||||
EXPECT_EQ(frame->last_seq_num(), frame_id);
|
||||
});
|
||||
// When the frame transformer for receiver 1 receives the frame to transform,
|
||||
// pipe it over to the callback for receiver 2.
|
||||
ON_CALL(*mock_frame_transformer1, Transform)
|
||||
.WillByDefault([&callback_for_2](
|
||||
std::unique_ptr<TransformableFrameInterface> frame) {
|
||||
callback_for_2->OnTransformedFrame(std::move(frame));
|
||||
});
|
||||
std::unique_ptr<RtpFrameObject> untransformed_frame =
|
||||
CreateRtpFrameObject(RTPVideoHeader(), csrcs);
|
||||
untransformed_frame->SetId(frame_id);
|
||||
delegate1->TransformFrame(std::move(untransformed_frame));
|
||||
rtc::ThreadManager::ProcessAllMessageQueuesForTesting();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user