Bug 1632489 - Use repaired-rtp-stream-id in rtx packets; r=ng

This imports a few fixes from tip of libwebrtc, which now supports mid, rid
and rrid. The rtx packet is now allocated as max_packet_size_, which is
necessary to have enough capacity for the rrid. It takes the
CopyHeaderAndExtensionsToRtxPacket function from upstream, which omits
copying extensions that should not be copied over, such as rid. It is necessary
to make AllocateExtension and FindExtension public in order for this
function to work.

It then copies the rid from the source packet over to rrid in the rtx packet.
Upstream has code for this as well, but taking it would require more
extensive changes to our copy of libwebrtc. We can drop these local
modifications with the next update.

Depends on D74839

Differential Revision: https://phabricator.services.mozilla.com/D74840
This commit is contained in:
Dan Minor 2020-05-12 21:35:10 +00:00
Родитель 06db56446e
Коммит 110b9c482b
2 изменённых файлов: 70 добавлений и 11 удалений

Просмотреть файл

@ -118,6 +118,14 @@ class RtpPacket {
// Returns empty arrayview on failure.
rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
// Find an extension |type|.
// Returns view of the raw extension or empty view on failure.
rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
// Find or allocate an extension |type|. Returns view of size |length|
// to write raw extension to or an empty view on failure.
rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
// Reserve size_bytes for payload. Returns nullptr on failure.
uint8_t* SetPayloadSize(size_t size_bytes);
// Same as SetPayloadSize but doesn't guarantee to keep current payload.
@ -135,14 +143,6 @@ class RtpPacket {
// but does not touch packet own buffer, leaving packet in invalid state.
bool ParseBuffer(const uint8_t* buffer, size_t size);
// Find an extension |type|.
// Returns view of the raw extension or empty view on failure.
rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
// Find or allocate an extension |type|. Returns view of size |length|
// to write raw extension to or an empty view on failure.
rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
uint8_t* WriteAt(size_t offset);
void WriteAt(size_t offset, uint8_t byte);

Просмотреть файл

@ -1193,14 +1193,63 @@ bool RTPSender::SetFecParameters(const FecProtectionParams& delta_params,
return true;
}
static void CopyHeaderAndExtensionsToRtxPacket(const RtpPacketToSend& packet,
RtpPacketToSend* rtx_packet) {
// Set the relevant fixed packet headers. The following are not set:
// * Payload type - it is replaced in rtx packets.
// * Sequence number - RTX has a separate sequence numbering.
// * SSRC - RTX stream has its own SSRC.
rtx_packet->SetMarker(packet.Marker());
rtx_packet->SetTimestamp(packet.Timestamp());
// Set the variable fields in the packet header:
// * CSRCs - must be set before header extensions.
// * Header extensions - replace Rid header with RepairedRid header.
const std::vector<uint32_t> csrcs = packet.Csrcs();
rtx_packet->SetCsrcs(csrcs);
for (int extension_num = kRtpExtensionNone + 1;
extension_num < kRtpExtensionNumberOfExtensions; ++extension_num) {
auto extension = static_cast<RTPExtensionType>(extension_num);
// Stream ID header extensions (MID, RSID) are sent per-SSRC. Since RTX
// operates on a different SSRC, the presence and values of these header
// extensions should be determined separately and not blindly copied.
if (extension == kRtpExtensionMid ||
extension == kRtpExtensionRtpStreamId) {
continue;
}
rtc::ArrayView<const uint8_t> source = packet.FindExtension(extension);
// Empty extensions should be supported, so not checking |source.empty()|.
// TODO: But this does not work in Mozilla's version of libwebrtc. Remove
// this check with the next update from tip of libwebrtc.
if (source.empty()) {
continue;
}
rtc::ArrayView<uint8_t> destination =
rtx_packet->AllocateExtension(extension, source.size());
// Could happen if any:
// 1. Extension has 0 length.
// 2. Extension is not registered in destination.
// 3. Allocating extension in destination failed.
if (destination.empty() || source.size() != destination.size()) {
continue;
}
std::memcpy(destination.begin(), source.begin(), destination.size());
}
}
std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket(
const RtpPacketToSend& packet) {
// TODO(danilchap): Create rtx packet with extra capacity for SRTP
// when transport interface would be updated to take buffer class.
std::unique_ptr<RtpPacketToSend> rtx_packet(new RtpPacketToSend(
&rtp_header_extension_map_, packet.size() + kRtxHeaderSize));
&rtp_header_extension_map_, max_packet_size_));
// Add original RTP header.
rtx_packet->CopyHeaderFrom(packet);
{
rtc::CritScope lock(&send_critsect_);
if (!sending_media_)
@ -1219,8 +1268,18 @@ std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket(
// Replace SSRC.
rtx_packet->SetSsrc(*ssrc_rtx_);
}
CopyHeaderAndExtensionsToRtxPacket(packet, rtx_packet.get());
// Copy rtp-stream-id from packet to repaired-rtp-stream-id
if (rtp_header_extension_map_.IsRegistered(kRtpExtensionRtpStreamId) &&
rtp_header_extension_map_.IsRegistered(kRtpExtensionRepairedRtpStreamId)) {
std::string rid;
if (packet.GetExtension<RtpStreamId>(&rid)) {
rtx_packet->SetExtension<RepairedRtpStreamId>(rid);
}
}
}
uint8_t* rtx_payload =
rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize);
RTC_DCHECK(rtx_payload);