summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/libwebrtc/video/rtp_video_stream_receiver2.cc121
1 files changed, 76 insertions, 45 deletions
diff --git a/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc b/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
index c4a021d6c0..077f522d41 100644
--- a/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
+++ b/third_party/libwebrtc/video/rtp_video_stream_receiver2.cc
@@ -358,7 +358,7 @@ RtpVideoStreamReceiver2::~RtpVideoStreamReceiver2() {
void RtpVideoStreamReceiver2::AddReceiveCodec(
uint8_t payload_type,
VideoCodecType video_codec,
- const std::map<std::string, std::string>& codec_params,
+ const webrtc::CodecParameterMap& codec_params,
bool raw_payload) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
if (codec_params.count(cricket::kH264FmtpSpsPpsIdrInKeyframe) > 0 ||
@@ -433,23 +433,21 @@ RtpVideoStreamReceiver2::ParseGenericDependenciesExtension(
const RtpPacketReceived& rtp_packet,
RTPVideoHeader* video_header) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
- if (rtp_packet.HasExtension<RtpDependencyDescriptorExtension>()) {
- webrtc::DependencyDescriptor dependency_descriptor;
+ if (DependencyDescriptorMandatory dd_mandatory;
+ rtp_packet.GetExtension<RtpDependencyDescriptorExtensionMandatory>(
+ &dd_mandatory)) {
+ const int64_t frame_id =
+ frame_id_unwrapper_.Unwrap(dd_mandatory.frame_number());
+ DependencyDescriptor dependency_descriptor;
if (!rtp_packet.GetExtension<RtpDependencyDescriptorExtension>(
video_structure_.get(), &dependency_descriptor)) {
- // Descriptor is there, but failed to parse. Either it is invalid,
- // or too old packet (after relevant video_structure_ changed),
- // or too new packet (before relevant video_structure_ arrived).
- // Drop such packet to be on the safe side.
- // TODO(bugs.webrtc.org/10342): Stash too new packet.
- Timestamp now = clock_->CurrentTime();
- if (now - last_logged_failed_to_parse_dd_ > TimeDelta::Seconds(1)) {
- last_logged_failed_to_parse_dd_ = now;
- RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
- << " Failed to parse dependency descriptor.";
+ if (!video_structure_frame_id_ || frame_id < video_structure_frame_id_) {
+ return kDropPacket;
+ } else {
+ return kStashPacket;
}
- return kDropPacket;
}
+
if (dependency_descriptor.attached_structure != nullptr &&
!dependency_descriptor.first_packet_in_frame) {
RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
@@ -462,8 +460,6 @@ RtpVideoStreamReceiver2::ParseGenericDependenciesExtension(
video_header->is_last_packet_in_frame =
dependency_descriptor.last_packet_in_frame;
- int64_t frame_id =
- frame_id_unwrapper_.Unwrap(dependency_descriptor.frame_number);
auto& generic_descriptor_info = video_header->generic.emplace();
generic_descriptor_info.frame_id = frame_id;
generic_descriptor_info.spatial_index =
@@ -538,10 +534,11 @@ RtpVideoStreamReceiver2::ParseGenericDependenciesExtension(
return kHasGenericDescriptor;
}
-void RtpVideoStreamReceiver2::OnReceivedPayloadData(
+bool RtpVideoStreamReceiver2::OnReceivedPayloadData(
rtc::CopyOnWriteBuffer codec_payload,
const RtpPacketReceived& rtp_packet,
- const RTPVideoHeader& video) {
+ const RTPVideoHeader& video,
+ int times_nacked) {
RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
auto packet =
@@ -594,16 +591,23 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData(
video_header.playout_delay = rtp_packet.GetExtension<PlayoutDelayLimits>();
}
- ParseGenericDependenciesResult generic_descriptor_state =
- ParseGenericDependenciesExtension(rtp_packet, &video_header);
-
if (!rtp_packet.recovered()) {
UpdatePacketReceiveTimestamps(
rtp_packet, video_header.frame_type == VideoFrameType::kVideoFrameKey);
}
- if (generic_descriptor_state == kDropPacket) {
+ ParseGenericDependenciesResult generic_descriptor_state =
+ ParseGenericDependenciesExtension(rtp_packet, &video_header);
+
+ if (generic_descriptor_state == kStashPacket) {
+ return true;
+ } else if (generic_descriptor_state == kDropPacket) {
Timestamp now = clock_->CurrentTime();
+ if (now - last_logged_failed_to_parse_dd_ > TimeDelta::Seconds(1)) {
+ last_logged_failed_to_parse_dd_ = now;
+ RTC_LOG(LS_WARNING) << "ssrc: " << rtp_packet.Ssrc()
+ << " Failed to parse dependency descriptor.";
+ }
if (video_structure_ == nullptr &&
next_keyframe_request_for_missing_video_structure_ < now) {
// No video structure received yet, most likely part of the initial
@@ -612,7 +616,7 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData(
next_keyframe_request_for_missing_video_structure_ =
now + TimeDelta::Seconds(1);
}
- return;
+ return false;
}
// Color space should only be transmitted in the last packet of a frame,
@@ -658,21 +662,12 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData(
}
}
- if (nack_module_) {
- const bool is_keyframe =
- video_header.is_first_packet_in_frame &&
- video_header.frame_type == VideoFrameType::kVideoFrameKey;
-
- packet->times_nacked = nack_module_->OnReceivedPacket(
- rtp_packet.SequenceNumber(), is_keyframe, rtp_packet.recovered());
- } else {
- packet->times_nacked = -1;
- }
+ packet->times_nacked = times_nacked;
if (codec_payload.size() == 0) {
NotifyReceiverOfEmptyPacket(packet->seq_num);
rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
- return;
+ return false;
}
if (packet->codec() == kVideoCodecH264) {
@@ -695,7 +690,7 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData(
rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
[[fallthrough]];
case video_coding::H264SpsPpsTracker::kDrop:
- return;
+ return false;
case video_coding::H264SpsPpsTracker::kInsert:
packet->video_payload = std::move(fixed.bitstream);
break;
@@ -708,6 +703,7 @@ void RtpVideoStreamReceiver2::OnReceivedPayloadData(
rtcp_feedback_buffer_.SendBufferedRtcpFeedback();
frame_counter_.Add(packet->timestamp);
OnInsertedPacket(packet_buffer_.InsertPacket(std::move(packet)));
+ return false;
}
void RtpVideoStreamReceiver2::OnRecoveredPacket(
@@ -1111,15 +1107,51 @@ void RtpVideoStreamReceiver2::ReceivePacket(const RtpPacketReceived& packet) {
if (type_it == payload_type_map_.end()) {
return;
}
- absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload =
- type_it->second->Parse(packet.PayloadBuffer());
- if (parsed_payload == absl::nullopt) {
- RTC_LOG(LS_WARNING) << "Failed parsing payload.";
- return;
- }
- OnReceivedPayloadData(std::move(parsed_payload->video_payload), packet,
- parsed_payload->video_header);
+ auto parse_and_insert = [&](const RtpPacketReceived& packet) {
+ RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
+ absl::optional<VideoRtpDepacketizer::ParsedRtpPayload> parsed_payload =
+ type_it->second->Parse(packet.PayloadBuffer());
+ if (parsed_payload == absl::nullopt) {
+ RTC_LOG(LS_WARNING) << "Failed parsing payload.";
+ return false;
+ }
+
+ int times_nacked = nack_module_
+ ? nack_module_->OnReceivedPacket(
+ packet.SequenceNumber(), packet.recovered())
+ : -1;
+
+ return OnReceivedPayloadData(std::move(parsed_payload->video_payload),
+ packet, parsed_payload->video_header,
+ times_nacked);
+ };
+
+ // When the dependency descriptor is used and the descriptor fail to parse
+ // then `OnReceivedPayloadData` may return true to signal the the packet
+ // should be retried at a later stage, which is why they are stashed here.
+ //
+ // TODO(bugs.webrtc.org/15782):
+ // This is an ugly solution. The way things should work is for the
+ // `RtpFrameReferenceFinder` to stash assembled frames until the keyframe with
+ // the relevant template structure has been received, but unfortunately the
+ // `frame_transformer_delegate_` is called before the frames are inserted into
+ // the `RtpFrameReferenceFinder`, and it expects the dependency descriptor to
+ // be parsed at that stage.
+ if (parse_and_insert(packet)) {
+ if (stashed_packets_.size() == 100) {
+ stashed_packets_.clear();
+ }
+ stashed_packets_.push_back(packet);
+ } else {
+ for (auto it = stashed_packets_.begin(); it != stashed_packets_.end();) {
+ if (parse_and_insert(*it)) {
+ ++it; // keep in the stash.
+ } else {
+ it = stashed_packets_.erase(it);
+ }
+ }
+ }
}
void RtpVideoStreamReceiver2::ParseAndHandleEncapsulatingHeader(
@@ -1151,8 +1183,7 @@ void RtpVideoStreamReceiver2::NotifyReceiverOfEmptyPacket(uint16_t seq_num) {
OnInsertedPacket(packet_buffer_.InsertPadding(seq_num));
if (nack_module_) {
- nack_module_->OnReceivedPacket(seq_num, /* is_keyframe = */ false,
- /* is _recovered = */ false);
+ nack_module_->OnReceivedPacket(seq_num, /*is_recovered=*/false);
}
if (loss_notification_controller_) {
// TODO(bugs.webrtc.org/10336): Handle empty packets.