mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 06:10:40 +01:00

This patch adds a method for setting the keyframe request method to VideoReceiveStream. This code exists in the version that Mozilla is shipping, with a review https://phabricator.services.mozilla.com/D105773 . Bug: webrtc:13486 Change-Id: I7cc19dec95d6523368d73395319854bd8c2166f7 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/240140 Reviewed-by: Stefan Holmer <stefan@webrtc.org> Commit-Queue: Stefan Holmer <stefan@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35793}
486 lines
16 KiB
C++
486 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2012 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.
|
|
*/
|
|
|
|
#ifndef MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_
|
|
#define MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <list>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "absl/algorithm/container.h"
|
|
#include "absl/strings/string_view.h"
|
|
#include "absl/types/optional.h"
|
|
#include "absl/types/variant.h"
|
|
#include "api/array_view.h"
|
|
#include "api/audio_codecs/audio_format.h"
|
|
#include "api/rtp_headers.h"
|
|
#include "api/transport/network_types.h"
|
|
#include "modules/rtp_rtcp/source/rtcp_packet/remote_estimate.h"
|
|
#include "system_wrappers/include/clock.h"
|
|
|
|
#define RTCP_CNAME_SIZE 256 // RFC 3550 page 44, including null termination
|
|
#define IP_PACKET_SIZE 1500 // we assume ethernet
|
|
|
|
namespace webrtc {
|
|
class RtpPacket;
|
|
class RtpPacketToSend;
|
|
namespace rtcp {
|
|
class TransportFeedback;
|
|
}
|
|
|
|
const int kVideoPayloadTypeFrequency = 90000;
|
|
|
|
// TODO(bugs.webrtc.org/6458): Remove this when all the depending projects are
|
|
// updated to correctly set rtp rate for RtcpSender.
|
|
const int kBogusRtpRateForAudioRtcp = 8000;
|
|
|
|
// Minimum RTP header size in bytes.
|
|
const uint8_t kRtpHeaderSize = 12;
|
|
|
|
bool IsLegalMidName(absl::string_view name);
|
|
bool IsLegalRsidName(absl::string_view name);
|
|
|
|
// This enum must not have any gaps, i.e., all integers between
|
|
// kRtpExtensionNone and kRtpExtensionNumberOfExtensions must be valid enum
|
|
// entries.
|
|
enum RTPExtensionType : int {
|
|
kRtpExtensionNone,
|
|
kRtpExtensionTransmissionTimeOffset,
|
|
kRtpExtensionAudioLevel,
|
|
kRtpExtensionCsrcAudioLevel,
|
|
kRtpExtensionInbandComfortNoise,
|
|
kRtpExtensionAbsoluteSendTime,
|
|
kRtpExtensionAbsoluteCaptureTime,
|
|
kRtpExtensionVideoRotation,
|
|
kRtpExtensionTransportSequenceNumber,
|
|
kRtpExtensionTransportSequenceNumber02,
|
|
kRtpExtensionPlayoutDelay,
|
|
kRtpExtensionVideoContentType,
|
|
kRtpExtensionVideoLayersAllocation,
|
|
kRtpExtensionVideoTiming,
|
|
kRtpExtensionRtpStreamId,
|
|
kRtpExtensionRepairedRtpStreamId,
|
|
kRtpExtensionMid,
|
|
kRtpExtensionGenericFrameDescriptor00,
|
|
kRtpExtensionGenericFrameDescriptor = kRtpExtensionGenericFrameDescriptor00,
|
|
kRtpExtensionGenericFrameDescriptor02,
|
|
kRtpExtensionColorSpace,
|
|
kRtpExtensionVideoFrameTrackingId,
|
|
kRtpExtensionNumberOfExtensions // Must be the last entity in the enum.
|
|
};
|
|
|
|
enum RTCPAppSubTypes { kAppSubtypeBwe = 0x00 };
|
|
|
|
// TODO(sprang): Make this an enum class once rtcp_receiver has been cleaned up.
|
|
enum RTCPPacketType : uint32_t {
|
|
kRtcpReport = 0x0001,
|
|
kRtcpSr = 0x0002,
|
|
kRtcpRr = 0x0004,
|
|
kRtcpSdes = 0x0008,
|
|
kRtcpBye = 0x0010,
|
|
kRtcpPli = 0x0020,
|
|
kRtcpNack = 0x0040,
|
|
kRtcpFir = 0x0080,
|
|
kRtcpTmmbr = 0x0100,
|
|
kRtcpTmmbn = 0x0200,
|
|
kRtcpSrReq = 0x0400,
|
|
kRtcpLossNotification = 0x2000,
|
|
kRtcpRemb = 0x10000,
|
|
kRtcpTransmissionTimeOffset = 0x20000,
|
|
kRtcpXrReceiverReferenceTime = 0x40000,
|
|
kRtcpXrDlrrReportBlock = 0x80000,
|
|
kRtcpTransportFeedback = 0x100000,
|
|
kRtcpXrTargetBitrate = 0x200000
|
|
};
|
|
|
|
enum class KeyFrameReqMethod : uint8_t {
|
|
kNone, // Don't request keyframes.
|
|
kPliRtcp, // Request keyframes through Picture Loss Indication.
|
|
kFirRtcp // Request keyframes through Full Intra-frame Request.
|
|
};
|
|
|
|
enum RtxMode {
|
|
kRtxOff = 0x0,
|
|
kRtxRetransmitted = 0x1, // Only send retransmissions over RTX.
|
|
kRtxRedundantPayloads = 0x2 // Preventively send redundant payloads
|
|
// instead of padding.
|
|
};
|
|
|
|
const size_t kRtxHeaderSize = 2;
|
|
|
|
struct RTCPReportBlock {
|
|
RTCPReportBlock()
|
|
: sender_ssrc(0),
|
|
source_ssrc(0),
|
|
fraction_lost(0),
|
|
packets_lost(0),
|
|
extended_highest_sequence_number(0),
|
|
jitter(0),
|
|
last_sender_report_timestamp(0),
|
|
delay_since_last_sender_report(0) {}
|
|
|
|
RTCPReportBlock(uint32_t sender_ssrc,
|
|
uint32_t source_ssrc,
|
|
uint8_t fraction_lost,
|
|
int32_t packets_lost,
|
|
uint32_t extended_highest_sequence_number,
|
|
uint32_t jitter,
|
|
uint32_t last_sender_report_timestamp,
|
|
uint32_t delay_since_last_sender_report)
|
|
: sender_ssrc(sender_ssrc),
|
|
source_ssrc(source_ssrc),
|
|
fraction_lost(fraction_lost),
|
|
packets_lost(packets_lost),
|
|
extended_highest_sequence_number(extended_highest_sequence_number),
|
|
jitter(jitter),
|
|
last_sender_report_timestamp(last_sender_report_timestamp),
|
|
delay_since_last_sender_report(delay_since_last_sender_report) {}
|
|
|
|
// Fields as described by RFC 3550 6.4.2.
|
|
uint32_t sender_ssrc; // SSRC of sender of this report.
|
|
uint32_t source_ssrc; // SSRC of the RTP packet sender.
|
|
uint8_t fraction_lost;
|
|
int32_t packets_lost; // 24 bits valid.
|
|
uint32_t extended_highest_sequence_number;
|
|
uint32_t jitter;
|
|
uint32_t last_sender_report_timestamp;
|
|
uint32_t delay_since_last_sender_report;
|
|
};
|
|
|
|
typedef std::list<RTCPReportBlock> ReportBlockList;
|
|
|
|
struct RtpState {
|
|
RtpState()
|
|
: sequence_number(0),
|
|
start_timestamp(0),
|
|
timestamp(0),
|
|
capture_time_ms(-1),
|
|
last_timestamp_time_ms(-1),
|
|
ssrc_has_acked(false) {}
|
|
uint16_t sequence_number;
|
|
uint32_t start_timestamp;
|
|
uint32_t timestamp;
|
|
int64_t capture_time_ms;
|
|
int64_t last_timestamp_time_ms;
|
|
bool ssrc_has_acked;
|
|
};
|
|
|
|
// Callback interface for packets recovered by FlexFEC or ULPFEC. In
|
|
// the FlexFEC case, the implementation should be able to demultiplex
|
|
// the recovered RTP packets based on SSRC.
|
|
class RecoveredPacketReceiver {
|
|
public:
|
|
virtual void OnRecoveredPacket(const uint8_t* packet, size_t length) = 0;
|
|
|
|
protected:
|
|
virtual ~RecoveredPacketReceiver() = default;
|
|
};
|
|
|
|
class RtcpIntraFrameObserver {
|
|
public:
|
|
virtual ~RtcpIntraFrameObserver() {}
|
|
|
|
virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) = 0;
|
|
};
|
|
|
|
// Observer for incoming LossNotification RTCP messages.
|
|
// See the documentation of LossNotification for details.
|
|
class RtcpLossNotificationObserver {
|
|
public:
|
|
virtual ~RtcpLossNotificationObserver() = default;
|
|
|
|
virtual void OnReceivedLossNotification(uint32_t ssrc,
|
|
uint16_t seq_num_of_last_decodable,
|
|
uint16_t seq_num_of_last_received,
|
|
bool decodability_flag) = 0;
|
|
};
|
|
|
|
class RtcpBandwidthObserver {
|
|
public:
|
|
// REMB or TMMBR
|
|
virtual void OnReceivedEstimatedBitrate(uint32_t bitrate) = 0;
|
|
|
|
virtual void OnReceivedRtcpReceiverReport(
|
|
const ReportBlockList& report_blocks,
|
|
int64_t rtt,
|
|
int64_t now_ms) = 0;
|
|
|
|
virtual ~RtcpBandwidthObserver() {}
|
|
};
|
|
|
|
// NOTE! `kNumMediaTypes` must be kept in sync with RtpPacketMediaType!
|
|
static constexpr size_t kNumMediaTypes = 5;
|
|
enum class RtpPacketMediaType : size_t {
|
|
kAudio, // Audio media packets.
|
|
kVideo, // Video media packets.
|
|
kRetransmission, // Retransmisions, sent as response to NACK.
|
|
kForwardErrorCorrection, // FEC packets.
|
|
kPadding = kNumMediaTypes - 1, // RTX or plain padding sent to maintain BWE.
|
|
// Again, don't forget to udate `kNumMediaTypes` if you add another value!
|
|
};
|
|
|
|
struct RtpPacketSendInfo {
|
|
public:
|
|
RtpPacketSendInfo() = default;
|
|
|
|
uint16_t transport_sequence_number = 0;
|
|
absl::optional<uint32_t> media_ssrc;
|
|
uint16_t rtp_sequence_number = 0; // Only valid if `media_ssrc` is set.
|
|
uint32_t rtp_timestamp = 0;
|
|
size_t length = 0;
|
|
absl::optional<RtpPacketMediaType> packet_type;
|
|
PacedPacketInfo pacing_info;
|
|
};
|
|
|
|
class NetworkStateEstimateObserver {
|
|
public:
|
|
virtual void OnRemoteNetworkEstimate(NetworkStateEstimate estimate) = 0;
|
|
virtual ~NetworkStateEstimateObserver() = default;
|
|
};
|
|
|
|
class TransportFeedbackObserver {
|
|
public:
|
|
TransportFeedbackObserver() {}
|
|
virtual ~TransportFeedbackObserver() {}
|
|
|
|
virtual void OnAddPacket(const RtpPacketSendInfo& packet_info) = 0;
|
|
virtual void OnTransportFeedback(const rtcp::TransportFeedback& feedback) = 0;
|
|
};
|
|
|
|
// Interface for PacketRouter to send rtcp feedback on behalf of
|
|
// congestion controller.
|
|
// TODO(bugs.webrtc.org/8239): Remove and use RtcpTransceiver directly
|
|
// when RtcpTransceiver always present in rtp transport.
|
|
class RtcpFeedbackSenderInterface {
|
|
public:
|
|
virtual ~RtcpFeedbackSenderInterface() = default;
|
|
virtual void SendCombinedRtcpPacket(
|
|
std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets) = 0;
|
|
virtual void SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) = 0;
|
|
virtual void UnsetRemb() = 0;
|
|
};
|
|
|
|
class StreamFeedbackObserver {
|
|
public:
|
|
struct StreamPacketInfo {
|
|
bool received;
|
|
|
|
// `rtp_sequence_number` and `is_retransmission` are only valid if `ssrc`
|
|
// is populated.
|
|
absl::optional<uint32_t> ssrc;
|
|
uint16_t rtp_sequence_number;
|
|
bool is_retransmission;
|
|
};
|
|
virtual ~StreamFeedbackObserver() = default;
|
|
|
|
virtual void OnPacketFeedbackVector(
|
|
std::vector<StreamPacketInfo> packet_feedback_vector) = 0;
|
|
};
|
|
|
|
class StreamFeedbackProvider {
|
|
public:
|
|
virtual void RegisterStreamFeedbackObserver(
|
|
std::vector<uint32_t> ssrcs,
|
|
StreamFeedbackObserver* observer) = 0;
|
|
virtual void DeRegisterStreamFeedbackObserver(
|
|
StreamFeedbackObserver* observer) = 0;
|
|
virtual ~StreamFeedbackProvider() = default;
|
|
};
|
|
|
|
class RtcpRttStats {
|
|
public:
|
|
virtual void OnRttUpdate(int64_t rtt) = 0;
|
|
|
|
virtual int64_t LastProcessedRtt() const = 0;
|
|
|
|
virtual ~RtcpRttStats() {}
|
|
};
|
|
|
|
struct RtpPacketCounter {
|
|
RtpPacketCounter()
|
|
: header_bytes(0), payload_bytes(0), padding_bytes(0), packets(0) {}
|
|
|
|
explicit RtpPacketCounter(const RtpPacket& packet);
|
|
|
|
void Add(const RtpPacketCounter& other) {
|
|
header_bytes += other.header_bytes;
|
|
payload_bytes += other.payload_bytes;
|
|
padding_bytes += other.padding_bytes;
|
|
packets += other.packets;
|
|
}
|
|
|
|
void Subtract(const RtpPacketCounter& other) {
|
|
RTC_DCHECK_GE(header_bytes, other.header_bytes);
|
|
header_bytes -= other.header_bytes;
|
|
RTC_DCHECK_GE(payload_bytes, other.payload_bytes);
|
|
payload_bytes -= other.payload_bytes;
|
|
RTC_DCHECK_GE(padding_bytes, other.padding_bytes);
|
|
padding_bytes -= other.padding_bytes;
|
|
RTC_DCHECK_GE(packets, other.packets);
|
|
packets -= other.packets;
|
|
}
|
|
|
|
bool operator==(const RtpPacketCounter& other) const {
|
|
return header_bytes == other.header_bytes &&
|
|
payload_bytes == other.payload_bytes &&
|
|
padding_bytes == other.padding_bytes && packets == other.packets;
|
|
}
|
|
|
|
// Not inlined, since use of RtpPacket would result in circular includes.
|
|
void AddPacket(const RtpPacket& packet);
|
|
|
|
size_t TotalBytes() const {
|
|
return header_bytes + payload_bytes + padding_bytes;
|
|
}
|
|
|
|
size_t header_bytes; // Number of bytes used by RTP headers.
|
|
size_t payload_bytes; // Payload bytes, excluding RTP headers and padding.
|
|
size_t padding_bytes; // Number of padding bytes.
|
|
uint32_t packets; // Number of packets.
|
|
};
|
|
|
|
// Data usage statistics for a (rtp) stream.
|
|
struct StreamDataCounters {
|
|
StreamDataCounters();
|
|
|
|
void Add(const StreamDataCounters& other) {
|
|
transmitted.Add(other.transmitted);
|
|
retransmitted.Add(other.retransmitted);
|
|
fec.Add(other.fec);
|
|
if (other.first_packet_time_ms != -1 &&
|
|
(other.first_packet_time_ms < first_packet_time_ms ||
|
|
first_packet_time_ms == -1)) {
|
|
// Use oldest time.
|
|
first_packet_time_ms = other.first_packet_time_ms;
|
|
}
|
|
}
|
|
|
|
void Subtract(const StreamDataCounters& other) {
|
|
transmitted.Subtract(other.transmitted);
|
|
retransmitted.Subtract(other.retransmitted);
|
|
fec.Subtract(other.fec);
|
|
if (other.first_packet_time_ms != -1 &&
|
|
(other.first_packet_time_ms > first_packet_time_ms ||
|
|
first_packet_time_ms == -1)) {
|
|
// Use youngest time.
|
|
first_packet_time_ms = other.first_packet_time_ms;
|
|
}
|
|
}
|
|
|
|
int64_t TimeSinceFirstPacketInMs(int64_t now_ms) const {
|
|
return (first_packet_time_ms == -1) ? -1 : (now_ms - first_packet_time_ms);
|
|
}
|
|
|
|
// Returns the number of bytes corresponding to the actual media payload (i.e.
|
|
// RTP headers, padding, retransmissions and fec packets are excluded).
|
|
// Note this function does not have meaning for an RTX stream.
|
|
size_t MediaPayloadBytes() const {
|
|
return transmitted.payload_bytes - retransmitted.payload_bytes -
|
|
fec.payload_bytes;
|
|
}
|
|
|
|
int64_t first_packet_time_ms; // Time when first packet is sent/received.
|
|
// The timestamp at which the last packet was received, i.e. the time of the
|
|
// local clock when it was received - not the RTP timestamp of that packet.
|
|
// https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-lastpacketreceivedtimestamp
|
|
absl::optional<int64_t> last_packet_received_timestamp_ms;
|
|
RtpPacketCounter transmitted; // Number of transmitted packets/bytes.
|
|
RtpPacketCounter retransmitted; // Number of retransmitted packets/bytes.
|
|
RtpPacketCounter fec; // Number of redundancy packets/bytes.
|
|
};
|
|
|
|
class RtpSendRates {
|
|
template <std::size_t... Is>
|
|
constexpr std::array<DataRate, sizeof...(Is)> make_zero_array(
|
|
std::index_sequence<Is...>) {
|
|
return {{(static_cast<void>(Is), DataRate::Zero())...}};
|
|
}
|
|
|
|
public:
|
|
RtpSendRates()
|
|
: send_rates_(
|
|
make_zero_array(std::make_index_sequence<kNumMediaTypes>())) {}
|
|
RtpSendRates(const RtpSendRates& rhs) = default;
|
|
RtpSendRates& operator=(const RtpSendRates&) = default;
|
|
|
|
DataRate& operator[](RtpPacketMediaType type) {
|
|
return send_rates_[static_cast<size_t>(type)];
|
|
}
|
|
const DataRate& operator[](RtpPacketMediaType type) const {
|
|
return send_rates_[static_cast<size_t>(type)];
|
|
}
|
|
DataRate Sum() const {
|
|
return absl::c_accumulate(send_rates_, DataRate::Zero());
|
|
}
|
|
|
|
private:
|
|
std::array<DataRate, kNumMediaTypes> send_rates_;
|
|
};
|
|
|
|
// Callback, called whenever byte/packet counts have been updated.
|
|
class StreamDataCountersCallback {
|
|
public:
|
|
virtual ~StreamDataCountersCallback() {}
|
|
|
|
virtual void DataCountersUpdated(const StreamDataCounters& counters,
|
|
uint32_t ssrc) = 0;
|
|
};
|
|
|
|
// Information exposed through the GetStats api.
|
|
struct RtpReceiveStats {
|
|
// `packets_lost` and `jitter` are defined by RFC 3550, and exposed in the
|
|
// RTCReceivedRtpStreamStats dictionary, see
|
|
// https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict*
|
|
int32_t packets_lost = 0;
|
|
uint32_t jitter = 0;
|
|
|
|
// Timestamp and counters exposed in RTCInboundRtpStreamStats, see
|
|
// https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
|
|
absl::optional<int64_t> last_packet_received_timestamp_ms;
|
|
RtpPacketCounter packet_counter;
|
|
};
|
|
|
|
// Callback, used to notify an observer whenever new rates have been estimated.
|
|
class BitrateStatisticsObserver {
|
|
public:
|
|
virtual ~BitrateStatisticsObserver() {}
|
|
|
|
virtual void Notify(uint32_t total_bitrate_bps,
|
|
uint32_t retransmit_bitrate_bps,
|
|
uint32_t ssrc) = 0;
|
|
};
|
|
|
|
// Callback, used to notify an observer whenever the send-side delay is updated.
|
|
class SendSideDelayObserver {
|
|
public:
|
|
virtual ~SendSideDelayObserver() {}
|
|
virtual void SendSideDelayUpdated(int avg_delay_ms,
|
|
int max_delay_ms,
|
|
uint64_t total_delay_ms,
|
|
uint32_t ssrc) = 0;
|
|
};
|
|
|
|
// Callback, used to notify an observer whenever a packet is sent to the
|
|
// transport.
|
|
// TODO(asapersson): This class will remove the need for SendSideDelayObserver.
|
|
// Remove SendSideDelayObserver once possible.
|
|
class SendPacketObserver {
|
|
public:
|
|
virtual ~SendPacketObserver() {}
|
|
virtual void OnSendPacket(uint16_t packet_id,
|
|
int64_t capture_time_ms,
|
|
uint32_t ssrc) = 0;
|
|
};
|
|
|
|
} // namespace webrtc
|
|
#endif // MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_
|