diff options
Diffstat (limited to 'webrtc/modules/rtp_rtcp')
156 files changed, 6197 insertions, 6860 deletions
diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn index c651424611..a3d3403172 100644 --- a/webrtc/modules/rtp_rtcp/BUILD.gn +++ b/webrtc/modules/rtp_rtcp/BUILD.gn @@ -10,14 +10,14 @@ import("../../build/webrtc.gni") source_set("rtp_rtcp") { sources = [ - "interface/fec_receiver.h", - "interface/receive_statistics.h", - "interface/remote_ntp_time_estimator.h", - "interface/rtp_header_parser.h", - "interface/rtp_payload_registry.h", - "interface/rtp_receiver.h", - "interface/rtp_rtcp.h", - "interface/rtp_rtcp_defines.h", + "include/fec_receiver.h", + "include/receive_statistics.h", + "include/remote_ntp_time_estimator.h", + "include/rtp_header_parser.h", + "include/rtp_payload_registry.h", + "include/rtp_receiver.h", + "include/rtp_rtcp.h", + "include/rtp_rtcp_defines.h", "mocks/mock_rtp_rtcp.h", "source/bitrate.cc", "source/bitrate.h", @@ -46,8 +46,40 @@ source_set("rtp_rtcp") { "source/remote_ntp_time_estimator.cc", "source/rtcp_packet.cc", "source/rtcp_packet.h", + "source/rtcp_packet/app.cc", + "source/rtcp_packet/app.h", + "source/rtcp_packet/bye.cc", + "source/rtcp_packet/bye.h", + "source/rtcp_packet/compound_packet.cc", + "source/rtcp_packet/compound_packet.h", + "source/rtcp_packet/dlrr.cc", + "source/rtcp_packet/dlrr.h", + "source/rtcp_packet/extended_jitter_report.cc", + "source/rtcp_packet/extended_jitter_report.h", + "source/rtcp_packet/nack.cc", + "source/rtcp_packet/nack.h", + "source/rtcp_packet/pli.cc", + "source/rtcp_packet/pli.h", + "source/rtcp_packet/psfb.cc", + "source/rtcp_packet/psfb.h", + "source/rtcp_packet/receiver_report.cc", + "source/rtcp_packet/receiver_report.h", + "source/rtcp_packet/report_block.cc", + "source/rtcp_packet/report_block.h", + "source/rtcp_packet/rrtr.cc", + "source/rtcp_packet/rrtr.h", + "source/rtcp_packet/rtpfb.cc", + "source/rtcp_packet/rtpfb.h", + "source/rtcp_packet/sli.cc", + "source/rtcp_packet/sli.h", + "source/rtcp_packet/tmmbn.cc", + "source/rtcp_packet/tmmbn.h", + "source/rtcp_packet/tmmbr.cc", + "source/rtcp_packet/tmmbr.h", "source/rtcp_packet/transport_feedback.cc", "source/rtcp_packet/transport_feedback.h", + "source/rtcp_packet/voip_metric.cc", + "source/rtcp_packet/voip_metric.h", "source/rtcp_receiver.cc", "source/rtcp_receiver.h", "source/rtcp_receiver_help.cc", diff --git a/webrtc/modules/rtp_rtcp/OWNERS b/webrtc/modules/rtp_rtcp/OWNERS index 2b08b6b2dc..fd12dcea0c 100644 --- a/webrtc/modules/rtp_rtcp/OWNERS +++ b/webrtc/modules/rtp_rtcp/OWNERS @@ -1,6 +1,11 @@ -stefan@webrtc.org
-henrik.lundin@webrtc.org
-mflodman@webrtc.org
-asapersson@webrtc.org
-
-per-file BUILD.gn=kjellander@webrtc.org
+stefan@webrtc.org +henrik.lundin@webrtc.org +mflodman@webrtc.org +asapersson@webrtc.org + +# These are for the common case of adding or renaming files. If you're doing +# structural changes, please get a review from a reviewer in this file. +per-file *.gyp=* +per-file *.gypi=* + +per-file BUILD.gn=kjellander@webrtc.org diff --git a/webrtc/modules/rtp_rtcp/interface/fec_receiver.h b/webrtc/modules/rtp_rtcp/include/fec_receiver.h index 3608165dab..65e85ad7a5 100644 --- a/webrtc/modules/rtp_rtcp/interface/fec_receiver.h +++ b/webrtc/modules/rtp_rtcp/include/fec_receiver.h @@ -8,10 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_FEC_RECEIVER_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_FEC_RECEIVER_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_FEC_RECEIVER_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_FEC_RECEIVER_H_ -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -43,4 +43,4 @@ class FecReceiver { virtual FecPacketCounter GetPacketCounter() const = 0; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_FEC_RECEIVER_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_FEC_RECEIVER_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/receive_statistics.h b/webrtc/modules/rtp_rtcp/include/receive_statistics.h index 6bd5cd846e..b4a7cd0de2 100644 --- a/webrtc/modules/rtp_rtcp/interface/receive_statistics.h +++ b/webrtc/modules/rtp_rtcp/include/receive_statistics.h @@ -8,13 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RECEIVE_STATISTICS_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RECEIVE_STATISTICS_H_ #include <map> -#include "webrtc/modules/interface/module.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -99,4 +99,4 @@ class NullReceiveStatistics : public ReceiveStatistics { }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RECEIVE_STATISTICS_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RECEIVE_STATISTICS_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h b/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h index 0ffba212a6..56c6e48691 100644 --- a/webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h +++ b/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_REMOTE_NTP_TIME_ESTIMATOR_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_REMOTE_NTP_TIME_ESTIMATOR_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_REMOTE_NTP_TIME_ESTIMATOR_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_REMOTE_NTP_TIME_ESTIMATOR_H_ #include "webrtc/base/scoped_ptr.h" #include "webrtc/system_wrappers/include/rtp_to_ntp.h" @@ -48,4 +48,4 @@ class RemoteNtpTimeEstimator { } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_REMOTE_NTP_TIME_ESTIMATOR_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_REMOTE_NTP_TIME_ESTIMATOR_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_cvo.h b/webrtc/modules/rtp_rtcp/include/rtp_cvo.h index c7a0268ef0..2e30d898ec 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_cvo.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_cvo.h @@ -7,8 +7,8 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_CVO__H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_CVO__H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_CVO_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_CVO_H_ #include "webrtc/common_video/rotation.h" @@ -51,4 +51,4 @@ inline VideoRotation ConvertCVOByteToVideoRotation(uint8_t rotation) { } } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_CVO__H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_CVO_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h b/webrtc/modules/rtp_rtcp/include/rtp_header_parser.h index 2809996b25..329de32611 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_header_parser.h @@ -7,10 +7,10 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_HEADER_PARSER_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_HEADER_PARSER_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_HEADER_PARSER_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_HEADER_PARSER_H_ -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -41,4 +41,4 @@ class RtpHeaderParser { virtual bool DeregisterRtpHeaderExtension(RTPExtensionType type) = 0; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_HEADER_PARSER_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_HEADER_PARSER_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h b/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h index 313bef1112..fae864107f 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h @@ -8,8 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_PAYLOAD_REGISTRY_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_PAYLOAD_REGISTRY_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_PAYLOAD_REGISTRY_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_PAYLOAD_REGISTRY_H_ + +#include <map> #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" @@ -27,7 +29,7 @@ class RTPPayloadStrategy { virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) const = 0; virtual void UpdatePayloadRate(RtpUtility::Payload* payload, @@ -37,7 +39,7 @@ class RTPPayloadStrategy { const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int8_t payloadType, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) const = 0; virtual int GetPayloadTypeFrequency( @@ -52,14 +54,14 @@ class RTPPayloadStrategy { class RTPPayloadRegistry { public: // The registry takes ownership of the strategy. - RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy); + explicit RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy); ~RTPPayloadRegistry(); int32_t RegisterReceivePayload( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const int8_t payload_type, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate, bool* created_new_payload_type); @@ -69,7 +71,7 @@ class RTPPayloadRegistry { int32_t ReceivePayloadType( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate, int8_t* payload_type) const; @@ -108,8 +110,16 @@ class RTPPayloadRegistry { int GetPayloadTypeFrequency(uint8_t payload_type) const; + // DEPRECATED. Use PayloadTypeToPayload below that returns const Payload* + // instead of taking output parameter. + // TODO(danilchap): Remove this when all callers have been updated. bool PayloadTypeToPayload(const uint8_t payload_type, - RtpUtility::Payload*& payload) const; + RtpUtility::Payload*& payload) const { // NOLINT + payload = + const_cast<RtpUtility::Payload*>(PayloadTypeToPayload(payload_type)); + return payload != nullptr; + } + const RtpUtility::Payload* PayloadTypeToPayload(uint8_t payload_type) const; void ResetLastReceivedPayloadTypes() { CriticalSectionScoped cs(crit_sect_.get()); @@ -145,7 +155,7 @@ class RTPPayloadRegistry { int8_t last_received_media_payload_type() const { CriticalSectionScoped cs(crit_sect_.get()); return last_received_media_payload_type_; - }; + } bool use_rtx_payload_mapping_on_restore() const { CriticalSectionScoped cs(crit_sect_.get()); @@ -163,7 +173,7 @@ class RTPPayloadRegistry { const char payload_name[RTP_PAYLOAD_NAME_SIZE], const size_t payload_name_length, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate); bool IsRtxInternal(const RTPHeader& header) const; @@ -190,4 +200,4 @@ class RTPPayloadRegistry { } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_PAYLOAD_REGISTRY_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_PAYLOAD_REGISTRY_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_receiver.h b/webrtc/modules/rtp_rtcp/include/rtp_receiver.h index 2fb8ac5d61..0640d5cc19 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_receiver.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_receiver.h @@ -8,10 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RECEIVER_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RECEIVER_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RECEIVER_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RECEIVER_H_ -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -61,7 +61,7 @@ class RtpReceiver { const char payload_name[RTP_PAYLOAD_NAME_SIZE], const int8_t payload_type, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) = 0; // De-registers |payload_type| from the payload registry. @@ -100,4 +100,4 @@ class RtpReceiver { }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RECEIVER_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RECEIVER_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h index f907408573..6a7022a94c 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h @@ -8,14 +8,15 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_H_ #include <set> +#include <utility> #include <vector> -#include "webrtc/modules/interface/module.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/include/module.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { // Forward declarations. @@ -580,9 +581,13 @@ class RtpRtcp : public Module { * * return -1 on failure else 0 */ - virtual int32_t SendREDPayloadType( - int8_t& payloadType) const = 0; - + // DEPRECATED. Use SendREDPayloadType below that takes output parameter + // by pointer instead of by reference. + // TODO(danilchap): Remove this when all callers have been updated. + int32_t SendREDPayloadType(int8_t& payloadType) const { // NOLINT + return SendREDPayloadType(&payloadType); + } + virtual int32_t SendREDPayloadType(int8_t* payload_type) const = 0; /* * Store the audio level in dBov for header-extension-for-audio-level- * indication. @@ -614,10 +619,17 @@ class RtpRtcp : public Module { /* * Get generic FEC setting */ - virtual void GenericFECStatus(bool& enable, - uint8_t& payloadTypeRED, - uint8_t& payloadTypeFEC) = 0; - + // DEPRECATED. Use GenericFECStatus below that takes output parameters + // by pointers instead of by references. + // TODO(danilchap): Remove this when all callers have been updated. + void GenericFECStatus(bool& enable, // NOLINT + uint8_t& payloadTypeRED, // NOLINT + uint8_t& payloadTypeFEC) { // NOLINT + GenericFECStatus(&enable, &payloadTypeRED, &payloadTypeFEC); + } + virtual void GenericFECStatus(bool* enable, + uint8_t* payload_type_red, + uint8_t* payload_type_fec) = 0; virtual int32_t SetFecParameters( const FecProtectionParams* delta_params, @@ -638,4 +650,4 @@ class RtpRtcp : public Module { virtual int32_t RequestKeyFrame() = 0; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_H_ diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 6936352aca..fad97f19cc 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -8,13 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_ -#define WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_ #include <stddef.h> #include <list> -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/typedefs.h" @@ -33,31 +33,23 @@ const int kVideoPayloadTypeFrequency = 90000; // Minimum RTP header size in bytes. const uint8_t kRtpHeaderSize = 12; -struct AudioPayload -{ +struct AudioPayload { uint32_t frequency; - uint8_t channels; + size_t channels; uint32_t rate; }; -struct VideoPayload -{ +struct VideoPayload { RtpVideoCodecTypes videoCodecType; uint32_t maxRate; }; -union PayloadUnion -{ +union PayloadUnion { AudioPayload Audio; VideoPayload Video; }; -enum RTPAliveType -{ - kRtpDead = 0, - kRtpNoRtp = 1, - kRtpAlive = 2 -}; +enum RTPAliveType { kRtpDead = 0, kRtpNoRtp = 1, kRtpAlive = 2 }; enum ProtectionType { kUnprotectedPacket, @@ -78,10 +70,7 @@ enum RTPExtensionType { kRtpExtensionTransportSequenceNumber, }; -enum RTCPAppSubTypes -{ - kAppSubtypeBwe = 0x00 -}; +enum RTCPAppSubTypes { kAppSubtypeBwe = 0x00 }; // TODO(sprang): Make this an enum class once rtcp_receiver has been cleaned up. enum RTCPPacketType : uint32_t { @@ -109,17 +98,9 @@ enum RTCPPacketType : uint32_t { enum KeyFrameRequestMethod { kKeyFrameReqPliRtcp, kKeyFrameReqFirRtcp }; -enum RtpRtcpPacketType -{ - kPacketRtp = 0, - kPacketKeepAlive = 1 -}; +enum RtpRtcpPacketType { kPacketRtp = 0, kPacketKeepAlive = 1 }; -enum NACKMethod -{ - kNackOff = 0, - kNackRtcp = 2 -}; +enum NACKMethod { kNackOff = 0, kNackRtcp = 2 }; enum RetransmissionMode : uint8_t { kRetransmitOff = 0x0, @@ -138,8 +119,7 @@ enum RtxMode { const size_t kRtxHeaderSize = 2; -struct RTCPSenderInfo -{ +struct RTCPSenderInfo { uint32_t NTPseconds; uint32_t NTPfraction; uint32_t RTPtimeStamp; @@ -206,40 +186,36 @@ struct RtpState { bool media_has_been_sent; }; -class RtpData -{ -public: - virtual ~RtpData() {} +class RtpData { + public: + virtual ~RtpData() {} - virtual int32_t OnReceivedPayloadData( - const uint8_t* payloadData, - const size_t payloadSize, - const WebRtcRTPHeader* rtpHeader) = 0; + virtual int32_t OnReceivedPayloadData(const uint8_t* payloadData, + const size_t payloadSize, + const WebRtcRTPHeader* rtpHeader) = 0; - virtual bool OnRecoveredPacket(const uint8_t* packet, - size_t packet_length) = 0; + virtual bool OnRecoveredPacket(const uint8_t* packet, + size_t packet_length) = 0; }; -class RtpFeedback -{ -public: - virtual ~RtpFeedback() {} - - // Receiving payload change or SSRC change. (return success!) - /* - * channels - number of channels in codec (1 = mono, 2 = stereo) - */ - virtual int32_t OnInitializeDecoder( - const int8_t payloadType, - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int frequency, - const uint8_t channels, - const uint32_t rate) = 0; - - virtual void OnIncomingSSRCChanged(const uint32_t ssrc) = 0; - - virtual void OnIncomingCSRCChanged(const uint32_t CSRC, - const bool added) = 0; +class RtpFeedback { + public: + virtual ~RtpFeedback() {} + + // Receiving payload change or SSRC change. (return success!) + /* + * channels - number of channels in codec (1 = mono, 2 = stereo) + */ + virtual int32_t OnInitializeDecoder( + const int8_t payloadType, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const int frequency, + const size_t channels, + const uint32_t rate) = 0; + + virtual void OnIncomingSSRCChanged(const uint32_t ssrc) = 0; + + virtual void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) = 0; }; class RtpAudioFeedback { @@ -346,7 +322,7 @@ class RtcpRttStats { virtual int64_t LastProcessedRtt() const = 0; - virtual ~RtcpRttStats() {}; + virtual ~RtcpRttStats() {} }; // Null object version of RtpFeedback. @@ -357,7 +333,7 @@ class NullRtpFeedback : public RtpFeedback { int32_t OnInitializeDecoder(const int8_t payloadType, const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) override { return 0; } @@ -437,4 +413,4 @@ class TransportSequenceNumberAllocator { }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INTERFACE_RTP_RTCP_DEFINES_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_ diff --git a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index bc4aec8967..796be1304c 100644 --- a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -11,11 +11,15 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTP_RTCP_H_ #define WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTP_RTCP_H_ +#include <set> +#include <utility> +#include <vector> + #include "testing/gmock/include/gmock/gmock.h" -#include "webrtc/modules/interface/module.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/include/module.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" namespace webrtc { @@ -108,7 +112,10 @@ class MockRtpRtcp : public RtpRtcp { MOCK_CONST_METHOD0(SendingMedia, bool()); MOCK_CONST_METHOD4(BitrateSent, - void(uint32_t* totalRate, uint32_t* videoRate, uint32_t* fecRate, uint32_t* nackRate)); + void(uint32_t* totalRate, + uint32_t* videoRate, + uint32_t* fecRate, + uint32_t* nackRate)); MOCK_METHOD1(RegisterVideoBitrateObserver, void(BitrateStatisticsObserver*)); MOCK_CONST_METHOD0(GetVideoBitrateObserver, BitrateStatisticsObserver*(void)); MOCK_CONST_METHOD1(EstimatedReceiveBandwidth, @@ -172,7 +179,10 @@ class MockRtpRtcp : public RtpRtcp { MOCK_CONST_METHOD1(RemoteRTCPStat, int32_t(std::vector<RTCPReportBlock>* receiveBlocks)); MOCK_METHOD4(SetRTCPApplicationSpecificData, - int32_t(const uint8_t subType, const uint32_t name, const uint8_t* data, const uint16_t length)); + int32_t(const uint8_t subType, + const uint32_t name, + const uint8_t* data, + const uint16_t length)); MOCK_METHOD1(SetRTCPVoIPMetrics, int32_t(const RTCPVoIPMetric* VoIPMetric)); MOCK_METHOD1(SetRtcpXrRrtrStatus, @@ -214,12 +224,9 @@ class MockRtpRtcp : public RtpRtcp { int32_t(const uint8_t key, const uint16_t time_ms, const uint8_t level)); MOCK_METHOD1(SetSendREDPayloadType, int32_t(const int8_t payloadType)); - MOCK_CONST_METHOD1(SendREDPayloadType, - int32_t(int8_t& payloadType)); + MOCK_CONST_METHOD1(SendREDPayloadType, int32_t(int8_t* payloadType)); MOCK_METHOD2(SetRTPAudioLevelIndicationStatus, int32_t(const bool enable, const uint8_t ID)); - MOCK_CONST_METHOD2(GetRTPAudioLevelIndicationStatus, - int32_t(bool& enable, uint8_t& ID)); MOCK_METHOD1(SetAudioLevel, int32_t(const uint8_t level_dBov)); MOCK_METHOD1(SetTargetSendBitrate, @@ -229,9 +236,9 @@ class MockRtpRtcp : public RtpRtcp { const uint8_t payload_type_red, const uint8_t payload_type_fec)); MOCK_METHOD3(GenericFECStatus, - void(bool& enable, - uint8_t& payloadTypeRED, - uint8_t& payloadTypeFEC)); + void(bool* enable, + uint8_t* payloadTypeRED, + uint8_t* payloadTypeFEC)); MOCK_METHOD2(SetFecParameters, int32_t(const FecProtectionParams* delta_params, const FecProtectionParams* key_params)); @@ -239,8 +246,6 @@ class MockRtpRtcp : public RtpRtcp { int32_t(const KeyFrameRequestMethod method)); MOCK_METHOD0(RequestKeyFrame, int32_t()); - MOCK_CONST_METHOD3(Version, - int32_t(char* version, uint32_t& remaining_buffer_in_bytes, uint32_t& position)); MOCK_METHOD0(TimeUntilNextProcess, int64_t()); MOCK_METHOD0(Process, diff --git a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi index e35a75cd0f..d340f746be 100644 --- a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi +++ b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi @@ -17,14 +17,14 @@ ], 'sources': [ # Common - 'interface/fec_receiver.h', - 'interface/receive_statistics.h', - 'interface/remote_ntp_time_estimator.h', - 'interface/rtp_header_parser.h', - 'interface/rtp_payload_registry.h', - 'interface/rtp_receiver.h', - 'interface/rtp_rtcp.h', - 'interface/rtp_rtcp_defines.h', + 'include/fec_receiver.h', + 'include/receive_statistics.h', + 'include/remote_ntp_time_estimator.h', + 'include/rtp_header_parser.h', + 'include/rtp_payload_registry.h', + 'include/rtp_receiver.h', + 'include/rtp_rtcp.h', + 'include/rtp_rtcp_defines.h', 'source/bitrate.cc', 'source/bitrate.h', 'source/byte_io.h', @@ -41,8 +41,40 @@ 'source/rtp_rtcp_impl.h', 'source/rtcp_packet.cc', 'source/rtcp_packet.h', + 'source/rtcp_packet/app.cc', + 'source/rtcp_packet/app.h', + 'source/rtcp_packet/bye.cc', + 'source/rtcp_packet/bye.h', + 'source/rtcp_packet/compound_packet.cc', + 'source/rtcp_packet/compound_packet.h', + 'source/rtcp_packet/dlrr.cc', + 'source/rtcp_packet/dlrr.h', + 'source/rtcp_packet/extended_jitter_report.cc', + 'source/rtcp_packet/extended_jitter_report.h', + 'source/rtcp_packet/nack.cc', + 'source/rtcp_packet/nack.h', + 'source/rtcp_packet/pli.cc', + 'source/rtcp_packet/pli.h', + 'source/rtcp_packet/psfb.cc', + 'source/rtcp_packet/psfb.h', + 'source/rtcp_packet/receiver_report.cc', + 'source/rtcp_packet/receiver_report.h', + 'source/rtcp_packet/report_block.cc', + 'source/rtcp_packet/report_block.h', + 'source/rtcp_packet/rrtr.cc', + 'source/rtcp_packet/rrtr.h', + 'source/rtcp_packet/rtpfb.cc', + 'source/rtcp_packet/rtpfb.h', + 'source/rtcp_packet/sli.cc', + 'source/rtcp_packet/sli.h', + 'source/rtcp_packet/tmmbn.cc', + 'source/rtcp_packet/tmmbn.h', + 'source/rtcp_packet/tmmbr.cc', + 'source/rtcp_packet/tmmbr.h', 'source/rtcp_packet/transport_feedback.cc', 'source/rtcp_packet/transport_feedback.h', + 'source/rtcp_packet/voip_metric.cc', + 'source/rtcp_packet/voip_metric.h', 'source/rtcp_receiver.cc', 'source/rtcp_receiver.h', 'source/rtcp_receiver_help.cc', diff --git a/webrtc/modules/rtp_rtcp/source/CPPLINT.cfg b/webrtc/modules/rtp_rtcp/source/CPPLINT.cfg new file mode 100644 index 0000000000..c318452482 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/CPPLINT.cfg @@ -0,0 +1,6 @@ +#tmmbr_help is refactored in CL#1474693002 +exclude_files=tmmbr_help.* +#rtcp_utility planned to be removed when webrtc:5260 will be finished. +exclude_files=rtcp_utility.* +#rtcp_receiver/rtcp_receiver_help will be refactored more deeply as part of webrtc:5260 +exclude_files=rtcp_receiver.* diff --git a/webrtc/modules/rtp_rtcp/source/byte_io.h b/webrtc/modules/rtp_rtcp/source/byte_io.h index d8903b8483..c69c178078 100644 --- a/webrtc/modules/rtp_rtcp/source/byte_io.h +++ b/webrtc/modules/rtp_rtcp/source/byte_io.h @@ -51,17 +51,14 @@ namespace webrtc { // platform that doesn't use two's complement, implement conversion to/from // wire format. -namespace { -inline void AssertTwosComplement() { - // Assume the if any one signed integer type is two's complement, then all - // other will be too. - static_assert( - (-1 & 0x03) == 0x03, - "Only two's complement representation of signed integers supported."); -} +// Assume the if any one signed integer type is two's complement, then all +// other will be too. +static_assert( + (-1 & 0x03) == 0x03, + "Only two's complement representation of signed integers supported."); + // Plain const char* won't work for static_assert, use #define instead. #define kSizeErrorMsg "Byte size must be less than or equal to data type size." -} // Utility class for getting the unsigned equivalent of a signed type. template <typename T> diff --git a/webrtc/modules/rtp_rtcp/source/dtmf_queue.cc b/webrtc/modules/rtp_rtcp/source/dtmf_queue.cc index becea912ab..ab21b8704a 100644 --- a/webrtc/modules/rtp_rtcp/source/dtmf_queue.cc +++ b/webrtc/modules/rtp_rtcp/source/dtmf_queue.cc @@ -10,7 +10,7 @@ #include "webrtc/modules/rtp_rtcp/source/dtmf_queue.h" -#include <string.h> //memset +#include <string.h> namespace webrtc { DTMFqueue::DTMFqueue() @@ -21,7 +21,9 @@ DTMFqueue::DTMFqueue() memset(dtmf_level_, 0, sizeof(dtmf_level_)); } -DTMFqueue::~DTMFqueue() { delete dtmf_critsect_; } +DTMFqueue::~DTMFqueue() { + delete dtmf_critsect_; +} int32_t DTMFqueue::AddDTMF(uint8_t key, uint16_t len, uint8_t level) { CriticalSectionScoped lock(dtmf_critsect_); diff --git a/webrtc/modules/rtp_rtcp/source/fec_private_tables_bursty.h b/webrtc/modules/rtp_rtcp/source/fec_private_tables_bursty.h index 6105ae1d24..0b39908bb1 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_private_tables_bursty.h +++ b/webrtc/modules/rtp_rtcp/source/fec_private_tables_bursty.h @@ -27,7 +27,8 @@ #include "webrtc/typedefs.h" -namespace { +namespace webrtc { +namespace fec_private_tables { const uint8_t kMaskBursty1_1[2] = { 0x80, 0x00 @@ -756,5 +757,6 @@ const uint8_t** kPacketMaskBurstyTbl[12] = { kPacketMaskBursty12 }; -} // namespace +} // namespace fec_private_tables +} // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_BURSTY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/fec_private_tables_random.h b/webrtc/modules/rtp_rtcp/source/fec_private_tables_random.h index ff6de43b76..295d749873 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_private_tables_random.h +++ b/webrtc/modules/rtp_rtcp/source/fec_private_tables_random.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_RANDOM_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_RANDOM_H_ // This file contains a set of packets masks for the FEC code. The masks in // this table are specifically designed to favor recovery to random loss. @@ -17,7 +17,8 @@ #include "webrtc/typedefs.h" -namespace { +namespace webrtc { +namespace fec_private_tables { const uint8_t kMaskRandom10_1[2] = { 0xff, 0xc0 @@ -24518,5 +24519,6 @@ const uint8_t** kPacketMaskRandomTbl[48] = { kPacketMaskRandom48 }; -} // namespace -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_H_ +} // namespace fec_private_tables +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_PRIVATE_TABLES_RANDOM_H_ diff --git a/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h b/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h index 24db39b902..6a63813f40 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h +++ b/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h @@ -14,8 +14,8 @@ // This header is included to get the nested declaration of Packet structure. #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/fec_receiver.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" #include "webrtc/typedefs.h" @@ -25,7 +25,7 @@ class CriticalSectionWrapper; class FecReceiverImpl : public FecReceiver { public: - FecReceiverImpl(RtpData* callback); + explicit FecReceiverImpl(RtpData* callback); virtual ~FecReceiverImpl(); int32_t AddReceivedRedPacket(const RTPHeader& rtp_header, diff --git a/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc index f64b537a52..bb22e1d580 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc @@ -15,8 +15,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/fec_receiver.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" diff --git a/webrtc/modules/rtp_rtcp/source/fec_test_helper.h b/webrtc/modules/rtp_rtcp/source/fec_test_helper.h index e1791adba3..aacc2d1ecc 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_test_helper.h +++ b/webrtc/modules/rtp_rtcp/source/fec_test_helper.h @@ -11,7 +11,7 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_TEST_HELPER_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_TEST_HELPER_H_ -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" namespace webrtc { @@ -54,6 +54,6 @@ class FrameGenerator { uint16_t seq_num_; uint32_t timestamp_; }; -} +} // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_TEST_HELPER_H_ diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc index aad418f015..b85d813790 100644 --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.cc @@ -10,15 +10,15 @@ #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" -#include <assert.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <iterator> +#include "webrtc/base/checks.h" #include "webrtc/base/logging.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" @@ -36,11 +36,11 @@ const uint8_t kUlpHeaderSizeLBitClear = (2 + kMaskSizeLBitClear); // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum. const uint8_t kTransportOverhead = 28; -enum { - kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets -}; +enum { kMaxFecPackets = ForwardErrorCorrection::kMaxMediaPackets }; -int32_t ForwardErrorCorrection::Packet::AddRef() { return ++ref_count_; } +int32_t ForwardErrorCorrection::Packet::AddRef() { + return ++ref_count_; +} int32_t ForwardErrorCorrection::Packet::Release() { int32_t ref_count; @@ -72,7 +72,8 @@ class FecPacket : public ForwardErrorCorrection::SortablePacket { }; bool ForwardErrorCorrection::SortablePacket::LessThan( - const SortablePacket* first, const SortablePacket* second) { + const SortablePacket* first, + const SortablePacket* second) { return IsNewerSequenceNumber(second->seq_num, first->seq_num); } @@ -83,8 +84,7 @@ ForwardErrorCorrection::RecoveredPacket::RecoveredPacket() {} ForwardErrorCorrection::RecoveredPacket::~RecoveredPacket() {} ForwardErrorCorrection::ForwardErrorCorrection() - : generated_fec_packets_(kMaxMediaPackets), - fec_packet_received_(false) {} + : generated_fec_packets_(kMaxMediaPackets), fec_packet_received_(false) {} ForwardErrorCorrection::~ForwardErrorCorrection() {} @@ -112,7 +112,6 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, FecMaskType fec_mask_type, PacketList* fec_packet_list) { const uint16_t num_media_packets = media_packet_list.size(); - // Sanity check arguments. assert(num_media_packets > 0); assert(num_important_packets >= 0 && @@ -126,12 +125,10 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, } bool l_bit = (num_media_packets > 8 * kMaskSizeLBitClear); - int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; + int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; // Do some error checking on the media packets. - PacketList::const_iterator media_list_it = media_packet_list.begin(); - while (media_list_it != media_packet_list.end()) { - Packet* media_packet = *media_list_it; + for (Packet* media_packet : media_packet_list) { assert(media_packet); if (media_packet->length < kRtpHeaderSize) { @@ -146,7 +143,6 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, LOG(LS_WARNING) << "Media packet " << media_packet->length << " bytes " << "with overhead is larger than " << IP_PACKET_SIZE; } - media_list_it++; } int num_fec_packets = @@ -167,29 +163,29 @@ int32_t ForwardErrorCorrection::GenerateFEC(const PacketList& media_packet_list, // -- Generate packet masks -- // Always allocate space for a large mask. - uint8_t* packet_mask = new uint8_t[num_fec_packets * kMaskSizeLBitSet]; - memset(packet_mask, 0, num_fec_packets * num_maskBytes); + rtc::scoped_ptr<uint8_t[]> packet_mask( + new uint8_t[num_fec_packets * kMaskSizeLBitSet]); + memset(packet_mask.get(), 0, num_fec_packets * num_mask_bytes); internal::GeneratePacketMasks(num_media_packets, num_fec_packets, num_important_packets, use_unequal_protection, - mask_table, packet_mask); - - int num_maskBits = InsertZerosInBitMasks(media_packet_list, packet_mask, - num_maskBytes, num_fec_packets); + mask_table, packet_mask.get()); - l_bit = (num_maskBits > 8 * kMaskSizeLBitClear); + int num_mask_bits = InsertZerosInBitMasks( + media_packet_list, packet_mask.get(), num_mask_bytes, num_fec_packets); - if (num_maskBits < 0) { - delete[] packet_mask; + if (num_mask_bits < 0) { return -1; } + l_bit = (num_mask_bits > 8 * kMaskSizeLBitClear); if (l_bit) { - num_maskBytes = kMaskSizeLBitSet; + num_mask_bytes = kMaskSizeLBitSet; } - GenerateFecBitStrings(media_packet_list, packet_mask, num_fec_packets, l_bit); - GenerateFecUlpHeaders(media_packet_list, packet_mask, l_bit, num_fec_packets); + GenerateFecBitStrings(media_packet_list, packet_mask.get(), num_fec_packets, + l_bit); + GenerateFecUlpHeaders(media_packet_list, packet_mask.get(), l_bit, + num_fec_packets); - delete[] packet_mask; return 0; } @@ -206,26 +202,30 @@ int ForwardErrorCorrection::GetNumberOfFecPackets(int num_media_packets, } void ForwardErrorCorrection::GenerateFecBitStrings( - const PacketList& media_packet_list, uint8_t* packet_mask, - int num_fec_packets, bool l_bit) { + const PacketList& media_packet_list, + uint8_t* packet_mask, + int num_fec_packets, + bool l_bit) { if (media_packet_list.empty()) { return; } uint8_t media_payload_length[2]; - const int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; + const int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; const uint16_t ulp_header_size = l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; const uint16_t fec_rtp_offset = kFecHeaderSize + ulp_header_size - kRtpHeaderSize; for (int i = 0; i < num_fec_packets; ++i) { + Packet* const fec_packet = &generated_fec_packets_[i]; PacketList::const_iterator media_list_it = media_packet_list.begin(); - uint32_t pkt_mask_idx = i * num_maskBytes; + uint32_t pkt_mask_idx = i * num_mask_bytes; uint32_t media_pkt_idx = 0; uint16_t fec_packet_length = 0; uint16_t prev_seq_num = ParseSequenceNumber((*media_list_it)->data); while (media_list_it != media_packet_list.end()) { - // Each FEC packet has a multiple byte mask. + // Each FEC packet has a multiple byte mask. Determine if this media + // packet should be included in FEC packet i. if (packet_mask[pkt_mask_idx] & (1 << (7 - media_pkt_idx))) { Packet* media_packet = *media_list_it; @@ -235,42 +235,40 @@ void ForwardErrorCorrection::GenerateFecBitStrings( fec_packet_length = media_packet->length + fec_rtp_offset; // On the first protected packet, we don't need to XOR. - if (generated_fec_packets_[i].length == 0) { + if (fec_packet->length == 0) { // Copy the first 2 bytes of the RTP header. - memcpy(generated_fec_packets_[i].data, media_packet->data, 2); + memcpy(fec_packet->data, media_packet->data, 2); // Copy the 5th to 8th bytes of the RTP header. - memcpy(&generated_fec_packets_[i].data[4], &media_packet->data[4], 4); + memcpy(&fec_packet->data[4], &media_packet->data[4], 4); // Copy network-ordered payload size. - memcpy(&generated_fec_packets_[i].data[8], media_payload_length, 2); + memcpy(&fec_packet->data[8], media_payload_length, 2); // Copy RTP payload, leaving room for the ULP header. - memcpy( - &generated_fec_packets_[i].data[kFecHeaderSize + ulp_header_size], - &media_packet->data[kRtpHeaderSize], - media_packet->length - kRtpHeaderSize); + memcpy(&fec_packet->data[kFecHeaderSize + ulp_header_size], + &media_packet->data[kRtpHeaderSize], + media_packet->length - kRtpHeaderSize); } else { // XOR with the first 2 bytes of the RTP header. - generated_fec_packets_[i].data[0] ^= media_packet->data[0]; - generated_fec_packets_[i].data[1] ^= media_packet->data[1]; + fec_packet->data[0] ^= media_packet->data[0]; + fec_packet->data[1] ^= media_packet->data[1]; // XOR with the 5th to 8th bytes of the RTP header. for (uint32_t j = 4; j < 8; ++j) { - generated_fec_packets_[i].data[j] ^= media_packet->data[j]; + fec_packet->data[j] ^= media_packet->data[j]; } // XOR with the network-ordered payload size. - generated_fec_packets_[i].data[8] ^= media_payload_length[0]; - generated_fec_packets_[i].data[9] ^= media_payload_length[1]; + fec_packet->data[8] ^= media_payload_length[0]; + fec_packet->data[9] ^= media_payload_length[1]; // XOR with RTP payload, leaving room for the ULP header. for (int32_t j = kFecHeaderSize + ulp_header_size; j < fec_packet_length; j++) { - generated_fec_packets_[i].data[j] ^= - media_packet->data[j - fec_rtp_offset]; + fec_packet->data[j] ^= media_packet->data[j - fec_rtp_offset]; } } - if (fec_packet_length > generated_fec_packets_[i].length) { - generated_fec_packets_[i].length = fec_packet_length; + if (fec_packet_length > fec_packet->length) { + fec_packet->length = fec_packet_length; } } media_list_it++; @@ -279,19 +277,18 @@ void ForwardErrorCorrection::GenerateFecBitStrings( media_pkt_idx += static_cast<uint16_t>(seq_num - prev_seq_num); prev_seq_num = seq_num; } - if (media_pkt_idx == 8) { - // Switch to the next mask byte. - media_pkt_idx = 0; - pkt_mask_idx++; - } + pkt_mask_idx += media_pkt_idx / 8; + media_pkt_idx %= 8; } - assert(generated_fec_packets_[i].length); - //Note: This shouldn't happen: means packet mask is wrong or poorly designed + RTC_DCHECK_GT(fec_packet->length, 0u) + << "Packet mask is wrong or poorly designed."; } } int ForwardErrorCorrection::InsertZerosInBitMasks( - const PacketList& media_packets, uint8_t* packet_mask, int num_mask_bytes, + const PacketList& media_packets, + uint8_t* packet_mask, + int num_mask_bytes, int num_fec_packets) { uint8_t* new_mask = NULL; if (media_packets.size() <= 1) { @@ -307,6 +304,9 @@ int ForwardErrorCorrection::InsertZerosInBitMasks( // required. return media_packets.size(); } + // We can only protect 8 * kMaskSizeLBitSet packets. + if (total_missing_seq_nums + media_packets.size() > 8 * kMaskSizeLBitSet) + return -1; // Allocate the new mask. int new_mask_bytes = kMaskSizeLBitClear; if (media_packets.size() + total_missing_seq_nums > 8 * kMaskSizeLBitClear) { @@ -357,7 +357,8 @@ int ForwardErrorCorrection::InsertZerosInBitMasks( return new_bit_index; } -void ForwardErrorCorrection::InsertZeroColumns(int num_zeros, uint8_t* new_mask, +void ForwardErrorCorrection::InsertZeroColumns(int num_zeros, + uint8_t* new_mask, int new_mask_bytes, int num_fec_packets, int new_bit_index) { @@ -368,9 +369,12 @@ void ForwardErrorCorrection::InsertZeroColumns(int num_zeros, uint8_t* new_mask, } } -void ForwardErrorCorrection::CopyColumn(uint8_t* new_mask, int new_mask_bytes, - uint8_t* old_mask, int old_mask_bytes, - int num_fec_packets, int new_bit_index, +void ForwardErrorCorrection::CopyColumn(uint8_t* new_mask, + int new_mask_bytes, + uint8_t* old_mask, + int old_mask_bytes, + int num_fec_packets, + int new_bit_index, int old_bit_index) { // Copy column from the old mask to the beginning of the new mask and shift it // out from the old mask. @@ -386,7 +390,9 @@ void ForwardErrorCorrection::CopyColumn(uint8_t* new_mask, int new_mask_bytes, } void ForwardErrorCorrection::GenerateFecUlpHeaders( - const PacketList& media_packet_list, uint8_t* packet_mask, bool l_bit, + const PacketList& media_packet_list, + uint8_t* packet_mask, + bool l_bit, int num_fec_packets) { // -- Generate FEC and ULP headers -- // @@ -412,33 +418,34 @@ void ForwardErrorCorrection::GenerateFecUlpHeaders( PacketList::const_iterator media_list_it = media_packet_list.begin(); Packet* media_packet = *media_list_it; assert(media_packet != NULL); - int num_maskBytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; + int num_mask_bytes = l_bit ? kMaskSizeLBitSet : kMaskSizeLBitClear; const uint16_t ulp_header_size = l_bit ? kUlpHeaderSizeLBitSet : kUlpHeaderSizeLBitClear; for (int i = 0; i < num_fec_packets; ++i) { + Packet* const fec_packet = &generated_fec_packets_[i]; // -- FEC header -- - generated_fec_packets_[i].data[0] &= 0x7f; // Set E to zero. + fec_packet->data[0] &= 0x7f; // Set E to zero. if (l_bit == 0) { - generated_fec_packets_[i].data[0] &= 0xbf; // Clear the L bit. + fec_packet->data[0] &= 0xbf; // Clear the L bit. } else { - generated_fec_packets_[i].data[0] |= 0x40; // Set the L bit. + fec_packet->data[0] |= 0x40; // Set the L bit. } // Two byte sequence number from first RTP packet to SN base. // We use the same sequence number base for every FEC packet, // but that's not required in general. - memcpy(&generated_fec_packets_[i].data[2], &media_packet->data[2], 2); + memcpy(&fec_packet->data[2], &media_packet->data[2], 2); // -- ULP header -- // Copy the payload size to the protection length field. // (We protect the entire packet.) ByteWriter<uint16_t>::WriteBigEndian( - &generated_fec_packets_[i].data[10], - generated_fec_packets_[i].length - kFecHeaderSize - ulp_header_size); + &fec_packet->data[10], + fec_packet->length - kFecHeaderSize - ulp_header_size); // Copy the packet mask. - memcpy(&generated_fec_packets_[i].data[12], &packet_mask[i * num_maskBytes], - num_maskBytes); + memcpy(&fec_packet->data[12], &packet_mask[i * num_mask_bytes], + num_mask_bytes); } } @@ -460,7 +467,7 @@ void ForwardErrorCorrection::ResetState( ProtectedPacketList::iterator protected_packet_list_it; protected_packet_list_it = fec_packet->protected_pkt_list.begin(); while (protected_packet_list_it != fec_packet->protected_pkt_list.end()) { - delete* protected_packet_list_it; + delete *protected_packet_list_it; protected_packet_list_it = fec_packet->protected_pkt_list.erase(protected_packet_list_it); } @@ -472,7 +479,8 @@ void ForwardErrorCorrection::ResetState( } void ForwardErrorCorrection::InsertMediaPacket( - ReceivedPacket* rx_packet, RecoveredPacketList* recovered_packet_list) { + ReceivedPacket* rx_packet, + RecoveredPacketList* recovered_packet_list) { RecoveredPacketList::iterator recovered_packet_list_it = recovered_packet_list->begin(); @@ -538,9 +546,9 @@ void ForwardErrorCorrection::InsertFECPacket( const uint16_t seq_num_base = ByteReader<uint16_t>::ReadBigEndian(&fec_packet->pkt->data[2]); - const uint16_t maskSizeBytes = - (fec_packet->pkt->data[0] & 0x40) ? kMaskSizeLBitSet - : kMaskSizeLBitClear; // L bit set? + const uint16_t maskSizeBytes = (fec_packet->pkt->data[0] & 0x40) + ? kMaskSizeLBitSet + : kMaskSizeLBitClear; // L bit set? for (uint16_t byte_idx = 0; byte_idx < maskSizeBytes; ++byte_idx) { uint8_t packet_mask = fec_packet->pkt->data[12 + byte_idx]; @@ -574,7 +582,8 @@ void ForwardErrorCorrection::InsertFECPacket( } void ForwardErrorCorrection::AssignRecoveredPackets( - FecPacket* fec_packet, const RecoveredPacketList* recovered_packets) { + FecPacket* fec_packet, + const RecoveredPacketList* recovered_packets) { // Search for missing packets which have arrived or have been recovered by // another FEC packet. ProtectedPacketList* not_recovered = &fec_packet->protected_pkt_list; @@ -599,7 +608,6 @@ void ForwardErrorCorrection::AssignRecoveredPackets( void ForwardErrorCorrection::InsertPackets( ReceivedPacketList* received_packet_list, RecoveredPacketList* recovered_packet_list) { - while (!received_packet_list->empty()) { ReceivedPacket* rx_packet = received_packet_list->front(); @@ -611,9 +619,9 @@ void ForwardErrorCorrection::InsertPackets( // old FEC packets based on timestamp information or better sequence number // thresholding (e.g., to distinguish between wrap-around and reordering). if (!fec_packet_list_.empty()) { - uint16_t seq_num_diff = abs( - static_cast<int>(rx_packet->seq_num) - - static_cast<int>(fec_packet_list_.front()->seq_num)); + uint16_t seq_num_diff = + abs(static_cast<int>(rx_packet->seq_num) - + static_cast<int>(fec_packet_list_.front()->seq_num)); if (seq_num_diff > 0x3fff) { DiscardFECPacket(fec_packet_list_.front()); fec_packet_list_.pop_front(); @@ -637,9 +645,9 @@ void ForwardErrorCorrection::InsertPackets( bool ForwardErrorCorrection::InitRecovery(const FecPacket* fec_packet, RecoveredPacket* recovered) { // This is the first packet which we try to recover with. - const uint16_t ulp_header_size = - fec_packet->pkt->data[0] & 0x40 ? kUlpHeaderSizeLBitSet - : kUlpHeaderSizeLBitClear; // L bit set? + const uint16_t ulp_header_size = fec_packet->pkt->data[0] & 0x40 + ? kUlpHeaderSizeLBitSet + : kUlpHeaderSizeLBitClear; // L bit set? if (fec_packet->pkt->length < static_cast<size_t>(kFecHeaderSize + ulp_header_size)) { LOG(LS_WARNING) diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction.h b/webrtc/modules/rtp_rtcp/source/forward_error_correction.h index f92f014db3..9ba6ce0438 100644 --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction.h +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction.h @@ -15,7 +15,7 @@ #include <vector> #include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/system_wrappers/include/ref_count.h" #include "webrtc/typedefs.h" diff --git a/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.cc b/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.cc index 6d9be90de1..fae59078b1 100644 --- a/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.cc +++ b/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.cc @@ -17,6 +17,8 @@ #include "webrtc/modules/rtp_rtcp/source/fec_private_tables_random.h" namespace { +using webrtc::fec_private_tables::kPacketMaskBurstyTbl; +using webrtc::fec_private_tables::kPacketMaskRandomTbl; // Allow for different modes of protection for packets in UEP case. enum ProtectionMode { @@ -37,8 +39,11 @@ enum ProtectionMode { // [0, num_rows * num_sub_mask_bytes] // \param[out] packet_mask A pointer to hold the output mask, of size // [0, x * num_mask_bytes], where x >= num_rows. -void FitSubMask(int num_mask_bytes, int num_sub_mask_bytes, int num_rows, - const uint8_t* sub_mask, uint8_t* packet_mask) { +void FitSubMask(int num_mask_bytes, + int num_sub_mask_bytes, + int num_rows, + const uint8_t* sub_mask, + uint8_t* packet_mask) { if (num_mask_bytes == num_sub_mask_bytes) { memcpy(packet_mask, sub_mask, num_rows * num_sub_mask_bytes); } else { @@ -70,13 +75,15 @@ void FitSubMask(int num_mask_bytes, int num_sub_mask_bytes, int num_rows, // \param[out] packet_mask A pointer to hold the output mask, of size // [0, x * num_mask_bytes], // where x >= end_row_fec. -// TODO (marpan): This function is doing three things at the same time: +// TODO(marpan): This function is doing three things at the same time: // shift within a byte, byte shift and resizing. // Split up into subroutines. -void ShiftFitSubMask(int num_mask_bytes, int res_mask_bytes, - int num_column_shift, int end_row, const uint8_t* sub_mask, +void ShiftFitSubMask(int num_mask_bytes, + int res_mask_bytes, + int num_column_shift, + int end_row, + const uint8_t* sub_mask, uint8_t* packet_mask) { - // Number of bit shifts within a byte const int num_bit_shifts = (num_column_shift % 8); const int num_byte_shifts = num_column_shift >> 3; @@ -128,7 +135,6 @@ void ShiftFitSubMask(int num_mask_bytes, int res_mask_bytes, // For the first byte in the row (j=0 case). shift_right_curr_byte = sub_mask[pkt_mask_idx2] >> num_bit_shifts; packet_mask[pkt_mask_idx] = shift_right_curr_byte; - } } } // namespace @@ -151,7 +157,9 @@ FecMaskType PacketMaskTable::InitMaskType(FecMaskType fec_mask_type, assert(num_media_packets <= static_cast<int>(sizeof(kPacketMaskRandomTbl) / sizeof(*kPacketMaskRandomTbl))); switch (fec_mask_type) { - case kFecMaskRandom: { return kFecMaskRandom; } + case kFecMaskRandom: { + return kFecMaskRandom; + } case kFecMaskBursty: { int max_media_packets = static_cast<int>(sizeof(kPacketMaskBurstyTbl) / sizeof(*kPacketMaskBurstyTbl)); @@ -170,17 +178,24 @@ FecMaskType PacketMaskTable::InitMaskType(FecMaskType fec_mask_type, // |fec_mask_type|. const uint8_t*** PacketMaskTable::InitMaskTable(FecMaskType fec_mask_type) { switch (fec_mask_type) { - case kFecMaskRandom: { return kPacketMaskRandomTbl; } - case kFecMaskBursty: { return kPacketMaskBurstyTbl; } + case kFecMaskRandom: { + return kPacketMaskRandomTbl; + } + case kFecMaskBursty: { + return kPacketMaskBurstyTbl; + } } assert(false); return kPacketMaskRandomTbl; } // Remaining protection after important (first partition) packet protection -void RemainingPacketProtection(int num_media_packets, int num_fec_remaining, - int num_fec_for_imp_packets, int num_mask_bytes, - ProtectionMode mode, uint8_t* packet_mask, +void RemainingPacketProtection(int num_media_packets, + int num_fec_remaining, + int num_fec_for_imp_packets, + int num_mask_bytes, + ProtectionMode mode, + uint8_t* packet_mask, const PacketMaskTable& mask_table) { if (mode == kModeNoOverlap) { // sub_mask21 @@ -191,8 +206,10 @@ void RemainingPacketProtection(int num_media_packets, int num_fec_remaining, const int res_mask_bytes = (l_bit == 1) ? kMaskSizeLBitSet : kMaskSizeLBitClear; - const uint8_t* packet_mask_sub_21 = mask_table.fec_packet_mask_table()[ - num_media_packets - num_fec_for_imp_packets - 1][num_fec_remaining - 1]; + const uint8_t* packet_mask_sub_21 = + mask_table.fec_packet_mask_table()[num_media_packets - + num_fec_for_imp_packets - + 1][num_fec_remaining - 1]; ShiftFitSubMask(num_mask_bytes, res_mask_bytes, num_fec_for_imp_packets, (num_fec_for_imp_packets + num_fec_remaining), @@ -201,8 +218,9 @@ void RemainingPacketProtection(int num_media_packets, int num_fec_remaining, } else if (mode == kModeOverlap || mode == kModeBiasFirstPacket) { // sub_mask22 - const uint8_t* packet_mask_sub_22 = mask_table - .fec_packet_mask_table()[num_media_packets - 1][num_fec_remaining - 1]; + const uint8_t* packet_mask_sub_22 = + mask_table.fec_packet_mask_table()[num_media_packets - + 1][num_fec_remaining - 1]; FitSubMask(num_mask_bytes, num_mask_bytes, num_fec_remaining, packet_mask_sub_22, @@ -217,41 +235,42 @@ void RemainingPacketProtection(int num_media_packets, int num_fec_remaining, } else { assert(false); } - } // Protection for important (first partition) packets -void ImportantPacketProtection(int num_fec_for_imp_packets, int num_imp_packets, - int num_mask_bytes, uint8_t* packet_mask, +void ImportantPacketProtection(int num_fec_for_imp_packets, + int num_imp_packets, + int num_mask_bytes, + uint8_t* packet_mask, const PacketMaskTable& mask_table) { const int l_bit = num_imp_packets > 16 ? 1 : 0; const int num_imp_mask_bytes = (l_bit == 1) ? kMaskSizeLBitSet : kMaskSizeLBitClear; // Get sub_mask1 from table - const uint8_t* packet_mask_sub_1 = mask_table.fec_packet_mask_table()[ - num_imp_packets - 1][num_fec_for_imp_packets - 1]; + const uint8_t* packet_mask_sub_1 = + mask_table.fec_packet_mask_table()[num_imp_packets - + 1][num_fec_for_imp_packets - 1]; FitSubMask(num_mask_bytes, num_imp_mask_bytes, num_fec_for_imp_packets, packet_mask_sub_1, packet_mask); - } // This function sets the protection allocation: i.e., how many FEC packets // to use for num_imp (1st partition) packets, given the: number of media // packets, number of FEC packets, and number of 1st partition packets. -int SetProtectionAllocation(int num_media_packets, int num_fec_packets, +int SetProtectionAllocation(int num_media_packets, + int num_fec_packets, int num_imp_packets) { - - // TODO (marpan): test different cases for protection allocation: + // TODO(marpan): test different cases for protection allocation: // Use at most (alloc_par * num_fec_packets) for important packets. float alloc_par = 0.5; int max_num_fec_for_imp = alloc_par * num_fec_packets; - int num_fec_for_imp_packets = - (num_imp_packets < max_num_fec_for_imp) ? num_imp_packets - : max_num_fec_for_imp; + int num_fec_for_imp_packets = (num_imp_packets < max_num_fec_for_imp) + ? num_imp_packets + : max_num_fec_for_imp; // Fall back to equal protection in this case if (num_fec_packets == 1 && (num_media_packets > 2 * num_imp_packets)) { @@ -268,7 +287,7 @@ int SetProtectionAllocation(int num_media_packets, int num_fec_packets, // Current version has 3 modes (options) to build UEP mask from existing ones. // Various other combinations may be added in future versions. // Longer-term, we may add another set of tables specifically for UEP cases. -// TODO (marpan): also consider modification of masks for bursty loss cases. +// TODO(marpan): also consider modification of masks for bursty loss cases. // Mask is characterized as (#packets_to_protect, #fec_for_protection). // Protection factor defined as: (#fec_for_protection / #packets_to_protect). @@ -306,13 +325,14 @@ int SetProtectionAllocation(int num_media_packets, int num_fec_packets, // Protection Mode 2 may be extended for a sort of sliding protection // (i.e., vary the number/density of "1s" across columns) across packets. -void UnequalProtectionMask(int num_media_packets, int num_fec_packets, - int num_imp_packets, int num_mask_bytes, +void UnequalProtectionMask(int num_media_packets, + int num_fec_packets, + int num_imp_packets, + int num_mask_bytes, uint8_t* packet_mask, const PacketMaskTable& mask_table) { - // Set Protection type and allocation - // TODO (marpan): test/update for best mode and some combinations thereof. + // TODO(marpan): test/update for best mode and some combinations thereof. ProtectionMode mode = kModeOverlap; int num_fec_for_imp_packets = 0; @@ -341,11 +361,12 @@ void UnequalProtectionMask(int num_media_packets, int num_fec_packets, num_fec_for_imp_packets, num_mask_bytes, mode, packet_mask, mask_table); } - } -void GeneratePacketMasks(int num_media_packets, int num_fec_packets, - int num_imp_packets, bool use_unequal_protection, +void GeneratePacketMasks(int num_media_packets, + int num_fec_packets, + int num_imp_packets, + bool use_unequal_protection, const PacketMaskTable& mask_table, uint8_t* packet_mask) { assert(num_media_packets > 0); @@ -361,16 +382,15 @@ void GeneratePacketMasks(int num_media_packets, int num_fec_packets, // Retrieve corresponding mask table directly:for equal-protection case. // Mask = (k,n-k), with protection factor = (n-k)/k, // where k = num_media_packets, n=total#packets, (n-k)=num_fec_packets. - memcpy(packet_mask, mask_table.fec_packet_mask_table()[ - num_media_packets - 1][num_fec_packets - 1], + memcpy(packet_mask, + mask_table.fec_packet_mask_table()[num_media_packets - + 1][num_fec_packets - 1], num_fec_packets * num_mask_bytes); - } else //UEP case - { + } else { // UEP case UnequalProtectionMask(num_media_packets, num_fec_packets, num_imp_packets, num_mask_bytes, packet_mask, mask_table); - } // End of UEP modification -} //End of GetPacketMasks +} // End of GetPacketMasks } // namespace internal } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h b/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h index 53ef2a61f4..28276afb72 100644 --- a/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h +++ b/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ -#include <stdint.h> #include <stddef.h> +#include <stdint.h> namespace rtc { class BitBuffer; diff --git a/webrtc/modules/rtp_rtcp/source/h264_sps_parser_unittest.cc b/webrtc/modules/rtp_rtcp/source/h264_sps_parser_unittest.cc index ceadf4cb6b..7a7e3ed293 100644 --- a/webrtc/modules/rtp_rtcp/source/h264_sps_parser_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/h264_sps_parser_unittest.cc @@ -12,6 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/arraysize.h" #include "webrtc/base/bitbuffer.h" namespace webrtc { @@ -121,7 +122,7 @@ TEST(H264SpsParserTest, TestSampleSPSHdLandscape) { const uint8_t buffer[] = {0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40, 0x50, 0x05, 0xBA, 0x10, 0x00, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x2A, 0xE0, 0xF1, 0x83, 0x19, 0x60}; - H264SpsParser parser = H264SpsParser(buffer, ARRAY_SIZE(buffer)); + H264SpsParser parser = H264SpsParser(buffer, arraysize(buffer)); EXPECT_TRUE(parser.Parse()); EXPECT_EQ(1280u, parser.width()); EXPECT_EQ(720u, parser.height()); @@ -133,7 +134,7 @@ TEST(H264SpsParserTest, TestSampleSPSVgaLandscape) { const uint8_t buffer[] = {0x7A, 0x00, 0x1E, 0xBC, 0xD9, 0x40, 0xA0, 0x2F, 0xF8, 0x98, 0x40, 0x00, 0x00, 0x03, 0x01, 0x80, 0x00, 0x00, 0x56, 0x83, 0xC5, 0x8B, 0x65, 0x80}; - H264SpsParser parser = H264SpsParser(buffer, ARRAY_SIZE(buffer)); + H264SpsParser parser = H264SpsParser(buffer, arraysize(buffer)); EXPECT_TRUE(parser.Parse()); EXPECT_EQ(640u, parser.width()); EXPECT_EQ(360u, parser.height()); @@ -145,7 +146,7 @@ TEST(H264SpsParserTest, TestSampleSPSWeirdResolution) { const uint8_t buffer[] = {0x7A, 0x00, 0x0D, 0xBC, 0xD9, 0x43, 0x43, 0x3E, 0x5E, 0x10, 0x00, 0x00, 0x03, 0x00, 0x60, 0x00, 0x00, 0x15, 0xA0, 0xF1, 0x42, 0x99, 0x60}; - H264SpsParser parser = H264SpsParser(buffer, ARRAY_SIZE(buffer)); + H264SpsParser parser = H264SpsParser(buffer, arraysize(buffer)); EXPECT_TRUE(parser.Parse()); EXPECT_EQ(200u, parser.width()); EXPECT_EQ(400u, parser.height()); @@ -154,7 +155,7 @@ TEST(H264SpsParserTest, TestSampleSPSWeirdResolution) { TEST(H264SpsParserTest, TestSyntheticSPSQvgaLandscape) { uint8_t buffer[kSpsBufferMaxSize] = {0}; GenerateFakeSps(320u, 180u, buffer); - H264SpsParser parser = H264SpsParser(buffer, ARRAY_SIZE(buffer)); + H264SpsParser parser = H264SpsParser(buffer, arraysize(buffer)); EXPECT_TRUE(parser.Parse()); EXPECT_EQ(320u, parser.width()); EXPECT_EQ(180u, parser.height()); @@ -163,7 +164,7 @@ TEST(H264SpsParserTest, TestSyntheticSPSQvgaLandscape) { TEST(H264SpsParserTest, TestSyntheticSPSWeirdResolution) { uint8_t buffer[kSpsBufferMaxSize] = {0}; GenerateFakeSps(156u, 122u, buffer); - H264SpsParser parser = H264SpsParser(buffer, ARRAY_SIZE(buffer)); + H264SpsParser parser = H264SpsParser(buffer, arraysize(buffer)); EXPECT_TRUE(parser.Parse()); EXPECT_EQ(156u, parser.width()); EXPECT_EQ(122u, parser.height()); diff --git a/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h b/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h index f577cbaad1..011829cc6c 100644 --- a/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h +++ b/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h @@ -8,11 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_REGISTRY_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_REGISTRY_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_ #include "testing/gmock/include/gmock/gmock.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" namespace webrtc { @@ -23,7 +23,7 @@ class MockRTPPayloadStrategy : public RTPPayloadStrategy { MOCK_CONST_METHOD4(PayloadIsCompatible, bool(const RtpUtility::Payload& payload, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate)); MOCK_CONST_METHOD2(UpdatePayloadRate, void(RtpUtility::Payload* payload, const uint32_t rate)); @@ -34,10 +34,10 @@ class MockRTPPayloadStrategy : public RTPPayloadStrategy { RtpUtility::Payload*(const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int8_t payloadType, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate)); }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_REGISTRY_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc index 07a3693507..e19c31bfec 100644 --- a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc @@ -16,15 +16,15 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/transport.h" -using namespace webrtc; +namespace webrtc { const int kVideoNackListSize = 30; const uint32_t kTestSsrc = 3456; @@ -35,8 +35,7 @@ const int kNumFrames = 30; const int kPayloadType = 123; const int kRtxPayloadType = 98; -class VerifyingRtxReceiver : public NullRtpData -{ +class VerifyingRtxReceiver : public NullRtpData { public: VerifyingRtxReceiver() {} @@ -54,7 +53,7 @@ class VerifyingRtxReceiver : public NullRtpData class TestRtpFeedback : public NullRtpFeedback { public: - TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {} + explicit TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {} virtual ~TestRtpFeedback() {} void OnIncomingSSRCChanged(const uint32_t ssrc) override { @@ -86,9 +85,7 @@ class RtxLoopBackTransport : public webrtc::Transport { rtp_receiver_ = receiver; } - void DropEveryNthPacket(int n) { - packet_loss_ = n; - } + void DropEveryNthPacket(int n) { packet_loss_ = n; } void DropConsecutivePackets(int start, int total) { consecutive_drop_start_ = start; @@ -100,15 +97,13 @@ class RtxLoopBackTransport : public webrtc::Transport { size_t len, const PacketOptions& options) override { count_++; - const unsigned char* ptr = static_cast<const unsigned char*>(data); + const unsigned char* ptr = static_cast<const unsigned char*>(data); uint32_t ssrc = (ptr[8] << 24) + (ptr[9] << 16) + (ptr[10] << 8) + ptr[11]; - if (ssrc == rtx_ssrc_) count_rtx_ssrc_++; + if (ssrc == rtx_ssrc_) + count_rtx_ssrc_++; uint16_t sequence_number = (ptr[2] << 8) + ptr[3]; size_t packet_length = len; - // TODO(pbos): Figure out why this needs to be initialized. Likely this - // is hiding a bug either in test setup or other code. - // https://code.google.com/p/webrtc/issues/detail?id=3183 - uint8_t restored_packet[1500] = {0}; + uint8_t restored_packet[1500]; RTPHeader header; rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create()); if (!parser->Parse(ptr, len, &header)) { @@ -136,21 +131,19 @@ class RtxLoopBackTransport : public webrtc::Transport { if (!parser->Parse(restored_packet, packet_length, &header)) { return false; } + ptr = restored_packet; } else { rtp_payload_registry_->SetIncomingPayloadType(header); } - const uint8_t* restored_packet_payload = - restored_packet + header.headerLength; - packet_length -= header.headerLength; PayloadUnion payload_specific; if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType, &payload_specific)) { return false; } - if (!rtp_receiver_->IncomingRtpPacket(header, restored_packet_payload, - packet_length, payload_specific, - true)) { + if (!rtp_receiver_->IncomingRtpPacket(header, ptr + header.headerLength, + packet_length - header.headerLength, + payload_specific, true)) { return false; } return true; @@ -194,8 +187,7 @@ class RtpRtcpRtxNackTest : public ::testing::Test { rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_)); rtp_receiver_.reset(RtpReceiver::CreateVideoReceiver( - &fake_clock, &receiver_, rtp_feedback_.get(), - &rtp_payload_registry_)); + &fake_clock, &receiver_, rtp_feedback_.get(), &rtp_payload_registry_)); rtp_rtcp_module_->SetSSRC(kTestSsrc); rtp_rtcp_module_->SetRTCPStatus(RtcpMode::kCompound); @@ -215,11 +207,9 @@ class RtpRtcpRtxNackTest : public ::testing::Test { EXPECT_EQ(0, rtp_rtcp_module_->RegisterSendPayload(video_codec)); rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType); - EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(video_codec.plName, - video_codec.plType, - 90000, - 0, - video_codec.maxBitrate)); + EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload( + video_codec.plName, video_codec.plType, 90000, 0, + video_codec.maxBitrate)); rtp_payload_registry_.SetRtxPayloadType(kRtxPayloadType, kPayloadType); for (size_t n = 0; n < payload_data_length; n++) { @@ -230,8 +220,7 @@ class RtpRtcpRtxNackTest : public ::testing::Test { int BuildNackList(uint16_t* nack_list) { receiver_.sequence_numbers_.sort(); std::list<uint16_t> missing_sequence_numbers; - std::list<uint16_t>::iterator it = - receiver_.sequence_numbers_.begin(); + std::list<uint16_t>::iterator it = receiver_.sequence_numbers_.begin(); while (it != receiver_.sequence_numbers_.end()) { uint16_t sequence_number_1 = *it; @@ -239,15 +228,14 @@ class RtpRtcpRtxNackTest : public ::testing::Test { if (it != receiver_.sequence_numbers_.end()) { uint16_t sequence_number_2 = *it; // Add all missing sequence numbers to list - for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2; - ++i) { + for (uint16_t i = sequence_number_1 + 1; i < sequence_number_2; ++i) { missing_sequence_numbers.push_back(i); } } } int n = 0; for (it = missing_sequence_numbers.begin(); - it != missing_sequence_numbers.end(); ++it) { + it != missing_sequence_numbers.end(); ++it) { nack_list[n++] = (*it); } return n; @@ -298,7 +286,7 @@ class RtpRtcpRtxNackTest : public ::testing::Test { rtc::scoped_ptr<TestRtpFeedback> rtp_feedback_; RtxLoopBackTransport transport_; VerifyingRtxReceiver receiver_; - uint8_t payload_data[65000]; + uint8_t payload_data[65000]; size_t payload_data_length; SimulatedClock fake_clock; }; @@ -345,8 +333,10 @@ TEST_F(RtpRtcpRtxNackTest, RtxNack) { RunRtxTest(kRtxRetransmitted, 10); EXPECT_EQ(kTestSequenceNumber, *(receiver_.sequence_numbers_.begin())); EXPECT_EQ(kTestSequenceNumber + kTestNumberOfPackets - 1, - *(receiver_.sequence_numbers_.rbegin())); + *(receiver_.sequence_numbers_.rbegin())); EXPECT_EQ(kTestNumberOfPackets, receiver_.sequence_numbers_.size()); EXPECT_EQ(kTestNumberOfRtxPackets, transport_.count_rtx_ssrc_); EXPECT_TRUE(ExpectedPacketsReceived()); } + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc b/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc index 683b951f1e..be4b453454 100644 --- a/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc @@ -9,8 +9,10 @@ */ #include <list> +#include <vector> #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" @@ -54,6 +56,53 @@ class ProducerFecTest : public ::testing::Test { FrameGenerator* generator_; }; +// Verifies bug found via fuzzing, where a gap in the packet sequence caused us +// to move past the end of the current FEC packet mask byte without moving to +// the next byte. That likely caused us to repeatedly read from the same byte, +// and if that byte didn't protect packets we would generate empty FEC. +TEST_F(ProducerFecTest, NoEmptyFecWithSeqNumGaps) { + struct Packet { + size_t header_size; + size_t payload_size; + uint16_t seq_num; + bool marker_bit; + }; + std::vector<Packet> protected_packets; + protected_packets.push_back({15, 3, 41, 0}); + protected_packets.push_back({14, 1, 43, 0}); + protected_packets.push_back({19, 0, 48, 0}); + protected_packets.push_back({19, 0, 50, 0}); + protected_packets.push_back({14, 3, 51, 0}); + protected_packets.push_back({13, 8, 52, 0}); + protected_packets.push_back({19, 2, 53, 0}); + protected_packets.push_back({12, 3, 54, 0}); + protected_packets.push_back({21, 0, 55, 0}); + protected_packets.push_back({13, 3, 57, 1}); + FecProtectionParams params = {117, 0, 3, kFecMaskBursty}; + producer_->SetFecParameters(¶ms, 0); + uint8_t packet[28] = {0}; + for (Packet p : protected_packets) { + if (p.marker_bit) { + packet[1] |= 0x80; + } else { + packet[1] &= ~0x80; + } + ByteWriter<uint16_t>::WriteBigEndian(&packet[2], p.seq_num); + producer_->AddRtpPacketAndGenerateFec(packet, p.payload_size, + p.header_size); + uint16_t num_fec_packets = producer_->NumAvailableFecPackets(); + std::vector<RedPacket*> fec_packets; + if (num_fec_packets > 0) { + fec_packets = + producer_->GetFecPackets(kRedPayloadType, 99, 100, p.header_size); + EXPECT_EQ(num_fec_packets, fec_packets.size()); + } + for (RedPacket* fec_packet : fec_packets) { + delete fec_packet; + } + } +} + TEST_F(ProducerFecTest, OneFrameFec) { // The number of media packets (|kNumPackets|), number of frames (one for // this test), and the protection factor (|params->fec_rate|) are set to make diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc index 8ac7e0a383..24f1e2c96e 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -14,7 +14,7 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" +#include "webrtc/modules/rtp_rtcp/source/time_util.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" namespace webrtc { @@ -37,8 +37,6 @@ StreamStatisticianImpl::StreamStatisticianImpl( cumulative_loss_(0), jitter_q4_transmission_time_offset_(0), last_receive_time_ms_(0), - last_receive_time_secs_(0), - last_receive_time_frac_(0), last_received_timestamp_(0), last_received_transmission_time_offset_(0), received_seq_first_(0), @@ -79,9 +77,7 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, // are received, 4 will be ignored. if (in_order) { // Current time in samples. - uint32_t receive_time_secs; - uint32_t receive_time_frac; - clock_->CurrentNtp(receive_time_secs, receive_time_frac); + NtpTime receive_time(*clock_); // Wrong if we use RetransmitOfOldPacket. if (receive_counters_.transmitted.packets > 1 && @@ -97,11 +93,10 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, if (header.timestamp != last_received_timestamp_ && (receive_counters_.transmitted.packets - receive_counters_.retransmitted.packets) > 1) { - UpdateJitter(header, receive_time_secs, receive_time_frac); + UpdateJitter(header, receive_time); } last_received_timestamp_ = header.timestamp; - last_receive_time_secs_ = receive_time_secs; - last_receive_time_frac_ = receive_time_frac; + last_receive_time_ntp_ = receive_time; last_receive_time_ms_ = clock_->TimeInMilliseconds(); } @@ -113,14 +108,11 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, } void StreamStatisticianImpl::UpdateJitter(const RTPHeader& header, - uint32_t receive_time_secs, - uint32_t receive_time_frac) { - uint32_t receive_time_rtp = RtpUtility::ConvertNTPTimeToRTP( - receive_time_secs, receive_time_frac, header.payload_type_frequency); + NtpTime receive_time) { + uint32_t receive_time_rtp = + NtpToRtp(receive_time, header.payload_type_frequency); uint32_t last_receive_time_rtp = - RtpUtility::ConvertNTPTimeToRTP(last_receive_time_secs_, - last_receive_time_frac_, - header.payload_type_frequency); + NtpToRtp(last_receive_time_ntp_, header.payload_type_frequency); int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - (header.timestamp - last_received_timestamp_); @@ -267,6 +259,7 @@ RtcpStatistics StreamStatisticianImpl::CalculateRtcpStatistics() { stats.fraction_lost = local_fraction_lost; // We need a counter for cumulative loss too. + // TODO(danilchap): Ensure cumulative loss is below maximum value of 2^24. cumulative_loss_ += missing; stats.cumulative_lost = cumulative_loss_; stats.extended_max_sequence_number = @@ -319,8 +312,8 @@ void StreamStatisticianImpl::ProcessBitrate() { void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const { CriticalSectionScoped cs(stream_lock_.get()); - *secs = last_receive_time_secs_; - *frac = last_receive_time_frac_; + *secs = last_receive_time_ntp_.seconds(); + *frac = last_receive_time_ntp_.fractions(); } bool StreamStatisticianImpl::IsRetransmitOfOldPacket( diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h index fe42990fe9..025dcd42c7 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -11,13 +11,15 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVE_STATISTICS_IMPL_H_ -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" #include <algorithm> +#include <map> #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" +#include "webrtc/system_wrappers/include/ntp_time.h" namespace webrtc { @@ -51,9 +53,7 @@ class StreamStatisticianImpl : public StreamStatistician { private: bool InOrderPacketInternal(uint16_t sequence_number) const; RtcpStatistics CalculateRtcpStatistics(); - void UpdateJitter(const RTPHeader& header, - uint32_t receive_time_secs, - uint32_t receive_time_frac); + void UpdateJitter(const RTPHeader& header, NtpTime receive_time); void UpdateCounters(const RTPHeader& rtp_header, size_t packet_length, bool retransmitted); @@ -72,8 +72,7 @@ class StreamStatisticianImpl : public StreamStatistician { uint32_t jitter_q4_transmission_time_offset_; int64_t last_receive_time_ms_; - uint32_t last_receive_time_secs_; - uint32_t last_receive_time_frac_; + NtpTime last_receive_time_ntp_; uint32_t last_received_timestamp_; int32_t last_received_transmission_time_offset_; uint16_t received_seq_first_; diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc index 5b522281df..c265c17c04 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_unittest.cc @@ -11,7 +11,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" #include "webrtc/system_wrappers/include/clock.h" namespace webrtc { diff --git a/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc b/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc index 74fc9cdc56..ccc15ec417 100644 --- a/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc +++ b/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h" +#include "webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h" #include "webrtc/base/logging.h" #include "webrtc/system_wrappers/include/clock.h" diff --git a/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator_unittest.cc b/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator_unittest.cc index bc9cf2ee39..797c7883a9 100644 --- a/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator_unittest.cc @@ -11,7 +11,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/remote_ntp_time_estimator.h" +#include "webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h" #include "webrtc/system_wrappers/include/clock.h" using ::testing::_; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc index 7a7645fd1b..87c0259b3e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_format_remb_unittest.cc @@ -21,16 +21,13 @@ #include "webrtc/test/null_transport.h" #include "webrtc/typedefs.h" +namespace webrtc { namespace { -using namespace webrtc; - - class TestTransport : public Transport { public: - TestTransport(RTCPReceiver* rtcp_receiver) : - rtcp_receiver_(rtcp_receiver) { - } + explicit TestTransport(RTCPReceiver* rtcp_receiver) + : rtcp_receiver_(rtcp_receiver) {} bool SendRtp(const uint8_t* /*data*/, size_t /*len*/, @@ -38,9 +35,8 @@ class TestTransport : public Transport { return false; } bool SendRtcp(const uint8_t* packet, size_t packetLength) override { - RTCPUtility::RTCPParserV2 rtcpParser((uint8_t*)packet, - packetLength, - true); // Allow non-compound RTCP + RTCPUtility::RTCPParserV2 rtcpParser(packet, packetLength, + true); // Allow non-compound RTCP EXPECT_TRUE(rtcpParser.IsValid()); RTCPHelp::RTCPPacketInformation rtcpPacketInformation; @@ -53,11 +49,11 @@ class TestTransport : public Transport { rtcpPacketInformation.receiverEstimatedMaxBitrate); return true; } + private: RTCPReceiver* rtcp_receiver_; }; - class RtcpFormatRembTest : public ::testing::Test { protected: RtcpFormatRembTest() @@ -134,3 +130,4 @@ TEST_F(RtcpFormatRembTest, TestCompund) { EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpRemb)); } } // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc index 792caa7b8b..eef2978371 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc @@ -10,6 +10,8 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include <algorithm> + #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" @@ -19,38 +21,25 @@ using webrtc::RTCPUtility::kBtReceiverReferenceTime; using webrtc::RTCPUtility::kBtVoipMetric; using webrtc::RTCPUtility::PT_APP; -using webrtc::RTCPUtility::PT_BYE; using webrtc::RTCPUtility::PT_IJ; using webrtc::RTCPUtility::PT_PSFB; -using webrtc::RTCPUtility::PT_RR; using webrtc::RTCPUtility::PT_RTPFB; using webrtc::RTCPUtility::PT_SDES; using webrtc::RTCPUtility::PT_SR; using webrtc::RTCPUtility::PT_XR; using webrtc::RTCPUtility::RTCPPacketAPP; -using webrtc::RTCPUtility::RTCPPacketBYE; using webrtc::RTCPUtility::RTCPPacketPSFBAPP; using webrtc::RTCPUtility::RTCPPacketPSFBFIR; using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem; -using webrtc::RTCPUtility::RTCPPacketPSFBPLI; using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem; using webrtc::RTCPUtility::RTCPPacketPSFBRPSI; -using webrtc::RTCPUtility::RTCPPacketPSFBSLI; -using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem; using webrtc::RTCPUtility::RTCPPacketReportBlockItem; -using webrtc::RTCPUtility::RTCPPacketRR; using webrtc::RTCPUtility::RTCPPacketRTPFBNACK; using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem; -using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN; -using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem; -using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR; -using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem; using webrtc::RTCPUtility::RTCPPacketSR; using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem; -using webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem; using webrtc::RTCPUtility::RTCPPacketXR; -using webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem; namespace webrtc { namespace rtcp { @@ -122,21 +111,6 @@ void CreateSenderReport(const RTCPPacketSR& sr, AssignUWord32(buffer, pos, sr.SenderOctetCount); } -// Receiver report (RR), header (RFC 3550). -// -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| RC | PT=RR=201 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of packet sender | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - -void CreateReceiverReport(const RTCPPacketRR& rr, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, rr.SenderSSRC); -} - // Report block (RFC 3550). // // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -154,43 +128,15 @@ void CreateReceiverReport(const RTCPPacketRR& rr, // | delay since last SR (DLSR) | // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks, +void CreateReportBlocks(const std::vector<ReportBlock>& blocks, uint8_t* buffer, size_t* pos) { - for (std::vector<RTCPPacketReportBlockItem>::const_iterator - it = blocks.begin(); it != blocks.end(); ++it) { - AssignUWord32(buffer, pos, (*it).SSRC); - AssignUWord8(buffer, pos, (*it).FractionLost); - AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost); - AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber); - AssignUWord32(buffer, pos, (*it).Jitter); - AssignUWord32(buffer, pos, (*it).LastSR); - AssignUWord32(buffer, pos, (*it).DelayLastSR); + for (const ReportBlock& block : blocks) { + block.Create(buffer + *pos); + *pos += ReportBlock::kLength; } } -// Transmission Time Offsets in RTP Streams (RFC 5450). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// hdr |V=2|P| RC | PT=IJ=195 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | inter-arrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// . . -// . . -// . . -// | inter-arrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateIj(const std::vector<uint32_t>& ij_items, - uint8_t* buffer, - size_t* pos) { - for (uint32_t item : ij_items) - AssignUWord32(buffer, pos, item); -} - // Source Description (SDES) (RFC 3550). // // 0 1 2 3 @@ -233,129 +179,6 @@ void CreateSdes(const std::vector<Sdes::Chunk>& chunks, } } -// Bye packet (BYE) (RFC 3550). -// -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| SC | PT=BYE=203 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC/CSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : ... : -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// (opt) | length | reason for leaving ... -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateBye(const RTCPPacketBYE& bye, - const std::vector<uint32_t>& csrcs, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, bye.SenderSSRC); - for (uint32_t csrc : csrcs) - AssignUWord32(buffer, pos, csrc); -} - -// Application-Defined packet (APP) (RFC 3550). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| subtype | PT=APP=204 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC/CSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | name (ASCII) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | application-dependent data ... -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateApp(const RTCPPacketAPP& app, - uint32_t ssrc, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, ssrc); - AssignUWord32(buffer, pos, app.Name); - memcpy(buffer + *pos, app.Data, app.Size); - *pos += app.Size; -} - -// RFC 4585: Feedback format. -// -// Common packet format: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| FMT | PT | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of packet sender | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of media source | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : Feedback Control Information (FCI) : -// : -// - -// Picture loss indication (PLI) (RFC 4585). -// -// FCI: no feedback control information. - -void CreatePli(const RTCPPacketPSFBPLI& pli, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, pli.SenderSSRC); - AssignUWord32(buffer, pos, pli.MediaSSRC); -} - -// Slice loss indication (SLI) (RFC 4585). -// -// FCI: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | First | Number | PictureID | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateSli(const RTCPPacketPSFBSLI& sli, - const RTCPPacketPSFBSLIItem& sli_item, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, sli.SenderSSRC); - AssignUWord32(buffer, pos, sli.MediaSSRC); - - AssignUWord8(buffer, pos, sli_item.FirstMB >> 5); - AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) + - ((sli_item.NumberOfMB >> 10) & 0x07)); - AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2); - AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId); -} - -// Generic NACK (RFC 4585). -// -// FCI: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | PID | BLP | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateNack(const RTCPPacketRTPFBNACK& nack, - const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields, - size_t start_index, - size_t end_index, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, nack.SenderSSRC); - AssignUWord32(buffer, pos, nack.MediaSSRC); - for (size_t i = start_index; i < end_index; ++i) { - const RTCPPacketRTPFBNACKItem& nack_item = nack_fields[i]; - AssignUWord16(buffer, pos, nack_item.PacketID); - AssignUWord16(buffer, pos, nack_item.BitMask); - } -} - // Reference picture selection indication (RPSI) (RFC 4585). // // FCI: @@ -407,66 +230,6 @@ void CreateFir(const RTCPPacketPSFBFIR& fir, AssignUWord24(buffer, pos, 0); } -void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item, - uint8_t* buffer, - size_t* pos) { - uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000; - uint32_t mantissa = 0; - uint8_t exp = 0; - ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp); - - AssignUWord32(buffer, pos, tmmbr_item.SSRC); - AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03)); - AssignUWord8(buffer, pos, mantissa >> 7); - AssignUWord8(buffer, pos, (mantissa << 1) + - ((tmmbr_item.MeasuredOverhead >> 8) & 0x01)); - AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead); -} - -// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). -// -// FCI: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr, - const RTCPPacketRTPFBTMMBRItem& tmmbr_item, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, tmmbr.SenderSSRC); - AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); - CreateTmmbrItem(tmmbr_item, buffer, pos); -} - -// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104). -// -// FCI: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn, - const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items, - uint8_t* buffer, - size_t* pos) { - AssignUWord32(buffer, pos, tmmbn.SenderSSRC); - AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); - for (uint8_t i = 0; i < tmmbn_items.size(); ++i) { - CreateTmmbrItem(tmmbn_items[i], buffer, pos); - } -} - // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb). // // 0 1 2 3 @@ -529,130 +292,6 @@ void CreateXrHeader(const RTCPPacketXR& header, AssignUWord32(buffer, pos, header.OriginatorSSRC); } -void CreateXrBlockHeader(uint8_t block_type, - uint16_t block_length, - uint8_t* buffer, - size_t* pos) { - AssignUWord8(buffer, pos, block_type); - AssignUWord8(buffer, pos, 0); - AssignUWord16(buffer, pos, block_length); -} - -// Receiver Reference Time Report Block (RFC 3611). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | BT=4 | reserved | block length = 2 | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NTP timestamp, most significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NTP timestamp, least significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem>& rrtrs, - uint8_t* buffer, - size_t* pos) { - const uint16_t kBlockLength = 2; - for (std::vector<RTCPPacketXRReceiverReferenceTimeItem>::const_iterator it = - rrtrs.begin(); it != rrtrs.end(); ++it) { - CreateXrBlockHeader(kBtReceiverReferenceTime, kBlockLength, buffer, pos); - AssignUWord32(buffer, pos, (*it).NTPMostSignificant); - AssignUWord32(buffer, pos, (*it).NTPLeastSignificant); - } -} - -// DLRR Report Block (RFC 3611). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | BT=5 | reserved | block length | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_1 (SSRC of first receiver) | sub- -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block -// | last RR (LRR) | 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | delay since last RR (DLRR) | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_2 (SSRC of second receiver) | sub- -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block -// : ... : 2 - -void CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs, - uint8_t* buffer, - size_t* pos) { - for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin(); - it != dlrrs.end(); ++it) { - if ((*it).empty()) { - continue; - } - uint16_t block_length = 3 * (*it).size(); - CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos); - for (Xr::DlrrBlock::const_iterator it_block = (*it).begin(); - it_block != (*it).end(); ++it_block) { - AssignUWord32(buffer, pos, (*it_block).SSRC); - AssignUWord32(buffer, pos, (*it_block).LastRR); - AssignUWord32(buffer, pos, (*it_block).DelayLastRR); - } - } -} - -// VoIP Metrics Report Block (RFC 3611). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | BT=7 | reserved | block length = 8 | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of source | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | loss rate | discard rate | burst density | gap density | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | burst duration | gap duration | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | round trip delay | end system delay | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | signal level | noise level | RERL | Gmin | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | R factor | ext. R factor | MOS-LQ | MOS-CQ | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | RX config | reserved | JB nominal | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | JB maximum | JB abs max | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -void CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem>& metrics, - uint8_t* buffer, - size_t* pos) { - const uint16_t kBlockLength = 8; - for (std::vector<RTCPPacketXRVOIPMetricItem>::const_iterator it = - metrics.begin(); it != metrics.end(); ++it) { - CreateXrBlockHeader(kBtVoipMetric, kBlockLength, buffer, pos); - AssignUWord32(buffer, pos, (*it).SSRC); - AssignUWord8(buffer, pos, (*it).lossRate); - AssignUWord8(buffer, pos, (*it).discardRate); - AssignUWord8(buffer, pos, (*it).burstDensity); - AssignUWord8(buffer, pos, (*it).gapDensity); - AssignUWord16(buffer, pos, (*it).burstDuration); - AssignUWord16(buffer, pos, (*it).gapDuration); - AssignUWord16(buffer, pos, (*it).roundTripDelay); - AssignUWord16(buffer, pos, (*it).endSystemDelay); - AssignUWord8(buffer, pos, (*it).signalLevel); - AssignUWord8(buffer, pos, (*it).noiseLevel); - AssignUWord8(buffer, pos, (*it).RERL); - AssignUWord8(buffer, pos, (*it).Gmin); - AssignUWord8(buffer, pos, (*it).Rfactor); - AssignUWord8(buffer, pos, (*it).extRfactor); - AssignUWord8(buffer, pos, (*it).MOSLQ); - AssignUWord8(buffer, pos, (*it).MOSCQ); - AssignUWord8(buffer, pos, (*it).RXconfig); - AssignUWord8(buffer, pos, 0); - AssignUWord16(buffer, pos, (*it).JBnominal); - AssignUWord16(buffer, pos, (*it).JBmax); - AssignUWord16(buffer, pos, (*it).JBabsMax); - } -} } // namespace void RtcpPacket::Append(RtcpPacket* packet) { @@ -751,17 +390,6 @@ void RtcpPacket::CreateHeader( AssignUWord16(buffer, pos, length); } -bool Empty::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - return true; -} - -size_t Empty::BlockLength() const { - return 0; -} - bool SenderReport::Create(uint8_t* packet, size_t* index, size_t max_length, @@ -781,58 +409,11 @@ bool SenderReport::WithReportBlock(const ReportBlock& block) { LOG(LS_WARNING) << "Max report blocks reached."; return false; } - report_blocks_.push_back(block.report_block_); + report_blocks_.push_back(block); sr_.NumberOfReportBlocks = report_blocks_.size(); return true; } -bool ReceiverReport::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - CreateHeader(rr_.NumberOfReportBlocks, PT_RR, HeaderLength(), packet, index); - CreateReceiverReport(rr_, packet, index); - CreateReportBlocks(report_blocks_, packet, index); - return true; -} - -bool ReceiverReport::WithReportBlock(const ReportBlock& block) { - if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { - LOG(LS_WARNING) << "Max report blocks reached."; - return false; - } - report_blocks_.push_back(block.report_block_); - rr_.NumberOfReportBlocks = report_blocks_.size(); - return true; -} - -bool Ij::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - size_t length = ij_items_.size(); - CreateHeader(length, PT_IJ, length, packet, index); - CreateIj(ij_items_, packet, index); - return true; -} - -bool Ij::WithJitterItem(uint32_t jitter) { - if (ij_items_.size() >= kMaxNumberOfIjItems) { - LOG(LS_WARNING) << "Max inter-arrival jitter items reached."; - return false; - } - ij_items_.push_back(jitter); - return true; -} - bool Sdes::Create(uint8_t* packet, size_t* index, size_t max_length, @@ -876,129 +457,6 @@ size_t Sdes::BlockLength() const { return length; } -bool Bye::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - size_t length = HeaderLength(); - CreateHeader(length, PT_BYE, length, packet, index); - CreateBye(bye_, csrcs_, packet, index); - return true; -} - -bool Bye::WithCsrc(uint32_t csrc) { - if (csrcs_.size() >= kMaxNumberOfCsrcs) { - LOG(LS_WARNING) << "Max CSRC size reached."; - return false; - } - csrcs_.push_back(csrc); - return true; -} - -bool App::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - CreateHeader(app_.SubType, PT_APP, HeaderLength(), packet, index); - CreateApp(app_, ssrc_, packet, index); - return true; -} - -bool Pli::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - const uint8_t kFmt = 1; - CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index); - CreatePli(pli_, packet, index); - return true; -} - -bool Sli::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - const uint8_t kFmt = 2; - CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index); - CreateSli(sli_, sli_item_, packet, index); - return true; -} - -bool Nack::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - assert(!nack_fields_.empty()); - // If nack list can't fit in packet, try to fragment. - size_t nack_index = 0; - do { - size_t bytes_left_in_buffer = max_length - *index; - if (bytes_left_in_buffer < kCommonFbFmtLength + 4) { - if (!OnBufferFull(packet, index, callback)) - return false; - continue; - } - int64_t num_nack_fields = - std::min((bytes_left_in_buffer - kCommonFbFmtLength) / 4, - nack_fields_.size() - nack_index); - - const uint8_t kFmt = 1; - size_t size_bytes = (num_nack_fields * 4) + kCommonFbFmtLength; - size_t header_length = ((size_bytes + 3) / 4) - 1; // As 32bit words - 1 - CreateHeader(kFmt, PT_RTPFB, header_length, packet, index); - CreateNack(nack_, nack_fields_, nack_index, nack_index + num_nack_fields, - packet, index); - - nack_index += num_nack_fields; - } while (nack_index < nack_fields_.size()); - - return true; -} - -size_t Nack::BlockLength() const { - return (nack_fields_.size() * 4) + kCommonFbFmtLength; -} - -void Nack::WithList(const uint16_t* nack_list, int length) { - assert(nack_list); - assert(nack_fields_.empty()); - int i = 0; - while (i < length) { - uint16_t pid = nack_list[i++]; - // Bitmask specifies losses in any of the 16 packets following the pid. - uint16_t bitmask = 0; - while (i < length) { - int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1; - if (shift >= 0 && shift <= 15) { - bitmask |= (1 << shift); - ++i; - } else { - break; - } - } - RTCPUtility::RTCPPacketRTPFBNACKItem item; - item.PacketID = pid; - item.BitMask = bitmask; - nack_fields_.push_back(item); - } -} - bool Rpsi::Create(uint8_t* packet, size_t* index, size_t max_length, @@ -1077,48 +535,6 @@ void Remb::AppliesTo(uint32_t ssrc) { remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc; } -bool Tmmbr::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - const uint8_t kFmt = 3; - CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index); - CreateTmmbr(tmmbr_, tmmbr_item_, packet, index); - return true; -} - -bool Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) { - assert(overhead <= 0x1ff); - if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) { - LOG(LS_WARNING) << "Max TMMBN size reached."; - return false; - } - RTCPPacketRTPFBTMMBRItem tmmbn_item; - tmmbn_item.SSRC = ssrc; - tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps; - tmmbn_item.MeasuredOverhead = overhead; - tmmbn_items_.push_back(tmmbn_item); - return true; -} - -bool Tmmbn::Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const { - while (*index + BlockLength() > max_length) { - if (!OnBufferFull(packet, index, callback)) - return false; - } - const uint8_t kFmt = 4; - CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index); - CreateTmmbn(tmmbn_, tmmbn_items_, packet, index); - return true; -} - bool Xr::Create(uint8_t* packet, size_t* index, size_t max_length, @@ -1129,29 +545,38 @@ bool Xr::Create(uint8_t* packet, } CreateHeader(0U, PT_XR, HeaderLength(), packet, index); CreateXrHeader(xr_header_, packet, index); - CreateRrtr(rrtr_blocks_, packet, index); - CreateDlrr(dlrr_blocks_, packet, index); - CreateVoipMetric(voip_metric_blocks_, packet, index); + for (const Rrtr& block : rrtr_blocks_) { + block.Create(packet + *index); + *index += Rrtr::kLength; + } + for (const Dlrr& block : dlrr_blocks_) { + block.Create(packet + *index); + *index += block.BlockLength(); + } + for (const VoipMetric& block : voip_metric_blocks_) { + block.Create(packet + *index); + *index += VoipMetric::kLength; + } return true; } bool Xr::WithRrtr(Rrtr* rrtr) { - assert(rrtr); + RTC_DCHECK(rrtr); if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) { LOG(LS_WARNING) << "Max RRTR blocks reached."; return false; } - rrtr_blocks_.push_back(rrtr->rrtr_block_); + rrtr_blocks_.push_back(*rrtr); return true; } bool Xr::WithDlrr(Dlrr* dlrr) { - assert(dlrr); + RTC_DCHECK(dlrr); if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) { LOG(LS_WARNING) << "Max DLRR blocks reached."; return false; } - dlrr_blocks_.push_back(dlrr->dlrr_block_); + dlrr_blocks_.push_back(*dlrr); return true; } @@ -1161,38 +586,18 @@ bool Xr::WithVoipMetric(VoipMetric* voip_metric) { LOG(LS_WARNING) << "Max Voip Metric blocks reached."; return false; } - voip_metric_blocks_.push_back(voip_metric->metric_); + voip_metric_blocks_.push_back(*voip_metric); return true; } size_t Xr::DlrrLength() const { - const size_t kBlockHeaderLen = 4; - const size_t kSubBlockLen = 12; size_t length = 0; - for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin(); - it != dlrr_blocks_.end(); ++it) { - if (!(*it).empty()) { - length += kBlockHeaderLen + kSubBlockLen * (*it).size(); - } + for (const Dlrr& block : dlrr_blocks_) { + length += block.BlockLength(); } return length; } -bool Dlrr::WithDlrrItem(uint32_t ssrc, - uint32_t last_rr, - uint32_t delay_last_rr) { - if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) { - LOG(LS_WARNING) << "Max DLRR items reached."; - return false; - } - RTCPPacketXRDLRRReportBlockItem dlrr; - dlrr.SSRC = ssrc; - dlrr.LastRR = last_rr; - dlrr.DelayLastRR = delay_last_rr; - dlrr_block_.push_back(dlrr); - return true; -} - RawPacket::RawPacket(size_t buffer_length) : buffer_length_(buffer_length), length_(0) { buffer_.reset(new uint8_t[buffer_length]); diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h index 3c34957c36..01c97c38ba 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h @@ -9,16 +9,20 @@ * */ -#ifndef WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_ -#define WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ #include <map> #include <string> #include <vector> #include "webrtc/base/scoped_ptr.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -27,10 +31,7 @@ namespace rtcp { static const int kCommonFbFmtLength = 12; static const int kReportBlockLength = 24; -class Dlrr; class RawPacket; -class Rrtr; -class VoipMetric; // Class for building RTCP packets. // @@ -115,93 +116,17 @@ class RtcpPacket { size_t HeaderLength() const; static const size_t kHeaderLength = 4; + std::vector<RtcpPacket*> appended_packets_; private: bool CreateAndAddAppended(uint8_t* packet, size_t* index, size_t max_length, PacketReadyCallback* callback) const; - - std::vector<RtcpPacket*> appended_packets_; }; // TODO(sprang): Move RtcpPacket subclasses out to separate files. -class Empty : public RtcpPacket { - public: - Empty() : RtcpPacket() {} - - virtual ~Empty() {} - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - size_t BlockLength() const override; - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(Empty); -}; - -// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications. -// -// RTCP report block (RFC 3550). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_1 (SSRC of first source) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | fraction lost | cumulative number of packets lost | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | extended highest sequence number received | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | interarrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | last SR (LSR) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | delay since last SR (DLSR) | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - -class ReportBlock { - public: - ReportBlock() { - // TODO(asapersson): Consider adding a constructor to struct. - memset(&report_block_, 0, sizeof(report_block_)); - } - - ~ReportBlock() {} - - void To(uint32_t ssrc) { - report_block_.SSRC = ssrc; - } - void WithFractionLost(uint8_t fraction_lost) { - report_block_.FractionLost = fraction_lost; - } - void WithCumulativeLost(uint32_t cumulative_lost) { - report_block_.CumulativeNumOfPacketsLost = cumulative_lost; - } - void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) { - report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num; - } - void WithJitter(uint32_t jitter) { - report_block_.Jitter = jitter; - } - void WithLastSr(uint32_t last_sr) { - report_block_.LastSR = last_sr; - } - void WithDelayLastSr(uint32_t delay_last_sr) { - report_block_.DelayLastSR = delay_last_sr; - } - - private: - friend class SenderReport; - friend class ReceiverReport; - RTCPUtility::RTCPPacketReportBlockItem report_block_; -}; - // RTCP sender report (RFC 3550). // // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -268,102 +193,11 @@ class SenderReport : public RtcpPacket { } RTCPUtility::RTCPPacketSR sr_; - std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_; + std::vector<ReportBlock> report_blocks_; RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport); }; -// -// RTCP receiver report (RFC 3550). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| RC | PT=RR=201 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of packet sender | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | report block(s) | -// | .... | - -class ReceiverReport : public RtcpPacket { - public: - ReceiverReport() : RtcpPacket() { - memset(&rr_, 0, sizeof(rr_)); - } - - virtual ~ReceiverReport() {} - - void From(uint32_t ssrc) { - rr_.SenderSSRC = ssrc; - } - bool WithReportBlock(const ReportBlock& block); - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - static const int kMaxNumberOfReportBlocks = 0x1F; - - size_t BlockLength() const { - const size_t kRrHeaderLength = 8; - return kRrHeaderLength + report_blocks_.size() * kReportBlockLength; - } - - RTCPUtility::RTCPPacketRR rr_; - std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ReceiverReport); -}; - -// Transmission Time Offsets in RTP Streams (RFC 5450). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// hdr |V=2|P| RC | PT=IJ=195 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | inter-arrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// . . -// . . -// . . -// | inter-arrival jitter | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// If present, this RTCP packet must be placed after a receiver report -// (inside a compound RTCP packet), and MUST have the same value for RC -// (reception report count) as the receiver report. - -class Ij : public RtcpPacket { - public: - Ij() : RtcpPacket() {} - - virtual ~Ij() {} - - bool WithJitterItem(uint32_t jitter); - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - static const int kMaxNumberOfIjItems = 0x1f; - - size_t BlockLength() const { - return kHeaderLength + 4 * ij_items_.size(); - } - - std::vector<uint32_t> ij_items_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Ij); -}; - // Source Description (SDES) (RFC 3550). // // 0 1 2 3 @@ -420,262 +254,6 @@ class Sdes : public RtcpPacket { RTC_DISALLOW_COPY_AND_ASSIGN(Sdes); }; -// -// Bye packet (BYE) (RFC 3550). -// -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| SC | PT=BYE=203 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC/CSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : ... : -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// (opt) | length | reason for leaving ... -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class Bye : public RtcpPacket { - public: - Bye() : RtcpPacket() { - memset(&bye_, 0, sizeof(bye_)); - } - - virtual ~Bye() {} - - void From(uint32_t ssrc) { - bye_.SenderSSRC = ssrc; - } - - bool WithCsrc(uint32_t csrc); - - // TODO(sprang): Add support for reason field? - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - static const int kMaxNumberOfCsrcs = 0x1f - 1; // First item is sender SSRC. - - size_t BlockLength() const { - size_t source_count = 1 + csrcs_.size(); - return kHeaderLength + 4 * source_count; - } - - RTCPUtility::RTCPPacketBYE bye_; - std::vector<uint32_t> csrcs_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Bye); -}; - -// Application-Defined packet (APP) (RFC 3550). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| subtype | PT=APP=204 | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC/CSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | name (ASCII) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | application-dependent data ... -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class App : public RtcpPacket { - public: - App() - : RtcpPacket(), - ssrc_(0) { - memset(&app_, 0, sizeof(app_)); - } - - virtual ~App() {} - - void From(uint32_t ssrc) { - ssrc_ = ssrc; - } - void WithSubType(uint8_t subtype) { - assert(subtype <= 0x1f); - app_.SubType = subtype; - } - void WithName(uint32_t name) { - app_.Name = name; - } - void WithData(const uint8_t* data, uint16_t data_length) { - assert(data); - assert(data_length <= kRtcpAppCode_DATA_SIZE); - assert(data_length % 4 == 0); - memcpy(app_.Data, data, data_length); - app_.Size = data_length; - } - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - size_t BlockLength() const { - return 12 + app_.Size; - } - - uint32_t ssrc_; - RTCPUtility::RTCPPacketAPP app_; - - RTC_DISALLOW_COPY_AND_ASSIGN(App); -}; - -// RFC 4585: Feedback format. -// -// Common packet format: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |V=2|P| FMT | PT | length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of packet sender | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of media source | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : Feedback Control Information (FCI) : -// : - -// Picture loss indication (PLI) (RFC 4585). -// -// FCI: no feedback control information. - -class Pli : public RtcpPacket { - public: - Pli() : RtcpPacket() { - memset(&pli_, 0, sizeof(pli_)); - } - - virtual ~Pli() {} - - void From(uint32_t ssrc) { - pli_.SenderSSRC = ssrc; - } - void To(uint32_t ssrc) { - pli_.MediaSSRC = ssrc; - } - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - size_t BlockLength() const { - return kCommonFbFmtLength; - } - - RTCPUtility::RTCPPacketPSFBPLI pli_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Pli); -}; - -// Slice loss indication (SLI) (RFC 4585). -// -// FCI: -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | First | Number | PictureID | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class Sli : public RtcpPacket { - public: - Sli() : RtcpPacket() { - memset(&sli_, 0, sizeof(sli_)); - memset(&sli_item_, 0, sizeof(sli_item_)); - } - - virtual ~Sli() {} - - void From(uint32_t ssrc) { - sli_.SenderSSRC = ssrc; - } - void To(uint32_t ssrc) { - sli_.MediaSSRC = ssrc; - } - void WithFirstMb(uint16_t first_mb) { - assert(first_mb <= 0x1fff); - sli_item_.FirstMB = first_mb; - } - void WithNumberOfMb(uint16_t number_mb) { - assert(number_mb <= 0x1fff); - sli_item_.NumberOfMB = number_mb; - } - void WithPictureId(uint8_t picture_id) { - assert(picture_id <= 0x3f); - sli_item_.PictureId = picture_id; - } - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - size_t BlockLength() const { - const size_t kFciLength = 4; - return kCommonFbFmtLength + kFciLength; - } - - RTCPUtility::RTCPPacketPSFBSLI sli_; - RTCPUtility::RTCPPacketPSFBSLIItem sli_item_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Sli); -}; - -// Generic NACK (RFC 4585). -// -// FCI: -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | PID | BLP | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class Nack : public RtcpPacket { - public: - Nack() : RtcpPacket() { - memset(&nack_, 0, sizeof(nack_)); - } - - virtual ~Nack() {} - - void From(uint32_t ssrc) { - nack_.SenderSSRC = ssrc; - } - void To(uint32_t ssrc) { - nack_.MediaSSRC = ssrc; - } - void WithList(const uint16_t* nack_list, int length); - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - size_t BlockLength() const override; - - private: - - RTCPUtility::RTCPPacketRTPFBNACK nack_; - std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Nack); -}; - // Reference picture selection indication (RPSI) (RFC 4585). // // FCI: @@ -775,105 +353,6 @@ class Fir : public RtcpPacket { RTCPUtility::RTCPPacketPSFBFIRItem fir_item_; }; -// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). -// -// FCI: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class Tmmbr : public RtcpPacket { - public: - Tmmbr() : RtcpPacket() { - memset(&tmmbr_, 0, sizeof(tmmbr_)); - memset(&tmmbr_item_, 0, sizeof(tmmbr_item_)); - } - - virtual ~Tmmbr() {} - - void From(uint32_t ssrc) { - tmmbr_.SenderSSRC = ssrc; - } - void To(uint32_t ssrc) { - tmmbr_item_.SSRC = ssrc; - } - void WithBitrateKbps(uint32_t bitrate_kbps) { - tmmbr_item_.MaxTotalMediaBitRate = bitrate_kbps; - } - void WithOverhead(uint16_t overhead) { - assert(overhead <= 0x1ff); - tmmbr_item_.MeasuredOverhead = overhead; - } - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - size_t BlockLength() const { - const size_t kFciLen = 8; - return kCommonFbFmtLength + kFciLen; - } - - RTCPUtility::RTCPPacketRTPFBTMMBR tmmbr_; - RTCPUtility::RTCPPacketRTPFBTMMBRItem tmmbr_item_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbr); -}; - -// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104). -// -// FCI: -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class Tmmbn : public RtcpPacket { - public: - Tmmbn() : RtcpPacket() { - memset(&tmmbn_, 0, sizeof(tmmbn_)); - } - - virtual ~Tmmbn() {} - - void From(uint32_t ssrc) { - tmmbn_.SenderSSRC = ssrc; - } - // Max 50 TMMBR can be added per TMMBN. - bool WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead); - - protected: - bool Create(uint8_t* packet, - size_t* index, - size_t max_length, - RtcpPacket::PacketReadyCallback* callback) const override; - - private: - static const int kMaxNumberOfTmmbrs = 50; - - size_t BlockLength() const { - const size_t kFciLen = 8; - return kCommonFbFmtLength + kFciLen * tmmbn_items_.size(); - } - - RTCPUtility::RTCPPacketRTPFBTMMBN tmmbn_; - std::vector<RTCPUtility::RTCPPacketRTPFBTMMBRItem> tmmbn_items_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbn); -}; - // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb). // // 0 1 2 3 @@ -978,163 +457,22 @@ class Xr : public RtcpPacket { return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength(); } - size_t RrtrLength() const { - const size_t kRrtrBlockLength = 12; - return kRrtrBlockLength * rrtr_blocks_.size(); - } + size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); } size_t DlrrLength() const; size_t VoipMetricLength() const { - const size_t kVoipMetricBlockLength = 36; - return kVoipMetricBlockLength * voip_metric_blocks_.size(); + return VoipMetric::kLength * voip_metric_blocks_.size(); } RTCPUtility::RTCPPacketXR xr_header_; - std::vector<RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem> rrtr_blocks_; - std::vector<DlrrBlock> dlrr_blocks_; - std::vector<RTCPUtility::RTCPPacketXRVOIPMetricItem> voip_metric_blocks_; + std::vector<Rrtr> rrtr_blocks_; + std::vector<Dlrr> dlrr_blocks_; + std::vector<VoipMetric> voip_metric_blocks_; RTC_DISALLOW_COPY_AND_ASSIGN(Xr); }; -// Receiver Reference Time Report Block (RFC 3611). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | BT=4 | reserved | block length = 2 | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NTP timestamp, most significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NTP timestamp, least significant word | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class Rrtr { - public: - Rrtr() { - memset(&rrtr_block_, 0, sizeof(rrtr_block_)); - } - ~Rrtr() {} - - void WithNtpSec(uint32_t sec) { - rrtr_block_.NTPMostSignificant = sec; - } - void WithNtpFrac(uint32_t frac) { - rrtr_block_.NTPLeastSignificant = frac; - } - - private: - friend class Xr; - RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem rrtr_block_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Rrtr); -}; - -// DLRR Report Block (RFC 3611). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | BT=5 | reserved | block length | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_1 (SSRC of first receiver) | sub- -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block -// | last RR (LRR) | 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | delay since last RR (DLRR) | -// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// | SSRC_2 (SSRC of second receiver) | sub- -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block -// : ... : 2 - -class Dlrr { - public: - Dlrr() {} - ~Dlrr() {} - - // Max 100 DLRR Items can be added per DLRR report block. - bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr); - - private: - friend class Xr; - static const int kMaxNumberOfDlrrItems = 100; - - std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> dlrr_block_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Dlrr); -}; - -// VoIP Metrics Report Block (RFC 3611). -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | BT=7 | reserved | block length = 8 | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | SSRC of source | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | loss rate | discard rate | burst density | gap density | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | burst duration | gap duration | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | round trip delay | end system delay | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | signal level | noise level | RERL | Gmin | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | R factor | ext. R factor | MOS-LQ | MOS-CQ | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | RX config | reserved | JB nominal | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | JB maximum | JB abs max | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -class VoipMetric { - public: - VoipMetric() { - memset(&metric_, 0, sizeof(metric_)); - } - ~VoipMetric() {} - - void To(uint32_t ssrc) { metric_.SSRC = ssrc; } - void LossRate(uint8_t loss_rate) { metric_.lossRate = loss_rate; } - void DiscardRate(uint8_t discard_rate) { metric_.discardRate = discard_rate; } - void BurstDensity(uint8_t burst_density) { - metric_.burstDensity = burst_density; - } - void GapDensity(uint8_t gap_density) { metric_.gapDensity = gap_density; } - void BurstDuration(uint16_t burst_duration) { - metric_.burstDuration = burst_duration; - } - void GapDuration(uint16_t gap_duration) { - metric_.gapDuration = gap_duration; - } - void RoundTripDelay(uint16_t round_trip_delay) { - metric_.roundTripDelay = round_trip_delay; - } - void EndSystemDelay(uint16_t end_system_delay) { - metric_.endSystemDelay = end_system_delay; - } - void SignalLevel(uint8_t signal_level) { metric_.signalLevel = signal_level; } - void NoiseLevel(uint8_t noise_level) { metric_.noiseLevel = noise_level; } - void Rerl(uint8_t rerl) { metric_.RERL = rerl; } - void Gmin(uint8_t gmin) { metric_.Gmin = gmin; } - void Rfactor(uint8_t rfactor) { metric_.Rfactor = rfactor; } - void ExtRfactor(uint8_t extrfactor) { metric_.extRfactor = extrfactor; } - void MosLq(uint8_t moslq) { metric_.MOSLQ = moslq; } - void MosCq(uint8_t moscq) { metric_.MOSCQ = moscq; } - void RxConfig(uint8_t rxconfig) { metric_.RXconfig = rxconfig; } - void JbNominal(uint16_t jbnominal) { metric_.JBnominal = jbnominal; } - void JbMax(uint16_t jbmax) { metric_.JBmax = jbmax; } - void JbAbsMax(uint16_t jbabsmax) { metric_.JBabsMax = jbabsmax; } - - private: - friend class Xr; - RTCPUtility::RTCPPacketXRVOIPMetricItem metric_; - - RTC_DISALLOW_COPY_AND_ASSIGN(VoipMetric); -}; - // Class holding a RTCP packet. // // Takes a built rtcp packet. @@ -1163,4 +501,4 @@ class RawPacket { } // namespace rtcp } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.cc new file mode 100644 index 0000000000..a1ad8d6427 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.cc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { + +// Application-Defined packet (APP) (RFC 3550). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| subtype | PT=APP=204 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 | SSRC/CSRC | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | name (ASCII) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | application-dependent data ... +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +bool App::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + + sub_type_ = header.count_or_format; + ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&payload[0]); + name_ = ByteReader<uint32_t>::ReadBigEndian(&payload[4]); + data_.SetData(&payload[8], header.payload_size_bytes - 8); + return true; +} + +void App::WithSubType(uint8_t subtype) { + RTC_DCHECK_LE(subtype, 0x1f); + sub_type_ = subtype; +} + +void App::WithData(const uint8_t* data, size_t data_length) { + RTC_DCHECK(data); + RTC_DCHECK_EQ(0u, data_length % 4) << "Data must be 32 bits aligned."; + RTC_DCHECK(data_length <= kMaxDataSize) << "App data size << " << data_length + << "exceed maximum of " + << kMaxDataSize << " bytes."; + data_.SetData(data, data_length); +} + +bool App::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + const size_t index_end = *index + BlockLength(); + CreateHeader(sub_type_, kPacketType, HeaderLength(), packet, index); + + ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 0], ssrc_); + ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 4], name_); + memcpy(&packet[*index + 8], data_.data(), data_.size()); + *index += (8 + data_.size()); + RTC_DCHECK_EQ(index_end, *index); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h new file mode 100644 index 0000000000..16bd3fc2a2 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_APP_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_APP_H_ + +#include "webrtc/base/buffer.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +class App : public RtcpPacket { + public: + static const uint8_t kPacketType = 204; + // 28 bytes for UDP header + // 12 bytes for RTCP app header + static const size_t kMaxDataSize = IP_PACKET_SIZE - 12 - 28; + App() : sub_type_(0), ssrc_(0), name_(0) {} + + virtual ~App() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + void From(uint32_t ssrc) { ssrc_ = ssrc; } + void WithSubType(uint8_t subtype); + void WithName(uint32_t name) { name_ = name; } + void WithData(const uint8_t* data, size_t data_length); + + uint8_t sub_type() const { return sub_type_; } + uint32_t ssrc() const { return ssrc_; } + uint32_t name() const { return name_; } + size_t data_size() const { return data_.size(); } + const uint8_t* data() const { return data_.data(); } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + size_t BlockLength() const override { return 12 + data_.size(); } + + uint8_t sub_type_; + uint32_t ssrc_; + uint32_t name_; + rtc::Buffer data_; + + RTC_DISALLOW_COPY_AND_ASSIGN(App); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_APP_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/app_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/app_unittest.cc new file mode 100644 index 0000000000..4451fe8fb5 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/app_unittest.cc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" + +#include <limits> + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +using webrtc::rtcp::App; +using webrtc::rtcp::RawPacket; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { + +const uint32_t kName = ((uint32_t)'n' << 24) | ((uint32_t)'a' << 16) | + ((uint32_t)'m' << 8) | (uint32_t)'e'; +const uint32_t kSenderSsrc = 0x12345678; + +class RtcpPacketAppTest : public ::testing::Test { + protected: + void BuildPacket() { packet = app.Build(); } + void ParsePacket() { + RtcpCommonHeader header; + EXPECT_TRUE( + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header)); + // Check there is exactly one RTCP packet in the buffer. + EXPECT_EQ(header.BlockSize(), packet->Length()); + EXPECT_TRUE(parsed_.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); + } + + App app; + rtc::scoped_ptr<RawPacket> packet; + const App& parsed() { return parsed_; } + + private: + App parsed_; +}; + +TEST_F(RtcpPacketAppTest, WithNoData) { + app.WithSubType(30); + app.WithName(kName); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(30U, parsed().sub_type()); + EXPECT_EQ(kName, parsed().name()); + EXPECT_EQ(0u, parsed().data_size()); +} + +TEST_F(RtcpPacketAppTest, WithData) { + app.From(kSenderSsrc); + app.WithSubType(30); + app.WithName(kName); + const uint8_t kData[] = {'t', 'e', 's', 't', 'd', 'a', 't', 'a'}; + const size_t kDataLength = sizeof(kData) / sizeof(kData[0]); + app.WithData(kData, kDataLength); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(30U, parsed().sub_type()); + EXPECT_EQ(kName, parsed().name()); + EXPECT_EQ(kDataLength, parsed().data_size()); + EXPECT_EQ(0, memcmp(kData, parsed().data(), kDataLength)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.cc new file mode 100644 index 0000000000..4cfc921ce5 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { + +// Bye packet (BYE) (RFC 3550). +// +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| SC | PT=BYE=203 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC/CSRC | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : ... : +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// (opt) | length | reason for leaving ... +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +Bye::Bye() : sender_ssrc_(0) {} + +bool Bye::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + + const uint8_t src_count = header.count_or_format; + // Validate packet. + if (header.payload_size_bytes < 4u * src_count) { + LOG(LS_WARNING) + << "Packet is too small to contain CSRCs it promise to have."; + return false; + } + bool has_reason = (header.payload_size_bytes > 4u * src_count); + uint8_t reason_length = 0; + if (has_reason) { + reason_length = payload[4u * src_count]; + if (header.payload_size_bytes - 4u * src_count < 1u + reason_length) { + LOG(LS_WARNING) << "Invalid reason length: " << reason_length; + return false; + } + } + // Once sure packet is valid, copy values. + if (src_count == 0) { // A count value of zero is valid, but useless. + sender_ssrc_ = 0; + csrcs_.clear(); + } else { + sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload); + csrcs_.resize(src_count - 1); + for (size_t i = 1; i < src_count; ++i) + csrcs_[i - 1] = ByteReader<uint32_t>::ReadBigEndian(&payload[4 * i]); + } + + if (has_reason) { + reason_.assign(reinterpret_cast<const char*>(&payload[4u * src_count + 1]), + reason_length); + } else { + reason_.clear(); + } + + return true; +} + +bool Bye::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + const size_t index_end = *index + BlockLength(); + + CreateHeader(1 + csrcs_.size(), kPacketType, HeaderLength(), packet, index); + // Store srcs of the leaving clients. + ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], sender_ssrc_); + *index += sizeof(uint32_t); + for (uint32_t csrc : csrcs_) { + ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], csrc); + *index += sizeof(uint32_t); + } + // Store the reason to leave. + if (!reason_.empty()) { + uint8_t reason_length = reason_.size(); + packet[(*index)++] = reason_length; + memcpy(&packet[*index], reason_.data(), reason_length); + *index += reason_length; + // Add padding bytes if needed. + size_t bytes_to_pad = index_end - *index; + RTC_DCHECK_LE(bytes_to_pad, 3u); + if (bytes_to_pad > 0) { + memset(&packet[*index], 0, bytes_to_pad); + *index += bytes_to_pad; + } + } + RTC_DCHECK_EQ(index_end, *index); + return true; +} + +bool Bye::WithCsrc(uint32_t csrc) { + if (csrcs_.size() >= kMaxNumberOfCsrcs) { + LOG(LS_WARNING) << "Max CSRC size reached."; + return false; + } + csrcs_.push_back(csrc); + return true; +} + +void Bye::WithReason(const std::string& reason) { + RTC_DCHECK_LE(reason.size(), 0xffu); + reason_ = reason; +} + +size_t Bye::BlockLength() const { + size_t src_count = (1 + csrcs_.size()); + size_t reason_size_in_32bits = reason_.empty() ? 0 : (reason_.size() / 4 + 1); + return kHeaderLength + 4 * (src_count + reason_size_in_32bits); +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h new file mode 100644 index 0000000000..6b4a181330 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_BYE_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_BYE_H_ + +#include <string> +#include <vector> + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +class Bye : public RtcpPacket { + public: + static const uint8_t kPacketType = 203; + + Bye(); + virtual ~Bye() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } + bool WithCsrc(uint32_t csrc); + void WithReason(const std::string& reason); + + uint32_t sender_ssrc() const { return sender_ssrc_; } + const std::vector<uint32_t>& csrcs() const { return csrcs_; } + const std::string& reason() const { return reason_; } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + static const int kMaxNumberOfCsrcs = 0x1f - 1; // First item is sender SSRC. + + size_t BlockLength() const override; + + uint32_t sender_ssrc_; + std::vector<uint32_t> csrcs_; + std::string reason_; + + RTC_DISALLOW_COPY_AND_ASSIGN(Bye); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_BYE_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye_unittest.cc new file mode 100644 index 0000000000..d2ae8ed782 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye_unittest.cc @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +using ::testing::ElementsAre; + +using webrtc::rtcp::Bye; +using webrtc::rtcp::RawPacket; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { + +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kCsrc1 = 0x22232425; +const uint32_t kCsrc2 = 0x33343536; + +class RtcpPacketByeTest : public ::testing::Test { + protected: + void BuildPacket() { packet = bye.Build(); } + void ParsePacket() { + RtcpCommonHeader header; + EXPECT_TRUE( + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header)); + // Check that there is exactly one RTCP packet in the buffer. + EXPECT_EQ(header.BlockSize(), packet->Length()); + EXPECT_TRUE(parsed_bye.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); + } + + Bye bye; + rtc::scoped_ptr<RawPacket> packet; + Bye parsed_bye; +}; + +TEST_F(RtcpPacketByeTest, Bye) { + bye.From(kSenderSsrc); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(kSenderSsrc, parsed_bye.sender_ssrc()); + EXPECT_TRUE(parsed_bye.csrcs().empty()); + EXPECT_TRUE(parsed_bye.reason().empty()); +} + +TEST_F(RtcpPacketByeTest, WithCsrcs) { + bye.From(kSenderSsrc); + EXPECT_TRUE(bye.WithCsrc(kCsrc1)); + EXPECT_TRUE(bye.WithCsrc(kCsrc2)); + EXPECT_TRUE(bye.reason().empty()); + + BuildPacket(); + EXPECT_EQ(16u, packet->Length()); // Header: 4, 3xSRCs: 12, Reason: 0. + + ParsePacket(); + + EXPECT_EQ(kSenderSsrc, parsed_bye.sender_ssrc()); + EXPECT_THAT(parsed_bye.csrcs(), ElementsAre(kCsrc1, kCsrc2)); + EXPECT_TRUE(parsed_bye.reason().empty()); +} + +TEST_F(RtcpPacketByeTest, WithCsrcsAndReason) { + const std::string kReason = "Some Reason"; + + bye.From(kSenderSsrc); + EXPECT_TRUE(bye.WithCsrc(kCsrc1)); + EXPECT_TRUE(bye.WithCsrc(kCsrc2)); + bye.WithReason(kReason); + + BuildPacket(); + EXPECT_EQ(28u, packet->Length()); // Header: 4, 3xSRCs: 12, Reason: 12. + + ParsePacket(); + + EXPECT_EQ(kSenderSsrc, parsed_bye.sender_ssrc()); + EXPECT_THAT(parsed_bye.csrcs(), ElementsAre(kCsrc1, kCsrc2)); + EXPECT_EQ(kReason, parsed_bye.reason()); +} + +TEST_F(RtcpPacketByeTest, WithTooManyCsrcs) { + bye.From(kSenderSsrc); + const int kMaxCsrcs = (1 << 5) - 2; // 5 bit len, first item is sender SSRC. + for (int i = 0; i < kMaxCsrcs; ++i) { + EXPECT_TRUE(bye.WithCsrc(i)); + } + EXPECT_FALSE(bye.WithCsrc(kMaxCsrcs)); +} + +TEST_F(RtcpPacketByeTest, WithAReason) { + const std::string kReason = "Some Random Reason"; + + bye.From(kSenderSsrc); + bye.WithReason(kReason); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(kSenderSsrc, parsed_bye.sender_ssrc()); + EXPECT_TRUE(parsed_bye.csrcs().empty()); + EXPECT_EQ(kReason, parsed_bye.reason()); +} + +TEST_F(RtcpPacketByeTest, WithReasons) { + // Test that packet creation/parsing behave with reasons of different length + // both when it require padding and when it does not. + for (size_t reminder = 0; reminder < 4; ++reminder) { + const std::string kReason(4 + reminder, 'a' + reminder); + bye.From(kSenderSsrc); + bye.WithReason(kReason); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(kReason, parsed_bye.reason()); + } +} + +TEST_F(RtcpPacketByeTest, ParseEmptyPacket) { + RtcpCommonHeader header; + header.packet_type = Bye::kPacketType; + header.count_or_format = 0; + header.payload_size_bytes = 0; + uint8_t empty_payload[1]; + + EXPECT_TRUE(parsed_bye.Parse(header, empty_payload + 1)); + EXPECT_EQ(0u, parsed_bye.sender_ssrc()); + EXPECT_TRUE(parsed_bye.csrcs().empty()); + EXPECT_TRUE(parsed_bye.reason().empty()); +} + +TEST_F(RtcpPacketByeTest, ParseFailOnInvalidSrcCount) { + bye.From(kSenderSsrc); + + BuildPacket(); + + RtcpCommonHeader header; + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header); + header.count_or_format = 2; // Lie there are 2 ssrcs, not one. + + EXPECT_FALSE(parsed_bye.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); +} + +TEST_F(RtcpPacketByeTest, ParseFailOnInvalidReasonLength) { + bye.From(kSenderSsrc); + bye.WithReason("18 characters long"); + + BuildPacket(); + + RtcpCommonHeader header; + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header); + header.payload_size_bytes -= 4; // Payload is usually 32bit aligned. + + EXPECT_FALSE(parsed_bye.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.cc new file mode 100644 index 0000000000..8f5afd5dd1 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.cc @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h" + +namespace webrtc { +namespace rtcp { + +bool CompoundPacket::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + return true; +} + +size_t CompoundPacket::BlockLength() const { + return 0; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h new file mode 100644 index 0000000000..f2f49a8ffb --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_COMPOUND_PACKET_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_COMPOUND_PACKET_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" + +namespace webrtc { +namespace rtcp { + +class CompoundPacket : public RtcpPacket { + public: + CompoundPacket() : RtcpPacket() {} + + virtual ~CompoundPacket() {} + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + size_t BlockLength() const override; + + private: + RTC_DISALLOW_COPY_AND_ASSIGN(CompoundPacket); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_COMPOUND_PACKET_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc new file mode 100644 index 0000000000..83dc5f6ed3 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet_unittest.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" +#include "webrtc/test/rtcp_packet_parser.h" + +using webrtc::rtcp::Bye; +using webrtc::rtcp::CompoundPacket; +using webrtc::rtcp::Fir; +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::ReceiverReport; +using webrtc::rtcp::ReportBlock; +using webrtc::rtcp::SenderReport; +using webrtc::test::RtcpPacketParser; + +namespace webrtc { + +const uint32_t kSenderSsrc = 0x12345678; + +TEST(RtcpCompoundPacketTest, AppendPacket) { + Fir fir; + ReportBlock rb; + ReceiverReport rr; + rr.From(kSenderSsrc); + EXPECT_TRUE(rr.WithReportBlock(rb)); + rr.Append(&fir); + + rtc::scoped_ptr<RawPacket> packet(rr.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.receiver_report()->num_packets()); + EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc()); + EXPECT_EQ(1, parser.report_block()->num_packets()); + EXPECT_EQ(1, parser.fir()->num_packets()); +} + +TEST(RtcpCompoundPacketTest, AppendPacketOnEmpty) { + CompoundPacket empty; + ReceiverReport rr; + rr.From(kSenderSsrc); + empty.Append(&rr); + + rtc::scoped_ptr<RawPacket> packet(empty.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.receiver_report()->num_packets()); + EXPECT_EQ(0, parser.report_block()->num_packets()); +} + +TEST(RtcpCompoundPacketTest, AppendPacketWithOwnAppendedPacket) { + Fir fir; + Bye bye; + ReportBlock rb; + + ReceiverReport rr; + EXPECT_TRUE(rr.WithReportBlock(rb)); + rr.Append(&fir); + + SenderReport sr; + sr.Append(&bye); + sr.Append(&rr); + + rtc::scoped_ptr<RawPacket> packet(sr.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.sender_report()->num_packets()); + EXPECT_EQ(1, parser.receiver_report()->num_packets()); + EXPECT_EQ(1, parser.report_block()->num_packets()); + EXPECT_EQ(1, parser.bye()->num_packets()); + EXPECT_EQ(1, parser.fir()->num_packets()); +} + +TEST(RtcpCompoundPacketTest, BuildWithInputBuffer) { + Fir fir; + ReportBlock rb; + ReceiverReport rr; + rr.From(kSenderSsrc); + EXPECT_TRUE(rr.WithReportBlock(rb)); + rr.Append(&fir); + + const size_t kRrLength = 8; + const size_t kReportBlockLength = 24; + const size_t kFirLength = 20; + + class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { + public: + void OnPacketReady(uint8_t* data, size_t length) override { + RtcpPacketParser parser; + parser.Parse(data, length); + EXPECT_EQ(1, parser.receiver_report()->num_packets()); + EXPECT_EQ(1, parser.report_block()->num_packets()); + EXPECT_EQ(1, parser.fir()->num_packets()); + ++packets_created_; + } + + int packets_created_ = 0; + } verifier; + const size_t kBufferSize = kRrLength + kReportBlockLength + kFirLength; + uint8_t buffer[kBufferSize]; + EXPECT_TRUE(rr.BuildExternalBuffer(buffer, kBufferSize, &verifier)); + EXPECT_EQ(1, verifier.packets_created_); +} + +TEST(RtcpCompoundPacketTest, BuildWithTooSmallBuffer_FragmentedSend) { + Fir fir; + ReportBlock rb; + ReceiverReport rr; + rr.From(kSenderSsrc); + EXPECT_TRUE(rr.WithReportBlock(rb)); + rr.Append(&fir); + + const size_t kRrLength = 8; + const size_t kReportBlockLength = 24; + + class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { + public: + void OnPacketReady(uint8_t* data, size_t length) override { + RtcpPacketParser parser; + parser.Parse(data, length); + switch (packets_created_++) { + case 0: + EXPECT_EQ(1, parser.receiver_report()->num_packets()); + EXPECT_EQ(1, parser.report_block()->num_packets()); + EXPECT_EQ(0, parser.fir()->num_packets()); + break; + case 1: + EXPECT_EQ(0, parser.receiver_report()->num_packets()); + EXPECT_EQ(0, parser.report_block()->num_packets()); + EXPECT_EQ(1, parser.fir()->num_packets()); + break; + default: + ADD_FAILURE() << "OnPacketReady not expected to be called " + << packets_created_ << " times."; + } + } + + int packets_created_ = 0; + } verifier; + const size_t kBufferSize = kRrLength + kReportBlockLength; + uint8_t buffer[kBufferSize]; + EXPECT_TRUE(rr.BuildExternalBuffer(buffer, kBufferSize, &verifier)); + EXPECT_EQ(2, verifier.packets_created_); +} + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc new file mode 100644 index 0000000000..6d6c48fada --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.cc @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace rtcp { +// DLRR Report Block (RFC 3611). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | BT=5 | reserved | block length | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | SSRC_1 (SSRC of first receiver) | sub- +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block +// | last RR (LRR) | 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | delay since last RR (DLRR) | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | SSRC_2 (SSRC of second receiver) | sub- +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block +// : ... : 2 +bool Dlrr::Parse(const uint8_t* buffer, uint16_t block_length_32bits) { + RTC_DCHECK(buffer[0] == kBlockType); + // kReserved = buffer[1]; + RTC_DCHECK_EQ(block_length_32bits, + ByteReader<uint16_t>::ReadBigEndian(&buffer[2])); + if (block_length_32bits % 3 != 0) { + LOG(LS_WARNING) << "Invalid size for dlrr block."; + return false; + } + + size_t blocks_count = block_length_32bits / 3; + const uint8_t* read_at = buffer + kBlockHeaderLength; + sub_blocks_.resize(blocks_count); + for (SubBlock& sub_block : sub_blocks_) { + sub_block.ssrc = ByteReader<uint32_t>::ReadBigEndian(&read_at[0]); + sub_block.last_rr = ByteReader<uint32_t>::ReadBigEndian(&read_at[4]); + sub_block.delay_since_last_rr = + ByteReader<uint32_t>::ReadBigEndian(&read_at[8]); + read_at += kSubBlockLength; + } + return true; +} + +size_t Dlrr::BlockLength() const { + if (sub_blocks_.empty()) + return 0; + return kBlockHeaderLength + kSubBlockLength * sub_blocks_.size(); +} + +void Dlrr::Create(uint8_t* buffer) const { + if (sub_blocks_.empty()) // No subblocks, no need to write header either. + return; + // Create block header. + const uint8_t kReserved = 0; + buffer[0] = kBlockType; + buffer[1] = kReserved; + ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], 3 * sub_blocks_.size()); + // Create sub blocks. + uint8_t* write_at = buffer + kBlockHeaderLength; + for (const SubBlock& sub_block : sub_blocks_) { + ByteWriter<uint32_t>::WriteBigEndian(&write_at[0], sub_block.ssrc); + ByteWriter<uint32_t>::WriteBigEndian(&write_at[4], sub_block.last_rr); + ByteWriter<uint32_t>::WriteBigEndian(&write_at[8], + sub_block.delay_since_last_rr); + write_at += kSubBlockLength; + } + RTC_DCHECK_EQ(buffer + BlockLength(), write_at); +} + +bool Dlrr::WithDlrrItem(uint32_t ssrc, + uint32_t last_rr, + uint32_t delay_last_rr) { + if (sub_blocks_.size() >= kMaxNumberOfDlrrItems) { + LOG(LS_WARNING) << "Max DLRR items reached."; + return false; + } + SubBlock block; + block.ssrc = ssrc; + block.last_rr = last_rr; + block.delay_since_last_rr = delay_last_rr; + sub_blocks_.push_back(block); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h new file mode 100644 index 0000000000..9af2dedf3f --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_DLRR_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_DLRR_H_ + +#include <vector> + +#include "webrtc/base/basictypes.h" + +namespace webrtc { +namespace rtcp { + +// DLRR Report Block: Delay since the Last Receiver Report (RFC 3611). +class Dlrr { + public: + struct SubBlock { + // RFC 3611 4.5 + uint32_t ssrc; + uint32_t last_rr; + uint32_t delay_since_last_rr; + }; + + static const uint8_t kBlockType = 5; + static const size_t kMaxNumberOfDlrrItems = 100; + + Dlrr() {} + Dlrr(const Dlrr& other) = default; + ~Dlrr() {} + + Dlrr& operator=(const Dlrr& other) = default; + + // Second parameter is value read from block header, + // i.e. size of block in 32bits excluding block header itself. + bool Parse(const uint8_t* buffer, uint16_t block_length_32bits); + + size_t BlockLength() const; + // Fills buffer with the Dlrr. + // Consumes BlockLength() bytes. + void Create(uint8_t* buffer) const; + + // Max 100 DLRR Items can be added per DLRR report block. + bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr); + + const std::vector<SubBlock>& sub_blocks() const { return sub_blocks_; } + + private: + static const size_t kBlockHeaderLength = 4; + static const size_t kSubBlockLength = 12; + + std::vector<SubBlock> sub_blocks_; +}; +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_DLRR_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc new file mode 100644 index 0000000000..c7c139c560 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr_unittest.cc @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" + +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::rtcp::Dlrr; + +namespace webrtc { +namespace { + +const uint32_t kSsrc = 0x12345678; +const uint32_t kLastRR = 0x23344556; +const uint32_t kDelay = 0x33343536; +const uint8_t kBlock[] = {0x05, 0x00, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x34, 0x45, 0x56, 0x33, 0x34, 0x35, 0x36}; +const size_t kBlockSizeBytes = sizeof(kBlock); + +TEST(RtcpPacketDlrrTest, Empty) { + Dlrr dlrr; + + EXPECT_EQ(0u, dlrr.BlockLength()); +} + +TEST(RtcpPacketDlrrTest, Create) { + Dlrr dlrr; + EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc, kLastRR, kDelay)); + + ASSERT_EQ(kBlockSizeBytes, dlrr.BlockLength()); + uint8_t buffer[kBlockSizeBytes]; + + dlrr.Create(buffer); + EXPECT_EQ(0, memcmp(buffer, kBlock, kBlockSizeBytes)); +} + +TEST(RtcpPacketDlrrTest, Parse) { + Dlrr dlrr; + uint16_t block_length = ByteReader<uint16_t>::ReadBigEndian(&kBlock[2]); + EXPECT_TRUE(dlrr.Parse(kBlock, block_length)); + + EXPECT_EQ(1u, dlrr.sub_blocks().size()); + const Dlrr::SubBlock& block = dlrr.sub_blocks().front(); + EXPECT_EQ(kSsrc, block.ssrc); + EXPECT_EQ(kLastRR, block.last_rr); + EXPECT_EQ(kDelay, block.delay_since_last_rr); +} + +TEST(RtcpPacketDlrrTest, ParseFailsOnBadSize) { + const size_t kBigBufferSize = 0x100; // More than enough. + uint8_t buffer[kBigBufferSize]; + buffer[0] = Dlrr::kBlockType; + buffer[1] = 0; // Reserved. + buffer[2] = 0; // Most significant size byte. + for (uint8_t size = 3; size < 6; ++size) { + buffer[3] = size; + Dlrr dlrr; + // Parse should be successful only when size is multiple of 3. + EXPECT_EQ(size % 3 == 0, dlrr.Parse(buffer, static_cast<uint16_t>(size))); + } +} + +TEST(RtcpPacketDlrrTest, FailsOnTooManySubBlocks) { + Dlrr dlrr; + for (size_t i = 1; i <= Dlrr::kMaxNumberOfDlrrItems; ++i) { + EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc + i, kLastRR + i, kDelay + i)); + } + EXPECT_FALSE(dlrr.WithDlrrItem(kSsrc, kLastRR, kDelay)); +} + +TEST(RtcpPacketDlrrTest, CreateAndParseMaxSubBlocks) { + const size_t kBufferSize = 0x1000; // More than enough. + uint8_t buffer[kBufferSize]; + + // Create. + Dlrr dlrr; + for (size_t i = 1; i <= Dlrr::kMaxNumberOfDlrrItems; ++i) { + EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc + i, kLastRR + i, kDelay + i)); + } + size_t used_buffer_size = dlrr.BlockLength(); + ASSERT_LE(used_buffer_size, kBufferSize); + dlrr.Create(buffer); + + // Parse. + Dlrr parsed; + uint16_t block_length = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]); + EXPECT_EQ(used_buffer_size, (block_length + 1) * 4u); + EXPECT_TRUE(parsed.Parse(buffer, block_length)); + EXPECT_TRUE(parsed.sub_blocks().size() == Dlrr::kMaxNumberOfDlrrItems); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.cc new file mode 100644 index 0000000000..030f9f81fa --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.cc @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { + +// Transmission Time Offsets in RTP Streams (RFC 5450). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// hdr |V=2|P| RC | PT=IJ=195 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | inter-arrival jitter | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . . +// . . +// . . +// | inter-arrival jitter | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// If present, this RTCP packet must be placed after a receiver report +// (inside a compound RTCP packet), and MUST have the same value for RC +// (reception report count) as the receiver report. + +bool ExtendedJitterReport::Parse(const RtcpCommonHeader& header, + const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + + const uint8_t jitters_count = header.count_or_format; + const size_t kJitterSizeBytes = 4u; + + if (header.payload_size_bytes < jitters_count * kJitterSizeBytes) { + LOG(LS_WARNING) << "Packet is too small to contain all the jitter."; + return false; + } + + inter_arrival_jitters_.resize(jitters_count); + for (size_t index = 0; index < jitters_count; ++index) { + inter_arrival_jitters_[index] = + ByteReader<uint32_t>::ReadBigEndian(&payload[index * kJitterSizeBytes]); + } + + return true; +} + +bool ExtendedJitterReport::WithJitter(uint32_t jitter) { + if (inter_arrival_jitters_.size() >= kMaxNumberOfJitters) { + LOG(LS_WARNING) << "Max inter-arrival jitter items reached."; + return false; + } + inter_arrival_jitters_.push_back(jitter); + return true; +} + +bool ExtendedJitterReport::Create( + uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + const size_t index_end = *index + BlockLength(); + size_t length = inter_arrival_jitters_.size(); + CreateHeader(length, kPacketType, length, packet, index); + + for (uint32_t jitter : inter_arrival_jitters_) { + ByteWriter<uint32_t>::WriteBigEndian(packet + *index, jitter); + *index += sizeof(uint32_t); + } + // Sanity check. + RTC_DCHECK_EQ(index_end, *index); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h new file mode 100644 index 0000000000..49de7be1a8 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_EXTENDED_JITTER_REPORT_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_EXTENDED_JITTER_REPORT_H_ + +#include <vector> + +#include "webrtc/base/checks.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +class ExtendedJitterReport : public RtcpPacket { + public: + static const uint8_t kPacketType = 195; + + ExtendedJitterReport() : RtcpPacket() {} + + virtual ~ExtendedJitterReport() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + bool WithJitter(uint32_t jitter); + + size_t jitters_count() const { return inter_arrival_jitters_.size(); } + uint32_t jitter(size_t index) const { + RTC_DCHECK_LT(index, jitters_count()); + return inter_arrival_jitters_[index]; + } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + static const int kMaxNumberOfJitters = 0x1f; + + size_t BlockLength() const override { + return kHeaderLength + 4 * inter_arrival_jitters_.size(); + } + + std::vector<uint32_t> inter_arrival_jitters_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ExtendedJitterReport); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_EXTENDED_JITTER_REPORT_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report_unittest.cc new file mode 100644 index 0000000000..09d7b6305f --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report_unittest.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" + +#include <limits> + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::ExtendedJitterReport; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { + +class RtcpPacketExtendedJitterReportTest : public ::testing::Test { + protected: + void BuildPacket() { packet = ij.Build(); } + void ParsePacket() { + RtcpCommonHeader header; + EXPECT_TRUE( + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header)); + EXPECT_EQ(header.BlockSize(), packet->Length()); + EXPECT_TRUE(parsed_.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); + } + + ExtendedJitterReport ij; + rtc::scoped_ptr<RawPacket> packet; + const ExtendedJitterReport& parsed() { return parsed_; } + + private: + ExtendedJitterReport parsed_; +}; + +TEST_F(RtcpPacketExtendedJitterReportTest, NoItem) { + // No initialization because packet is empty. + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(0u, parsed().jitters_count()); +} + +TEST_F(RtcpPacketExtendedJitterReportTest, OneItem) { + EXPECT_TRUE(ij.WithJitter(0x11121314)); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(1u, parsed().jitters_count()); + EXPECT_EQ(0x11121314U, parsed().jitter(0)); +} + +TEST_F(RtcpPacketExtendedJitterReportTest, TwoItems) { + EXPECT_TRUE(ij.WithJitter(0x11121418)); + EXPECT_TRUE(ij.WithJitter(0x22242628)); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(2u, parsed().jitters_count()); + EXPECT_EQ(0x11121418U, parsed().jitter(0)); + EXPECT_EQ(0x22242628U, parsed().jitter(1)); +} + +TEST_F(RtcpPacketExtendedJitterReportTest, TooManyItems) { + const int kMaxIjItems = (1 << 5) - 1; + for (int i = 0; i < kMaxIjItems; ++i) { + EXPECT_TRUE(ij.WithJitter(i)); + } + EXPECT_FALSE(ij.WithJitter(kMaxIjItems)); +} + +TEST_F(RtcpPacketExtendedJitterReportTest, ParseFailWithTooManyItems) { + ij.WithJitter(0x11121418); + BuildPacket(); + RtcpCommonHeader header; + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header); + header.count_or_format++; // Damage package. + + ExtendedJitterReport parsed; + + EXPECT_FALSE(parsed.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.cc new file mode 100644 index 0000000000..8b9b354a06 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.cc @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" + +#include <algorithm> + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { + +// RFC 4585: Feedback format. +// +// Common packet format: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT | PT | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : Feedback Control Information (FCI) : +// : : +// +// Generic NACK (RFC 4585). +// +// FCI: +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | PID | BLP | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +bool Nack::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + RTC_DCHECK(header.count_or_format == kFeedbackMessageType); + + if (header.payload_size_bytes < kCommonFeedbackLength + kNackItemLength) { + LOG(LS_WARNING) << "Payload length " << header.payload_size_bytes + << " is too small for a Nack."; + return false; + } + size_t nack_items = + (header.payload_size_bytes - kCommonFeedbackLength) / kNackItemLength; + + ParseCommonFeedback(payload); + const uint8_t* next_nack = payload + kCommonFeedbackLength; + + packet_ids_.clear(); + packed_.resize(nack_items); + for (size_t index = 0; index < nack_items; ++index) { + packed_[index].first_pid = ByteReader<uint16_t>::ReadBigEndian(next_nack); + packed_[index].bitmask = ByteReader<uint16_t>::ReadBigEndian(next_nack + 2); + next_nack += kNackItemLength; + } + Unpack(); + + return true; +} + +bool Nack::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + RTC_DCHECK(!packed_.empty()); + // If nack list can't fit in packet, try to fragment. + size_t nack_index = 0; + const size_t kCommonFbFmtLength = kHeaderLength + kCommonFeedbackLength; + do { + size_t bytes_left_in_buffer = max_length - *index; + if (bytes_left_in_buffer < kCommonFbFmtLength + kNackItemLength) { + if (!OnBufferFull(packet, index, callback)) + return false; + continue; + } + size_t num_nack_fields = + std::min((bytes_left_in_buffer - kCommonFbFmtLength) / kNackItemLength, + packed_.size() - nack_index); + + size_t size_bytes = + (num_nack_fields * kNackItemLength) + kCommonFbFmtLength; + size_t header_length = ((size_bytes + 3) / 4) - 1; // As 32bit words - 1 + CreateHeader(kFeedbackMessageType, kPacketType, header_length, packet, + index); + CreateCommonFeedback(packet + *index); + *index += kCommonFeedbackLength; + size_t end_index = nack_index + num_nack_fields; + for (; nack_index < end_index; ++nack_index) { + const auto& item = packed_[nack_index]; + ByteWriter<uint16_t>::WriteBigEndian(packet + *index + 0, item.first_pid); + ByteWriter<uint16_t>::WriteBigEndian(packet + *index + 2, item.bitmask); + *index += kNackItemLength; + } + RTC_DCHECK_LE(*index, max_length); + } while (nack_index < packed_.size()); + + return true; +} + +size_t Nack::BlockLength() const { + return (packed_.size() * kNackItemLength) + kCommonFeedbackLength + + kHeaderLength; +} + +void Nack::WithList(const uint16_t* nack_list, size_t length) { + RTC_DCHECK(nack_list); + RTC_DCHECK(packet_ids_.empty()); + RTC_DCHECK(packed_.empty()); + packet_ids_.assign(nack_list, nack_list + length); + Pack(); +} + +void Nack::Pack() { + RTC_DCHECK(!packet_ids_.empty()); + RTC_DCHECK(packed_.empty()); + auto it = packet_ids_.begin(); + const auto end = packet_ids_.end(); + while (it != end) { + PackedNack item; + item.first_pid = *it++; + // Bitmask specifies losses in any of the 16 packets following the pid. + item.bitmask = 0; + while (it != end) { + uint16_t shift = static_cast<uint16_t>(*it - item.first_pid - 1); + if (shift <= 15) { + item.bitmask |= (1 << shift); + ++it; + } else { + break; + } + } + packed_.push_back(item); + } +} + +void Nack::Unpack() { + RTC_DCHECK(packet_ids_.empty()); + RTC_DCHECK(!packed_.empty()); + for (const PackedNack& item : packed_) { + packet_ids_.push_back(item.first_pid); + uint16_t pid = item.first_pid + 1; + for (uint16_t bitmask = item.bitmask; bitmask != 0; bitmask >>= 1, ++pid) + if (bitmask & 1) + packet_ids_.push_back(pid); + } +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h new file mode 100644 index 0000000000..fb2be113a2 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_NACK_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_NACK_H_ + +#include <vector> + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +class Nack : public Rtpfb { + public: + const uint8_t kFeedbackMessageType = 1; + Nack() {} + + virtual ~Nack() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + void WithList(const uint16_t* nack_list, size_t length); + const std::vector<uint16_t>& packet_ids() const { return packet_ids_; } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + size_t BlockLength() const override; + + private: + const size_t kNackItemLength = 4; + struct PackedNack { + uint16_t first_pid; + uint16_t bitmask; + }; + + void Pack(); // Fills packed_ using packed_ids_. (used in WithList). + void Unpack(); // Fills packet_ids_ using packed_. (used in Parse). + + std::vector<PackedNack> packed_; + std::vector<uint16_t> packet_ids_; + + RTC_DISALLOW_COPY_AND_ASSIGN(Nack); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_NACK_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack_unittest.cc new file mode 100644 index 0000000000..01e30f5644 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack_unittest.cc @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; +using ::testing::ElementsAreArray; +using ::testing::Invoke; +using ::testing::UnorderedElementsAreArray; + +using webrtc::rtcp::Nack; +using webrtc::rtcp::RawPacket; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { + +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; + +const uint16_t kList[] = {0, 1, 3, 8, 16}; +const size_t kListLength = sizeof(kList) / sizeof(kList[0]); +const uint8_t kPacket[] = {0x81, 205, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x00, 0x00, 0x80, 0x85}; +const size_t kPacketLength = sizeof(kPacket); + +const uint16_t kWrapList[] = {0xffdc, 0xffec, 0xfffe, 0xffff, 0x0000, + 0x0001, 0x0003, 0x0014, 0x0064}; +const size_t kWrapListLength = sizeof(kWrapList) / sizeof(kWrapList[0]); +const uint8_t kWrapPacket[] = {0x81, 205, 0x00, 0x06, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0xff, 0xdc, 0x80, 0x00, + 0xff, 0xfe, 0x00, 0x17, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x64, 0x00, 0x00}; +const size_t kWrapPacketLength = sizeof(kWrapPacket); + +TEST(RtcpPacketNackTest, Create) { + Nack nack; + nack.From(kSenderSsrc); + nack.To(kRemoteSsrc); + nack.WithList(kList, kListLength); + + rtc::scoped_ptr<RawPacket> packet = nack.Build(); + + EXPECT_EQ(kPacketLength, packet->Length()); + EXPECT_EQ(0, memcmp(kPacket, packet->Buffer(), kPacketLength)); +} + +TEST(RtcpPacketNackTest, Parse) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); + EXPECT_EQ(kPacketLength, header.BlockSize()); + Nack parsed; + + EXPECT_TRUE( + parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); + const Nack& const_parsed = parsed; + + EXPECT_EQ(kSenderSsrc, const_parsed.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, const_parsed.media_ssrc()); + EXPECT_THAT(const_parsed.packet_ids(), ElementsAreArray(kList)); +} + +TEST(RtcpPacketNackTest, CreateWrap) { + Nack nack; + nack.From(kSenderSsrc); + nack.To(kRemoteSsrc); + nack.WithList(kWrapList, kWrapListLength); + + rtc::scoped_ptr<RawPacket> packet = nack.Build(); + + EXPECT_EQ(kWrapPacketLength, packet->Length()); + EXPECT_EQ(0, memcmp(kWrapPacket, packet->Buffer(), kWrapPacketLength)); +} + +TEST(RtcpPacketNackTest, ParseWrap) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(kWrapPacket, kWrapPacketLength, &header)); + EXPECT_EQ(kWrapPacketLength, header.BlockSize()); + + Nack parsed; + EXPECT_TRUE( + parsed.Parse(header, kWrapPacket + RtcpCommonHeader::kHeaderSizeBytes)); + + EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); + EXPECT_THAT(parsed.packet_ids(), ElementsAreArray(kWrapList)); +} + +TEST(RtcpPacketNackTest, BadOrder) { + // Does not guarantee optimal packing, but should guarantee correctness. + const uint16_t kUnorderedList[] = {1, 25, 13, 12, 9, 27, 29}; + const size_t kUnorderedListLength = + sizeof(kUnorderedList) / sizeof(kUnorderedList[0]); + Nack nack; + nack.From(kSenderSsrc); + nack.To(kRemoteSsrc); + nack.WithList(kUnorderedList, kUnorderedListLength); + + rtc::scoped_ptr<RawPacket> packet = nack.Build(); + + Nack parsed; + RtcpCommonHeader header; + EXPECT_TRUE( + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header)); + EXPECT_TRUE(parsed.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); + + EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); + EXPECT_THAT(parsed.packet_ids(), UnorderedElementsAreArray(kUnorderedList)); +} + +TEST(RtcpPacketNackTest, CreateFragmented) { + Nack nack; + const uint16_t kList[] = {1, 100, 200, 300, 400}; + const uint16_t kListLength = sizeof(kList) / sizeof(kList[0]); + nack.From(kSenderSsrc); + nack.To(kRemoteSsrc); + nack.WithList(kList, kListLength); + + class MockPacketReadyCallback : public rtcp::RtcpPacket::PacketReadyCallback { + public: + MOCK_METHOD2(OnPacketReady, void(uint8_t*, size_t)); + } verifier; + + class NackVerifier { + public: + explicit NackVerifier(std::vector<uint16_t> ids) : ids_(ids) {} + void operator()(uint8_t* data, size_t length) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(data, length, &header)); + EXPECT_EQ(length, header.BlockSize()); + Nack nack; + EXPECT_TRUE( + nack.Parse(header, data + RtcpCommonHeader::kHeaderSizeBytes)); + EXPECT_EQ(kSenderSsrc, nack.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, nack.media_ssrc()); + EXPECT_THAT(nack.packet_ids(), ElementsAreArray(ids_)); + } + std::vector<uint16_t> ids_; + } packet1({1, 100, 200}), packet2({300, 400}); + + EXPECT_CALL(verifier, OnPacketReady(_, _)) + .WillOnce(Invoke(packet1)) + .WillOnce(Invoke(packet2)); + const size_t kBufferSize = 12 + (3 * 4); // Fits common header + 3 nack items + uint8_t buffer[kBufferSize]; + EXPECT_TRUE(nack.BuildExternalBuffer(buffer, kBufferSize, &verifier)); +} + +TEST(RtcpPacketNackTest, CreateFailsWithTooSmallBuffer) { + const uint16_t kList[] = {1}; + const size_t kMinNackBlockSize = 16; + Nack nack; + nack.From(kSenderSsrc); + nack.To(kRemoteSsrc); + nack.WithList(kList, 1); + class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { + public: + void OnPacketReady(uint8_t* data, size_t length) override { + ADD_FAILURE() << "Buffer should be too small."; + } + } verifier; + uint8_t buffer[kMinNackBlockSize - 1]; + EXPECT_FALSE( + nack.BuildExternalBuffer(buffer, kMinNackBlockSize - 1, &verifier)); +} + +TEST(RtcpPacketNackTest, ParseFailsWithTooSmallBuffer) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); + header.payload_size_bytes--; // Damage the packet + Nack parsed; + EXPECT_FALSE( + parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.cc new file mode 100644 index 0000000000..3673491058 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { + +// RFC 4585: Feedback format. +// +// Common packet format: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT | PT | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : Feedback Control Information (FCI) : +// : : + +// +// Picture loss indication (PLI) (RFC 4585). +// FCI: no feedback control information. +bool Pli::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + RTC_DCHECK(header.count_or_format == kFeedbackMessageType); + + if (header.payload_size_bytes < kCommonFeedbackLength) { + LOG(LS_WARNING) << "Packet is too small to be a valid PLI packet"; + return false; + } + + ParseCommonFeedback(payload); + return true; +} + +bool Pli::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + + CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet, + index); + CreateCommonFeedback(packet + *index); + *index += kCommonFeedbackLength; + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h new file mode 100644 index 0000000000..5567825830 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PLI_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PLI_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" + +namespace webrtc { +namespace rtcp { + +// Picture loss indication (PLI) (RFC 4585). +class Pli : public Psfb { + public: + static const uint8_t kFeedbackMessageType = 1; + + Pli() {} + virtual ~Pli() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + size_t BlockLength() const override { + return kHeaderLength + kCommonFeedbackLength; + } + + RTC_DISALLOW_COPY_AND_ASSIGN(Pli); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PLI_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli_unittest.cc new file mode 100644 index 0000000000..1c47c3ffb1 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli_unittest.cc @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +using webrtc::rtcp::Pli; +using webrtc::rtcp::RawPacket; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { + +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; +// Manually created Pli packet matching constants above. +const uint8_t kPacket[] = {0x81, 206, 0x00, 0x02, + 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89}; +const size_t kPacketLength = sizeof(kPacket); + +TEST(RtcpPacketPliTest, Parse) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); + Pli mutable_parsed; + EXPECT_TRUE(mutable_parsed.Parse( + header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); + const Pli& parsed = mutable_parsed; // Read values from constant object. + + EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); +} + +TEST(RtcpPacketPliTest, Create) { + Pli pli; + pli.From(kSenderSsrc); + pli.To(kRemoteSsrc); + + rtc::scoped_ptr<RawPacket> packet(pli.Build()); + + ASSERT_EQ(kPacketLength, packet->Length()); + EXPECT_EQ(0, memcmp(kPacket, packet->Buffer(), kPacketLength)); +} + +TEST(RtcpPacketPliTest, ParseFailsOnTooSmallPacket) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); + header.payload_size_bytes--; + + Pli parsed; + EXPECT_FALSE( + parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.cc new file mode 100644 index 0000000000..d1ee401dab --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" + +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace rtcp { + +// RFC 4585: Feedback format. +// +// Common packet format: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT | PT | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : Feedback Control Information (FCI) : +// : : + +void Psfb::ParseCommonFeedback(const uint8_t* payload) { + sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&payload[0]); + media_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&payload[4]); +} + +void Psfb::CreateCommonFeedback(uint8_t* payload) const { + ByteWriter<uint32_t>::WriteBigEndian(&payload[0], sender_ssrc_); + ByteWriter<uint32_t>::WriteBigEndian(&payload[4], media_ssrc_); +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h new file mode 100644 index 0000000000..dddcdecba6 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PSFB_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PSFB_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" + +namespace webrtc { +namespace rtcp { + +// PSFB: Payload-specific feedback message. +// RFC 4585, Section 6.3. +class Psfb : public RtcpPacket { + public: + static const uint8_t kPacketType = 206; + + Psfb() : sender_ssrc_(0), media_ssrc_(0) {} + virtual ~Psfb() {} + + void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void To(uint32_t ssrc) { media_ssrc_ = ssrc; } + + uint32_t sender_ssrc() const { return sender_ssrc_; } + uint32_t media_ssrc() const { return media_ssrc_; } + + protected: + static const size_t kCommonFeedbackLength = 8; + void ParseCommonFeedback(const uint8_t* payload); + void CreateCommonFeedback(uint8_t* payload) const; + + private: + uint32_t sender_ssrc_; + uint32_t media_ssrc_; +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PSFB_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.cc new file mode 100644 index 0000000000..ef64b4f51b --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.cc @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { + +// +// RTCP receiver report (RFC 3550). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| RC | PT=RR=201 | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// | report block(s) | +// | .... | +bool ReceiverReport::Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + + const uint8_t report_blocks_count = header.count_or_format; + + if (header.payload_size_bytes < + kRrBaseLength + report_blocks_count * ReportBlock::kLength) { + LOG(LS_WARNING) << "Packet is too small to contain all the data."; + return false; + } + + sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload); + + const uint8_t* next_report_block = payload + kRrBaseLength; + + report_blocks_.resize(report_blocks_count); + for (ReportBlock& block : report_blocks_) { + block.Parse(next_report_block, ReportBlock::kLength); + next_report_block += ReportBlock::kLength; + } + + RTC_DCHECK_LE(next_report_block, payload + header.payload_size_bytes); + return true; +} + +bool ReceiverReport::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet, + index); + ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc_); + *index += kRrBaseLength; + for (const ReportBlock& block : report_blocks_) { + block.Create(packet + *index); + *index += ReportBlock::kLength; + } + return true; +} + +bool ReceiverReport::WithReportBlock(const ReportBlock& block) { + if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { + LOG(LS_WARNING) << "Max report blocks reached."; + return false; + } + report_blocks_.push_back(block); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h new file mode 100644 index 0000000000..172a84ea2f --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RECEIVER_REPORT_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RECEIVER_REPORT_H_ + +#include <vector> + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +class ReceiverReport : public RtcpPacket { + public: + static const uint8_t kPacketType = 201; + ReceiverReport() : sender_ssrc_(0) {} + + virtual ~ReceiverReport() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } + bool WithReportBlock(const ReportBlock& block); + + uint32_t sender_ssrc() const { return sender_ssrc_; } + const std::vector<ReportBlock>& report_blocks() const { + return report_blocks_; + } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + static const size_t kRrBaseLength = 4; + static const size_t kMaxNumberOfReportBlocks = 0x1F; + + size_t BlockLength() const { + return kHeaderLength + kRrBaseLength + + report_blocks_.size() * ReportBlock::kLength; + } + + uint32_t sender_ssrc_; + std::vector<ReportBlock> report_blocks_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ReceiverReport); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RECEIVER_REPORT_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc new file mode 100644 index 0000000000..ff3da600a5 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::ReceiverReport; +using webrtc::rtcp::ReportBlock; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; +const uint8_t kFractionLost = 55; +const uint32_t kCumulativeLost = 0x111213; +const uint32_t kExtHighestSeqNum = 0x22232425; +const uint32_t kJitter = 0x33343536; +const uint32_t kLastSr = 0x44454647; +const uint32_t kDelayLastSr = 0x55565758; +// Manually created ReceiverReport with one ReportBlock matching constants +// above. +// Having this block allows to test Create and Parse separately. +const uint8_t kPacket[] = {0x81, 201, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 55, 0x11, 0x12, 0x13, + 0x22, 0x23, 0x24, 0x25, 0x33, 0x34, 0x35, 0x36, + 0x44, 0x45, 0x46, 0x47, 0x55, 0x56, 0x57, 0x58}; +const size_t kPacketLength = sizeof(kPacket); + +class RtcpPacketReceiverReportTest : public ::testing::Test { + protected: + void BuildPacket() { packet = rr.Build(); } + void ParsePacket() { + RtcpCommonHeader header; + EXPECT_TRUE( + RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header)); + EXPECT_EQ(header.BlockSize(), packet->Length()); + EXPECT_TRUE(parsed_.Parse( + header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); + } + + ReceiverReport rr; + rtc::scoped_ptr<RawPacket> packet; + const ReceiverReport& parsed() { return parsed_; } + + private: + ReceiverReport parsed_; +}; + +TEST_F(RtcpPacketReceiverReportTest, Parse) { + RtcpCommonHeader header; + RtcpParseCommonHeader(kPacket, kPacketLength, &header); + EXPECT_TRUE(rr.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); + const ReceiverReport& parsed = rr; + + EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); + EXPECT_EQ(1u, parsed.report_blocks().size()); + const ReportBlock& rb = parsed.report_blocks().front(); + EXPECT_EQ(kRemoteSsrc, rb.source_ssrc()); + EXPECT_EQ(kFractionLost, rb.fraction_lost()); + EXPECT_EQ(kCumulativeLost, rb.cumulative_lost()); + EXPECT_EQ(kExtHighestSeqNum, rb.extended_high_seq_num()); + EXPECT_EQ(kJitter, rb.jitter()); + EXPECT_EQ(kLastSr, rb.last_sr()); + EXPECT_EQ(kDelayLastSr, rb.delay_since_last_sr()); +} + +TEST_F(RtcpPacketReceiverReportTest, ParseFailsOnIncorrectSize) { + RtcpCommonHeader header; + RtcpParseCommonHeader(kPacket, kPacketLength, &header); + header.count_or_format++; // Damage the packet. + EXPECT_FALSE(rr.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); +} + +TEST_F(RtcpPacketReceiverReportTest, Create) { + rr.From(kSenderSsrc); + ReportBlock rb; + rb.To(kRemoteSsrc); + rb.WithFractionLost(kFractionLost); + rb.WithCumulativeLost(kCumulativeLost); + rb.WithExtHighestSeqNum(kExtHighestSeqNum); + rb.WithJitter(kJitter); + rb.WithLastSr(kLastSr); + rb.WithDelayLastSr(kDelayLastSr); + rr.WithReportBlock(rb); + + BuildPacket(); + + ASSERT_EQ(kPacketLength, packet->Length()); + EXPECT_EQ(0, memcmp(kPacket, packet->Buffer(), kPacketLength)); +} + +TEST_F(RtcpPacketReceiverReportTest, WithoutReportBlocks) { + rr.From(kSenderSsrc); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc()); + EXPECT_EQ(0u, parsed().report_blocks().size()); +} + +TEST_F(RtcpPacketReceiverReportTest, WithTwoReportBlocks) { + ReportBlock rb1; + rb1.To(kRemoteSsrc); + ReportBlock rb2; + rb2.To(kRemoteSsrc + 1); + + rr.From(kSenderSsrc); + EXPECT_TRUE(rr.WithReportBlock(rb1)); + EXPECT_TRUE(rr.WithReportBlock(rb2)); + + BuildPacket(); + ParsePacket(); + + EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc()); + EXPECT_EQ(2u, parsed().report_blocks().size()); + EXPECT_EQ(kRemoteSsrc, parsed().report_blocks()[0].source_ssrc()); + EXPECT_EQ(kRemoteSsrc + 1, parsed().report_blocks()[1].source_ssrc()); +} + +TEST_F(RtcpPacketReceiverReportTest, WithTooManyReportBlocks) { + rr.From(kSenderSsrc); + const size_t kMaxReportBlocks = (1 << 5) - 1; + ReportBlock rb; + for (size_t i = 0; i < kMaxReportBlocks; ++i) { + rb.To(kRemoteSsrc + i); + EXPECT_TRUE(rr.WithReportBlock(rb)); + } + rb.To(kRemoteSsrc + kMaxReportBlocks); + EXPECT_FALSE(rr.WithReportBlock(rb)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.cc new file mode 100644 index 0000000000..4911dbf5b7 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.cc @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace rtcp { + +// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications. +// +// RTCP report block (RFC 3550). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// 0 | SSRC_1 (SSRC of first source) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | fraction lost | cumulative number of packets lost | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | extended highest sequence number received | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 12 | interarrival jitter | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 16 | last SR (LSR) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 20 | delay since last SR (DLSR) | +// 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +ReportBlock::ReportBlock() + : source_ssrc_(0), + fraction_lost_(0), + cumulative_lost_(0), + extended_high_seq_num_(0), + jitter_(0), + last_sr_(0), + delay_since_last_sr_(0) {} + +bool ReportBlock::Parse(const uint8_t* buffer, size_t length) { + RTC_DCHECK(buffer != nullptr); + if (length < ReportBlock::kLength) { + LOG(LS_ERROR) << "Report Block should be 24 bytes long"; + return false; + } + + source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[0]); + fraction_lost_ = buffer[4]; + cumulative_lost_ = ByteReader<uint32_t, 3>::ReadBigEndian(&buffer[5]); + extended_high_seq_num_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]); + jitter_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[12]); + last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[16]); + delay_since_last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[20]); + + return true; +} + +void ReportBlock::Create(uint8_t* buffer) const { + // Runtime check should be done while setting cumulative_lost. + RTC_DCHECK_LT(cumulative_lost(), (1u << 24)); // Have only 3 bytes for it. + + ByteWriter<uint32_t>::WriteBigEndian(&buffer[0], source_ssrc()); + ByteWriter<uint8_t>::WriteBigEndian(&buffer[4], fraction_lost()); + ByteWriter<uint32_t, 3>::WriteBigEndian(&buffer[5], cumulative_lost()); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[8], extended_high_seq_num()); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[12], jitter()); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[16], last_sr()); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[20], delay_since_last_sr()); +} + +bool ReportBlock::WithCumulativeLost(uint32_t cumulative_lost) { + if (cumulative_lost >= (1u << 24)) { // Have only 3 bytes to store it. + LOG(LS_WARNING) << "Cumulative lost is too big to fit into Report Block"; + return false; + } + cumulative_lost_ = cumulative_lost; + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h new file mode 100644 index 0000000000..ef99e17297 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_REPORT_BLOCK_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_REPORT_BLOCK_H_ + +#include "webrtc/base/basictypes.h" + +namespace webrtc { +namespace rtcp { + +class ReportBlock { + public: + static const size_t kLength = 24; + + ReportBlock(); + ~ReportBlock() {} + + bool Parse(const uint8_t* buffer, size_t length); + + // Fills buffer with the ReportBlock. + // Consumes ReportBlock::kLength bytes. + void Create(uint8_t* buffer) const; + + void To(uint32_t ssrc) { source_ssrc_ = ssrc; } + void WithFractionLost(uint8_t fraction_lost) { + fraction_lost_ = fraction_lost; + } + bool WithCumulativeLost(uint32_t cumulative_lost); + void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) { + extended_high_seq_num_ = ext_highest_seq_num; + } + void WithJitter(uint32_t jitter) { jitter_ = jitter; } + void WithLastSr(uint32_t last_sr) { last_sr_ = last_sr; } + void WithDelayLastSr(uint32_t delay_last_sr) { + delay_since_last_sr_ = delay_last_sr; + } + + uint32_t source_ssrc() const { return source_ssrc_; } + uint8_t fraction_lost() const { return fraction_lost_; } + uint32_t cumulative_lost() const { return cumulative_lost_; } + uint32_t extended_high_seq_num() const { return extended_high_seq_num_; } + uint32_t jitter() const { return jitter_; } + uint32_t last_sr() const { return last_sr_; } + uint32_t delay_since_last_sr() const { return delay_since_last_sr_; } + + private: + uint32_t source_ssrc_; + uint8_t fraction_lost_; + uint32_t cumulative_lost_; + uint32_t extended_high_seq_num_; + uint32_t jitter_; + uint32_t last_sr_; + uint32_t delay_since_last_sr_; +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_REPORT_BLOCK_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc new file mode 100644 index 0000000000..85bbb404a4 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" + +#include <limits> + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/random.h" + +using webrtc::rtcp::ReportBlock; + +namespace webrtc { +namespace { + +const uint32_t kRemoteSsrc = 0x23456789; +const uint8_t kFractionLost = 55; +// Use values that are streamed differently LE and BE. +const uint32_t kCumulativeLost = 0x111213; +const uint32_t kExtHighestSeqNum = 0x22232425; +const uint32_t kJitter = 0x33343536; +const uint32_t kLastSr = 0x44454647; +const uint32_t kDelayLastSr = 0x55565758; +const size_t kBufferLength = ReportBlock::kLength; + +TEST(RtcpPacketReportBlockTest, ParseChecksLength) { + uint8_t buffer[kBufferLength]; + memset(buffer, 0, sizeof(buffer)); + + ReportBlock rb; + EXPECT_FALSE(rb.Parse(buffer, kBufferLength - 1)); + EXPECT_TRUE(rb.Parse(buffer, kBufferLength)); +} + +TEST(RtcpPacketReportBlockTest, ParseAnyData) { + uint8_t buffer[kBufferLength]; + // Fill buffer with semi-random data. + Random generator(0x256F8A285EC829ull); + for (size_t i = 0; i < kBufferLength; ++i) + buffer[i] = static_cast<uint8_t>(generator.Rand(0, 0xff)); + + ReportBlock rb; + EXPECT_TRUE(rb.Parse(buffer, kBufferLength)); +} + +TEST(RtcpPacketReportBlockTest, ParseMatchCreate) { + ReportBlock rb; + rb.To(kRemoteSsrc); + rb.WithFractionLost(kFractionLost); + rb.WithCumulativeLost(kCumulativeLost); + rb.WithExtHighestSeqNum(kExtHighestSeqNum); + rb.WithJitter(kJitter); + rb.WithLastSr(kLastSr); + rb.WithDelayLastSr(kDelayLastSr); + + uint8_t buffer[kBufferLength]; + rb.Create(buffer); + + ReportBlock parsed; + EXPECT_TRUE(parsed.Parse(buffer, kBufferLength)); + + EXPECT_EQ(kRemoteSsrc, parsed.source_ssrc()); + EXPECT_EQ(kFractionLost, parsed.fraction_lost()); + EXPECT_EQ(kCumulativeLost, parsed.cumulative_lost()); + EXPECT_EQ(kExtHighestSeqNum, parsed.extended_high_seq_num()); + EXPECT_EQ(kJitter, parsed.jitter()); + EXPECT_EQ(kLastSr, parsed.last_sr()); + EXPECT_EQ(kDelayLastSr, parsed.delay_since_last_sr()); +} + +TEST(RtcpPacketReportBlockTest, ValidateCumulativeLost) { + const uint32_t kMaxCumulativeLost = 0xffffff; + ReportBlock rb; + EXPECT_FALSE(rb.WithCumulativeLost(kMaxCumulativeLost + 1)); + EXPECT_TRUE(rb.WithCumulativeLost(kMaxCumulativeLost)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.cc new file mode 100644 index 0000000000..db4ae67326 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.cc @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h" + +#include "webrtc/base/checks.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace rtcp { +// Receiver Reference Time Report Block (RFC 3611). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | BT=4 | reserved | block length = 2 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NTP timestamp, most significant word | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | NTP timestamp, least significant word | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +void Rrtr::Parse(const uint8_t* buffer) { + RTC_DCHECK(buffer[0] == kBlockType); + // reserved = buffer[1]; + RTC_DCHECK(ByteReader<uint16_t>::ReadBigEndian(&buffer[2]) == kBlockLength); + uint32_t seconds = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]); + uint32_t fraction = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]); + ntp_.Set(seconds, fraction); +} + +void Rrtr::Create(uint8_t* buffer) const { + const uint8_t kReserved = 0; + buffer[0] = kBlockType; + buffer[1] = kReserved; + ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], kBlockLength); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[4], ntp_.seconds()); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[8], ntp_.fractions()); +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h new file mode 100644 index 0000000000..3354f61df6 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RRTR_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RRTR_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/system_wrappers/include/ntp_time.h" + +namespace webrtc { +namespace rtcp { + +class Rrtr { + public: + static const uint8_t kBlockType = 4; + static const uint16_t kBlockLength = 2; + static const size_t kLength = 4 * (kBlockLength + 1); // 12 + + Rrtr() {} + Rrtr(const Rrtr&) = default; + ~Rrtr() {} + + Rrtr& operator=(const Rrtr&) = default; + + void Parse(const uint8_t* buffer); + + // Fills buffer with the Rrtr. + // Consumes Rrtr::kLength bytes. + void Create(uint8_t* buffer) const; + + void WithNtp(const NtpTime& ntp) { ntp_ = ntp; } + + NtpTime ntp() const { return ntp_; } + + private: + NtpTime ntp_; +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RRTR_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr_unittest.cc new file mode 100644 index 0000000000..6536e06186 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr_unittest.cc @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using webrtc::rtcp::Rrtr; + +namespace webrtc { +namespace { + +const uint32_t kNtpSec = 0x12345678; +const uint32_t kNtpFrac = 0x23456789; +const uint8_t kBlock[] = {0x04, 0x00, 0x00, 0x02, + 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89}; +const size_t kBlockSizeBytes = sizeof(kBlock); +static_assert( + kBlockSizeBytes == Rrtr::kLength, + "Size of manually created Rrtr block should match class constant"); + +TEST(RtcpPacketRrtrTest, Create) { + uint8_t buffer[Rrtr::kLength]; + Rrtr rrtr; + rrtr.WithNtp(NtpTime(kNtpSec, kNtpFrac)); + + rrtr.Create(buffer); + EXPECT_EQ(0, memcmp(buffer, kBlock, kBlockSizeBytes)); +} + +TEST(RtcpPacketRrtrTest, Parse) { + Rrtr read_rrtr; + read_rrtr.Parse(kBlock); + + // Run checks on const object to ensure all accessors have const modifier. + const Rrtr& parsed = read_rrtr; + + EXPECT_EQ(kNtpSec, parsed.ntp().seconds()); + EXPECT_EQ(kNtpFrac, parsed.ntp().fractions()); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.cc new file mode 100644 index 0000000000..b5571d45a3 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.cc @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" + +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace rtcp { + +// RFC 4585, Section 6.1: Feedback format. +// +// Common packet format: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT | PT | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : Feedback Control Information (FCI) : +// : : + +void Rtpfb::ParseCommonFeedback(const uint8_t* payload) { + sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&payload[0]); + media_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&payload[4]); +} + +void Rtpfb::CreateCommonFeedback(uint8_t* payload) const { + ByteWriter<uint32_t>::WriteBigEndian(&payload[0], sender_ssrc_); + ByteWriter<uint32_t>::WriteBigEndian(&payload[4], media_ssrc_); +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h new file mode 100644 index 0000000000..801aa085c4 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RTPFB_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RTPFB_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" + +namespace webrtc { +namespace rtcp { + +// RTPFB: Transport layer feedback message. +// RFC4585, Section 6.2 +class Rtpfb : public RtcpPacket { + public: + static const uint8_t kPacketType = 205; + + Rtpfb() : sender_ssrc_(0), media_ssrc_(0) {} + virtual ~Rtpfb() {} + + void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void To(uint32_t ssrc) { media_ssrc_ = ssrc; } + + uint32_t sender_ssrc() const { return sender_ssrc_; } + uint32_t media_ssrc() const { return media_ssrc_; } + + protected: + static const size_t kCommonFeedbackLength = 8; + void ParseCommonFeedback(const uint8_t* payload); + void CreateCommonFeedback(uint8_t* payload) const; + + private: + uint32_t sender_ssrc_; + uint32_t media_ssrc_; +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RTPFB_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.cc new file mode 100644 index 0000000000..829f3a9db9 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.cc @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h" + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::RtcpCommonHeader; + +namespace webrtc { +namespace rtcp { +// RFC 4585: Feedback format. +// +// Common packet format: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |V=2|P| FMT | PT | length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of packet sender | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC of media source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// : Feedback Control Information (FCI) : +// : : +// +// Slice loss indication (SLI) (RFC 4585). +// FCI: +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | First | Number | PictureID | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +Sli::Macroblocks::Macroblocks(uint8_t picture_id, + uint16_t first, + uint16_t number) { + RTC_DCHECK_LE(first, 0x1fff); + RTC_DCHECK_LE(number, 0x1fff); + RTC_DCHECK_LE(picture_id, 0x3f); + item_ = (first << 19) | (number << 6) | picture_id; +} + +void Sli::Macroblocks::Parse(const uint8_t* buffer) { + item_ = ByteReader<uint32_t>::ReadBigEndian(buffer); +} + +void Sli::Macroblocks::Create(uint8_t* buffer) const { + ByteWriter<uint32_t>::WriteBigEndian(buffer, item_); +} + +bool Sli::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { + RTC_DCHECK(header.packet_type == kPacketType); + RTC_DCHECK(header.count_or_format == kFeedbackMessageType); + + if (header.payload_size_bytes < + kCommonFeedbackLength + Macroblocks::kLength) { + LOG(LS_WARNING) << "Packet is too small to be a valid SLI packet"; + return false; + } + + size_t number_of_items = + (header.payload_size_bytes - kCommonFeedbackLength) / + Macroblocks::kLength; + + ParseCommonFeedback(payload); + items_.resize(number_of_items); + + const uint8_t* next_item = payload + kCommonFeedbackLength; + for (Macroblocks& item : items_) { + item.Parse(next_item); + next_item += Macroblocks::kLength; + } + + return true; +} + +bool Sli::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + RTC_DCHECK(!items_.empty()); + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + CreateHeader(kFeedbackMessageType, kPacketType, HeaderLength(), packet, + index); + CreateCommonFeedback(packet + *index); + *index += kCommonFeedbackLength; + for (const Macroblocks& item : items_) { + item.Create(packet + *index); + *index += Macroblocks::kLength; + } + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h new file mode 100644 index 0000000000..5d9e6c93e9 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SLI_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SLI_H_ + +#include <vector> + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +// Slice loss indication (SLI) (RFC 4585). +class Sli : public Psfb { + public: + static const uint8_t kFeedbackMessageType = 2; + class Macroblocks { + public: + static const size_t kLength = 4; + Macroblocks() : item_(0) {} + Macroblocks(uint8_t picture_id, uint16_t first, uint16_t number); + ~Macroblocks() {} + + void Parse(const uint8_t* buffer); + void Create(uint8_t* buffer) const; + + uint16_t first() const { return item_ >> 19; } + uint16_t number() const { return (item_ >> 6) & 0x1fff; } + uint8_t picture_id() const { return (item_ & 0x3f); } + + private: + uint32_t item_; + }; + + Sli() {} + virtual ~Sli() {} + + // Parse assumes header is already parsed and validated. + bool Parse(const RTCPUtility::RtcpCommonHeader& header, + const uint8_t* payload); // Size of the payload is in the header. + + void WithPictureId(uint8_t picture_id, + uint16_t first_macroblock = 0, + uint16_t number_macroblocks = 0x1fff) { + items_.push_back( + Macroblocks(picture_id, first_macroblock, number_macroblocks)); + } + + const std::vector<Macroblocks>& macroblocks() const { return items_; } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + size_t BlockLength() const override { + return RtcpPacket::kHeaderLength + Psfb::kCommonFeedbackLength + + items_.size() * Macroblocks::kLength; + } + + std::vector<Macroblocks> items_; + + RTC_DISALLOW_COPY_AND_ASSIGN(Sli); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SLI_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli_unittest.cc new file mode 100644 index 0000000000..c2be16846b --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli_unittest.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::ElementsAreArray; +using testing::make_tuple; +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::Sli; +using webrtc::RTCPUtility::RtcpCommonHeader; +using webrtc::RTCPUtility::RtcpParseCommonHeader; + +namespace webrtc { +namespace { + +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; + +const uint8_t kPictureId = 0x3f; +const uint16_t kFirstMb = 0x1e61; +const uint16_t kNumberOfMb = 0x1a0a; +const uint32_t kSliItem = (static_cast<uint32_t>(kFirstMb) << 19) | + (static_cast<uint32_t>(kNumberOfMb) << 6) | + static_cast<uint32_t>(kPictureId); + +// Manually created Sli packet matching constants above. +const uint8_t kPacket[] = {0x82, 206, 0x00, 0x03, + 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, + (kSliItem >> 24) & 0xff, + (kSliItem >> 16) & 0xff, + (kSliItem >> 8) & 0xff, + kSliItem & 0xff}; +const size_t kPacketLength = sizeof(kPacket); + +bool ParseSli(const uint8_t* buffer, size_t length, Sli* sli) { + RtcpCommonHeader header; + EXPECT_TRUE(RtcpParseCommonHeader(buffer, length, &header)); + EXPECT_EQ(length, header.BlockSize()); + return sli->Parse(header, buffer + RtcpCommonHeader::kHeaderSizeBytes); +} + +TEST(RtcpPacketSliTest, Create) { + Sli sli; + sli.From(kSenderSsrc); + sli.To(kRemoteSsrc); + sli.WithPictureId(kPictureId, kFirstMb, kNumberOfMb); + + rtc::scoped_ptr<RawPacket> packet(sli.Build()); + + EXPECT_THAT(make_tuple(packet->Buffer(), packet->Length()), + ElementsAreArray(kPacket)); +} + +TEST(RtcpPacketSliTest, Parse) { + Sli mutable_parsed; + EXPECT_TRUE(ParseSli(kPacket, kPacketLength, &mutable_parsed)); + const Sli& parsed = mutable_parsed; // Read values from constant object. + + EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); + EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); + EXPECT_EQ(1u, parsed.macroblocks().size()); + EXPECT_EQ(kFirstMb, parsed.macroblocks()[0].first()); + EXPECT_EQ(kNumberOfMb, parsed.macroblocks()[0].number()); + EXPECT_EQ(kPictureId, parsed.macroblocks()[0].picture_id()); +} + +TEST(RtcpPacketSliTest, ParseFailsOnTooSmallPacket) { + Sli sli; + sli.From(kSenderSsrc); + sli.To(kRemoteSsrc); + sli.WithPictureId(kPictureId, kFirstMb, kNumberOfMb); + + rtc::scoped_ptr<RawPacket> packet(sli.Build()); + packet->MutableBuffer()[3]--; // Decrease size by 1 word (4 bytes). + + EXPECT_FALSE(ParseSli(packet->Buffer(), packet->Length() - 4, &sli)); +} + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.cc new file mode 100644 index 0000000000..fd0219cf82 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.cc @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h" + +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::PT_RTPFB; +using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN; +using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem; + +namespace webrtc { +namespace rtcp { +namespace { +const uint32_t kUnusedMediaSourceSsrc0 = 0; +void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) { + buffer[(*offset)++] = value; +} +void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { + ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value); + *offset += 4; +} + +void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10, + uint8_t bits_mantissa, + uint32_t* mantissa, + uint8_t* exp) { + // input_base10 = mantissa * 2^exp + assert(bits_mantissa <= 32); + uint32_t mantissa_max = (1 << bits_mantissa) - 1; + uint8_t exponent = 0; + for (uint32_t i = 0; i < 64; ++i) { + if (input_base10 <= (mantissa_max << i)) { + exponent = i; + break; + } + } + *exp = exponent; + *mantissa = (input_base10 >> exponent); +} + +void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item, + uint8_t* buffer, + size_t* pos) { + uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000; + uint32_t mantissa = 0; + uint8_t exp = 0; + ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp); + + AssignUWord32(buffer, pos, tmmbr_item.SSRC); + AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03)); + AssignUWord8(buffer, pos, mantissa >> 7); + AssignUWord8(buffer, pos, (mantissa << 1) + + ((tmmbr_item.MeasuredOverhead >> 8) & 0x01)); + AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead); +} + +// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104). +// +// FCI: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn, + const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items, + uint8_t* buffer, + size_t* pos) { + AssignUWord32(buffer, pos, tmmbn.SenderSSRC); + AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); + for (uint8_t i = 0; i < tmmbn_items.size(); ++i) { + CreateTmmbrItem(tmmbn_items[i], buffer, pos); + } +} +} // namespace + +bool Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) { + assert(overhead <= 0x1ff); + if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) { + LOG(LS_WARNING) << "Max TMMBN size reached."; + return false; + } + RTCPPacketRTPFBTMMBRItem tmmbn_item; + tmmbn_item.SSRC = ssrc; + tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps; + tmmbn_item.MeasuredOverhead = overhead; + tmmbn_items_.push_back(tmmbn_item); + return true; +} + +bool Tmmbn::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + const uint8_t kFmt = 4; + CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index); + CreateTmmbn(tmmbn_, tmmbn_items_, packet, index); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h new file mode 100644 index 0000000000..82bf9dd9e9 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TMMBN_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TMMBN_H_ + +#include <vector> +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { + +// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104). +class Tmmbn : public RtcpPacket { + public: + Tmmbn() : RtcpPacket() { + memset(&tmmbn_, 0, sizeof(tmmbn_)); + } + + virtual ~Tmmbn() {} + + void From(uint32_t ssrc) { + tmmbn_.SenderSSRC = ssrc; + } + // Max 50 TMMBR can be added per TMMBN. + bool WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead); + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + static const int kMaxNumberOfTmmbrs = 50; + + size_t BlockLength() const { + const size_t kFciLen = 8; + return kCommonFbFmtLength + kFciLen * tmmbn_items_.size(); + } + + RTCPUtility::RTCPPacketRTPFBTMMBN tmmbn_; + std::vector<RTCPUtility::RTCPPacketRTPFBTMMBRItem> tmmbn_items_; + + RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbn); +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TMMBN_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn_unittest.cc new file mode 100644 index 0000000000..32d64a97b4 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn_unittest.cc @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h" + +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/test/rtcp_packet_parser.h" + +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::Tmmbn; +using webrtc::test::RtcpPacketParser; + +namespace webrtc { +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; + +TEST(RtcpPacketTest, TmmbnWithNoItem) { + Tmmbn tmmbn; + tmmbn.From(kSenderSsrc); + + rtc::scoped_ptr<RawPacket> packet(tmmbn.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.tmmbn()->num_packets()); + EXPECT_EQ(kSenderSsrc, parser.tmmbn()->Ssrc()); + EXPECT_EQ(0, parser.tmmbn_items()->num_packets()); +} + +TEST(RtcpPacketTest, TmmbnWithOneItem) { + Tmmbn tmmbn; + tmmbn.From(kSenderSsrc); + EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc, 312, 60)); + + rtc::scoped_ptr<RawPacket> packet(tmmbn.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.tmmbn()->num_packets()); + EXPECT_EQ(kSenderSsrc, parser.tmmbn()->Ssrc()); + EXPECT_EQ(1, parser.tmmbn_items()->num_packets()); + EXPECT_EQ(kRemoteSsrc, parser.tmmbn_items()->Ssrc(0)); + EXPECT_EQ(312U, parser.tmmbn_items()->BitrateKbps(0)); + EXPECT_EQ(60U, parser.tmmbn_items()->Overhead(0)); +} + +TEST(RtcpPacketTest, TmmbnWithTwoItems) { + Tmmbn tmmbn; + tmmbn.From(kSenderSsrc); + EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc, 312, 60)); + EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc + 1, 1288, 40)); + + rtc::scoped_ptr<RawPacket> packet(tmmbn.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.tmmbn()->num_packets()); + EXPECT_EQ(kSenderSsrc, parser.tmmbn()->Ssrc()); + EXPECT_EQ(2, parser.tmmbn_items()->num_packets()); + EXPECT_EQ(kRemoteSsrc, parser.tmmbn_items()->Ssrc(0)); + EXPECT_EQ(312U, parser.tmmbn_items()->BitrateKbps(0)); + EXPECT_EQ(60U, parser.tmmbn_items()->Overhead(0)); + EXPECT_EQ(kRemoteSsrc + 1, parser.tmmbn_items()->Ssrc(1)); + EXPECT_EQ(1288U, parser.tmmbn_items()->BitrateKbps(1)); + EXPECT_EQ(40U, parser.tmmbn_items()->Overhead(1)); +} + +TEST(RtcpPacketTest, TmmbnWithTooManyItems) { + Tmmbn tmmbn; + tmmbn.From(kSenderSsrc); + const int kMaxTmmbrItems = 50; + for (int i = 0; i < kMaxTmmbrItems; ++i) + EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc + i, 312, 60)); + + EXPECT_FALSE(tmmbn.WithTmmbr(kRemoteSsrc + kMaxTmmbrItems, 312, 60)); +} + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.cc new file mode 100644 index 0000000000..4df167de79 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.cc @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" + +#include "webrtc/base/logging.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +using webrtc::RTCPUtility::PT_RTPFB; +using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR; +using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem; + +namespace webrtc { +namespace rtcp { +namespace { +const uint32_t kUnusedMediaSourceSsrc0 = 0; + +void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) { + buffer[(*offset)++] = value; +} + +void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { + ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value); + *offset += 4; +} + +void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10, + uint8_t bits_mantissa, + uint32_t* mantissa, + uint8_t* exp) { + // input_base10 = mantissa * 2^exp + assert(bits_mantissa <= 32); + uint32_t mantissa_max = (1 << bits_mantissa) - 1; + uint8_t exponent = 0; + for (uint32_t i = 0; i < 64; ++i) { + if (input_base10 <= (mantissa_max << i)) { + exponent = i; + break; + } + } + *exp = exponent; + *mantissa = (input_base10 >> exponent); +} + +void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item, + uint8_t* buffer, + size_t* pos) { + uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000; + uint32_t mantissa = 0; + uint8_t exp = 0; + ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp); + + AssignUWord32(buffer, pos, tmmbr_item.SSRC); + AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03)); + AssignUWord8(buffer, pos, mantissa >> 7); + AssignUWord8(buffer, pos, (mantissa << 1) + + ((tmmbr_item.MeasuredOverhead >> 8) & 0x01)); + AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead); +} + +// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). +// +// FCI: +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | SSRC | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr, + const RTCPPacketRTPFBTMMBRItem& tmmbr_item, + uint8_t* buffer, + size_t* pos) { + AssignUWord32(buffer, pos, tmmbr.SenderSSRC); + AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); + CreateTmmbrItem(tmmbr_item, buffer, pos); +} +} // namespace + +bool Tmmbr::Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const { + while (*index + BlockLength() > max_length) { + if (!OnBufferFull(packet, index, callback)) + return false; + } + const uint8_t kFmt = 3; + CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index); + CreateTmmbr(tmmbr_, tmmbr_item_, packet, index); + return true; +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h new file mode 100644 index 0000000000..84a4180ad3 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TMMBR_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TMMBR_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" + +namespace webrtc { +namespace rtcp { +// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). +class Tmmbr : public RtcpPacket { + public: + Tmmbr() : RtcpPacket() { + memset(&tmmbr_, 0, sizeof(tmmbr_)); + memset(&tmmbr_item_, 0, sizeof(tmmbr_item_)); + } + + virtual ~Tmmbr() {} + + void From(uint32_t ssrc) { + tmmbr_.SenderSSRC = ssrc; + } + void To(uint32_t ssrc) { + tmmbr_item_.SSRC = ssrc; + } + void WithBitrateKbps(uint32_t bitrate_kbps) { + tmmbr_item_.MaxTotalMediaBitRate = bitrate_kbps; + } + void WithOverhead(uint16_t overhead) { + assert(overhead <= 0x1ff); + tmmbr_item_.MeasuredOverhead = overhead; + } + + protected: + bool Create(uint8_t* packet, + size_t* index, + size_t max_length, + RtcpPacket::PacketReadyCallback* callback) const override; + + private: + size_t BlockLength() const { + const size_t kFciLen = 8; + return kCommonFbFmtLength + kFciLen; + } + + RTCPUtility::RTCPPacketRTPFBTMMBR tmmbr_; + RTCPUtility::RTCPPacketRTPFBTMMBRItem tmmbr_item_; + + RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbr); +}; +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TMMBR_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr_unittest.cc new file mode 100644 index 0000000000..6d71caa251 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr_unittest.cc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" + +#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/test/rtcp_packet_parser.h" + +using webrtc::rtcp::RawPacket; +using webrtc::rtcp::Tmmbr; +using webrtc::test::RtcpPacketParser; + +namespace webrtc { +const uint32_t kSenderSsrc = 0x12345678; +const uint32_t kRemoteSsrc = 0x23456789; + +TEST(RtcpPacketTest, Tmmbr) { + Tmmbr tmmbr; + tmmbr.From(kSenderSsrc); + tmmbr.To(kRemoteSsrc); + tmmbr.WithBitrateKbps(312); + tmmbr.WithOverhead(60); + + rtc::scoped_ptr<RawPacket> packet(tmmbr.Build()); + RtcpPacketParser parser; + parser.Parse(packet->Buffer(), packet->Length()); + EXPECT_EQ(1, parser.tmmbr()->num_packets()); + EXPECT_EQ(kSenderSsrc, parser.tmmbr()->Ssrc()); + EXPECT_EQ(1, parser.tmmbr_item()->num_packets()); + EXPECT_EQ(312U, parser.tmmbr_item()->BitrateKbps()); + EXPECT_EQ(60U, parser.tmmbr_item()->Overhead()); +} + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h index 4cc1f38479..ad6fd166f2 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h @@ -15,7 +15,7 @@ #include <vector> #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" namespace webrtc { diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.cc new file mode 100644 index 0000000000..a79d48e1ca --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.cc @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h" + +#include "webrtc/base/checks.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" + +namespace webrtc { +namespace rtcp { +// VoIP Metrics Report Block (RFC 3611). +// +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 | BT=7 | reserved | block length = 8 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | SSRC of source | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | loss rate | discard rate | burst density | gap density | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 12 | burst duration | gap duration | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 16 | round trip delay | end system delay | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 20 | signal level | noise level | RERL | Gmin | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 24 | R factor | ext. R factor | MOS-LQ | MOS-CQ | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 28 | RX config | reserved | JB nominal | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 32 | JB maximum | JB abs max | +// 36 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +VoipMetric::VoipMetric() : ssrc_(0) { + memset(&voip_metric_, 0, sizeof(voip_metric_)); +} + +void VoipMetric::Parse(const uint8_t* buffer) { + RTC_DCHECK(buffer[0] == kBlockType); + // reserved = buffer[1]; + RTC_DCHECK(ByteReader<uint16_t>::ReadBigEndian(&buffer[2]) == kBlockLength); + ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[4]); + voip_metric_.lossRate = buffer[8]; + voip_metric_.discardRate = buffer[9]; + voip_metric_.burstDensity = buffer[10]; + voip_metric_.gapDensity = buffer[11]; + voip_metric_.burstDuration = ByteReader<uint16_t>::ReadBigEndian(&buffer[12]); + voip_metric_.gapDuration = ByteReader<uint16_t>::ReadBigEndian(&buffer[14]); + voip_metric_.roundTripDelay = + ByteReader<uint16_t>::ReadBigEndian(&buffer[16]); + voip_metric_.endSystemDelay = + ByteReader<uint16_t>::ReadBigEndian(&buffer[18]); + voip_metric_.signalLevel = buffer[20]; + voip_metric_.noiseLevel = buffer[21]; + voip_metric_.RERL = buffer[22]; + voip_metric_.Gmin = buffer[23]; + voip_metric_.Rfactor = buffer[24]; + voip_metric_.extRfactor = buffer[25]; + voip_metric_.MOSLQ = buffer[26]; + voip_metric_.MOSCQ = buffer[27]; + voip_metric_.RXconfig = buffer[28]; + // reserved = buffer[29]; + voip_metric_.JBnominal = ByteReader<uint16_t>::ReadBigEndian(&buffer[30]); + voip_metric_.JBmax = ByteReader<uint16_t>::ReadBigEndian(&buffer[32]); + voip_metric_.JBabsMax = ByteReader<uint16_t>::ReadBigEndian(&buffer[34]); +} + +void VoipMetric::Create(uint8_t* buffer) const { + const uint8_t kReserved = 0; + buffer[0] = kBlockType; + buffer[1] = kReserved; + ByteWriter<uint16_t>::WriteBigEndian(&buffer[2], kBlockLength); + ByteWriter<uint32_t>::WriteBigEndian(&buffer[4], ssrc_); + buffer[8] = voip_metric_.lossRate; + buffer[9] = voip_metric_.discardRate; + buffer[10] = voip_metric_.burstDensity; + buffer[11] = voip_metric_.gapDensity; + ByteWriter<uint16_t>::WriteBigEndian(&buffer[12], voip_metric_.burstDuration); + ByteWriter<uint16_t>::WriteBigEndian(&buffer[14], voip_metric_.gapDuration); + ByteWriter<uint16_t>::WriteBigEndian(&buffer[16], + voip_metric_.roundTripDelay); + ByteWriter<uint16_t>::WriteBigEndian(&buffer[18], + voip_metric_.endSystemDelay); + buffer[20] = voip_metric_.signalLevel; + buffer[21] = voip_metric_.noiseLevel; + buffer[22] = voip_metric_.RERL; + buffer[23] = voip_metric_.Gmin; + buffer[24] = voip_metric_.Rfactor; + buffer[25] = voip_metric_.extRfactor; + buffer[26] = voip_metric_.MOSLQ; + buffer[27] = voip_metric_.MOSCQ; + buffer[28] = voip_metric_.RXconfig; + buffer[29] = kReserved; + ByteWriter<uint16_t>::WriteBigEndian(&buffer[30], voip_metric_.JBnominal); + ByteWriter<uint16_t>::WriteBigEndian(&buffer[32], voip_metric_.JBmax); + ByteWriter<uint16_t>::WriteBigEndian(&buffer[34], voip_metric_.JBabsMax); +} + +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h new file mode 100644 index 0000000000..9e3e41995a --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_VOIP_METRIC_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_VOIP_METRIC_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { +namespace rtcp { + +class VoipMetric { + public: + static const uint8_t kBlockType = 7; + static const uint16_t kBlockLength = 8; + static const size_t kLength = 4 * (kBlockLength + 1); // 36 + VoipMetric(); + VoipMetric(const VoipMetric&) = default; + ~VoipMetric() {} + + VoipMetric& operator=(const VoipMetric&) = default; + + void Parse(const uint8_t* buffer); + + // Fills buffer with the VoipMetric. + // Consumes VoipMetric::kLength bytes. + void Create(uint8_t* buffer) const; + + void To(uint32_t ssrc) { ssrc_ = ssrc; } + void WithVoipMetric(const RTCPVoIPMetric& voip_metric) { + voip_metric_ = voip_metric; + } + + uint32_t ssrc() const { return ssrc_; } + const RTCPVoIPMetric& voip_metric() const { return voip_metric_; } + + private: + uint32_t ssrc_; + RTCPVoIPMetric voip_metric_; +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_VOIP_METRIC_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric_unittest.cc new file mode 100644 index 0000000000..44c82d67a9 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric_unittest.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 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. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace webrtc { +namespace rtcp { +namespace { + +const uint32_t kRemoteSsrc = 0x23456789; +const uint8_t kBlock[] = {0x07, 0x00, 0x00, 0x08, 0x23, 0x45, 0x67, 0x89, + 0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x22, 0x23, + 0x33, 0x34, 0x44, 0x45, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x55, 0x56, + 0x66, 0x67, 0x77, 0x78}; +const size_t kBlockSizeBytes = sizeof(kBlock); +static_assert( + kBlockSizeBytes == VoipMetric::kLength, + "Size of manually created Voip Metric block should match class constant"); + +TEST(RtcpPacketVoipMetricTest, Create) { + uint8_t buffer[VoipMetric::kLength]; + RTCPVoIPMetric metric; + metric.lossRate = 1; + metric.discardRate = 2; + metric.burstDensity = 3; + metric.gapDensity = 4; + metric.burstDuration = 0x1112; + metric.gapDuration = 0x2223; + metric.roundTripDelay = 0x3334; + metric.endSystemDelay = 0x4445; + metric.signalLevel = 5; + metric.noiseLevel = 6; + metric.RERL = 7; + metric.Gmin = 8; + metric.Rfactor = 9; + metric.extRfactor = 10; + metric.MOSLQ = 11; + metric.MOSCQ = 12; + metric.RXconfig = 13; + metric.JBnominal = 0x5556; + metric.JBmax = 0x6667; + metric.JBabsMax = 0x7778; + VoipMetric metric_block; + metric_block.To(kRemoteSsrc); + metric_block.WithVoipMetric(metric); + + metric_block.Create(buffer); + EXPECT_EQ(0, memcmp(buffer, kBlock, kBlockSizeBytes)); +} + +TEST(RtcpPacketVoipMetricTest, Parse) { + VoipMetric read_metric; + read_metric.Parse(kBlock); + + // Run checks on const object to ensure all accessors have const modifier. + const VoipMetric& parsed = read_metric; + + EXPECT_EQ(kRemoteSsrc, parsed.ssrc()); + EXPECT_EQ(1, parsed.voip_metric().lossRate); + EXPECT_EQ(2, parsed.voip_metric().discardRate); + EXPECT_EQ(3, parsed.voip_metric().burstDensity); + EXPECT_EQ(4, parsed.voip_metric().gapDensity); + EXPECT_EQ(0x1112, parsed.voip_metric().burstDuration); + EXPECT_EQ(0x2223, parsed.voip_metric().gapDuration); + EXPECT_EQ(0x3334, parsed.voip_metric().roundTripDelay); + EXPECT_EQ(0x4445, parsed.voip_metric().endSystemDelay); + EXPECT_EQ(5, parsed.voip_metric().signalLevel); + EXPECT_EQ(6, parsed.voip_metric().noiseLevel); + EXPECT_EQ(7, parsed.voip_metric().RERL); + EXPECT_EQ(8, parsed.voip_metric().Gmin); + EXPECT_EQ(9, parsed.voip_metric().Rfactor); + EXPECT_EQ(10, parsed.voip_metric().extRfactor); + EXPECT_EQ(11, parsed.voip_metric().MOSLQ); + EXPECT_EQ(12, parsed.voip_metric().MOSCQ); + EXPECT_EQ(13, parsed.voip_metric().RXconfig); + EXPECT_EQ(0x5556, parsed.voip_metric().JBnominal); + EXPECT_EQ(0x6667, parsed.voip_metric().JBmax); + EXPECT_EQ(0x7778, parsed.voip_metric().JBabsMax); +} + +} // namespace +} // namespace rtcp +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc index 77520b633b..22f61f5cab 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc @@ -14,6 +14,9 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" #include "webrtc/test/rtcp_packet_parser.h" using ::testing::ElementsAre; @@ -21,23 +24,15 @@ using ::testing::ElementsAre; using webrtc::rtcp::App; using webrtc::rtcp::Bye; using webrtc::rtcp::Dlrr; -using webrtc::rtcp::Empty; using webrtc::rtcp::Fir; -using webrtc::rtcp::Ij; -using webrtc::rtcp::Nack; -using webrtc::rtcp::Pli; -using webrtc::rtcp::Sdes; -using webrtc::rtcp::SenderReport; -using webrtc::rtcp::Sli; using webrtc::rtcp::RawPacket; using webrtc::rtcp::ReceiverReport; using webrtc::rtcp::Remb; using webrtc::rtcp::ReportBlock; using webrtc::rtcp::Rpsi; using webrtc::rtcp::Rrtr; +using webrtc::rtcp::Sdes; using webrtc::rtcp::SenderReport; -using webrtc::rtcp::Tmmbn; -using webrtc::rtcp::Tmmbr; using webrtc::rtcp::VoipMetric; using webrtc::rtcp::Xr; using webrtc::test::RtcpPacketParser; @@ -47,81 +42,6 @@ namespace webrtc { const uint32_t kSenderSsrc = 0x12345678; const uint32_t kRemoteSsrc = 0x23456789; -TEST(RtcpPacketTest, Rr) { - ReceiverReport rr; - rr.From(kSenderSsrc); - - rtc::scoped_ptr<RawPacket> packet(rr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc()); - EXPECT_EQ(0, parser.report_block()->num_packets()); -} - -TEST(RtcpPacketTest, RrWithOneReportBlock) { - ReportBlock rb; - rb.To(kRemoteSsrc); - rb.WithFractionLost(55); - rb.WithCumulativeLost(0x111111); - rb.WithExtHighestSeqNum(0x22222222); - rb.WithJitter(0x33333333); - rb.WithLastSr(0x44444444); - rb.WithDelayLastSr(0x55555555); - - ReceiverReport rr; - rr.From(kSenderSsrc); - EXPECT_TRUE(rr.WithReportBlock(rb)); - - rtc::scoped_ptr<RawPacket> packet(rr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc()); - EXPECT_EQ(1, parser.report_block()->num_packets()); - EXPECT_EQ(kRemoteSsrc, parser.report_block()->Ssrc()); - EXPECT_EQ(55U, parser.report_block()->FractionLost()); - EXPECT_EQ(0x111111U, parser.report_block()->CumPacketLost()); - EXPECT_EQ(0x22222222U, parser.report_block()->ExtHighestSeqNum()); - EXPECT_EQ(0x33333333U, parser.report_block()->Jitter()); - EXPECT_EQ(0x44444444U, parser.report_block()->LastSr()); - EXPECT_EQ(0x55555555U, parser.report_block()->DelayLastSr()); -} - -TEST(RtcpPacketTest, RrWithTwoReportBlocks) { - ReportBlock rb1; - rb1.To(kRemoteSsrc); - ReportBlock rb2; - rb2.To(kRemoteSsrc + 1); - - ReceiverReport rr; - rr.From(kSenderSsrc); - EXPECT_TRUE(rr.WithReportBlock(rb1)); - EXPECT_TRUE(rr.WithReportBlock(rb2)); - - rtc::scoped_ptr<RawPacket> packet(rr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc()); - EXPECT_EQ(2, parser.report_block()->num_packets()); - EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc)); - EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc + 1)); -} - -TEST(RtcpPacketTest, RrWithTooManyReportBlocks) { - ReceiverReport rr; - rr.From(kSenderSsrc); - const int kMaxReportBlocks = (1 << 5) - 1; - ReportBlock rb; - for (int i = 0; i < kMaxReportBlocks; ++i) { - rb.To(kRemoteSsrc + i); - EXPECT_TRUE(rr.WithReportBlock(rb)); - } - rb.To(kRemoteSsrc + kMaxReportBlocks); - EXPECT_FALSE(rr.WithReportBlock(rb)); -} - TEST(RtcpPacketTest, Sr) { SenderReport sr; sr.From(kSenderSsrc); @@ -196,50 +116,6 @@ TEST(RtcpPacketTest, SrWithTooManyReportBlocks) { EXPECT_FALSE(sr.WithReportBlock(rb)); } -TEST(RtcpPacketTest, IjNoItem) { - Ij ij; - - rtc::scoped_ptr<RawPacket> packet(ij.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.ij()->num_packets()); - EXPECT_EQ(0, parser.ij_item()->num_packets()); -} - -TEST(RtcpPacketTest, IjOneItem) { - Ij ij; - EXPECT_TRUE(ij.WithJitterItem(0x11111111)); - - rtc::scoped_ptr<RawPacket> packet(ij.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.ij()->num_packets()); - EXPECT_EQ(1, parser.ij_item()->num_packets()); - EXPECT_EQ(0x11111111U, parser.ij_item()->Jitter()); -} - -TEST(RtcpPacketTest, IjTwoItems) { - Ij ij; - EXPECT_TRUE(ij.WithJitterItem(0x11111111)); - EXPECT_TRUE(ij.WithJitterItem(0x22222222)); - - rtc::scoped_ptr<RawPacket> packet(ij.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.ij()->num_packets()); - EXPECT_EQ(2, parser.ij_item()->num_packets()); - EXPECT_EQ(0x22222222U, parser.ij_item()->Jitter()); -} - -TEST(RtcpPacketTest, IjTooManyItems) { - Ij ij; - const int kMaxIjItems = (1 << 5) - 1; - for (int i = 0; i < kMaxIjItems; ++i) { - EXPECT_TRUE(ij.WithJitterItem(i)); - } - EXPECT_FALSE(ij.WithJitterItem(kMaxIjItems)); -} - TEST(RtcpPacketTest, AppWithNoData) { App app; app.WithSubType(30); @@ -339,140 +215,6 @@ TEST(RtcpPacketTest, CnameItemWithEmptyString) { EXPECT_EQ("", parser.sdes_chunk()->Cname()); } -TEST(RtcpPacketTest, Pli) { - Pli pli; - pli.From(kSenderSsrc); - pli.To(kRemoteSsrc); - - rtc::scoped_ptr<RawPacket> packet(pli.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.pli()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.pli()->Ssrc()); - EXPECT_EQ(kRemoteSsrc, parser.pli()->MediaSsrc()); -} - -TEST(RtcpPacketTest, Sli) { - const uint16_t kFirstMb = 7777; - const uint16_t kNumberOfMb = 6666; - const uint8_t kPictureId = 60; - Sli sli; - sli.From(kSenderSsrc); - sli.To(kRemoteSsrc); - sli.WithFirstMb(kFirstMb); - sli.WithNumberOfMb(kNumberOfMb); - sli.WithPictureId(kPictureId); - - rtc::scoped_ptr<RawPacket> packet(sli.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.sli()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.sli()->Ssrc()); - EXPECT_EQ(kRemoteSsrc, parser.sli()->MediaSsrc()); - EXPECT_EQ(1, parser.sli_item()->num_packets()); - EXPECT_EQ(kFirstMb, parser.sli_item()->FirstMb()); - EXPECT_EQ(kNumberOfMb, parser.sli_item()->NumberOfMb()); - EXPECT_EQ(kPictureId, parser.sli_item()->PictureId()); -} - -TEST(RtcpPacketTest, Nack) { - Nack nack; - const uint16_t kList[] = {0, 1, 3, 8, 16}; - const uint16_t kListLength = sizeof(kList) / sizeof(kList[0]); - nack.From(kSenderSsrc); - nack.To(kRemoteSsrc); - nack.WithList(kList, kListLength); - rtc::scoped_ptr<RawPacket> packet(nack.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.nack()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.nack()->Ssrc()); - EXPECT_EQ(kRemoteSsrc, parser.nack()->MediaSsrc()); - EXPECT_EQ(1, parser.nack_item()->num_packets()); - std::vector<uint16_t> seqs = parser.nack_item()->last_nack_list(); - EXPECT_EQ(kListLength, seqs.size()); - for (size_t i = 0; i < kListLength; ++i) { - EXPECT_EQ(kList[i], seqs[i]); - } -} - -TEST(RtcpPacketTest, NackWithWrap) { - Nack nack; - const uint16_t kList[] = {65500, 65516, 65534, 65535, 0, 1, 3, 20, 100}; - const uint16_t kListLength = sizeof(kList) / sizeof(kList[0]); - nack.From(kSenderSsrc); - nack.To(kRemoteSsrc); - nack.WithList(kList, kListLength); - rtc::scoped_ptr<RawPacket> packet(nack.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.nack()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.nack()->Ssrc()); - EXPECT_EQ(kRemoteSsrc, parser.nack()->MediaSsrc()); - EXPECT_EQ(4, parser.nack_item()->num_packets()); - std::vector<uint16_t> seqs = parser.nack_item()->last_nack_list(); - EXPECT_EQ(kListLength, seqs.size()); - for (size_t i = 0; i < kListLength; ++i) { - EXPECT_EQ(kList[i], seqs[i]); - } -} - -TEST(RtcpPacketTest, NackFragmented) { - Nack nack; - const uint16_t kList[] = {1, 100, 200, 300, 400}; - const uint16_t kListLength = sizeof(kList) / sizeof(kList[0]); - nack.From(kSenderSsrc); - nack.To(kRemoteSsrc); - nack.WithList(kList, kListLength); - - class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { - public: - void OnPacketReady(uint8_t* data, size_t length) override { - ++packets_created_; - RtcpPacketParser parser; - parser.Parse(data, length); - EXPECT_EQ(1, parser.nack()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.nack()->Ssrc()); - EXPECT_EQ(kRemoteSsrc, parser.nack()->MediaSsrc()); - switch (packets_created_) { - case 1: - EXPECT_THAT(parser.nack_item()->last_nack_list(), - ElementsAre(1, 100, 200)); - break; - case 2: - EXPECT_THAT(parser.nack_item()->last_nack_list(), - ElementsAre(300, 400)); - break; - default: - ADD_FAILURE() << "Unexpected packet count: " << packets_created_; - } - } - int packets_created_ = 0; - } verifier; - const size_t kBufferSize = 12 + (3 * 4); // Fits common header + 3 nack items - uint8_t buffer[kBufferSize]; - EXPECT_TRUE(nack.BuildExternalBuffer(buffer, kBufferSize, &verifier)); - EXPECT_EQ(2, verifier.packets_created_); -} - -TEST(RtcpPacketTest, NackWithTooSmallBuffer) { - const uint16_t kList[] = {1}; - const size_t kMinNackBlockSize = 16; - Nack nack; - nack.From(kSenderSsrc); - nack.To(kRemoteSsrc); - nack.WithList(kList, 1); - class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { - public: - void OnPacketReady(uint8_t* data, size_t length) override { - ADD_FAILURE() << "Buffer should be too small."; - } - } verifier; - uint8_t buffer[kMinNackBlockSize - 1]; - EXPECT_FALSE( - nack.BuildExternalBuffer(buffer, kMinNackBlockSize - 1, &verifier)); -} - TEST(RtcpPacketTest, Rpsi) { Rpsi rpsi; // 1000001 (7 bits = 1 byte in native string). @@ -562,127 +304,6 @@ TEST(RtcpPacketTest, Fir) { EXPECT_EQ(123U, parser.fir_item()->SeqNum()); } -TEST(RtcpPacketTest, AppendPacket) { - Fir fir; - ReportBlock rb; - ReceiverReport rr; - rr.From(kSenderSsrc); - EXPECT_TRUE(rr.WithReportBlock(rb)); - rr.Append(&fir); - - rtc::scoped_ptr<RawPacket> packet(rr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc()); - EXPECT_EQ(1, parser.report_block()->num_packets()); - EXPECT_EQ(1, parser.fir()->num_packets()); -} - -TEST(RtcpPacketTest, AppendPacketOnEmpty) { - Empty empty; - ReceiverReport rr; - rr.From(kSenderSsrc); - empty.Append(&rr); - - rtc::scoped_ptr<RawPacket> packet(empty.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(0, parser.report_block()->num_packets()); -} - -TEST(RtcpPacketTest, AppendPacketWithOwnAppendedPacket) { - Fir fir; - Bye bye; - ReportBlock rb; - - ReceiverReport rr; - EXPECT_TRUE(rr.WithReportBlock(rb)); - rr.Append(&fir); - - SenderReport sr; - sr.Append(&bye); - sr.Append(&rr); - - rtc::scoped_ptr<RawPacket> packet(sr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.sender_report()->num_packets()); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(1, parser.report_block()->num_packets()); - EXPECT_EQ(1, parser.bye()->num_packets()); - EXPECT_EQ(1, parser.fir()->num_packets()); -} - -TEST(RtcpPacketTest, Bye) { - Bye bye; - bye.From(kSenderSsrc); - - rtc::scoped_ptr<RawPacket> packet(bye.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.bye()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.bye()->Ssrc()); -} - -TEST(RtcpPacketTest, ByeWithCsrcs) { - Fir fir; - Bye bye; - bye.From(kSenderSsrc); - EXPECT_TRUE(bye.WithCsrc(0x22222222)); - EXPECT_TRUE(bye.WithCsrc(0x33333333)); - bye.Append(&fir); - - rtc::scoped_ptr<RawPacket> packet(bye.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.bye()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.bye()->Ssrc()); - EXPECT_EQ(1, parser.fir()->num_packets()); -} - -TEST(RtcpPacketTest, ByeWithTooManyCsrcs) { - Bye bye; - bye.From(kSenderSsrc); - const int kMaxCsrcs = (1 << 5) - 2; // 5 bit len, first item is sender SSRC. - for (int i = 0; i < kMaxCsrcs; ++i) { - EXPECT_TRUE(bye.WithCsrc(i)); - } - EXPECT_FALSE(bye.WithCsrc(kMaxCsrcs)); -} - -TEST(RtcpPacketTest, BuildWithInputBuffer) { - Fir fir; - ReportBlock rb; - ReceiverReport rr; - rr.From(kSenderSsrc); - EXPECT_TRUE(rr.WithReportBlock(rb)); - rr.Append(&fir); - - const size_t kRrLength = 8; - const size_t kReportBlockLength = 24; - const size_t kFirLength = 20; - - class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { - public: - void OnPacketReady(uint8_t* data, size_t length) override { - RtcpPacketParser parser; - parser.Parse(data, length); - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(1, parser.report_block()->num_packets()); - EXPECT_EQ(1, parser.fir()->num_packets()); - ++packets_created_; - } - - int packets_created_ = 0; - } verifier; - const size_t kBufferSize = kRrLength + kReportBlockLength + kFirLength; - uint8_t buffer[kBufferSize]; - EXPECT_TRUE(rr.BuildExternalBuffer(buffer, kBufferSize, &verifier)); - EXPECT_EQ(1, verifier.packets_created_); -} - TEST(RtcpPacketTest, BuildWithTooSmallBuffer) { ReportBlock rb; ReceiverReport rr; @@ -703,47 +324,6 @@ TEST(RtcpPacketTest, BuildWithTooSmallBuffer) { EXPECT_FALSE(rr.BuildExternalBuffer(buffer, kBufferSize, &verifier)); } -TEST(RtcpPacketTest, BuildWithTooSmallBuffer_FragmentedSend) { - Fir fir; - ReportBlock rb; - ReceiverReport rr; - rr.From(kSenderSsrc); - EXPECT_TRUE(rr.WithReportBlock(rb)); - rr.Append(&fir); - - const size_t kRrLength = 8; - const size_t kReportBlockLength = 24; - - class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { - public: - void OnPacketReady(uint8_t* data, size_t length) override { - RtcpPacketParser parser; - parser.Parse(data, length); - switch (packets_created_++) { - case 0: - EXPECT_EQ(1, parser.receiver_report()->num_packets()); - EXPECT_EQ(1, parser.report_block()->num_packets()); - EXPECT_EQ(0, parser.fir()->num_packets()); - break; - case 1: - EXPECT_EQ(0, parser.receiver_report()->num_packets()); - EXPECT_EQ(0, parser.report_block()->num_packets()); - EXPECT_EQ(1, parser.fir()->num_packets()); - break; - default: - ADD_FAILURE() << "OnPacketReady not expected to be called " - << packets_created_ << " times."; - } - } - - int packets_created_ = 0; - } verifier; - const size_t kBufferSize = kRrLength + kReportBlockLength; - uint8_t buffer[kBufferSize]; - EXPECT_TRUE(rr.BuildExternalBuffer(buffer, kBufferSize, &verifier)); - EXPECT_EQ(2, verifier.packets_created_); -} - TEST(RtcpPacketTest, Remb) { Remb remb; remb.From(kSenderSsrc); @@ -765,81 +345,6 @@ TEST(RtcpPacketTest, Remb) { EXPECT_EQ(kRemoteSsrc + 2, ssrcs[2]); } -TEST(RtcpPacketTest, Tmmbr) { - Tmmbr tmmbr; - tmmbr.From(kSenderSsrc); - tmmbr.To(kRemoteSsrc); - tmmbr.WithBitrateKbps(312); - tmmbr.WithOverhead(60); - - rtc::scoped_ptr<RawPacket> packet(tmmbr.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.tmmbr()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.tmmbr()->Ssrc()); - EXPECT_EQ(1, parser.tmmbr_item()->num_packets()); - EXPECT_EQ(312U, parser.tmmbr_item()->BitrateKbps()); - EXPECT_EQ(60U, parser.tmmbr_item()->Overhead()); -} - -TEST(RtcpPacketTest, TmmbnWithNoItem) { - Tmmbn tmmbn; - tmmbn.From(kSenderSsrc); - - rtc::scoped_ptr<RawPacket> packet(tmmbn.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.tmmbn()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.tmmbn()->Ssrc()); - EXPECT_EQ(0, parser.tmmbn_items()->num_packets()); -} - -TEST(RtcpPacketTest, TmmbnWithOneItem) { - Tmmbn tmmbn; - tmmbn.From(kSenderSsrc); - EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc, 312, 60)); - - rtc::scoped_ptr<RawPacket> packet(tmmbn.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.tmmbn()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.tmmbn()->Ssrc()); - EXPECT_EQ(1, parser.tmmbn_items()->num_packets()); - EXPECT_EQ(kRemoteSsrc, parser.tmmbn_items()->Ssrc(0)); - EXPECT_EQ(312U, parser.tmmbn_items()->BitrateKbps(0)); - EXPECT_EQ(60U, parser.tmmbn_items()->Overhead(0)); -} - -TEST(RtcpPacketTest, TmmbnWithTwoItems) { - Tmmbn tmmbn; - tmmbn.From(kSenderSsrc); - EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc, 312, 60)); - EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc + 1, 1288, 40)); - - rtc::scoped_ptr<RawPacket> packet(tmmbn.Build()); - RtcpPacketParser parser; - parser.Parse(packet->Buffer(), packet->Length()); - EXPECT_EQ(1, parser.tmmbn()->num_packets()); - EXPECT_EQ(kSenderSsrc, parser.tmmbn()->Ssrc()); - EXPECT_EQ(2, parser.tmmbn_items()->num_packets()); - EXPECT_EQ(kRemoteSsrc, parser.tmmbn_items()->Ssrc(0)); - EXPECT_EQ(312U, parser.tmmbn_items()->BitrateKbps(0)); - EXPECT_EQ(60U, parser.tmmbn_items()->Overhead(0)); - EXPECT_EQ(kRemoteSsrc + 1, parser.tmmbn_items()->Ssrc(1)); - EXPECT_EQ(1288U, parser.tmmbn_items()->BitrateKbps(1)); - EXPECT_EQ(40U, parser.tmmbn_items()->Overhead(1)); -} - -TEST(RtcpPacketTest, TmmbnWithTooManyItems) { - Tmmbn tmmbn; - tmmbn.From(kSenderSsrc); - const int kMaxTmmbrItems = 50; - for (int i = 0; i < kMaxTmmbrItems; ++i) - EXPECT_TRUE(tmmbn.WithTmmbr(kRemoteSsrc + i, 312, 60)); - - EXPECT_FALSE(tmmbn.WithTmmbr(kRemoteSsrc + kMaxTmmbrItems, 312, 60)); -} - TEST(RtcpPacketTest, XrWithNoReportBlocks) { Xr xr; xr.From(kSenderSsrc); @@ -853,8 +358,7 @@ TEST(RtcpPacketTest, XrWithNoReportBlocks) { TEST(RtcpPacketTest, XrWithRrtr) { Rrtr rrtr; - rrtr.WithNtpSec(0x11111111); - rrtr.WithNtpFrac(0x22222222); + rrtr.WithNtp(NtpTime(0x11111111, 0x22222222)); Xr xr; xr.From(kSenderSsrc); EXPECT_TRUE(xr.WithRrtr(&rrtr)); @@ -871,11 +375,9 @@ TEST(RtcpPacketTest, XrWithRrtr) { TEST(RtcpPacketTest, XrWithTwoRrtrBlocks) { Rrtr rrtr1; - rrtr1.WithNtpSec(0x11111111); - rrtr1.WithNtpFrac(0x22222222); + rrtr1.WithNtp(NtpTime(0x11111111, 0x22222222)); Rrtr rrtr2; - rrtr2.WithNtpSec(0x33333333); - rrtr2.WithNtpFrac(0x44444444); + rrtr2.WithNtp(NtpTime(0x33333333, 0x44444444)); Xr xr; xr.From(kSenderSsrc); EXPECT_TRUE(xr.WithRrtr(&rrtr1)); @@ -967,32 +469,33 @@ TEST(RtcpPacketTest, XrWithTwoDlrrBlocks) { } TEST(RtcpPacketTest, XrWithVoipMetric) { - VoipMetric metric; - metric.To(kRemoteSsrc); - metric.LossRate(1); - metric.DiscardRate(2); - metric.BurstDensity(3); - metric.GapDensity(4); - metric.BurstDuration(0x1111); - metric.GapDuration(0x2222); - metric.RoundTripDelay(0x3333); - metric.EndSystemDelay(0x4444); - metric.SignalLevel(5); - metric.NoiseLevel(6); - metric.Rerl(7); - metric.Gmin(8); - metric.Rfactor(9); - metric.ExtRfactor(10); - metric.MosLq(11); - metric.MosCq(12); - metric.RxConfig(13); - metric.JbNominal(0x5555); - metric.JbMax(0x6666); - metric.JbAbsMax(0x7777); - + RTCPVoIPMetric metric; + metric.lossRate = 1; + metric.discardRate = 2; + metric.burstDensity = 3; + metric.gapDensity = 4; + metric.burstDuration = 0x1111; + metric.gapDuration = 0x2222; + metric.roundTripDelay = 0x3333; + metric.endSystemDelay = 0x4444; + metric.signalLevel = 5; + metric.noiseLevel = 6; + metric.RERL = 7; + metric.Gmin = 8; + metric.Rfactor = 9; + metric.extRfactor = 10; + metric.MOSLQ = 11; + metric.MOSCQ = 12; + metric.RXconfig = 13; + metric.JBnominal = 0x5555; + metric.JBmax = 0x6666; + metric.JBabsMax = 0x7777; + VoipMetric metric_block; + metric_block.To(kRemoteSsrc); + metric_block.WithVoipMetric(metric); Xr xr; xr.From(kSenderSsrc); - EXPECT_TRUE(xr.WithVoipMetric(&metric)); + EXPECT_TRUE(xr.WithVoipMetric(&metric_block)); rtc::scoped_ptr<RawPacket> packet(xr.Build()); RtcpPacketParser parser; diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc index b914838109..d65b04c8ab 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.cc @@ -23,8 +23,13 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h" namespace webrtc { -using namespace RTCPUtility; -using namespace RTCPHelp; +using RTCPHelp::RTCPPacketInformation; +using RTCPHelp::RTCPReceiveInformation; +using RTCPHelp::RTCPReportBlockInformation; +using RTCPUtility::kBtVoipMetric; +using RTCPUtility::RTCPCnameInformation; +using RTCPUtility::RTCPPacketReportBlockItem; +using RTCPUtility::RTCPPacketTypes; // The number of RTCP time intervals needed to trigger a timeout. const int kRrTimeoutIntervals = 3; @@ -741,7 +746,7 @@ bool RTCPReceiver::UpdateRTCPReceiveInformationTimers() { return updateBoundingSet; } -int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) { +int32_t RTCPReceiver::BoundingSet(bool* tmmbrOwner, TMMBRSet* boundingSetRec) { CriticalSectionScoped lock(_criticalSectionRTCPReceiver); std::map<uint32_t, RTCPReceiveInformation*>::iterator receiveInfoIt = @@ -761,7 +766,7 @@ int32_t RTCPReceiver::BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec) { i++) { if(receiveInfo->TmmbnBoundingSet.Ssrc(i) == main_ssrc_) { // owner of bounding set - tmmbrOwner = true; + *tmmbrOwner = true; } boundingSetRec->SetEntry(i, receiveInfo->TmmbnBoundingSet.Tmmbr(i), diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h index 272397675b..24861bd49e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h @@ -12,11 +12,11 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_ #include <map> -#include <vector> #include <set> +#include <vector> #include "webrtc/base/thread_annotations.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" @@ -103,7 +103,7 @@ public: bool UpdateRTCPReceiveInformationTimers(); - int32_t BoundingSet(bool &tmmbrOwner, TMMBRSet* boundingSetRec); + int32_t BoundingSet(bool* tmmbrOwner, TMMBRSet* boundingSetRec); int32_t UpdateTMMBR(); diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc index 718990d10b..a5c0e28282 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.cc @@ -17,7 +17,7 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" namespace webrtc { -using namespace RTCPHelp; +namespace RTCPHelp { RTCPPacketInformation::RTCPPacketInformation() : rtcpPacketTypeFlags(0), @@ -190,4 +190,5 @@ void RTCPReceiveInformation::VerifyAndAllocateBoundingSet( const uint32_t minimumSize) { TmmbnBoundingSet.VerifyAndAllocateSet(minimumSize); } +} // namespace RTCPHelp } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h index 37b7b88370..a792841962 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h @@ -11,10 +11,12 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ +#include <list> +#include <vector> #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" // RTCPReportBlock +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" // RTCPReportBlock #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" #include "webrtc/typedefs.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc index 1581845476..5d2fda347e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc @@ -15,17 +15,23 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -// Note: This file has no directory. Lint warning must be ignored. #include "webrtc/common_types.h" #include "webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h" #include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" namespace webrtc { @@ -384,20 +390,20 @@ TEST_F(RtcpReceiverTest, GetRtt) { } TEST_F(RtcpReceiverTest, InjectIjWithNoItem) { - rtcp::Ij ij; + rtcp::ExtendedJitterReport ij; rtc::scoped_ptr<rtcp::RawPacket> packet(ij.Build()); EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length())); EXPECT_EQ(0U, rtcp_packet_info_.rtcpPacketTypeFlags); } TEST_F(RtcpReceiverTest, InjectIjWithOneItem) { - rtcp::Ij ij; - ij.WithJitterItem(0x11111111); + rtcp::ExtendedJitterReport ij; + ij.WithJitter(0x11213141); rtc::scoped_ptr<rtcp::RawPacket> packet(ij.Build()); EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length())); EXPECT_EQ(kRtcpTransmissionTimeOffset, rtcp_packet_info_.rtcpPacketTypeFlags); - EXPECT_EQ(0x11111111U, rtcp_packet_info_.interArrivalJitter); + EXPECT_EQ(0x11213141U, rtcp_packet_info_.interArrivalJitter); } TEST_F(RtcpReceiverTest, InjectAppWithNoData) { @@ -586,7 +592,9 @@ TEST_F(RtcpReceiverTest, InjectXrVoipPacket) { const uint8_t kLossRate = 123; rtcp::VoipMetric voip_metric; voip_metric.To(kSourceSsrc); - voip_metric.LossRate(kLossRate); + RTCPVoIPMetric metric; + metric.lossRate = kLossRate; + voip_metric.WithVoipMetric(metric); rtcp::Xr xr; xr.From(0x2345); xr.WithVoipMetric(&voip_metric); @@ -615,8 +623,7 @@ TEST_F(RtcpReceiverTest, XrVoipPacketNotToUsIgnored) { TEST_F(RtcpReceiverTest, InjectXrReceiverReferenceTimePacket) { rtcp::Rrtr rrtr; - rrtr.WithNtpSec(0x10203); - rrtr.WithNtpFrac(0x40506); + rrtr.WithNtp(NtpTime(0x10203, 0x40506)); rtcp::Xr xr; xr.From(0x2345); xr.WithRrtr(&rrtr); @@ -751,13 +758,12 @@ TEST_F(RtcpReceiverTest, LastReceivedXrReferenceTimeInfoInitiallyFalse) { TEST_F(RtcpReceiverTest, GetLastReceivedXrReferenceTimeInfo) { const uint32_t kSenderSsrc = 0x123456; - const uint32_t kNtpSec = 0x10203; - const uint32_t kNtpFrac = 0x40506; - const uint32_t kNtpMid = RTCPUtility::MidNtp(kNtpSec, kNtpFrac); + const NtpTime kNtp(0x10203, 0x40506); + const uint32_t kNtpMid = + RTCPUtility::MidNtp(kNtp.seconds(), kNtp.fractions()); rtcp::Rrtr rrtr; - rrtr.WithNtpSec(kNtpSec); - rrtr.WithNtpFrac(kNtpFrac); + rrtr.WithNtp(kNtp); rtcp::Xr xr; xr.From(kSenderSsrc); xr.WithRrtr(&rrtr); diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc index 22b9477e05..848d73b2c4 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc @@ -11,17 +11,26 @@ #include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h" #include <assert.h> // assert -#include <stdlib.h> // rand #include <string.h> // memcpy #include <algorithm> // min #include <limits> // max +#include <utility> #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/trace_event.h" #include "webrtc/common_types.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" @@ -31,13 +40,11 @@ namespace webrtc { using RTCPUtility::RTCPCnameInformation; NACKStringBuilder::NACKStringBuilder() - : stream_(""), count_(0), prevNack_(0), consecutive_(false) { -} + : stream_(""), count_(0), prevNack_(0), consecutive_(false) {} NACKStringBuilder::~NACKStringBuilder() {} -void NACKStringBuilder::PushNACK(uint16_t nack) -{ +void NACKStringBuilder::PushNACK(uint16_t nack) { if (count_ == 0) { stream_ << nack; } else if (nack == prevNack_ + 1) { @@ -71,64 +78,63 @@ RTCPSender::FeedbackState::FeedbackState() last_rr_ntp_frac(0), remote_sr(0), has_last_xr_rr(false), - module(nullptr) { -} + module(nullptr) {} -struct RTCPSender::RtcpContext { - RtcpContext(const FeedbackState& feedback_state, - int32_t nack_size, - const uint16_t* nack_list, - bool repeat, - uint64_t picture_id, - uint8_t* buffer, - uint32_t buffer_size) - : feedback_state(feedback_state), - nack_size(nack_size), - nack_list(nack_list), - repeat(repeat), - picture_id(picture_id), - buffer(buffer), - buffer_size(buffer_size), - ntp_sec(0), - ntp_frac(0), - position(0) {} - - uint8_t* AllocateData(uint32_t bytes) { - RTC_DCHECK_LE(position + bytes, buffer_size); - uint8_t* ptr = &buffer[position]; - position += bytes; - return ptr; +class PacketContainer : public rtcp::CompoundPacket, + public rtcp::RtcpPacket::PacketReadyCallback { + public: + explicit PacketContainer(Transport* transport) + : transport_(transport), bytes_sent_(0) {} + virtual ~PacketContainer() { + for (RtcpPacket* packet : appended_packets_) + delete packet; } - const FeedbackState& feedback_state; - int32_t nack_size; - const uint16_t* nack_list; - bool repeat; - uint64_t picture_id; - uint8_t* buffer; - uint32_t buffer_size; - uint32_t ntp_sec; - uint32_t ntp_frac; - uint32_t position; -}; - -// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here. -class RTCPSender::PacketBuiltCallback - : public rtcp::RtcpPacket::PacketReadyCallback { - public: - PacketBuiltCallback(RtcpContext* context) : context_(context) {} - virtual ~PacketBuiltCallback() {} void OnPacketReady(uint8_t* data, size_t length) override { - context_->position += length; + if (transport_->SendRtcp(data, length)) + bytes_sent_ += length; } - bool BuildPacket(const rtcp::RtcpPacket& packet) { - return packet.BuildExternalBuffer( - &context_->buffer[context_->position], - context_->buffer_size - context_->position, this); + + size_t SendPackets() { + rtcp::CompoundPacket::Build(this); + return bytes_sent_; } private: - RtcpContext* const context_; + Transport* transport_; + size_t bytes_sent_; +}; + +class RTCPSender::RtcpContext { + public: + RtcpContext(const FeedbackState& feedback_state, + int32_t nack_size, + const uint16_t* nack_list, + bool repeat, + uint64_t picture_id, + uint32_t ntp_sec, + uint32_t ntp_frac, + PacketContainer* container) + : feedback_state_(feedback_state), + nack_size_(nack_size), + nack_list_(nack_list), + repeat_(repeat), + picture_id_(picture_id), + ntp_sec_(ntp_sec), + ntp_frac_(ntp_frac), + container_(container) {} + + virtual ~RtcpContext() {} + + const FeedbackState& feedback_state_; + const int32_t nack_size_; + const uint16_t* nack_list_; + const bool repeat_; + const uint64_t picture_id_; + const uint32_t ntp_sec_; + const uint32_t ntp_frac_; + + PacketContainer* const container_; }; RTCPSender::RTCPSender( @@ -139,6 +145,7 @@ RTCPSender::RTCPSender( Transport* outgoing_transport) : audio_(audio), clock_(clock), + random_(clock_->TimeInMicroseconds()), method_(RtcpMode::kOff), transport_(outgoing_transport), @@ -193,8 +200,7 @@ RTCPSender::RTCPSender( builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr; } -RTCPSender::~RTCPSender() { -} +RTCPSender::~RTCPSender() {} RtcpMode RTCPSender::Status() const { CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); @@ -340,63 +346,63 @@ int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) { } bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const { -/* - For audio we use a fix 5 sec interval + /* + For audio we use a fix 5 sec interval - For video we use 1 sec interval fo a BW smaller than 360 kbit/s, - technicaly we break the max 5% RTCP BW for video below 10 kbit/s but - that should be extremely rare + For video we use 1 sec interval fo a BW smaller than 360 kbit/s, + technicaly we break the max 5% RTCP BW for video below 10 kbit/s but + that should be extremely rare -From RFC 3550 + From RFC 3550 - MAX RTCP BW is 5% if the session BW - A send report is approximately 65 bytes inc CNAME - A receiver report is approximately 28 bytes + MAX RTCP BW is 5% if the session BW + A send report is approximately 65 bytes inc CNAME + A receiver report is approximately 28 bytes - The RECOMMENDED value for the reduced minimum in seconds is 360 - divided by the session bandwidth in kilobits/second. This minimum - is smaller than 5 seconds for bandwidths greater than 72 kb/s. + The RECOMMENDED value for the reduced minimum in seconds is 360 + divided by the session bandwidth in kilobits/second. This minimum + is smaller than 5 seconds for bandwidths greater than 72 kb/s. - If the participant has not yet sent an RTCP packet (the variable - initial is true), the constant Tmin is set to 2.5 seconds, else it - is set to 5 seconds. + If the participant has not yet sent an RTCP packet (the variable + initial is true), the constant Tmin is set to 2.5 seconds, else it + is set to 5 seconds. - The interval between RTCP packets is varied randomly over the - range [0.5,1.5] times the calculated interval to avoid unintended - synchronization of all participants + The interval between RTCP packets is varied randomly over the + range [0.5,1.5] times the calculated interval to avoid unintended + synchronization of all participants - if we send - If the participant is a sender (we_sent true), the constant C is - set to the average RTCP packet size (avg_rtcp_size) divided by 25% - of the RTCP bandwidth (rtcp_bw), and the constant n is set to the - number of senders. + if we send + If the participant is a sender (we_sent true), the constant C is + set to the average RTCP packet size (avg_rtcp_size) divided by 25% + of the RTCP bandwidth (rtcp_bw), and the constant n is set to the + number of senders. - if we receive only - If we_sent is not true, the constant C is set - to the average RTCP packet size divided by 75% of the RTCP - bandwidth. The constant n is set to the number of receivers - (members - senders). If the number of senders is greater than - 25%, senders and receivers are treated together. + if we receive only + If we_sent is not true, the constant C is set + to the average RTCP packet size divided by 75% of the RTCP + bandwidth. The constant n is set to the number of receivers + (members - senders). If the number of senders is greater than + 25%, senders and receivers are treated together. - reconsideration NOT required for peer-to-peer - "timer reconsideration" is - employed. This algorithm implements a simple back-off mechanism - which causes users to hold back RTCP packet transmission if the - group sizes are increasing. + reconsideration NOT required for peer-to-peer + "timer reconsideration" is + employed. This algorithm implements a simple back-off mechanism + which causes users to hold back RTCP packet transmission if the + group sizes are increasing. - n = number of members - C = avg_size/(rtcpBW/4) + n = number of members + C = avg_size/(rtcpBW/4) - 3. The deterministic calculated interval Td is set to max(Tmin, n*C). + 3. The deterministic calculated interval Td is set to max(Tmin, n*C). - 4. The calculated interval T is set to a number uniformly distributed - between 0.5 and 1.5 times the deterministic calculated interval. + 4. The calculated interval T is set to a number uniformly distributed + between 0.5 and 1.5 times the deterministic calculated interval. - 5. The resulting value of T is divided by e-3/2=1.21828 to compensate - for the fact that the timer reconsideration algorithm converges to - a value of the RTCP bandwidth below the intended average -*/ + 5. The resulting value of T is divided by e-3/2=1.21828 to compensate + for the fact that the timer reconsideration algorithm converges to + a value of the RTCP bandwidth below the intended average + */ int64_t now = clock_->TimeInMilliseconds(); @@ -451,32 +457,15 @@ bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp, return true; } -int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) { - if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) { - LOG(LS_WARNING) << "Too many report blocks."; - return -1; - } - rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC]; - block->To(report_block.remoteSSRC); - block->WithFractionLost(report_block.fractionLost); - block->WithCumulativeLost(report_block.cumulativeLost); - block->WithExtHighestSeqNum(report_block.extendedHighSeqNum); - block->WithJitter(report_block.jitter); - block->WithLastSr(report_block.lastSR); - block->WithDelayLastSr(report_block.delaySinceLastSR); - - return 0; -} - -RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) { +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) { for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) { // shift old last_send_report_[i + 1] = last_send_report_[i]; last_rtcp_time_[i + 1] = last_rtcp_time_[i]; } - last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac); - last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16); + last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_); + last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16); // The timestamp of this RTCP packet should be estimated as the timestamp of // the frame being captured at this moment. We are calculating that @@ -485,67 +474,52 @@ RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) { uint32_t rtp_timestamp = start_timestamp_ + last_rtp_timestamp_ + (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * - (ctx->feedback_state.frequency_hz / 1000); + (ctx.feedback_state_.frequency_hz / 1000); - rtcp::SenderReport report; - report.From(ssrc_); - report.WithNtpSec(ctx->ntp_sec); - report.WithNtpFrac(ctx->ntp_frac); - report.WithRtpTimestamp(rtp_timestamp); - report.WithPacketCount(ctx->feedback_state.packets_sent); - report.WithOctetCount(ctx->feedback_state.media_bytes_sent); + rtcp::SenderReport* report = new rtcp::SenderReport(); + report->From(ssrc_); + report->WithNtpSec(ctx.ntp_sec_); + report->WithNtpFrac(ctx.ntp_frac_); + report->WithRtpTimestamp(rtp_timestamp); + report->WithPacketCount(ctx.feedback_state_.packets_sent); + report->WithOctetCount(ctx.feedback_state_.media_bytes_sent); for (auto it : report_blocks_) - report.WithReportBlock(it.second); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(report)) - return BuildResult::kTruncated; + report->WithReportBlock(it.second); report_blocks_.clear(); - return BuildResult::kSuccess; + + return rtc::scoped_ptr<rtcp::SenderReport>(report); } -RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) { +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES( + const RtcpContext& ctx) { size_t length_cname = cname_.length(); RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE)); - rtcp::Sdes sdes; - sdes.WithCName(ssrc_, cname_); + rtcp::Sdes* sdes = new rtcp::Sdes(); + sdes->WithCName(ssrc_, cname_); for (const auto it : csrc_cnames_) - sdes.WithCName(it.first, it.second); + sdes->WithCName(it.first, it.second); - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(sdes)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Sdes>(sdes); } -RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) { - rtcp::ReceiverReport report; - report.From(ssrc_); +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) { + rtcp::ReceiverReport* report = new rtcp::ReceiverReport(); + report->From(ssrc_); for (auto it : report_blocks_) - report.WithReportBlock(it.second); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(report)) - return BuildResult::kTruncated; + report->WithReportBlock(it.second); report_blocks_.clear(); - - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::ReceiverReport>(report); } -RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) { - rtcp::Pli pli; - pli.From(ssrc_); - pli.To(remote_ssrc_); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(pli)) - return BuildResult::kTruncated; +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) { + rtcp::Pli* pli = new rtcp::Pli(); + pli->From(ssrc_); + pli->To(remote_ssrc_); TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCPSender::PLI"); @@ -553,21 +527,17 @@ RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) { TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount", ssrc_, packet_type_counter_.pli_packets); - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Pli>(pli); } -RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { - if (!ctx->repeat) +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) { + if (!ctx.repeat_) ++sequence_number_fir_; // Do not increase if repetition. - rtcp::Fir fir; - fir.From(ssrc_); - fir.To(remote_ssrc_); - fir.WithCommandSeqNum(sequence_number_fir_); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(fir)) - return BuildResult::kTruncated; + rtcp::Fir* fir = new rtcp::Fir(); + fir->From(ssrc_); + fir->To(remote_ssrc_); + fir->WithCommandSeqNum(sequence_number_fir_); TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCPSender::FIR"); @@ -575,7 +545,7 @@ RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount", ssrc_, packet_type_counter_.fir_packets); - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Fir>(fir); } /* @@ -585,20 +555,14 @@ RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { | First | Number | PictureID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) { - rtcp::Sli sli; - sli.From(ssrc_); - sli.To(remote_ssrc_); +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) { + rtcp::Sli* sli = new rtcp::Sli(); + sli->From(ssrc_); + sli->To(remote_ssrc_); // Crop picture id to 6 least significant bits. - sli.WithPictureId(ctx->picture_id & 0x3F); - sli.WithFirstMb(0); - sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now. - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(sli)) - return BuildResult::kTruncated; + sli->WithPictureId(ctx.picture_id_ & 0x3F); - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Sli>(sli); } /* @@ -613,38 +577,32 @@ RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) { /* * Note: not generic made for VP8 */ -RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) { - if (ctx->feedback_state.send_payload_type == 0xFF) - return BuildResult::kError; - - rtcp::Rpsi rpsi; - rpsi.From(ssrc_); - rpsi.To(remote_ssrc_); - rpsi.WithPayloadType(ctx->feedback_state.send_payload_type); - rpsi.WithPictureId(ctx->picture_id); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(rpsi)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI( + const RtcpContext& ctx) { + if (ctx.feedback_state_.send_payload_type == 0xFF) + return nullptr; + + rtcp::Rpsi* rpsi = new rtcp::Rpsi(); + rpsi->From(ssrc_); + rpsi->To(remote_ssrc_); + rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type); + rpsi->WithPictureId(ctx.picture_id_); + + return rtc::scoped_ptr<rtcp::Rpsi>(rpsi); } -RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) { - rtcp::Remb remb; - remb.From(ssrc_); +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB( + const RtcpContext& ctx) { + rtcp::Remb* remb = new rtcp::Remb(); + remb->From(ssrc_); for (uint32_t ssrc : remb_ssrcs_) - remb.AppliesTo(ssrc); - remb.WithBitrateBps(remb_bitrate_); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(remb)) - return BuildResult::kTruncated; + remb->AppliesTo(ssrc); + remb->WithBitrateBps(remb_bitrate_); TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCPSender::REMB"); - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Remb>(remb); } void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) { @@ -652,9 +610,10 @@ void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) { tmmbr_send_ = target_bitrate / 1000; } -RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { - if (ctx->feedback_state.module == NULL) - return BuildResult::kError; +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR( + const RtcpContext& ctx) { + if (ctx.feedback_state_.module == nullptr) + return nullptr; // Before sending the TMMBR check the received TMMBN, only an owner is // allowed to raise the bitrate: // * If the sender is an owner of the TMMBN -> send TMMBR @@ -669,14 +628,14 @@ RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but // since RTCPreceiver is not doing the reverse we should be fine int32_t lengthOfBoundingSet = - ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet); + ctx.feedback_state_.module->BoundingSet(&tmmbrOwner, candidateSet); if (lengthOfBoundingSet > 0) { for (int32_t i = 0; i < lengthOfBoundingSet; i++) { if (candidateSet->Tmmbr(i) == tmmbr_send_ && candidateSet->PacketOH(i) == packet_oh_send_) { - // do not send the same tuple - return BuildResult::kAborted; + // Do not send the same tuple. + return nullptr; } } if (!tmmbrOwner) { @@ -687,124 +646,69 @@ RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { int numCandidates = lengthOfBoundingSet + 1; // find bounding set - TMMBRSet* boundingSet = NULL; + TMMBRSet* boundingSet = nullptr; int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet); if (numBoundingSet > 0 || numBoundingSet <= numCandidates) tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet); if (!tmmbrOwner) { - // did not enter bounding set, no meaning to send this request - return BuildResult::kAborted; + // Did not enter bounding set, no meaning to send this request. + return nullptr; } } } - if (tmmbr_send_) { - rtcp::Tmmbr tmmbr; - tmmbr.From(ssrc_); - tmmbr.To(remote_ssrc_); - tmmbr.WithBitrateKbps(tmmbr_send_); - tmmbr.WithOverhead(packet_oh_send_); + if (!tmmbr_send_) + return nullptr; - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(tmmbr)) - return BuildResult::kTruncated; - } - return BuildResult::kSuccess; + rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr(); + tmmbr->From(ssrc_); + tmmbr->To(remote_ssrc_); + tmmbr->WithBitrateKbps(tmmbr_send_); + tmmbr->WithOverhead(packet_oh_send_); + + return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr); } -RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) { +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN( + const RtcpContext& ctx) { TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend(); - if (boundingSet == NULL) - return BuildResult::kError; + if (boundingSet == nullptr) + return nullptr; - rtcp::Tmmbn tmmbn; - tmmbn.From(ssrc_); + rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn(); + tmmbn->From(ssrc_); for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) { if (boundingSet->Tmmbr(i) > 0) { - tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i), - boundingSet->PacketOH(i)); + tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i), + boundingSet->PacketOH(i)); } } - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(tmmbn)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn); } -RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) { - rtcp::App app; - app.From(ssrc_); - app.WithSubType(app_sub_type_); - app.WithName(app_name_); - app.WithData(app_data_.get(), app_length_); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(app)) - return BuildResult::kTruncated; +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) { + rtcp::App* app = new rtcp::App(); + app->From(ssrc_); + app->WithSubType(app_sub_type_); + app->WithName(app_name_); + app->WithData(app_data_.get(), app_length_); - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::App>(app); } -RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) { - // sanity - if (ctx->position + 16 >= IP_PACKET_SIZE) { - LOG(LS_WARNING) << "Failed to build NACK."; - return BuildResult::kTruncated; - } - - // int size, uint16_t* nack_list - // add nack list - uint8_t FMT = 1; - *ctx->AllocateData(1) = 0x80 + FMT; - *ctx->AllocateData(1) = 205; - - *ctx->AllocateData(1) = 0; - int nack_size_pos_ = ctx->position; - *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default - - // Add our own SSRC - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_); - - // Add the remote SSRC - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_); - - // Build NACK bitmasks and write them to the RTCP message. - // The nack list should be sorted and not contain duplicates if one - // wants to build the smallest rtcp nack packet. - int numOfNackFields = 0; - int maxNackFields = - std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4); - int i = 0; - while (i < ctx->nack_size && numOfNackFields < maxNackFields) { - uint16_t nack = ctx->nack_list[i++]; - uint16_t bitmask = 0; - while (i < ctx->nack_size) { - int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1; - if (shift >= 0 && shift <= 15) { - bitmask |= (1 << shift); - ++i; - } else { - break; - } - } - // Write the sequence number and the bitmask to the packet. - assert(ctx->position + 4 < IP_PACKET_SIZE); - ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack); - ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask); - numOfNackFields++; - } - ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields); - - if (i != ctx->nack_size) - LOG(LS_WARNING) << "Nack list too large for one packet."; +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK( + const RtcpContext& ctx) { + rtcp::Nack* nack = new rtcp::Nack(); + nack->From(ssrc_); + nack->To(remote_ssrc_); + nack->WithList(ctx.nack_list_, ctx.nack_size_); // Report stats. NACKStringBuilder stringBuilder; - for (int idx = 0; idx < i; ++idx) { - stringBuilder.PushNACK(ctx->nack_list[idx]); - nack_stats_.ReportRequest(ctx->nack_list[idx]); + for (int idx = 0; idx < ctx.nack_size_; ++idx) { + stringBuilder.PushNACK(ctx.nack_list_[idx]); + nack_stats_.ReportRequest(ctx.nack_list_[idx]); } packet_type_counter_.nack_requests = nack_stats_.requests(); packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests(); @@ -816,101 +720,66 @@ RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) { TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount", ssrc_, packet_type_counter_.nack_packets); - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Nack>(nack); } -RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) { - rtcp::Bye bye; - bye.From(ssrc_); +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) { + rtcp::Bye* bye = new rtcp::Bye(); + bye->From(ssrc_); for (uint32_t csrc : csrcs_) - bye.WithCsrc(csrc); + bye->WithCsrc(csrc); - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(bye)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Bye>(bye); } -RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime( - RtcpContext* ctx) { - +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime( + const RtcpContext& ctx) { if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) last_xr_rr_.erase(last_xr_rr_.begin()); last_xr_rr_.insert(std::pair<uint32_t, int64_t>( - RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac), - Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac))); + RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_), + Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_))); - rtcp::Xr xr; - xr.From(ssrc_); + rtcp::Xr* xr = new rtcp::Xr(); + xr->From(ssrc_); rtcp::Rrtr rrtr; - rrtr.WithNtpSec(ctx->ntp_sec); - rrtr.WithNtpFrac(ctx->ntp_frac); + rrtr.WithNtp(NtpTime(ctx.ntp_sec_, ctx.ntp_frac_)); - xr.WithRrtr(&rrtr); + xr->WithRrtr(&rrtr); // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP? - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(xr)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Xr>(xr); } -RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) { - rtcp::Xr xr; - xr.From(ssrc_); +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr( + const RtcpContext& ctx) { + rtcp::Xr* xr = new rtcp::Xr(); + xr->From(ssrc_); rtcp::Dlrr dlrr; - const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr; + const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr; dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR); - xr.WithDlrr(&dlrr); + xr->WithDlrr(&dlrr); - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(xr)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; + return rtc::scoped_ptr<rtcp::Xr>(xr); } // TODO(sprang): Add a unit test for this, or remove if the code isn't used. -RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) { - rtcp::Xr xr; - xr.From(ssrc_); +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric( + const RtcpContext& context) { + rtcp::Xr* xr = new rtcp::Xr(); + xr->From(ssrc_); rtcp::VoipMetric voip; voip.To(remote_ssrc_); - voip.LossRate(xr_voip_metric_.lossRate); - voip.DiscardRate(xr_voip_metric_.discardRate); - voip.BurstDensity(xr_voip_metric_.burstDensity); - voip.GapDensity(xr_voip_metric_.gapDensity); - voip.BurstDuration(xr_voip_metric_.burstDuration); - voip.GapDuration(xr_voip_metric_.gapDuration); - voip.RoundTripDelay(xr_voip_metric_.roundTripDelay); - voip.EndSystemDelay(xr_voip_metric_.endSystemDelay); - voip.SignalLevel(xr_voip_metric_.signalLevel); - voip.NoiseLevel(xr_voip_metric_.noiseLevel); - voip.Rerl(xr_voip_metric_.RERL); - voip.Gmin(xr_voip_metric_.Gmin); - voip.Rfactor(xr_voip_metric_.Rfactor); - voip.ExtRfactor(xr_voip_metric_.extRfactor); - voip.MosLq(xr_voip_metric_.MOSLQ); - voip.MosCq(xr_voip_metric_.MOSCQ); - voip.RxConfig(xr_voip_metric_.RXconfig); - voip.JbNominal(xr_voip_metric_.JBnominal); - voip.JbMax(xr_voip_metric_.JBmax); - voip.JbAbsMax(xr_voip_metric_.JBabsMax); - - xr.WithVoipMetric(&voip); - - PacketBuiltCallback callback(ctx); - if (!callback.BuildPacket(xr)) - return BuildResult::kTruncated; - - return BuildResult::kSuccess; + voip.WithVoipMetric(xr_voip_metric_); + + xr->WithVoipMetric(&voip); + + return rtc::scoped_ptr<rtcp::Xr>(xr); } int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state, @@ -926,43 +795,59 @@ int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state, int32_t RTCPSender::SendCompoundRTCP( const FeedbackState& feedback_state, - const std::set<RTCPPacketType>& packetTypes, + const std::set<RTCPPacketType>& packet_types, int32_t nack_size, const uint16_t* nack_list, bool repeat, uint64_t pictureID) { + PacketContainer container(transport_); { CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); if (method_ == RtcpMode::kOff) { LOG(LS_WARNING) << "Can't send rtcp if it is disabled."; return -1; } - } - uint8_t rtcp_buffer[IP_PACKET_SIZE]; - int rtcp_length = - PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat, - pictureID, rtcp_buffer, IP_PACKET_SIZE); - // Sanity don't send empty packets. - if (rtcp_length <= 0) - return -1; + // We need to send our NTP even if we haven't received any reports. + uint32_t ntp_sec; + uint32_t ntp_frac; + clock_->CurrentNtp(ntp_sec, ntp_frac); + RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID, + ntp_sec, ntp_frac, &container); + + PrepareReport(packet_types, feedback_state); + + auto it = report_flags_.begin(); + while (it != report_flags_.end()) { + auto builder_it = builders_.find(it->type); + RTC_DCHECK(builder_it != builders_.end()); + if (it->is_volatile) { + report_flags_.erase(it++); + } else { + ++it; + } - return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length)); -} + BuilderFunc func = builder_it->second; + rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context); + if (packet.get() == nullptr) + return -1; + container.Append(packet.release()); + } -int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, - const std::set<RTCPPacketType>& packetTypes, - int32_t nack_size, - const uint16_t* nack_list, - bool repeat, - uint64_t pictureID, - uint8_t* rtcp_buffer, - int buffer_size) { - CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); + if (packet_type_counter_observer_ != nullptr) { + packet_type_counter_observer_->RtcpPacketTypesCounterUpdated( + remote_ssrc_, packet_type_counter_); + } - RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID, - rtcp_buffer, buffer_size); + RTC_DCHECK(AllVolatileFlagsConsumed()); + } + + size_t bytes_sent = container.SendPackets(); + return bytes_sent == 0 ? -1 : 0; +} +void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes, + const FeedbackState& feedback_state) { // Add all flags as volatile. Non volatile entries will not be overwritten // and all new volatile flags added will be consumed by the end of this call. SetFlags(packetTypes, true); @@ -986,9 +871,6 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty())) SetFlag(kRtcpSdes, true); - // We need to send our NTP even if we haven't received any reports. - clock_->CurrentNtp(context.ntp_sec, context.ntp_frac); - if (generate_report) { if (!sending_ && xr_send_receiver_reference_time_enabled_) SetFlag(kRtcpXrReceiverReferenceTime, true); @@ -996,15 +878,9 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, SetFlag(kRtcpXrDlrrReportBlock, true); // generate next time to send an RTCP report - // seeded from RTP constructor - int32_t random = rand() % 1000; - int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS; - - if (audio_) { - timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) + - (RTCP_INTERVAL_AUDIO_MS * random / 1000); - } else { - uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS; + uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS; + + if (!audio_) { if (sending_) { // Calculate bandwidth for video; 360 / send bandwidth in kbit/s. uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000; @@ -1013,74 +889,46 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, } if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS) minIntervalMs = RTCP_INTERVAL_VIDEO_MS; - timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000); } + // The interval between RTCP packets is varied randomly over the + // range [1/2,3/2] times the calculated interval. + uint32_t timeToNext = + random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2); next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext; StatisticianMap statisticians = receive_statistics_->GetActiveStatisticians(); - if (!statisticians.empty()) { - for (auto it = statisticians.begin(); it != statisticians.end(); ++it) { - RTCPReportBlock report_block; - if (PrepareReport(feedback_state, it->first, it->second, - &report_block)) { - AddReportBlock(report_block); - } - } - } - } - - auto it = report_flags_.begin(); - while (it != report_flags_.end()) { - auto builder = builders_.find(it->type); - RTC_DCHECK(builder != builders_.end()); - if (it->is_volatile) { - report_flags_.erase(it++); - } else { - ++it; - } - - uint32_t start_position = context.position; - BuildResult result = (this->*(builder->second))(&context); - switch (result) { - case BuildResult::kError: - return -1; - case BuildResult::kTruncated: - return context.position; - case BuildResult::kAborted: - context.position = start_position; - FALLTHROUGH(); - case BuildResult::kSuccess: - continue; - default: - abort(); + RTC_DCHECK(report_blocks_.empty()); + for (auto& it : statisticians) { + AddReportBlock(feedback_state, it.first, it.second); } } - - if (packet_type_counter_observer_ != NULL) { - packet_type_counter_observer_->RtcpPacketTypesCounterUpdated( - remote_ssrc_, packet_type_counter_); - } - - RTC_DCHECK(AllVolatileFlagsConsumed()); - - return context.position; } -bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, - uint32_t ssrc, - StreamStatistician* statistician, - RTCPReportBlock* report_block) { +bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state, + uint32_t ssrc, + StreamStatistician* statistician) { // Do we have receive statistics to send? RtcpStatistics stats; if (!statistician->GetStatistics(&stats, true)) return false; - report_block->fractionLost = stats.fraction_lost; - report_block->cumulativeLost = stats.cumulative_lost; - report_block->extendedHighSeqNum = - stats.extended_max_sequence_number; - report_block->jitter = stats.jitter; - report_block->remoteSSRC = ssrc; + + if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) { + LOG(LS_WARNING) << "Too many report blocks."; + return false; + } + RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end()); + rtcp::ReportBlock* block = &report_blocks_[ssrc]; + block->To(ssrc); + block->WithFractionLost(stats.fraction_lost); + if (!block->WithCumulativeLost(stats.cumulative_lost)) { + report_blocks_.erase(ssrc); + LOG(LS_WARNING) << "Cumulative lost is oversized."; + return false; + } + block->WithExtHighestSeqNum(stats.extended_max_sequence_number); + block->WithJitter(stats.jitter); + block->WithLastSr(feedback_state.remote_sr); // TODO(sprang): Do we really need separate time stamps for each report? // Get our NTP as late as possible to avoid a race. @@ -1089,7 +937,6 @@ bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, clock_->CurrentNtp(ntp_secs, ntp_frac); // Delay since last received report. - uint32_t delaySinceLastReceivedSR = 0; if ((feedback_state.last_rr_ntp_secs != 0) || (feedback_state.last_rr_ntp_frac != 0)) { // Get the 16 lowest bits of seconds and the 16 highest bits of fractions. @@ -1101,19 +948,11 @@ bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, receiveTime <<= 16; receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16; - delaySinceLastReceivedSR = now-receiveTime; + block->WithDelayLastSr(now - receiveTime); } - report_block->delaySinceLastSR = delaySinceLastReceivedSR; - report_block->lastSR = feedback_state.remote_sr; return true; } -int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) { - if (transport_->SendRtcp(dataBuffer, length)) - return 0; - return -1; -} - void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) { assert(csrcs.size() <= kRtpCsrcSize); CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); @@ -1203,7 +1042,7 @@ bool RTCPSender::AllVolatileFlagsConsumed() const { bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) { class Sender : public rtcp::RtcpPacket::PacketReadyCallback { public: - Sender(Transport* transport) + explicit Sender(Transport* transport) : transport_(transport), send_failure_(false) {} void OnPacketReady(uint8_t* data, size_t length) override { diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h index 9ec928363b..dd3aec4c9f 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h @@ -15,13 +15,15 @@ #include <set> #include <sstream> #include <string> +#include <vector> +#include "webrtc/base/random.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" @@ -50,277 +52,251 @@ class NACKStringBuilder { }; class RTCPSender { -public: - struct FeedbackState { - FeedbackState(); + public: + struct FeedbackState { + FeedbackState(); + + uint8_t send_payload_type; + uint32_t frequency_hz; + uint32_t packets_sent; + size_t media_bytes_sent; + uint32_t send_bitrate; + + uint32_t last_rr_ntp_secs; + uint32_t last_rr_ntp_frac; + uint32_t remote_sr; + + bool has_last_xr_rr; + RtcpReceiveTimeInfo last_xr_rr; + + // Used when generating TMMBR. + ModuleRtpRtcpImpl* module; + }; + + RTCPSender(bool audio, + Clock* clock, + ReceiveStatistics* receive_statistics, + RtcpPacketTypeCounterObserver* packet_type_counter_observer, + Transport* outgoing_transport); + virtual ~RTCPSender(); + + RtcpMode Status() const; + void SetRTCPStatus(RtcpMode method); + + bool Sending() const; + int32_t SetSendingStatus(const FeedbackState& feedback_state, + bool enabled); // combine the functions + + int32_t SetNackStatus(bool enable); - uint8_t send_payload_type; - uint32_t frequency_hz; - uint32_t packets_sent; - size_t media_bytes_sent; - uint32_t send_bitrate; + void SetStartTimestamp(uint32_t start_timestamp); - uint32_t last_rr_ntp_secs; - uint32_t last_rr_ntp_frac; - uint32_t remote_sr; + void SetLastRtpTime(uint32_t rtp_timestamp, int64_t capture_time_ms); - bool has_last_xr_rr; - RtcpReceiveTimeInfo last_xr_rr; + void SetSSRC(uint32_t ssrc); - // Used when generating TMMBR. - ModuleRtpRtcpImpl* module; - }; + void SetRemoteSSRC(uint32_t ssrc); - RTCPSender(bool audio, - Clock* clock, - ReceiveStatistics* receive_statistics, - RtcpPacketTypeCounterObserver* packet_type_counter_observer, - Transport* outgoing_transport); - virtual ~RTCPSender(); + int32_t SetCNAME(const char* cName); - RtcpMode Status() const; - void SetRTCPStatus(RtcpMode method); + int32_t AddMixedCNAME(uint32_t SSRC, const char* c_name); - bool Sending() const; - int32_t SetSendingStatus(const FeedbackState& feedback_state, - bool enabled); // combine the functions + int32_t RemoveMixedCNAME(uint32_t SSRC); - int32_t SetNackStatus(bool enable); + int64_t SendTimeOfSendReport(uint32_t sendReport); - void SetStartTimestamp(uint32_t start_timestamp); + bool SendTimeOfXrRrReport(uint32_t mid_ntp, int64_t* time_ms) const; - void SetLastRtpTime(uint32_t rtp_timestamp, int64_t capture_time_ms); + bool TimeToSendRTCPReport(bool sendKeyframeBeforeRTP = false) const; - void SetSSRC(uint32_t ssrc); + int32_t SendRTCP(const FeedbackState& feedback_state, + RTCPPacketType packetType, + int32_t nackSize = 0, + const uint16_t* nackList = 0, + bool repeat = false, + uint64_t pictureID = 0); - void SetRemoteSSRC(uint32_t ssrc); + int32_t SendCompoundRTCP(const FeedbackState& feedback_state, + const std::set<RTCPPacketType>& packetTypes, + int32_t nackSize = 0, + const uint16_t* nackList = 0, + bool repeat = false, + uint64_t pictureID = 0); - int32_t SetCNAME(const char* cName); + bool REMB() const; - int32_t AddMixedCNAME(uint32_t SSRC, const char* c_name); + void SetREMBStatus(bool enable); - int32_t RemoveMixedCNAME(uint32_t SSRC); + void SetREMBData(uint32_t bitrate, const std::vector<uint32_t>& ssrcs); - int64_t SendTimeOfSendReport(uint32_t sendReport); + bool TMMBR() const; - bool SendTimeOfXrRrReport(uint32_t mid_ntp, int64_t* time_ms) const; + void SetTMMBRStatus(bool enable); - bool TimeToSendRTCPReport(bool sendKeyframeBeforeRTP = false) const; + int32_t SetTMMBN(const TMMBRSet* boundingSet, uint32_t maxBitrateKbit); - int32_t SendRTCP(const FeedbackState& feedback_state, - RTCPPacketType packetType, - int32_t nackSize = 0, - const uint16_t* nackList = 0, - bool repeat = false, - uint64_t pictureID = 0); - - int32_t SendCompoundRTCP(const FeedbackState& feedback_state, - const std::set<RTCPPacketType>& packetTypes, - int32_t nackSize = 0, - const uint16_t* nackList = 0, - bool repeat = false, - uint64_t pictureID = 0); - - bool REMB() const; - - void SetREMBStatus(bool enable); - - void SetREMBData(uint32_t bitrate, const std::vector<uint32_t>& ssrcs); - - bool TMMBR() const; - - void SetTMMBRStatus(bool enable); - - int32_t SetTMMBN(const TMMBRSet* boundingSet, uint32_t maxBitrateKbit); - - int32_t SetApplicationSpecificData(uint8_t subType, - uint32_t name, - const uint8_t* data, - uint16_t length); - int32_t SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric); - - void SendRtcpXrReceiverReferenceTime(bool enable); - - bool RtcpXrReceiverReferenceTime() const; - - void SetCsrcs(const std::vector<uint32_t>& csrcs); - - void SetTargetBitrate(unsigned int target_bitrate); - bool SendFeedbackPacket(const rtcp::TransportFeedback& packet); - -private: - struct RtcpContext; - - // The BuildResult indicates the outcome of a call to a builder method, - // constructing a part of an RTCP packet: - // - // kError - // Building RTCP packet failed, propagate error out to caller. - // kAbort - // The (partial) block being build should not be included. Reset current - // buffer position to the state before the method call and proceed to the - // next packet type. - // kTruncated - // There is not enough room in the buffer to fit the data being constructed. - // (IP packet is full). Proceed to the next packet type, and call this - // method again when a new buffer has been allocated. - // TODO(sprang): Actually allocate multiple packets if needed. - // kSuccess - // Data has been successfully placed in the buffer. - - enum class BuildResult { kError, kAborted, kTruncated, kSuccess }; - - int32_t SendToNetwork(const uint8_t* dataBuffer, size_t length); - - int32_t AddReportBlock(const RTCPReportBlock& report_block) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - - bool PrepareReport(const FeedbackState& feedback_state, - uint32_t ssrc, - StreamStatistician* statistician, - RTCPReportBlock* report_block); - - int PrepareRTCP(const FeedbackState& feedback_state, - const std::set<RTCPPacketType>& packetTypes, - int32_t nackSize, - const uint16_t* nackList, - bool repeat, - uint64_t pictureID, - uint8_t* rtcp_buffer, - int buffer_size); - - BuildResult BuildSR(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildRR(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildSDES(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildPLI(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildREMB(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildTMMBR(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildTMMBN(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildAPP(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildVoIPMetric(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildBYE(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildFIR(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildSLI(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildRPSI(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildNACK(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildReceiverReferenceTime(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - BuildResult BuildDlrr(RtcpContext* context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - -private: - const bool audio_; - Clock* const clock_; - RtcpMode method_ GUARDED_BY(critical_section_rtcp_sender_); - - Transport* const transport_; - - rtc::scoped_ptr<CriticalSectionWrapper> critical_section_rtcp_sender_; - bool using_nack_ GUARDED_BY(critical_section_rtcp_sender_); - bool sending_ GUARDED_BY(critical_section_rtcp_sender_); - bool remb_enabled_ GUARDED_BY(critical_section_rtcp_sender_); - - int64_t next_time_to_send_rtcp_ GUARDED_BY(critical_section_rtcp_sender_); - - uint32_t start_timestamp_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t last_rtp_timestamp_ GUARDED_BY(critical_section_rtcp_sender_); - int64_t last_frame_capture_time_ms_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t ssrc_ GUARDED_BY(critical_section_rtcp_sender_); - // SSRC that we receive on our RTP channel - uint32_t remote_ssrc_ GUARDED_BY(critical_section_rtcp_sender_); - std::string cname_ GUARDED_BY(critical_section_rtcp_sender_); - - ReceiveStatistics* receive_statistics_ - GUARDED_BY(critical_section_rtcp_sender_); - std::map<uint32_t, rtcp::ReportBlock> report_blocks_ - GUARDED_BY(critical_section_rtcp_sender_); - std::map<uint32_t, std::string> csrc_cnames_ - GUARDED_BY(critical_section_rtcp_sender_); - - // Sent - uint32_t last_send_report_[RTCP_NUMBER_OF_SR] GUARDED_BY( - critical_section_rtcp_sender_); // allow packet loss and RTT above 1 sec - int64_t last_rtcp_time_[RTCP_NUMBER_OF_SR] GUARDED_BY( - critical_section_rtcp_sender_); - - // Sent XR receiver reference time report. - // <mid ntp (mid 32 bits of the 64 bits NTP timestamp), send time in ms>. - std::map<uint32_t, int64_t> last_xr_rr_ - GUARDED_BY(critical_section_rtcp_sender_); - - // send CSRCs - std::vector<uint32_t> csrcs_ GUARDED_BY(critical_section_rtcp_sender_); - - // Full intra request - uint8_t sequence_number_fir_ GUARDED_BY(critical_section_rtcp_sender_); - - // REMB - uint32_t remb_bitrate_ GUARDED_BY(critical_section_rtcp_sender_); - std::vector<uint32_t> remb_ssrcs_ GUARDED_BY(critical_section_rtcp_sender_); - - TMMBRHelp tmmbr_help_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t tmmbr_send_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t packet_oh_send_ GUARDED_BY(critical_section_rtcp_sender_); - - // APP - uint8_t app_sub_type_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t app_name_ GUARDED_BY(critical_section_rtcp_sender_); - rtc::scoped_ptr<uint8_t[]> app_data_ GUARDED_BY(critical_section_rtcp_sender_); - uint16_t app_length_ GUARDED_BY(critical_section_rtcp_sender_); - - // True if sending of XR Receiver reference time report is enabled. - bool xr_send_receiver_reference_time_enabled_ - GUARDED_BY(critical_section_rtcp_sender_); - - // XR VoIP metric - RTCPVoIPMetric xr_voip_metric_ GUARDED_BY(critical_section_rtcp_sender_); - - RtcpPacketTypeCounterObserver* const packet_type_counter_observer_; - RtcpPacketTypeCounter packet_type_counter_ - GUARDED_BY(critical_section_rtcp_sender_); - - RTCPUtility::NackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_); - - void SetFlag(RTCPPacketType type, bool is_volatile) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - void SetFlags(const std::set<RTCPPacketType>& types, bool is_volatile) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - bool IsFlagPresent(RTCPPacketType type) const - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - bool ConsumeFlag(RTCPPacketType type, bool forced = false) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - bool AllVolatileFlagsConsumed() const - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - struct ReportFlag { - ReportFlag(RTCPPacketType type, bool is_volatile) - : type(type), is_volatile(is_volatile) {} - bool operator<(const ReportFlag& flag) const { return type < flag.type; } - bool operator==(const ReportFlag& flag) const { return type == flag.type; } - const RTCPPacketType type; - const bool is_volatile; - }; - - std::set<ReportFlag> report_flags_ GUARDED_BY(critical_section_rtcp_sender_); - - typedef BuildResult (RTCPSender::*Builder)(RtcpContext*); - std::map<RTCPPacketType, Builder> builders_; - - class PacketBuiltCallback; + int32_t SetApplicationSpecificData(uint8_t subType, + uint32_t name, + const uint8_t* data, + uint16_t length); + int32_t SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric); + + void SendRtcpXrReceiverReferenceTime(bool enable); + + bool RtcpXrReceiverReferenceTime() const; + + void SetCsrcs(const std::vector<uint32_t>& csrcs); + + void SetTargetBitrate(unsigned int target_bitrate); + bool SendFeedbackPacket(const rtcp::TransportFeedback& packet); + + private: + class RtcpContext; + + // Determine which RTCP messages should be sent and setup flags. + void PrepareReport(const std::set<RTCPPacketType>& packetTypes, + const FeedbackState& feedback_state) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + + bool AddReportBlock(const FeedbackState& feedback_state, + uint32_t ssrc, + StreamStatistician* statistician) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + + rtc::scoped_ptr<rtcp::RtcpPacket> BuildSR(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildRR(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildSDES(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildPLI(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildREMB(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildTMMBR(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildTMMBN(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildAPP(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildVoIPMetric(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildBYE(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildFIR(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildSLI(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildRPSI(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildNACK(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildReceiverReferenceTime( + const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + rtc::scoped_ptr<rtcp::RtcpPacket> BuildDlrr(const RtcpContext& context) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + + private: + const bool audio_; + Clock* const clock_; + Random random_ GUARDED_BY(critical_section_rtcp_sender_); + RtcpMode method_ GUARDED_BY(critical_section_rtcp_sender_); + + Transport* const transport_; + + rtc::scoped_ptr<CriticalSectionWrapper> critical_section_rtcp_sender_; + bool using_nack_ GUARDED_BY(critical_section_rtcp_sender_); + bool sending_ GUARDED_BY(critical_section_rtcp_sender_); + bool remb_enabled_ GUARDED_BY(critical_section_rtcp_sender_); + + int64_t next_time_to_send_rtcp_ GUARDED_BY(critical_section_rtcp_sender_); + + uint32_t start_timestamp_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t last_rtp_timestamp_ GUARDED_BY(critical_section_rtcp_sender_); + int64_t last_frame_capture_time_ms_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t ssrc_ GUARDED_BY(critical_section_rtcp_sender_); + // SSRC that we receive on our RTP channel + uint32_t remote_ssrc_ GUARDED_BY(critical_section_rtcp_sender_); + std::string cname_ GUARDED_BY(critical_section_rtcp_sender_); + + ReceiveStatistics* receive_statistics_ + GUARDED_BY(critical_section_rtcp_sender_); + std::map<uint32_t, rtcp::ReportBlock> report_blocks_ + GUARDED_BY(critical_section_rtcp_sender_); + std::map<uint32_t, std::string> csrc_cnames_ + GUARDED_BY(critical_section_rtcp_sender_); + + // Sent + uint32_t last_send_report_[RTCP_NUMBER_OF_SR] GUARDED_BY( + critical_section_rtcp_sender_); // allow packet loss and RTT above 1 sec + int64_t last_rtcp_time_[RTCP_NUMBER_OF_SR] GUARDED_BY( + critical_section_rtcp_sender_); + + // Sent XR receiver reference time report. + // <mid ntp (mid 32 bits of the 64 bits NTP timestamp), send time in ms>. + std::map<uint32_t, int64_t> last_xr_rr_ + GUARDED_BY(critical_section_rtcp_sender_); + + // send CSRCs + std::vector<uint32_t> csrcs_ GUARDED_BY(critical_section_rtcp_sender_); + + // Full intra request + uint8_t sequence_number_fir_ GUARDED_BY(critical_section_rtcp_sender_); + + // REMB + uint32_t remb_bitrate_ GUARDED_BY(critical_section_rtcp_sender_); + std::vector<uint32_t> remb_ssrcs_ GUARDED_BY(critical_section_rtcp_sender_); + + TMMBRHelp tmmbr_help_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t tmmbr_send_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t packet_oh_send_ GUARDED_BY(critical_section_rtcp_sender_); + + // APP + uint8_t app_sub_type_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t app_name_ GUARDED_BY(critical_section_rtcp_sender_); + rtc::scoped_ptr<uint8_t[]> app_data_ + GUARDED_BY(critical_section_rtcp_sender_); + uint16_t app_length_ GUARDED_BY(critical_section_rtcp_sender_); + + // True if sending of XR Receiver reference time report is enabled. + bool xr_send_receiver_reference_time_enabled_ + GUARDED_BY(critical_section_rtcp_sender_); + + // XR VoIP metric + RTCPVoIPMetric xr_voip_metric_ GUARDED_BY(critical_section_rtcp_sender_); + + RtcpPacketTypeCounterObserver* const packet_type_counter_observer_; + RtcpPacketTypeCounter packet_type_counter_ + GUARDED_BY(critical_section_rtcp_sender_); + + RTCPUtility::NackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_); + + void SetFlag(RTCPPacketType type, bool is_volatile) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + void SetFlags(const std::set<RTCPPacketType>& types, bool is_volatile) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + bool IsFlagPresent(RTCPPacketType type) const + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + bool ConsumeFlag(RTCPPacketType type, bool forced = false) + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + bool AllVolatileFlagsConsumed() const + EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); + struct ReportFlag { + ReportFlag(RTCPPacketType type, bool is_volatile) + : type(type), is_volatile(is_volatile) {} + bool operator<(const ReportFlag& flag) const { return type < flag.type; } + bool operator==(const ReportFlag& flag) const { return type == flag.type; } + const RTCPPacketType type; + const bool is_volatile; + }; + + std::set<ReportFlag> report_flags_ GUARDED_BY(critical_section_rtcp_sender_); + + typedef rtc::scoped_ptr<rtcp::RtcpPacket> (RTCPSender::*BuilderFunc)( + const RtcpContext&); + std::map<RTCPPacketType, BuilderFunc> builders_; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_SENDER_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_SENDER_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc index d2b80438cc..e19499612d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc +++ b/webrtc/modules/rtp_rtcp/source/rtcp_utility.cc @@ -8,9 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/base/checks.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" #include <assert.h> #include <math.h> // ceil @@ -19,6 +17,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" namespace webrtc { @@ -42,8 +41,8 @@ void NackStats::ReportRequest(uint16_t sequence_number) { uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac) { return (ntp_sec << 16) + (ntp_frac >> 16); -} // end RTCPUtility } +} // namespace RTCPUtility // RTCPParserV2 : currently read only RTCPUtility::RTCPParserV2::RTCPParserV2(const uint8_t* rtcpData, diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_utility.h b/webrtc/modules/rtp_rtcp/source/rtcp_utility.h index f05d512919..0b03ceb56e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtcp_utility.h +++ b/webrtc/modules/rtp_rtcp/source/rtcp_utility.h @@ -14,7 +14,7 @@ #include <stddef.h> // size_t, ptrdiff_t #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/typedefs.h" @@ -487,6 +487,6 @@ class RTCPPacketIterator { RtcpCommonHeader _header; }; -} // RTCPUtility +} // namespace RTCPUtility } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_UTILITY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_fec_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_fec_unittest.cc index 541f522f8d..80f961bd1e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_fec_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_fec_unittest.cc @@ -11,6 +11,7 @@ #include <list> #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/random.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" @@ -41,8 +42,12 @@ template <typename T> void ClearList(std::list<T*>* my_list) { class RtpFecTest : public ::testing::Test { protected: RtpFecTest() - : fec_(new ForwardErrorCorrection()), ssrc_(rand()), fec_seq_num_(0) {} + : random_(0xfec133700742), + fec_(new ForwardErrorCorrection()), + ssrc_(random_.Rand<uint32_t>()), + fec_seq_num_(0) {} + webrtc::Random random_; ForwardErrorCorrection* fec_; int ssrc_; uint16_t fec_seq_num_; @@ -891,22 +896,20 @@ int RtpFecTest::ConstructMediaPacketsSeqNum(int num_media_packets, assert(num_media_packets > 0); ForwardErrorCorrection::Packet* media_packet = NULL; int sequence_number = start_seq_num; - int time_stamp = rand(); + int time_stamp = random_.Rand<int>(); for (int i = 0; i < num_media_packets; ++i) { media_packet = new ForwardErrorCorrection::Packet; media_packet_list_.push_back(media_packet); - media_packet->length = static_cast<size_t>( - (static_cast<float>(rand()) / RAND_MAX) * - (IP_PACKET_SIZE - kRtpHeaderSize - kTransportOverhead - - ForwardErrorCorrection::PacketOverhead())); + const uint32_t kMinPacketSize = kRtpHeaderSize; + const uint32_t kMaxPacketSize = IP_PACKET_SIZE - kRtpHeaderSize - + kTransportOverhead - + ForwardErrorCorrection::PacketOverhead(); + media_packet->length = random_.Rand(kMinPacketSize, kMaxPacketSize); - if (media_packet->length < kRtpHeaderSize) { - media_packet->length = kRtpHeaderSize; - } // Generate random values for the first 2 bytes - media_packet->data[0] = static_cast<uint8_t>(rand() % 256); - media_packet->data[1] = static_cast<uint8_t>(rand() % 256); + media_packet->data[0] = random_.Rand<uint8_t>(); + media_packet->data[1] = random_.Rand<uint8_t>(); // The first two bits are assumed to be 10 by the FEC encoder. // In fact the FEC decoder will set the two first bits to 10 regardless of @@ -929,7 +932,7 @@ int RtpFecTest::ConstructMediaPacketsSeqNum(int num_media_packets, // Generate random values for payload. for (size_t j = 12; j < media_packet->length; ++j) { - media_packet->data[j] = static_cast<uint8_t>(rand() % 256); + media_packet->data[j] = random_.Rand<uint8_t>(); } sequence_number++; } @@ -940,5 +943,5 @@ int RtpFecTest::ConstructMediaPacketsSeqNum(int num_media_packets, } int RtpFecTest::ConstructMediaPackets(int num_media_packets) { - return ConstructMediaPacketsSeqNum(num_media_packets, rand()); + return ConstructMediaPacketsSeqNum(num_media_packets, random_.Rand<int>()); } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format.h b/webrtc/modules/rtp_rtcp/source/rtp_format.h index 18225f9bb4..3519499248 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format.h @@ -14,8 +14,8 @@ #include <string> #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc index aeef44364a..c422577c81 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc @@ -11,7 +11,7 @@ #include <string.h> #include "webrtc/base/logging.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/h264_sps_parser.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc index 1a14b5554a..d29e3d4f21 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc @@ -13,7 +13,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc index 39b64c6ffa..b47e9b9359 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc @@ -11,7 +11,7 @@ #include <string> #include "webrtc/base/logging.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" namespace webrtc { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h index 63db349c74..d62ecba85f 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h @@ -30,7 +30,7 @@ #include <vector> #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" #include "webrtc/typedefs.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h index 2fe963251f..668476833d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h @@ -19,7 +19,7 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_TEST_HELPER_H_ #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" #include "webrtc/typedefs.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc index 0e76a8eae8..d2f22d5044 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc @@ -47,10 +47,6 @@ int16_t Tl0PicIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { return (hdr.tl0_pic_idx == kNoTl0PicIdx) ? def : hdr.tl0_pic_idx; } -uint8_t GofIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { - return (hdr.gof_idx == kNoGofIdx) ? def : hdr.gof_idx; -} - // Picture ID: // // +-+-+-+-+-+-+-+-+ @@ -74,19 +70,17 @@ bool PictureIdPresent(const RTPVideoHeaderVP9& hdr) { // Flexible mode (F=1): Non-flexible mode (F=0): // // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ -// L: | T |U| S |D| |GOF_IDX| S |D| +// L: | T |U| S |D| | T |U| S |D| // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ // | TL0PICIDX | // +-+-+-+-+-+-+-+-+ // size_t LayerInfoLength(const RTPVideoHeaderVP9& hdr) { - if (hdr.flexible_mode) { - return (hdr.temporal_idx == kNoTemporalIdx && - hdr.spatial_idx == kNoSpatialIdx) ? 0 : 1; - } else { - return (hdr.gof_idx == kNoGofIdx && - hdr.spatial_idx == kNoSpatialIdx) ? 0 : 2; + if (hdr.temporal_idx == kNoTemporalIdx && + hdr.spatial_idx == kNoSpatialIdx) { + return 0; } + return hdr.flexible_mode ? 1 : 2; } bool LayerInfoPresent(const RTPVideoHeaderVP9& hdr) { @@ -198,8 +192,8 @@ bool WritePictureId(const RTPVideoHeaderVP9& vp9, // L: | T |U| S |D| // +-+-+-+-+-+-+-+-+ // -bool WriteLayerInfoFlexibleMode(const RTPVideoHeaderVP9& vp9, - rtc::BitBufferWriter* writer) { +bool WriteLayerInfoCommon(const RTPVideoHeaderVP9& vp9, + rtc::BitBufferWriter* writer) { RETURN_FALSE_ON_ERROR(writer->WriteBits(TemporalIdxField(vp9, 0), 3)); RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.temporal_up_switch ? 1 : 0, 1)); RETURN_FALSE_ON_ERROR(writer->WriteBits(SpatialIdxField(vp9, 0), 3)); @@ -210,27 +204,26 @@ bool WriteLayerInfoFlexibleMode(const RTPVideoHeaderVP9& vp9, // Non-flexible mode (F=0): // // +-+-+-+-+-+-+-+-+ -// L: |GOF_IDX| S |D| +// L: | T |U| S |D| // +-+-+-+-+-+-+-+-+ // | TL0PICIDX | // +-+-+-+-+-+-+-+-+ // bool WriteLayerInfoNonFlexibleMode(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) { - RETURN_FALSE_ON_ERROR(writer->WriteBits(GofIdxField(vp9, 0), 4)); - RETURN_FALSE_ON_ERROR(writer->WriteBits(SpatialIdxField(vp9, 0), 3)); - RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.inter_layer_predicted ? 1: 0, 1)); RETURN_FALSE_ON_ERROR(writer->WriteUInt8(Tl0PicIdxField(vp9, 0))); return true; } bool WriteLayerInfo(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) { - if (vp9.flexible_mode) { - return WriteLayerInfoFlexibleMode(vp9, writer); - } else { - return WriteLayerInfoNonFlexibleMode(vp9, writer); - } + if (!WriteLayerInfoCommon(vp9, writer)) + return false; + + if (vp9.flexible_mode) + return true; + + return WriteLayerInfoNonFlexibleMode(vp9, writer); } // Reference indices: @@ -246,7 +239,7 @@ bool WriteRefIndices(const RTPVideoHeaderVP9& vp9, vp9.num_ref_pics == 0 || vp9.num_ref_pics > kMaxVp9RefPics) { return false; } - for (size_t i = 0; i < vp9.num_ref_pics; ++i) { + for (uint8_t i = 0; i < vp9.num_ref_pics; ++i) { bool n_bit = !(i == vp9.num_ref_pics - 1); RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.pid_diff[i], 7)); RETURN_FALSE_ON_ERROR(writer->WriteBits(n_bit ? 1 : 0, 1)); @@ -301,7 +294,7 @@ bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) { writer->WriteBits(vp9.gof.temporal_up_switch[i] ? 1 : 0, 1)); RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.gof.num_ref_pics[i], 2)); RETURN_FALSE_ON_ERROR(writer->WriteBits(kReservedBitValue0, 2)); - for (size_t r = 0; r < vp9.gof.num_ref_pics[i]; ++r) { + for (uint8_t r = 0; r < vp9.gof.num_ref_pics[i]; ++r) { RETURN_FALSE_ON_ERROR(writer->WriteUInt8(vp9.gof.pid_diff[i][r])); } } @@ -337,8 +330,7 @@ bool ParsePictureId(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { // L: | T |U| S |D| // +-+-+-+-+-+-+-+-+ // -bool ParseLayerInfoFlexibleMode(rtc::BitBuffer* parser, - RTPVideoHeaderVP9* vp9) { +bool ParseLayerInfoCommon(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { uint32_t t, u_bit, s, d_bit; RETURN_FALSE_ON_ERROR(parser->ReadBits(&t, 3)); RETURN_FALSE_ON_ERROR(parser->ReadBits(&u_bit, 1)); @@ -354,32 +346,27 @@ bool ParseLayerInfoFlexibleMode(rtc::BitBuffer* parser, // Layer indices (non-flexible mode): // // +-+-+-+-+-+-+-+-+ -// L: |GOF_IDX| S |D| +// L: | T |U| S |D| // +-+-+-+-+-+-+-+-+ // | TL0PICIDX | // +-+-+-+-+-+-+-+-+ // bool ParseLayerInfoNonFlexibleMode(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - uint32_t gof_idx, s, d_bit; uint8_t tl0picidx; - RETURN_FALSE_ON_ERROR(parser->ReadBits(&gof_idx, 4)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(&s, 3)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(&d_bit, 1)); RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&tl0picidx)); - vp9->gof_idx = gof_idx; - vp9->spatial_idx = s; - vp9->inter_layer_predicted = d_bit ? true : false; vp9->tl0_pic_idx = tl0picidx; return true; } bool ParseLayerInfo(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - if (vp9->flexible_mode) { - return ParseLayerInfoFlexibleMode(parser, vp9); - } else { - return ParseLayerInfoNonFlexibleMode(parser, vp9); - } + if (!ParseLayerInfoCommon(parser, vp9)) + return false; + + if (vp9->flexible_mode) + return true; + + return ParseLayerInfoNonFlexibleMode(parser, vp9); } // Reference indices: @@ -466,7 +453,7 @@ bool ParseSsData(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { vp9->gof.temporal_up_switch[i] = u_bit ? true : false; vp9->gof.num_ref_pics[i] = r; - for (size_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) { + for (uint8_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) { uint8_t p_diff; RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&p_diff)); vp9->gof.pid_diff[i][p] = p_diff; @@ -604,7 +591,7 @@ bool RtpPacketizerVp9::NextPacket(uint8_t* buffer, // +-+-+-+-+-+-+-+-+ // M: | EXTENDED PID | (RECOMMENDED) // +-+-+-+-+-+-+-+-+ -// L: |GOF_IDX| S |D| (CONDITIONALLY RECOMMENDED) +// L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) // +-+-+-+-+-+-+-+-+ // | TL0PICIDX | (CONDITIONALLY REQUIRED) // +-+-+-+-+-+-+-+-+ @@ -738,7 +725,8 @@ bool RtpDepacketizerVp9::Parse(ParsedPayload* parsed_payload, parsed_payload->type.Video.height = vp9->height[0]; } } - parsed_payload->type.Video.isFirstPacket = b_bit && (vp9->spatial_idx == 0); + parsed_payload->type.Video.isFirstPacket = + b_bit && (!l_bit || !vp9->inter_layer_predicted); uint64_t rem_bits = parser.RemainingBitCount(); assert(rem_bits % 8 == 0); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h index abce7e7791..3feca4392a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h @@ -25,7 +25,7 @@ #include <string> #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" #include "webrtc/typedefs.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc index 66ab5cdb71..5bbafe459d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc @@ -55,7 +55,7 @@ void VerifyHeader(const RTPVideoHeaderVP9& expected, actual.gof.temporal_up_switch[i]); EXPECT_EQ(expected.gof.temporal_idx[i], actual.gof.temporal_idx[i]); EXPECT_EQ(expected.gof.num_ref_pics[i], actual.gof.num_ref_pics[i]); - for (size_t j = 0; j < expected.gof.num_ref_pics[i]; j++) { + for (uint8_t j = 0; j < expected.gof.num_ref_pics[i]; j++) { EXPECT_EQ(expected.gof.pid_diff[i][j], actual.gof.pid_diff[i][j]); } } @@ -112,7 +112,7 @@ void ParseAndCheckPacket(const uint8_t* packet, // +-+-+-+-+-+-+-+-+ // M: | EXTENDED PID | (RECOMMENDED) // +-+-+-+-+-+-+-+-+ -// L: |GOF_IDX| S |D| (CONDITIONALLY RECOMMENDED) +// L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) // +-+-+-+-+-+-+-+-+ // | TL0PICIDX | (CONDITIONALLY REQUIRED) // +-+-+-+-+-+-+-+-+ @@ -255,7 +255,8 @@ TEST_F(RtpPacketizerVp9Test, TestLayerInfoWithNonFlexibleMode) { const size_t kFrameSize = 30; const size_t kPacketSize = 25; - expected_.gof_idx = 3; + expected_.temporal_idx = 3; + expected_.temporal_up_switch = true; // U expected_.num_spatial_layers = 3; expected_.spatial_idx = 2; expected_.inter_layer_predicted = true; // D @@ -264,9 +265,9 @@ TEST_F(RtpPacketizerVp9Test, TestLayerInfoWithNonFlexibleMode) { // Two packets: // | I:0, P:0, L:1, F:0, B:1, E:0, V:0 | (3hdr + 15 payload) - // L: | GOF_IDX:3, S:2, D:1 | TL0PICIDX:117 | + // L: | T:3, U:1, S:2, D:1 | TL0PICIDX:117 | // | I:0, P:0, L:1, F:0, B:0, E:1, V:0 | (3hdr + 15 payload) - // L: | GOF_IDX:3, S:2, D:1 | TL0PICIDX:117 | + // L: | T:3, U:1, S:2, D:1 | TL0PICIDX:117 | const size_t kExpectedHdrSizes[] = {3, 3}; const size_t kExpectedSizes[] = {18, 18}; const size_t kExpectedNum = GTEST_ARRAY_SIZE_(kExpectedSizes); @@ -505,16 +506,20 @@ TEST_F(RtpDepacketizerVp9Test, ParseTwoBytePictureId) { TEST_F(RtpDepacketizerVp9Test, ParseLayerInfoWithNonFlexibleMode) { const uint8_t kHeaderLength = 3; - const uint8_t kGofIdx = 7; + const uint8_t kTemporalIdx = 2; + const uint8_t kUbit = 1; const uint8_t kSpatialIdx = 1; const uint8_t kDbit = 1; const uint8_t kTl0PicIdx = 17; uint8_t packet[13] = {0}; packet[0] = 0x20; // I:0 P:0 L:1 F:0 B:0 E:0 V:0 R:0 - packet[1] = (kGofIdx << 4) | (kSpatialIdx << 1) | kDbit; // GOF_IDX:7 S:1 D:1 - packet[2] = kTl0PicIdx; // TL0PICIDX:17 + packet[1] = (kTemporalIdx << 5) | (kUbit << 4) | (kSpatialIdx << 1) | kDbit; + packet[2] = kTl0PicIdx; - expected_.gof_idx = kGofIdx; + // T:2 U:1 S:1 D:1 + // TL0PICIDX:17 + expected_.temporal_idx = kTemporalIdx; + expected_.temporal_up_switch = kUbit ? true : false; expected_.spatial_idx = kSpatialIdx; expected_.inter_layer_predicted = kDbit ? true : false; expected_.tl0_pic_idx = kTl0PicIdx; @@ -545,9 +550,9 @@ TEST_F(RtpDepacketizerVp9Test, ParseLayerInfoWithFlexibleMode) { TEST_F(RtpDepacketizerVp9Test, ParseRefIdx) { const uint8_t kHeaderLength = 6; const int16_t kPictureId = 17; - const int16_t kPdiff1 = 17; - const int16_t kPdiff2 = 18; - const int16_t kPdiff3 = 127; + const uint8_t kPdiff1 = 17; + const uint8_t kPdiff2 = 18; + const uint8_t kPdiff3 = 127; uint8_t packet[13] = {0}; packet[0] = 0xD8; // I:1 P:1 L:0 F:1 B:1 E:0 V:0 R:0 packet[1] = 0x80 | ((kPictureId >> 8) & 0x7F); // Two byte pictureID. @@ -577,7 +582,7 @@ TEST_F(RtpDepacketizerVp9Test, ParseRefIdx) { } TEST_F(RtpDepacketizerVp9Test, ParseRefIdxFailsWithNoPictureId) { - const int16_t kPdiff = 3; + const uint8_t kPdiff = 3; uint8_t packet[13] = {0}; packet[0] = 0x58; // I:0 P:1 L:0 F:1 B:1 E:0 V:0 R:0 packet[1] = (kPdiff << 1); // P,F: P_DIFF:3 N:0 @@ -587,7 +592,7 @@ TEST_F(RtpDepacketizerVp9Test, ParseRefIdxFailsWithNoPictureId) { } TEST_F(RtpDepacketizerVp9Test, ParseRefIdxFailsWithTooManyRefPics) { - const int16_t kPdiff = 3; + const uint8_t kPdiff = 3; uint8_t packet[13] = {0}; packet[0] = 0xD8; // I:1 P:1 L:0 F:1 B:1 E:0 V:0 R:0 packet[1] = kMaxOneBytePictureId; // I: PICTURE ID:127 diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h b/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h index 7be3c2e5c4..342e38a1f2 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h @@ -8,12 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_RTP_HEADER_EXTENSION_H_ -#define WEBRTC_MODULES_RTP_RTCP_RTP_HEADER_EXTENSION_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSION_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSION_H_ #include <map> -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -28,7 +28,7 @@ const size_t kVideoRotationLength = 2; const size_t kTransportSequenceNumberLength = 3; struct HeaderExtension { - HeaderExtension(RTPExtensionType extension_type) + explicit HeaderExtension(RTPExtensionType extension_type) : type(extension_type), length(0), active(true) { Init(); } @@ -112,6 +112,7 @@ class RtpHeaderExtensionMap { int32_t Register(const RTPExtensionType type, const uint8_t id, bool active); std::map<uint8_t, HeaderExtension*> extensionMap_; }; -} +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSION_H_ -#endif // WEBRTC_MODULES_RTP_RTCP_RTP_HEADER_EXTENSION_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extension_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_header_extension_unittest.cc index 520cf7a962..ca37750621 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extension_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extension_unittest.cc @@ -15,7 +15,7 @@ #include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/typedefs.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_parser.cc b/webrtc/modules/rtp_rtcp/source/rtp_header_parser.cc index 266bad8858..d4cbe544cc 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_header_parser.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_parser.cc @@ -7,7 +7,7 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" @@ -58,7 +58,7 @@ bool RtpHeaderParserImpl::Parse(const uint8_t* packet, rtp_header_extension_map_.GetCopy(&map); } - const bool valid_rtpheader = rtp_parser.Parse(*header, &map); + const bool valid_rtpheader = rtp_parser.Parse(header, &map); if (!valid_rtpheader) { return false; } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc index aa941d63ff..49f9d8530a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc @@ -13,6 +13,8 @@ #include <assert.h> #include <stdlib.h> #include <string.h> // memset + +#include <algorithm> #include <limits> #include <set> diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h index e97d11eeaa..8e1a732b19 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h @@ -10,14 +10,14 @@ * Class for storing RTP packets. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_RTP_PACKET_HISTORY_H_ -#define WEBRTC_MODULES_RTP_RTCP_RTP_PACKET_HISTORY_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ #include <vector> #include "webrtc/base/thread_annotations.h" -#include "webrtc/modules/interface/module_common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -29,7 +29,7 @@ static const size_t kMaxHistoryCapacity = 9600; class RTPPacketHistory { public: - RTPPacketHistory(Clock* clock); + explicit RTPPacketHistory(Clock* clock); ~RTPPacketHistory(); void SetStorePacketsStatus(bool enable, uint16_t number_to_store); @@ -101,4 +101,4 @@ class RTPPacketHistory { std::vector<StoredPacket> stored_packets_ GUARDED_BY(critsect_); }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_RTP_PACKET_HISTORY_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc index 00a6ac7ed2..a406d8bc9b 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc @@ -12,10 +12,9 @@ #include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" #include "webrtc/system_wrappers/include/clock.h" -#include "webrtc/video_engine/vie_defines.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -29,7 +28,7 @@ class RtpPacketHistoryTest : public ::testing::Test { ~RtpPacketHistoryTest() { delete hist_; } - + SimulatedClock fake_clock_; RTPPacketHistory* hist_; enum {kPayload = 127}; @@ -54,7 +53,7 @@ class RtpPacketHistoryTest : public ::testing::Test { array[(*cur_pos)++] = ssrc >> 16; array[(*cur_pos)++] = ssrc >> 8; array[(*cur_pos)++] = ssrc; - } + } }; TEST_F(RtpPacketHistoryTest, SetStoreStatus) { @@ -268,6 +267,7 @@ TEST_F(RtpPacketHistoryTest, DynamicExpansion) { } TEST_F(RtpPacketHistoryTest, FullExpansion) { + static const int kSendSidePacketHistorySize = 600; hist_->SetStorePacketsStatus(true, kSendSidePacketHistorySize); size_t len; int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc index 38d1450c23..ce0bcd7fed 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" #include "webrtc/base/logging.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" @@ -40,7 +40,7 @@ int32_t RTPPayloadRegistry::RegisterReceivePayload( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const int8_t payload_type, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate, bool* created_new_payload) { assert(payload_type >= 0); @@ -139,7 +139,7 @@ void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const size_t payload_name_length, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) { RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin(); for (; iterator != payload_type_map_.end(); ++iterator) { @@ -171,7 +171,7 @@ void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( int32_t RTPPayloadRegistry::ReceivePayloadType( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate, int8_t* payload_type) const { assert(payload_type); @@ -343,17 +343,16 @@ bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type, int RTPPayloadRegistry::GetPayloadTypeFrequency( uint8_t payload_type) const { - RtpUtility::Payload* payload; - if (!PayloadTypeToPayload(payload_type, payload)) { + const RtpUtility::Payload* payload = PayloadTypeToPayload(payload_type); + if (!payload) { return -1; } CriticalSectionScoped cs(crit_sect_.get()); return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload); } -bool RTPPayloadRegistry::PayloadTypeToPayload( - const uint8_t payload_type, - RtpUtility::Payload*& payload) const { +const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload( + uint8_t payload_type) const { CriticalSectionScoped cs(crit_sect_.get()); RtpUtility::PayloadTypeMap::const_iterator it = @@ -361,11 +360,10 @@ bool RTPPayloadRegistry::PayloadTypeToPayload( // Check that this is a registered payload type. if (it == payload_type_map_.end()) { - return false; + return nullptr; } - payload = it->second; - return true; + return it->second; } void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) { @@ -390,7 +388,7 @@ class RTPPayloadAudioStrategy : public RTPPayloadStrategy { bool PayloadIsCompatible(const RtpUtility::Payload& payload, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) const override { return payload.audio && @@ -409,7 +407,7 @@ class RTPPayloadAudioStrategy : public RTPPayloadStrategy { const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int8_t payloadType, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) const override { RtpUtility::Payload* payload = new RtpUtility::Payload; payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; @@ -433,7 +431,7 @@ class RTPPayloadVideoStrategy : public RTPPayloadStrategy { bool PayloadIsCompatible(const RtpUtility::Payload& payload, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) const override { return !payload.audio; } @@ -447,7 +445,7 @@ class RTPPayloadVideoStrategy : public RTPPayloadStrategy { const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int8_t payloadType, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) const override { RtpVideoCodecTypes videoType = kRtpVideoGeneric; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc index 0b9bf2751e..b73666d1af 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc @@ -8,12 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" @@ -25,7 +25,7 @@ using ::testing::Return; using ::testing::_; static const char* kTypicalPayloadName = "name"; -static const uint8_t kTypicalChannels = 1; +static const size_t kTypicalChannels = 1; static const int kTypicalFrequency = 44000; static const int kTypicalRate = 32 * 1024; @@ -52,10 +52,9 @@ class RtpPayloadRegistryTest : public ::testing::Test { RtpUtility::Payload* returned_payload_on_heap = new RtpUtility::Payload(returned_payload); EXPECT_CALL(*mock_payload_strategy_, - CreatePayloadType(kTypicalPayloadName, payload_type, - kTypicalFrequency, - kTypicalChannels, - rate)).WillOnce(Return(returned_payload_on_heap)); + CreatePayloadType(kTypicalPayloadName, payload_type, + kTypicalFrequency, kTypicalChannels, rate)) + .WillOnce(Return(returned_payload_on_heap)); return returned_payload_on_heap; } @@ -70,14 +69,14 @@ TEST_F(RtpPayloadRegistryTest, RegistersAndRemembersPayloadsUntilDeregistered) { bool new_payload_created = false; EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels, - kTypicalRate, &new_payload_created)); + kTypicalPayloadName, payload_type, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &new_payload_created)); EXPECT_TRUE(new_payload_created) << "A new payload WAS created."; - RtpUtility::Payload* retrieved_payload = NULL; - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type, - retrieved_payload)); + const RtpUtility::Payload* retrieved_payload = + rtp_payload_registry_->PayloadTypeToPayload(payload_type); + EXPECT_TRUE(retrieved_payload); // We should get back the exact pointer to the payload returned by the // payload strategy. @@ -85,32 +84,30 @@ TEST_F(RtpPayloadRegistryTest, RegistersAndRemembersPayloadsUntilDeregistered) { // Now forget about it and verify it's gone. EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type)); - EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload( - payload_type, retrieved_payload)); + EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type)); } TEST_F(RtpPayloadRegistryTest, AudioRedWorkProperly) { const uint8_t kRedPayloadType = 127; const int kRedSampleRate = 8000; - const int kRedChannels = 1; + const size_t kRedChannels = 1; const int kRedBitRate = 0; // This creates an audio RTP payload strategy. - rtp_payload_registry_.reset(new RTPPayloadRegistry( - RTPPayloadStrategy::CreateStrategy(true))); + rtp_payload_registry_.reset( + new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))); bool new_payload_created = false; EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - "red", kRedPayloadType, kRedSampleRate, kRedChannels, kRedBitRate, - &new_payload_created)); + "red", kRedPayloadType, kRedSampleRate, kRedChannels, + kRedBitRate, &new_payload_created)); EXPECT_TRUE(new_payload_created); EXPECT_EQ(kRedPayloadType, rtp_payload_registry_->red_payload_type()); - RtpUtility::Payload* retrieved_payload = NULL; - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(kRedPayloadType, - retrieved_payload)); - ASSERT_TRUE(retrieved_payload); + const RtpUtility::Payload* retrieved_payload = + rtp_payload_registry_->PayloadTypeToPayload(kRedPayloadType); + EXPECT_TRUE(retrieved_payload); EXPECT_TRUE(retrieved_payload->audio); EXPECT_STRCASEEQ("red", retrieved_payload->name); @@ -127,27 +124,29 @@ TEST_F(RtpPayloadRegistryTest, RtpUtility::Payload* first_payload_on_heap = ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels, - kTypicalRate, &ignored)); + kTypicalPayloadName, payload_type, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)); EXPECT_EQ(-1, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels, - kTypicalRate, &ignored)) << "Adding same codec twice = bad."; + kTypicalPayloadName, payload_type, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)) + << "Adding same codec twice = bad."; RtpUtility::Payload* second_payload_on_heap = ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type - 1, kTypicalFrequency, - kTypicalChannels, kTypicalRate, &ignored)) << - "With a different payload type is fine though."; + kTypicalPayloadName, payload_type - 1, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)) + << "With a different payload type is fine though."; // Ensure both payloads are preserved. - RtpUtility::Payload* retrieved_payload = NULL; - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type, - retrieved_payload)); + const RtpUtility::Payload* retrieved_payload = + rtp_payload_registry_->PayloadTypeToPayload(payload_type); + EXPECT_TRUE(retrieved_payload); EXPECT_EQ(first_payload_on_heap, retrieved_payload); - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1, - retrieved_payload)); + retrieved_payload = + rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1); + EXPECT_TRUE(retrieved_payload); EXPECT_EQ(second_payload_on_heap, retrieved_payload); // Ok, update the rate for one of the codecs. If either the incoming rate or @@ -158,8 +157,8 @@ TEST_F(RtpPayloadRegistryTest, EXPECT_CALL(*mock_payload_strategy_, UpdatePayloadRate(first_payload_on_heap, kTypicalRate)); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels, - kTypicalRate, &ignored)); + kTypicalPayloadName, payload_type, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)); } TEST_F(RtpPayloadRegistryTest, @@ -174,35 +173,31 @@ TEST_F(RtpPayloadRegistryTest, bool ignored = false; ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type, kTypicalFrequency, kTypicalChannels, - kTypicalRate, &ignored)); + kTypicalPayloadName, payload_type, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)); ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type - 1, kTypicalFrequency, - kTypicalChannels, kTypicalRate, &ignored)); + kTypicalPayloadName, payload_type - 1, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)); - RtpUtility::Payload* retrieved_payload = NULL; - EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload( - payload_type, retrieved_payload)) << "The first payload should be " - "deregistered because the only thing that differs is payload type."; - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload( - payload_type - 1, retrieved_payload)) << - "The second payload should still be registered though."; + EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type)) + << "The first payload should be " + "deregistered because the only thing that differs is payload type."; + EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1)) + << "The second payload should still be registered though."; // Now ensure non-compatible codecs aren't removed. ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _)) .WillByDefault(Return(false)); ExpectReturnOfTypicalAudioPayload(payload_type + 1, kTypicalRate); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, payload_type + 1, kTypicalFrequency, - kTypicalChannels, kTypicalRate, &ignored)); - - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload( - payload_type - 1, retrieved_payload)) << - "Not compatible; both payloads should be kept."; - EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload( - payload_type + 1, retrieved_payload)) << - "Not compatible; both payloads should be kept."; + kTypicalPayloadName, payload_type + 1, kTypicalFrequency, + kTypicalChannels, kTypicalRate, &ignored)); + + EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1)) + << "Not compatible; both payloads should be kept."; + EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type + 1)) + << "Not compatible; both payloads should be kept."; } TEST_F(RtpPayloadRegistryTest, @@ -218,18 +213,17 @@ TEST_F(RtpPayloadRegistryTest, bool ignored; ExpectReturnOfTypicalAudioPayload(34, kTypicalRate); EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( - kTypicalPayloadName, 34, kTypicalFrequency, kTypicalChannels, - kTypicalRate, &ignored)); + kTypicalPayloadName, 34, kTypicalFrequency, kTypicalChannels, + kTypicalRate, &ignored)); EXPECT_EQ(-1, rtp_payload_registry_->last_received_payload_type()); media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18); EXPECT_FALSE(media_type_unchanged); } -class ParameterizedRtpPayloadRegistryTest : - public RtpPayloadRegistryTest, - public ::testing::WithParamInterface<int> { -}; +class ParameterizedRtpPayloadRegistryTest + : public RtpPayloadRegistryTest, + public ::testing::WithParamInterface<int> {}; TEST_P(ParameterizedRtpPayloadRegistryTest, FailsToRegisterKnownPayloadsWeAreNotInterestedIn) { @@ -237,26 +231,26 @@ TEST_P(ParameterizedRtpPayloadRegistryTest, bool ignored; EXPECT_EQ(-1, rtp_payload_registry_->RegisterReceivePayload( - "whatever", static_cast<uint8_t>(payload_type), 19, 1, 17, &ignored)); + "whatever", static_cast<uint8_t>(payload_type), 19, 1, 17, + &ignored)); } INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes, ParameterizedRtpPayloadRegistryTest, testing::Values(64, 72, 73, 74, 75, 76, 77, 78, 79)); -class RtpPayloadRegistryGenericTest : - public RtpPayloadRegistryTest, - public ::testing::WithParamInterface<int> { -}; +class RtpPayloadRegistryGenericTest + : public RtpPayloadRegistryTest, + public ::testing::WithParamInterface<int> {}; TEST_P(RtpPayloadRegistryGenericTest, RegisterGenericReceivePayloadType) { int payload_type = GetParam(); bool ignored; - EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload("generic-codec", - static_cast<int8_t>(payload_type), - 19, 1, 17, &ignored)); // dummy values, except for payload_type + EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload( + "generic-codec", static_cast<int8_t>(payload_type), 19, 1, + 17, &ignored)); // dummy values, except for payload_type } // Generates an RTX packet for the given length and original sequence number. @@ -395,7 +389,8 @@ TEST_F(RtpPayloadRegistryTest, InvalidRtxConfiguration) { TestRtxPacket(rtp_payload_registry_.get(), 106, 0, false); } -INSTANTIATE_TEST_CASE_P(TestDynamicRange, RtpPayloadRegistryGenericTest, - testing::Range(96, 127+1)); +INSTANTIATE_TEST_CASE_P(TestDynamicRange, + RtpPayloadRegistryGenericTest, + testing::Range(96, 127 + 1)); } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h index 176852e01e..1dd07d1cc9 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h @@ -14,8 +14,8 @@ #include <set> #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" #include "webrtc/typedefs.h" @@ -42,9 +42,7 @@ class RTPReceiverAudio : public RTPReceiverStrategy, // Is TelephoneEvent configured with payload type payload_type bool TelephoneEventPayloadType(const int8_t payload_type) const; - TelephoneEventHandler* GetTelephoneEventHandler() { - return this; - } + TelephoneEventHandler* GetTelephoneEventHandler() { return this; } // Returns true if CNG is configured with payload type payload_type. If so, // the frequency and cng_payload_type_has_changed are filled in. @@ -96,13 +94,11 @@ class RTPReceiverAudio : public RTPReceiverStrategy, int Energy(uint8_t array_of_energy[kRtpCsrcSize]) const override; private: - - int32_t ParseAudioCodecSpecific( - WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - size_t payload_length, - const AudioPayload& audio_specific, - bool is_red); + int32_t ParseAudioCodecSpecific(WebRtcRTPHeader* rtp_header, + const uint8_t* payload_data, + size_t payload_length, + const AudioPayload& audio_specific, + bool is_red); uint32_t last_received_frequency_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc index e1ebd0c8bb..2e21f230d3 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc @@ -16,13 +16,12 @@ #include <string.h> #include "webrtc/base/logging.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" namespace webrtc { -using RtpUtility::GetCurrentRTP; using RtpUtility::Payload; using RtpUtility::StringCompare; @@ -97,7 +96,7 @@ int32_t RtpReceiverImpl::RegisterReceivePayload( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const int8_t payload_type, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) { CriticalSectionScoped lock(critical_section_rtp_receiver_.get()); @@ -170,7 +169,7 @@ bool RtpReceiverImpl::IncomingRtpPacket( int8_t first_payload_byte = payload_length > 0 ? payload[0] : 0; bool is_red = false; - if (CheckPayloadChanged(rtp_header, first_payload_byte, is_red, + if (CheckPayloadChanged(rtp_header, first_payload_byte, &is_red, &payload_specific) == -1) { if (payload_length == 0) { // OK, keep-alive packet. @@ -253,7 +252,7 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) { bool new_ssrc = false; bool re_initialize_decoder = false; char payload_name[RTP_PAYLOAD_NAME_SIZE]; - uint8_t channels = 1; + size_t channels = 1; uint32_t rate = 0; { @@ -276,12 +275,11 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) { if (rtp_header.payloadType == last_received_payload_type) { re_initialize_decoder = true; - Payload* payload; - if (!rtp_payload_registry_->PayloadTypeToPayload( - rtp_header.payloadType, payload)) { + const Payload* payload = rtp_payload_registry_->PayloadTypeToPayload( + rtp_header.payloadType); + if (!payload) { return; } - assert(payload); payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1); if (payload->audio) { @@ -321,7 +319,7 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) { // last known payload). int32_t RtpReceiverImpl::CheckPayloadChanged(const RTPHeader& rtp_header, const int8_t first_payload_byte, - bool& is_red, + bool* is_red, PayloadUnion* specific_payload) { bool re_initialize_decoder = false; @@ -339,7 +337,7 @@ int32_t RtpReceiverImpl::CheckPayloadChanged(const RTPHeader& rtp_header, if (rtp_payload_registry_->red_payload_type() == payload_type) { // Get the real codec payload type. payload_type = first_payload_byte & 0x7f; - is_red = true; + *is_red = true; if (rtp_payload_registry_->red_payload_type() == payload_type) { // Invalid payload type, traced by caller. If we proceeded here, @@ -361,16 +359,16 @@ int32_t RtpReceiverImpl::CheckPayloadChanged(const RTPHeader& rtp_header, &should_discard_changes); if (should_discard_changes) { - is_red = false; + *is_red = false; return 0; } - Payload* payload; - if (!rtp_payload_registry_->PayloadTypeToPayload(payload_type, payload)) { + const Payload* payload = + rtp_payload_registry_->PayloadTypeToPayload(payload_type); + if (!payload) { // Not a registered payload type. return -1; } - assert(payload); payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1); @@ -391,7 +389,7 @@ int32_t RtpReceiverImpl::CheckPayloadChanged(const RTPHeader& rtp_header, } } else { rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload); - is_red = false; + *is_red = false; } } // End critsect. diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h index 46741d59b4..5cf94c2859 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h @@ -12,8 +12,8 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_IMPL_H_ #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/typedefs.h" @@ -36,7 +36,7 @@ class RtpReceiverImpl : public RtpReceiver { int32_t RegisterReceivePayload(const char payload_name[RTP_PAYLOAD_NAME_SIZE], const int8_t payload_type, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) override; int32_t DeRegisterReceivePayload(const int8_t payload_type) override; @@ -71,7 +71,7 @@ class RtpReceiverImpl : public RtpReceiver { void CheckCSRC(const WebRtcRTPHeader& rtp_header); int32_t CheckPayloadChanged(const RTPHeader& rtp_header, const int8_t first_payload_byte, - bool& is_red, + bool* is_red, PayloadUnion* payload); Clock* clock_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h index 37c3e6e49a..0f7ad30e87 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h @@ -12,8 +12,8 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_ #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/typedefs.h" @@ -95,7 +95,7 @@ class RTPReceiverStrategy { // Note: Implementations may call the callback for other reasons than calls // to ParseRtpPacket, for instance if the implementation somehow recovers a // packet. - RTPReceiverStrategy(RtpData* data_callback); + explicit RTPReceiverStrategy(RtpData* data_callback); rtc::scoped_ptr<CriticalSectionWrapper> crit_sect_; PayloadUnion last_payload_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc index 1af2d4857e..53051dd321 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc @@ -16,8 +16,8 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/trace_event.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h index 23128df6e1..56f761a2e1 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h @@ -12,7 +12,7 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_VIDEO_H_ #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h index 7cfebd91a8..a2cd52736f 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h @@ -13,36 +13,37 @@ // Configuration file for RTP utilities (RTPSender, RTPReceiver ...) namespace webrtc { -enum { NACK_BYTECOUNT_SIZE = 60}; // size of our NACK history +enum { NACK_BYTECOUNT_SIZE = 60 }; // size of our NACK history // A sanity for the NACK list parsing at the send-side. enum { kSendSideNackListSizeSanity = 20000 }; enum { kDefaultMaxReorderingThreshold = 50 }; // In sequence numbers. enum { kRtcpMaxNackFields = 253 }; -enum { RTCP_INTERVAL_VIDEO_MS = 1000 }; -enum { RTCP_INTERVAL_AUDIO_MS = 5000 }; -enum { RTCP_SEND_BEFORE_KEY_FRAME_MS= 100 }; -enum { RTCP_MAX_REPORT_BLOCKS = 31}; // RFC 3550 page 37 -enum { RTCP_MIN_FRAME_LENGTH_MS = 17}; -enum { kRtcpAppCode_DATA_SIZE = 32*4}; // multiple of 4, this is not a limitation of the size -enum { RTCP_RPSI_DATA_SIZE = 30}; -enum { RTCP_NUMBER_OF_SR = 60 }; - -enum { MAX_NUMBER_OF_TEMPORAL_ID = 8 }; // RFC -enum { MAX_NUMBER_OF_DEPENDENCY_QUALITY_ID = 128 };// RFC +enum { RTCP_INTERVAL_VIDEO_MS = 1000 }; +enum { RTCP_INTERVAL_AUDIO_MS = 5000 }; +enum { RTCP_SEND_BEFORE_KEY_FRAME_MS = 100 }; +enum { RTCP_MAX_REPORT_BLOCKS = 31 }; // RFC 3550 page 37 +enum { RTCP_MIN_FRAME_LENGTH_MS = 17 }; +enum { + kRtcpAppCode_DATA_SIZE = 32 * 4 +}; // multiple of 4, this is not a limitation of the size +enum { RTCP_RPSI_DATA_SIZE = 30 }; +enum { RTCP_NUMBER_OF_SR = 60 }; + +enum { MAX_NUMBER_OF_TEMPORAL_ID = 8 }; // RFC +enum { MAX_NUMBER_OF_DEPENDENCY_QUALITY_ID = 128 }; // RFC enum { MAX_NUMBER_OF_REMB_FEEDBACK_SSRCS = 255 }; -enum { BW_HISTORY_SIZE = 35}; +enum { BW_HISTORY_SIZE = 35 }; -#define MIN_AUDIO_BW_MANAGEMENT_BITRATE 6 -#define MIN_VIDEO_BW_MANAGEMENT_BITRATE 30 +#define MIN_AUDIO_BW_MANAGEMENT_BITRATE 6 +#define MIN_VIDEO_BW_MANAGEMENT_BITRATE 30 -enum { DTMF_OUTBAND_MAX = 20}; +enum { DTMF_OUTBAND_MAX = 20 }; enum { RTP_MAX_BURST_SLEEP_TIME = 500 }; enum { RTP_AUDIO_LEVEL_UNIQUE_ID = 0xbede }; -enum { RTP_MAX_PACKETS_PER_FRAME= 512 }; // must be multiple of 32 +enum { RTP_MAX_PACKETS_PER_FRAME = 512 }; // must be multiple of 32 } // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_CONFIG_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_CONFIG_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 451f8bfa93..450eed698e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -183,8 +183,13 @@ int32_t ModuleRtpRtcpImpl::Process() { set_rtt_ms(rtt_stats_->LastProcessedRtt()); } - if (rtcp_sender_.TimeToSendRTCPReport()) - rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport); + // For sending streams, make sure to not send a SR before media has been sent. + if (rtcp_sender_.TimeToSendRTCPReport()) { + RTCPSender::FeedbackState state = GetFeedbackState(); + // Prevent sending streams to send SR before any media has been sent. + if (!rtcp_sender_.Sending() || state.packets_sent > 0) + rtcp_sender_.SendRTCP(state, kRtcpReport); + } if (UpdateRTCPReceiveInformationTimers()) { // A receiver has timed out @@ -402,6 +407,7 @@ int32_t ModuleRtpRtcpImpl::SendOutgoingData( const RTPFragmentationHeader* fragmentation, const RTPVideoHeader* rtp_video_hdr) { rtcp_sender_.SetLastRtpTime(time_stamp, capture_time_ms); + // Make sure an RTCP report isn't queued behind a key frame. if (rtcp_sender_.TimeToSendRTCPReport(kVideoFrameKey == frame_type)) { rtcp_sender_.SendRTCP(GetFeedbackState(), kRtcpReport); } @@ -794,9 +800,8 @@ int32_t ModuleRtpRtcpImpl::SetSendREDPayloadType( } // Get payload type for Redundant Audio Data RFC 2198. -int32_t ModuleRtpRtcpImpl::SendREDPayloadType( - int8_t& payload_type) const { - return rtp_sender_.RED(&payload_type); +int32_t ModuleRtpRtcpImpl::SendREDPayloadType(int8_t* payload_type) const { + return rtp_sender_.RED(payload_type); } void ModuleRtpRtcpImpl::SetTargetSendBitrate(uint32_t bitrate_bps) { @@ -832,11 +837,10 @@ void ModuleRtpRtcpImpl::SetGenericFECStatus( rtp_sender_.SetGenericFECStatus(enable, payload_type_red, payload_type_fec); } -void ModuleRtpRtcpImpl::GenericFECStatus(bool& enable, - uint8_t& payload_type_red, - uint8_t& payload_type_fec) { - rtp_sender_.GenericFECStatus(&enable, &payload_type_red, - &payload_type_fec); +void ModuleRtpRtcpImpl::GenericFECStatus(bool* enable, + uint8_t* payload_type_red, + uint8_t* payload_type_fec) { + rtp_sender_.GenericFECStatus(enable, payload_type_red, payload_type_fec); } int32_t ModuleRtpRtcpImpl::SetFecParameters( @@ -952,8 +956,8 @@ bool ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() { } // Called from RTCPsender. -int32_t ModuleRtpRtcpImpl::BoundingSet(bool& tmmbr_owner, - TMMBRSet*& bounding_set) { +int32_t ModuleRtpRtcpImpl::BoundingSet(bool* tmmbr_owner, + TMMBRSet* bounding_set) { return rtcp_receiver_.BoundingSet(tmmbr_owner, bounding_set); } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h index c9b6686c0a..04e09c1217 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -12,10 +12,12 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_IMPL_H_ #include <list> +#include <set> +#include <utility> #include <vector> #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/source/packet_loss_stats.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h" @@ -258,7 +260,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp { int32_t SetSendREDPayloadType(int8_t payload_type) override; // Get payload type for Redundant Audio Data RFC 2198. - int32_t SendREDPayloadType(int8_t& payload_type) const override; + int32_t SendREDPayloadType(int8_t* payload_type) const override; // Store the audio level in d_bov for header-extension-for-audio-level- // indication. @@ -280,9 +282,9 @@ class ModuleRtpRtcpImpl : public RtpRtcp { uint8_t payload_type_red, uint8_t payload_type_fec) override; - void GenericFECStatus(bool& enable, - uint8_t& payload_type_red, - uint8_t& payload_type_fec) override; + void GenericFECStatus(bool* enable, + uint8_t* payload_type_red, + uint8_t* payload_type_fec) override; int32_t SetFecParameters(const FecProtectionParams* delta_params, const FecProtectionParams* key_params) override; @@ -293,7 +295,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp { bool LastReceivedXrReferenceTimeInfo(RtcpReceiveTimeInfo* info) const; - virtual int32_t BoundingSet(bool& tmmbr_owner, TMMBRSet*& bounding_set_rec); + int32_t BoundingSet(bool* tmmbr_owner, TMMBRSet* bounding_set_rec); void BitrateSent(uint32_t* total_rate, uint32_t* video_rate, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc index 4c94764ee6..8329f603f9 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc @@ -8,13 +8,17 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include <map> +#include <set> + #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h" #include "webrtc/system_wrappers/include/scoped_vector.h" #include "webrtc/test/rtcp_packet_parser.h" @@ -94,7 +98,7 @@ class SendTransport : public Transport, class RtpRtcpModule : public RtcpPacketTypeCounterObserver { public: - RtpRtcpModule(SimulatedClock* clock) + explicit RtpRtcpModule(SimulatedClock* clock) : receive_statistics_(ReceiveStatistics::Create(clock)) { RtpRtcp::Configuration config; config.audio = false; @@ -346,6 +350,27 @@ TEST_F(RtpRtcpImplTest, RttForReceiverOnly) { EXPECT_EQ(2 * kOneWayNetworkDelayMs, receiver_.impl_->rtt_ms()); } +TEST_F(RtpRtcpImplTest, NoSrBeforeMedia) { + // Ignore fake transport delays in this test. + sender_.transport_.SimulateNetworkDelay(0, &clock_); + receiver_.transport_.SimulateNetworkDelay(0, &clock_); + + sender_.impl_->Process(); + EXPECT_EQ(-1, sender_.RtcpSent().first_packet_time_ms); + + // Verify no SR is sent before media has been sent, RR should still be sent + // from the receiving module though. + clock_.AdvanceTimeMilliseconds(2000); + int64_t current_time = clock_.TimeInMilliseconds(); + sender_.impl_->Process(); + receiver_.impl_->Process(); + EXPECT_EQ(-1, sender_.RtcpSent().first_packet_time_ms); + EXPECT_EQ(receiver_.RtcpSent().first_packet_time_ms, current_time); + + SendFrame(&sender_, kBaseLayerTid); + EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, current_time); +} + TEST_F(RtpRtcpImplTest, RtcpPacketTypeCounter_Nack) { EXPECT_EQ(-1, receiver_.RtcpSent().first_packet_time_ms); EXPECT_EQ(-1, sender_.RtcpReceived().first_packet_time_ms); @@ -522,5 +547,4 @@ TEST_F(RtpRtcpImplTest, UniqueNackRequests) { EXPECT_EQ(6U, sender_.RtcpReceived().unique_nack_requests); EXPECT_EQ(75, sender_.RtcpReceived().UniqueNackRequestsInPercent()); } - } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 50f476829d..f4933afdd9 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -11,15 +11,17 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" #include <stdlib.h> // srand +#include <algorithm> #include <utility> #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/trace_event.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" +#include "webrtc/modules/rtp_rtcp/source/time_util.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/system_wrappers/include/tick_util.h" @@ -33,6 +35,7 @@ static const uint32_t kAbsSendTimeFraction = 18; namespace { const size_t kRtpHeaderLength = 12; +const uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1. const char* FrameTypeToString(FrameType frame_type) { switch (frame_type) { @@ -125,6 +128,7 @@ RTPSender::RTPSender( // TickTime. clock_delta_ms_(clock_->TimeInMilliseconds() - TickTime::MillisecondTimestamp()), + random_(clock_->TimeInMicroseconds()), bitrates_(new BitrateAggregator(bitrate_callback)), total_bitrate_sent_(clock, bitrates_->total_bitrate_observer()), audio_configured_(audio), @@ -182,8 +186,8 @@ RTPSender::RTPSender( ssrc_rtx_ = ssrc_db_.CreateSSRC(); // Can't be 0. bitrates_->set_ssrc(ssrc_); // Random start, 16 bits. Can't be 0. - sequence_number_rtx_ = static_cast<uint16_t>(rand() + 1) & 0x7FFF; - sequence_number_ = static_cast<uint16_t>(rand() + 1) & 0x7FFF; + sequence_number_rtx_ = random_.Rand(1, kMaxInitRtpSeqNumber); + sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber); } RTPSender::~RTPSender() { @@ -292,7 +296,7 @@ int32_t RTPSender::RegisterPayload( const char payload_name[RTP_PAYLOAD_NAME_SIZE], int8_t payload_number, uint32_t frequency, - uint8_t channels, + size_t channels, uint32_t rate) { assert(payload_name); CriticalSectionScoped cs(send_critsect_.get()); @@ -323,11 +327,11 @@ int32_t RTPSender::RegisterPayload( return -1; } int32_t ret_val = 0; - RtpUtility::Payload* payload = NULL; + RtpUtility::Payload* payload = nullptr; if (audio_configured_) { // TODO(mflodman): Change to CreateAudioPayload and make static. ret_val = audio_->RegisterAudioPayload(payload_name, payload_number, - frequency, channels, rate, payload); + frequency, channels, rate, &payload); } else { payload = video_->CreateVideoPayload(payload_name, payload_number, rate); } @@ -452,7 +456,7 @@ int32_t RTPSender::CheckPayloadType(int8_t payload_type, } if (audio_configured_) { int8_t red_pl_type = -1; - if (audio_->RED(red_pl_type) == 0) { + if (audio_->RED(&red_pl_type) == 0) { // We have configured RED. if (red_pl_type == payload_type) { // And it's a match... @@ -469,7 +473,8 @@ int32_t RTPSender::CheckPayloadType(int8_t payload_type, std::map<int8_t, RtpUtility::Payload*>::iterator it = payload_type_map_.find(payload_type); if (it == payload_type_map_.end()) { - LOG(LS_WARNING) << "Payload type " << payload_type << " not registered."; + LOG(LS_WARNING) << "Payload type " << static_cast<int>(payload_type) + << " not registered."; return -1; } SetSendPayloadType(payload_type); @@ -512,7 +517,8 @@ int32_t RTPSender::SendOutgoingData(FrameType frame_type, } RtpVideoCodecTypes video_type = kRtpVideoGeneric; if (CheckPayloadType(payload_type, &video_type) != 0) { - LOG(LS_ERROR) << "Don't send data with unknown payload type."; + LOG(LS_ERROR) << "Don't send data with unknown payload type: " + << static_cast<int>(payload_type) << "."; return -1; } @@ -573,7 +579,7 @@ size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send) { break; RtpUtility::RtpHeaderParser rtp_parser(buffer, length); RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); bytes_left -= static_cast<int>(length - rtp_header.headerLength); } return bytes_to_send - bytes_left; @@ -583,8 +589,7 @@ void RTPSender::BuildPaddingPacket(uint8_t* packet, size_t header_length, size_t padding_length) { packet[0] |= 0x20; // Set padding bit. - int32_t *data = - reinterpret_cast<int32_t *>(&(packet[header_length])); + int32_t* data = reinterpret_cast<int32_t*>(&(packet[header_length])); // Fill data buffer with random data. for (size_t j = 0; j < (padding_length >> 2); ++j) { @@ -665,7 +670,7 @@ size_t RTPSender::SendPadData(size_t bytes, RtpUtility::RtpHeaderParser rtp_parser(padding_packet, length); RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); if (capture_time_ms > 0) { UpdateTransmissionTimeOffset( @@ -717,7 +722,7 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { if (paced_sender_) { RtpUtility::RtpHeaderParser rtp_parser(data_buffer, length); RTPHeader header; - if (!rtp_parser.Parse(header)) { + if (!rtp_parser.Parse(&header)) { assert(false); return -1; } @@ -725,7 +730,7 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { // TickTime. int64_t corrected_capture_tims_ms = capture_time_ms + clock_delta_ms_; paced_sender_->InsertPacket( - RtpPacketSender::kHighPriority, header.ssrc, header.sequenceNumber, + RtpPacketSender::kNormalPriority, header.ssrc, header.sequenceNumber, corrected_capture_tims_ms, length - header.headerLength, true); return length; @@ -903,11 +908,11 @@ bool RTPSender::PrepareAndSendPacket(uint8_t* buffer, int64_t capture_time_ms, bool send_over_rtx, bool is_retransmit) { - uint8_t *buffer_to_send_ptr = buffer; + uint8_t* buffer_to_send_ptr = buffer; RtpUtility::RtpHeaderParser rtp_parser(buffer, length); RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); if (!is_retransmit && rtp_header.markerBit) { TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PacedSend", capture_time_ms); @@ -996,14 +1001,14 @@ bool RTPSender::IsFecPacket(const uint8_t* buffer, bool fec_enabled; uint8_t pt_red; uint8_t pt_fec; - video_->GenericFECStatus(fec_enabled, pt_red, pt_fec); + video_->GenericFECStatus(&fec_enabled, &pt_red, &pt_fec); return fec_enabled && header.payloadType == pt_red && buffer[header.headerLength] == pt_fec; } size_t RTPSender::TimeToSendPadding(size_t bytes) { - if (bytes == 0) + if (audio_configured_ || bytes == 0) return 0; { CriticalSectionScoped cs(send_critsect_.get()); @@ -1026,7 +1031,7 @@ int32_t RTPSender::SendToNetwork(uint8_t* buffer, RtpUtility::RtpHeaderParser rtp_parser(buffer, payload_length + rtp_header_length); RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); int64_t now_ms = clock_->TimeInMilliseconds(); @@ -1169,7 +1174,7 @@ size_t RTPSender::CreateRtpHeader(uint8_t* header, int32_t rtp_header_length = kRtpHeaderLength; if (csrcs.size() > 0) { - uint8_t *ptr = &header[rtp_header_length]; + uint8_t* ptr = &header[rtp_header_length]; for (size_t i = 0; i < csrcs.size(); ++i) { ByteWriter<uint32_t>::WriteBigEndian(ptr, csrcs[i]); ptr += 4; @@ -1638,7 +1643,7 @@ uint16_t RTPSender::UpdateTransportSequenceNumber( void RTPSender::SetSendingStatus(bool enabled) { if (enabled) { uint32_t frequency_hz = SendPayloadFrequency(); - uint32_t RTPtime = RtpUtility::GetCurrentRTP(clock_, frequency_hz); + uint32_t RTPtime = CurrentRtp(*clock_, frequency_hz); // Will be ignored if it's already configured via API. SetStartTimestamp(RTPtime, false); @@ -1653,8 +1658,7 @@ void RTPSender::SetSendingStatus(bool enabled) { // Don't initialize seq number if SSRC passed externally. if (!sequence_number_forced_ && !ssrc_forced_) { // Generate a new sequence number. - sequence_number_ = - rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER); // NOLINT + sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber); } } } @@ -1716,8 +1720,7 @@ void RTPSender::SetSSRC(uint32_t ssrc) { ssrc_ = ssrc; bitrates_->set_ssrc(ssrc_); if (!sequence_number_forced_) { - sequence_number_ = - rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER); // NOLINT + sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber); } } @@ -1775,7 +1778,7 @@ int32_t RTPSender::RED(int8_t *payload_type) const { if (!audio_configured_) { return -1; } - return audio_->RED(*payload_type); + return audio_->RED(payload_type); } RtpVideoCodecTypes RTPSender::VideoCodecType() const { @@ -1801,7 +1804,7 @@ void RTPSender::GenericFECStatus(bool* enable, uint8_t* payload_type_red, uint8_t* payload_type_fec) const { RTC_DCHECK(!audio_configured_); - video_->GenericFECStatus(*enable, *payload_type_red, *payload_type_fec); + video_->GenericFECStatus(enable, payload_type_red, payload_type_fec); } int32_t RTPSender::SetFecParameters( @@ -1823,7 +1826,7 @@ void RTPSender::BuildRtxPacket(uint8_t* buffer, size_t* length, reinterpret_cast<const uint8_t*>(buffer), *length); RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); // Add original RTP header. memcpy(data_buffer_rtx, buffer, rtp_header.headerLength); @@ -1836,7 +1839,7 @@ void RTPSender::BuildRtxPacket(uint8_t* buffer, size_t* length, } // Replace sequence number. - uint8_t *ptr = data_buffer_rtx + 2; + uint8_t* ptr = data_buffer_rtx + 2; ByteWriter<uint16_t>::WriteBigEndian(ptr, sequence_number_rtx_++); // Replace SSRC. diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h index a134370c76..3c62336507 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h @@ -10,14 +10,16 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ -#include <assert.h> -#include <math.h> +#include <list> #include <map> +#include <utility> +#include <vector> +#include "webrtc/base/random.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" @@ -26,8 +28,6 @@ #include "webrtc/modules/rtp_rtcp/source/ssrc_database.h" #include "webrtc/transport.h" -#define MAX_INIT_RTP_SEQ_NUMBER 32767 // 2^15 -1. - namespace webrtc { class BitrateAggregator; @@ -116,7 +116,7 @@ class RTPSender : public RTPSenderInterface { int32_t RegisterPayload( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const int8_t payload_type, const uint32_t frequency, - const uint8_t channels, const uint32_t rate); + const size_t channels, const uint32_t rate); int32_t DeRegisterSendPayload(const int8_t payload_type); @@ -163,7 +163,7 @@ class RTPSender : public RTPSenderInterface { int32_t SetTransportSequenceNumber(uint16_t sequence_number); int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id); - virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override; + bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override; int32_t DeregisterRtpHeaderExtension(RTPExtensionType type); size_t RtpHeaderExtensionTotalLength() const; @@ -202,10 +202,10 @@ class RTPSender : public RTPSenderInterface { bool is_voiced, uint8_t dBov) const; - virtual bool UpdateVideoRotation(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - VideoRotation rotation) const override; + bool UpdateVideoRotation(uint8_t* rtp_packet, + size_t rtp_packet_length, + const RTPHeader& rtp_header, + VideoRotation rotation) const override; bool TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms, bool retransmission); @@ -386,6 +386,7 @@ class RTPSender : public RTPSenderInterface { Clock* clock_; int64_t clock_delta_ms_; + Random random_ GUARDED_BY(send_critsect_); rtc::scoped_ptr<BitrateAggregator> bitrates_; Bitrate total_bitrate_sent_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc index 1fc9a89ce1..2aa4961cdc 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc @@ -10,12 +10,12 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" -#include <assert.h> //assert -#include <string.h> //memcpy +#include <string.h> #include "webrtc/base/trace_event.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" +#include "webrtc/system_wrappers/include/tick_util.h" namespace webrtc { @@ -47,8 +47,7 @@ RTPSenderAudio::RTPSenderAudio(Clock* clock, _lastPayloadType(-1), _audioLevel_dBov(0) {} -RTPSenderAudio::~RTPSenderAudio() { -} +RTPSenderAudio::~RTPSenderAudio() {} int RTPSenderAudio::AudioFrequency() const { return kDtmfFrequencyHz; @@ -56,22 +55,20 @@ int RTPSenderAudio::AudioFrequency() const { // set audio packet size, used to determine when it's time to send a DTMF packet // in silence (CNG) -int32_t -RTPSenderAudio::SetAudioPacketSize(const uint16_t packetSizeSamples) -{ - CriticalSectionScoped cs(_sendAudioCritsect.get()); +int32_t RTPSenderAudio::SetAudioPacketSize(uint16_t packetSizeSamples) { + CriticalSectionScoped cs(_sendAudioCritsect.get()); - _packetSizeSamples = packetSizeSamples; - return 0; + _packetSizeSamples = packetSizeSamples; + return 0; } int32_t RTPSenderAudio::RegisterAudioPayload( const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int8_t payloadType, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate, - RtpUtility::Payload*& payload) { + RtpUtility::Payload** payload) { if (RtpUtility::StringCompare(payloadName, "cn", 2)) { CriticalSectionScoped cs(_sendAudioCritsect.get()); // we can have multiple CNG payload types @@ -99,72 +96,65 @@ int32_t RTPSenderAudio::RegisterAudioPayload( return 0; // The default timestamp rate is 8000 Hz, but other rates may be defined. } - payload = new RtpUtility::Payload; - payload->typeSpecific.Audio.frequency = frequency; - payload->typeSpecific.Audio.channels = channels; - payload->typeSpecific.Audio.rate = rate; - payload->audio = true; - payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0'; - strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); + *payload = new RtpUtility::Payload; + (*payload)->typeSpecific.Audio.frequency = frequency; + (*payload)->typeSpecific.Audio.channels = channels; + (*payload)->typeSpecific.Audio.rate = rate; + (*payload)->audio = true; + (*payload)->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0'; + strncpy((*payload)->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); return 0; } -bool -RTPSenderAudio::MarkerBit(const FrameType frameType, - const int8_t payload_type) -{ - CriticalSectionScoped cs(_sendAudioCritsect.get()); - // for audio true for first packet in a speech burst - bool markerBit = false; - if (_lastPayloadType != payload_type) { - if (payload_type != -1 && (_cngNBPayloadType == payload_type || - _cngWBPayloadType == payload_type || - _cngSWBPayloadType == payload_type || - _cngFBPayloadType == payload_type)) { - // Only set a marker bit when we change payload type to a non CNG - return false; - } +bool RTPSenderAudio::MarkerBit(FrameType frameType, int8_t payload_type) { + CriticalSectionScoped cs(_sendAudioCritsect.get()); + // for audio true for first packet in a speech burst + bool markerBit = false; + if (_lastPayloadType != payload_type) { + if (payload_type != -1 && (_cngNBPayloadType == payload_type || + _cngWBPayloadType == payload_type || + _cngSWBPayloadType == payload_type || + _cngFBPayloadType == payload_type)) { + // Only set a marker bit when we change payload type to a non CNG + return false; + } - // payload_type differ - if (_lastPayloadType == -1) { - if (frameType != kAudioFrameCN) { - // first packet and NOT CNG - return true; - } else { - // first packet and CNG - _inbandVADactive = true; - return false; - } + // payload_type differ + if (_lastPayloadType == -1) { + if (frameType != kAudioFrameCN) { + // first packet and NOT CNG + return true; + } else { + // first packet and CNG + _inbandVADactive = true; + return false; } - - // not first packet AND - // not CNG AND - // payload_type changed - - // set a marker bit when we change payload type - markerBit = true; } - // For G.723 G.729, AMR etc we can have inband VAD - if(frameType == kAudioFrameCN) - { - _inbandVADactive = true; + // not first packet AND + // not CNG AND + // payload_type changed - } else if(_inbandVADactive) - { - _inbandVADactive = false; - markerBit = true; - } - return markerBit; + // set a marker bit when we change payload type + markerBit = true; + } + + // For G.723 G.729, AMR etc we can have inband VAD + if (frameType == kAudioFrameCN) { + _inbandVADactive = true; + } else if (_inbandVADactive) { + _inbandVADactive = false; + markerBit = true; + } + return markerBit; } -int32_t RTPSenderAudio::SendAudio( - const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const uint8_t* payloadData, - const size_t dataSize, - const RTPFragmentationHeader* fragmentation) { +int32_t RTPSenderAudio::SendAudio(FrameType frameType, + int8_t payloadType, + uint32_t captureTimeStamp, + const uint8_t* payloadData, + size_t dataSize, + const RTPFragmentationHeader* fragmentation) { // TODO(pwestin) Breakup function in smaller functions. size_t payloadSize = dataSize; size_t maxPayloadLength = _rtpSender->MaxPayloadLength(); @@ -185,8 +175,8 @@ int32_t RTPSenderAudio::SendAudio( // Check if we have pending DTMFs to send if (!_dtmfEventIsOn && PendingDTMF()) { - int64_t delaySinceLastDTMF = _clock->TimeInMilliseconds() - - _dtmfTimeLastSent; + int64_t delaySinceLastDTMF = + _clock->TimeInMilliseconds() - _dtmfTimeLastSent; if (delaySinceLastDTMF > 100) { // New tone to play @@ -294,128 +284,120 @@ int32_t RTPSenderAudio::SendAudio( // Too large payload buffer. return -1; } - if (red_payload_type >= 0 && // Have we configured RED? - fragmentation && fragmentation->fragmentationVectorSize > 1 && - !markerBit) { - if (timestampOffset <= 0x3fff) { - if (fragmentation->fragmentationVectorSize != 2) { - // we only support 2 codecs when using RED - return -1; - } - // only 0x80 if we have multiple blocks - dataBuffer[rtpHeaderLength++] = - 0x80 + fragmentation->fragmentationPlType[1]; - size_t blockLength = fragmentation->fragmentationLength[1]; - - // sanity blockLength - if (blockLength > 0x3ff) { // block length 10 bits 1023 bytes - return -1; - } - uint32_t REDheader = (timestampOffset << 10) + blockLength; - ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + rtpHeaderLength, - REDheader); - rtpHeaderLength += 3; - - dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; - // copy the RED data - memcpy(dataBuffer + rtpHeaderLength, - payloadData + fragmentation->fragmentationOffset[1], - fragmentation->fragmentationLength[1]); - - // copy the normal data - memcpy(dataBuffer + rtpHeaderLength + - fragmentation->fragmentationLength[1], - payloadData + fragmentation->fragmentationOffset[0], - fragmentation->fragmentationLength[0]); - - payloadSize = fragmentation->fragmentationLength[0] + - fragmentation->fragmentationLength[1]; - } else { - // silence for too long send only new data - dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; - memcpy(dataBuffer + rtpHeaderLength, - payloadData + fragmentation->fragmentationOffset[0], - fragmentation->fragmentationLength[0]); + if (red_payload_type >= 0 && // Have we configured RED? + fragmentation && fragmentation->fragmentationVectorSize > 1 && + !markerBit) { + if (timestampOffset <= 0x3fff) { + if (fragmentation->fragmentationVectorSize != 2) { + // we only support 2 codecs when using RED + return -1; + } + // only 0x80 if we have multiple blocks + dataBuffer[rtpHeaderLength++] = + 0x80 + fragmentation->fragmentationPlType[1]; + size_t blockLength = fragmentation->fragmentationLength[1]; - payloadSize = fragmentation->fragmentationLength[0]; + // sanity blockLength + if (blockLength > 0x3ff) { // block length 10 bits 1023 bytes + return -1; } + uint32_t REDheader = (timestampOffset << 10) + blockLength; + ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + rtpHeaderLength, + REDheader); + rtpHeaderLength += 3; + + dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; + // copy the RED data + memcpy(dataBuffer + rtpHeaderLength, + payloadData + fragmentation->fragmentationOffset[1], + fragmentation->fragmentationLength[1]); + + // copy the normal data + memcpy( + dataBuffer + rtpHeaderLength + fragmentation->fragmentationLength[1], + payloadData + fragmentation->fragmentationOffset[0], + fragmentation->fragmentationLength[0]); + + payloadSize = fragmentation->fragmentationLength[0] + + fragmentation->fragmentationLength[1]; } else { - if (fragmentation && fragmentation->fragmentationVectorSize > 0) { - // use the fragment info if we have one - dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; - memcpy(dataBuffer + rtpHeaderLength, - payloadData + fragmentation->fragmentationOffset[0], - fragmentation->fragmentationLength[0]); - - payloadSize = fragmentation->fragmentationLength[0]; - } else { - memcpy(dataBuffer + rtpHeaderLength, payloadData, payloadSize); - } + // silence for too long send only new data + dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; + memcpy(dataBuffer + rtpHeaderLength, + payloadData + fragmentation->fragmentationOffset[0], + fragmentation->fragmentationLength[0]); + + payloadSize = fragmentation->fragmentationLength[0]; } - { - CriticalSectionScoped cs(_sendAudioCritsect.get()); - _lastPayloadType = payloadType; + } else { + if (fragmentation && fragmentation->fragmentationVectorSize > 0) { + // use the fragment info if we have one + dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0]; + memcpy(dataBuffer + rtpHeaderLength, + payloadData + fragmentation->fragmentationOffset[0], + fragmentation->fragmentationLength[0]); + + payloadSize = fragmentation->fragmentationLength[0]; + } else { + memcpy(dataBuffer + rtpHeaderLength, payloadData, payloadSize); } - // Update audio level extension, if included. - size_t packetSize = payloadSize + rtpHeaderLength; - RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize); - RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); - _rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header, - (frameType == kAudioFrameSpeech), - audio_level_dbov); - TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp, "timestamp", - _rtpSender->Timestamp(), "seqnum", - _rtpSender->SequenceNumber()); - return _rtpSender->SendToNetwork(dataBuffer, payloadSize, rtpHeaderLength, - -1, kAllowRetransmission, - RtpPacketSender::kHighPriority); } - - // Audio level magnitude and voice activity flag are set for each RTP packet -int32_t -RTPSenderAudio::SetAudioLevel(const uint8_t level_dBov) -{ - if (level_dBov > 127) - { - return -1; - } + { CriticalSectionScoped cs(_sendAudioCritsect.get()); - _audioLevel_dBov = level_dBov; - return 0; + _lastPayloadType = payloadType; + } + // Update audio level extension, if included. + size_t packetSize = payloadSize + rtpHeaderLength; + RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize); + RTPHeader rtp_header; + rtp_parser.Parse(&rtp_header); + _rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header, + (frameType == kAudioFrameSpeech), + audio_level_dbov); + TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp, "timestamp", + _rtpSender->Timestamp(), "seqnum", + _rtpSender->SequenceNumber()); + return _rtpSender->SendToNetwork(dataBuffer, payloadSize, rtpHeaderLength, + TickTime::MillisecondTimestamp(), + kAllowRetransmission, + RtpPacketSender::kHighPriority); } - // Set payload type for Redundant Audio Data RFC 2198 -int32_t -RTPSenderAudio::SetRED(const int8_t payloadType) -{ - if(payloadType < -1 ) - { - return -1; - } - CriticalSectionScoped cs(_sendAudioCritsect.get()); - _REDPayloadType = payloadType; - return 0; +// Audio level magnitude and voice activity flag are set for each RTP packet +int32_t RTPSenderAudio::SetAudioLevel(uint8_t level_dBov) { + if (level_dBov > 127) { + return -1; + } + CriticalSectionScoped cs(_sendAudioCritsect.get()); + _audioLevel_dBov = level_dBov; + return 0; } - // Get payload type for Redundant Audio Data RFC 2198 -int32_t -RTPSenderAudio::RED(int8_t& payloadType) const -{ - CriticalSectionScoped cs(_sendAudioCritsect.get()); - if(_REDPayloadType == -1) - { - // not configured - return -1; - } - payloadType = _REDPayloadType; - return 0; +// Set payload type for Redundant Audio Data RFC 2198 +int32_t RTPSenderAudio::SetRED(int8_t payloadType) { + if (payloadType < -1) { + return -1; + } + CriticalSectionScoped cs(_sendAudioCritsect.get()); + _REDPayloadType = payloadType; + return 0; +} + +// Get payload type for Redundant Audio Data RFC 2198 +int32_t RTPSenderAudio::RED(int8_t* payloadType) const { + CriticalSectionScoped cs(_sendAudioCritsect.get()); + if (_REDPayloadType == -1) { + // not configured + return -1; + } + *payloadType = _REDPayloadType; + return 0; } // Send a TelephoneEvent tone using RFC 2833 (4733) -int32_t RTPSenderAudio::SendTelephoneEvent(const uint8_t key, - const uint16_t time_ms, - const uint8_t level) { +int32_t RTPSenderAudio::SendTelephoneEvent(uint8_t key, + uint16_t time_ms, + uint8_t level) { { CriticalSectionScoped lock(_sendAudioCritsect.get()); if (_dtmfPayloadType < 0) { @@ -426,63 +408,57 @@ int32_t RTPSenderAudio::SendTelephoneEvent(const uint8_t key, return AddDTMF(key, time_ms, level); } -int32_t -RTPSenderAudio::SendTelephoneEventPacket(bool ended, - int8_t dtmf_payload_type, - uint32_t dtmfTimeStamp, - uint16_t duration, - bool markerBit) -{ - uint8_t dtmfbuffer[IP_PACKET_SIZE]; - uint8_t sendCount = 1; - int32_t retVal = 0; - - if(ended) - { - // resend last packet in an event 3 times - sendCount = 3; - } - do - { - //Send DTMF data - _rtpSender->BuildRTPheader(dtmfbuffer, dtmf_payload_type, markerBit, - dtmfTimeStamp, _clock->TimeInMilliseconds()); - - // reset CSRC and X bit - dtmfbuffer[0] &= 0xe0; - - //Create DTMF data - /* From RFC 2833: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | event |E|R| volume | duration | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - // R bit always cleared - uint8_t R = 0x00; - uint8_t volume = _dtmfLevel; - - // First packet un-ended - uint8_t E = ended ? 0x80 : 0x00; - - // First byte is Event number, equals key number - dtmfbuffer[12] = _dtmfKey; - dtmfbuffer[13] = E|R|volume; - ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 14, duration); - - TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), - "Audio::SendTelephoneEvent", "timestamp", - dtmfTimeStamp, "seqnum", - _rtpSender->SequenceNumber()); - retVal = _rtpSender->SendToNetwork(dtmfbuffer, 4, 12, -1, - kAllowRetransmission, - RtpPacketSender::kHighPriority); - sendCount--; - - }while (sendCount > 0 && retVal == 0); - - return retVal; +int32_t RTPSenderAudio::SendTelephoneEventPacket(bool ended, + int8_t dtmf_payload_type, + uint32_t dtmfTimeStamp, + uint16_t duration, + bool markerBit) { + uint8_t dtmfbuffer[IP_PACKET_SIZE]; + uint8_t sendCount = 1; + int32_t retVal = 0; + + if (ended) { + // resend last packet in an event 3 times + sendCount = 3; + } + do { + // Send DTMF data + _rtpSender->BuildRTPheader(dtmfbuffer, dtmf_payload_type, markerBit, + dtmfTimeStamp, _clock->TimeInMilliseconds()); + + // reset CSRC and X bit + dtmfbuffer[0] &= 0xe0; + + // Create DTMF data + /* From RFC 2833: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | event |E|R| volume | duration | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + // R bit always cleared + uint8_t R = 0x00; + uint8_t volume = _dtmfLevel; + + // First packet un-ended + uint8_t E = ended ? 0x80 : 0x00; + + // First byte is Event number, equals key number + dtmfbuffer[12] = _dtmfKey; + dtmfbuffer[13] = E | R | volume; + ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 14, duration); + + TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), + "Audio::SendTelephoneEvent", "timestamp", + dtmfTimeStamp, "seqnum", _rtpSender->SequenceNumber()); + retVal = _rtpSender->SendToNetwork( + dtmfbuffer, 4, 12, TickTime::MillisecondTimestamp(), + kAllowRetransmission, RtpPacketSender::kHighPriority); + sendCount--; + } while (sendCount > 0 && retVal == 0); + + return retVal; } } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h index dd16fe51b4..1e96d17a67 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h @@ -19,92 +19,91 @@ #include "webrtc/typedefs.h" namespace webrtc { -class RTPSenderAudio: public DTMFqueue -{ -public: - RTPSenderAudio(Clock* clock, - RTPSender* rtpSender, - RtpAudioFeedback* audio_feedback); - virtual ~RTPSenderAudio(); - - int32_t RegisterAudioPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int8_t payloadType, - const uint32_t frequency, - const uint8_t channels, - const uint32_t rate, - RtpUtility::Payload*& payload); - - int32_t SendAudio(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - const uint8_t* payloadData, - const size_t payloadSize, - const RTPFragmentationHeader* fragmentation); - - // set audio packet size, used to determine when it's time to send a DTMF packet in silence (CNG) - int32_t SetAudioPacketSize(const uint16_t packetSizeSamples); - - // Store the audio level in dBov for header-extension-for-audio-level-indication. - // Valid range is [0,100]. Actual value is negative. - int32_t SetAudioLevel(const uint8_t level_dBov); - - // Send a DTMF tone using RFC 2833 (4733) - int32_t SendTelephoneEvent(const uint8_t key, - const uint16_t time_ms, - const uint8_t level); - - int AudioFrequency() const; - - // Set payload type for Redundant Audio Data RFC 2198 - int32_t SetRED(const int8_t payloadType); - - // Get payload type for Redundant Audio Data RFC 2198 - int32_t RED(int8_t& payloadType) const; - -protected: - int32_t SendTelephoneEventPacket(bool ended, - int8_t dtmf_payload_type, - uint32_t dtmfTimeStamp, - uint16_t duration, - bool markerBit); // set on first packet in talk burst - - bool MarkerBit(const FrameType frameType, - const int8_t payloadType); - -private: - Clock* const _clock; - RTPSender* const _rtpSender; - RtpAudioFeedback* const _audioFeedback; - - rtc::scoped_ptr<CriticalSectionWrapper> _sendAudioCritsect; - - uint16_t _packetSizeSamples GUARDED_BY(_sendAudioCritsect); - - // DTMF - bool _dtmfEventIsOn; - bool _dtmfEventFirstPacketSent; - int8_t _dtmfPayloadType GUARDED_BY(_sendAudioCritsect); - uint32_t _dtmfTimestamp; - uint8_t _dtmfKey; - uint32_t _dtmfLengthSamples; - uint8_t _dtmfLevel; - int64_t _dtmfTimeLastSent; - uint32_t _dtmfTimestampLastSent; - - int8_t _REDPayloadType GUARDED_BY(_sendAudioCritsect); - - // VAD detection, used for markerbit - bool _inbandVADactive GUARDED_BY(_sendAudioCritsect); - int8_t _cngNBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _cngWBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _cngSWBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _cngFBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _lastPayloadType GUARDED_BY(_sendAudioCritsect); - - // Audio level indication - // (https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/) - uint8_t _audioLevel_dBov GUARDED_BY(_sendAudioCritsect); +class RTPSenderAudio : public DTMFqueue { + public: + RTPSenderAudio(Clock* clock, + RTPSender* rtpSender, + RtpAudioFeedback* audio_feedback); + virtual ~RTPSenderAudio(); + + int32_t RegisterAudioPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE], + int8_t payloadType, + uint32_t frequency, + size_t channels, + uint32_t rate, + RtpUtility::Payload** payload); + + int32_t SendAudio(FrameType frameType, + int8_t payloadType, + uint32_t captureTimeStamp, + const uint8_t* payloadData, + size_t payloadSize, + const RTPFragmentationHeader* fragmentation); + + // set audio packet size, used to determine when it's time to send a DTMF + // packet in silence (CNG) + int32_t SetAudioPacketSize(uint16_t packetSizeSamples); + + // Store the audio level in dBov for + // header-extension-for-audio-level-indication. + // Valid range is [0,100]. Actual value is negative. + int32_t SetAudioLevel(uint8_t level_dBov); + + // Send a DTMF tone using RFC 2833 (4733) + int32_t SendTelephoneEvent(uint8_t key, uint16_t time_ms, uint8_t level); + + int AudioFrequency() const; + + // Set payload type for Redundant Audio Data RFC 2198 + int32_t SetRED(int8_t payloadType); + + // Get payload type for Redundant Audio Data RFC 2198 + int32_t RED(int8_t* payloadType) const; + + protected: + int32_t SendTelephoneEventPacket( + bool ended, + int8_t dtmf_payload_type, + uint32_t dtmfTimeStamp, + uint16_t duration, + bool markerBit); // set on first packet in talk burst + + bool MarkerBit(const FrameType frameType, const int8_t payloadType); + + private: + Clock* const _clock; + RTPSender* const _rtpSender; + RtpAudioFeedback* const _audioFeedback; + + rtc::scoped_ptr<CriticalSectionWrapper> _sendAudioCritsect; + + uint16_t _packetSizeSamples GUARDED_BY(_sendAudioCritsect); + + // DTMF + bool _dtmfEventIsOn; + bool _dtmfEventFirstPacketSent; + int8_t _dtmfPayloadType GUARDED_BY(_sendAudioCritsect); + uint32_t _dtmfTimestamp; + uint8_t _dtmfKey; + uint32_t _dtmfLengthSamples; + uint8_t _dtmfLevel; + int64_t _dtmfTimeLastSent; + uint32_t _dtmfTimestampLastSent; + + int8_t _REDPayloadType GUARDED_BY(_sendAudioCritsect); + + // VAD detection, used for markerbit + bool _inbandVADactive GUARDED_BY(_sendAudioCritsect); + int8_t _cngNBPayloadType GUARDED_BY(_sendAudioCritsect); + int8_t _cngWBPayloadType GUARDED_BY(_sendAudioCritsect); + int8_t _cngSWBPayloadType GUARDED_BY(_sendAudioCritsect); + int8_t _cngFBPayloadType GUARDED_BY(_sendAudioCritsect); + int8_t _lastPayloadType GUARDED_BY(_sendAudioCritsect); + + // Audio level indication + // (https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/) + uint8_t _audioLevel_dBov GUARDED_BY(_sendAudioCritsect); }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_AUDIO_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_AUDIO_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc index fde6d47ceb..6bc122201a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -12,20 +12,22 @@ * This file includes unit tests for the RTPSender. */ +#include <list> +#include <vector> + #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" - #include "webrtc/base/buffer.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_cvo.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" -#include "webrtc/system_wrappers/include/stl_util.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" +#include "webrtc/system_wrappers/include/stl_util.h" #include "webrtc/test/mock_transport.h" #include "webrtc/typedefs.h" @@ -90,9 +92,7 @@ class LoopbackTransportTest : public webrtc::Transport { sent_packets_.push_back(buffer); return true; } - bool SendRtcp(const uint8_t* data, size_t len) override { - return false; - } + bool SendRtcp(const uint8_t* data, size_t len) override { return false; } int packets_sent_; size_t last_sent_packet_len_; size_t total_bytes_sent_; @@ -163,11 +163,8 @@ class RtpSenderTest : public ::testing::Test { void SendPacket(int64_t capture_time_ms, int payload_length) { uint32_t timestamp = capture_time_ms * 90; - int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_, - kPayload, - kMarkerBit, - timestamp, - capture_time_ms); + int32_t rtp_length = rtp_sender_->BuildRTPheader( + packet_, kPayload, kMarkerBit, timestamp, capture_time_ms); ASSERT_GE(rtp_length, 0); // Packet should be stored in a send bucket. @@ -186,7 +183,7 @@ class RtpSenderTestWithoutPacer : public RtpSenderTest { class RtpSenderVideoTest : public RtpSenderTest { protected: - virtual void SetUp() override { + void SetUp() override { // TODO(pbos): Set up to use pacer. SetUpRtpSender(false); rtp_sender_video_.reset( @@ -211,7 +208,7 @@ class RtpSenderVideoTest : public RtpSenderTest { } else { ASSERT_EQ(kRtpHeaderSize, length); } - ASSERT_TRUE(rtp_parser.Parse(rtp_header, map)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header, map)); ASSERT_FALSE(rtp_parser.RTCP()); EXPECT_EQ(payload_, rtp_header.payloadType); EXPECT_EQ(seq_num, rtp_header.sequenceNumber); @@ -228,53 +225,57 @@ TEST_F(RtpSenderTestWithoutPacer, RegisterRtpTransmissionTimeOffsetHeaderExtension) { EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength, rtp_sender_->RtpHeaderExtensionTotalLength()); EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset)); + kRtpExtensionTransmissionTimeOffset)); EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); } TEST_F(RtpSenderTestWithoutPacer, RegisterRtpAbsoluteSendTimeHeaderExtension) { EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength), rtp_sender_->RtpHeaderExtensionTotalLength()); EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime)); + kRtpExtensionAbsoluteSendTime)); EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); } TEST_F(RtpSenderTestWithoutPacer, RegisterRtpAudioLevelHeaderExtension) { EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAudioLevel, kAudioLevelExtensionId)); + EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, + kAudioLevelExtensionId)); EXPECT_EQ( RtpUtility::Word32Align(kRtpOneByteHeaderLength + kAudioLevelLength), rtp_sender_->RtpHeaderExtensionTotalLength()); - EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension( - kRtpExtensionAudioLevel)); + EXPECT_EQ(0, + rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel)); EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); } TEST_F(RtpSenderTestWithoutPacer, RegisterRtpHeaderExtensions) { EXPECT_EQ(0u, rtp_sender_->RtpHeaderExtensionTotalLength()); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength), rtp_sender_->RtpHeaderExtensionTotalLength()); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength + kAbsoluteSendTimeLength), rtp_sender_->RtpHeaderExtensionTotalLength()); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAudioLevel, kAudioLevelExtensionId)); + EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, + kAudioLevelExtensionId)); EXPECT_EQ(RtpUtility::Word32Align( kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength + kAbsoluteSendTimeLength + kAudioLevelLength), @@ -290,18 +291,18 @@ TEST_F(RtpSenderTestWithoutPacer, RegisterRtpHeaderExtensions) { // Deregister starts. EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset)); + kRtpExtensionTransmissionTimeOffset)); EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength + kAudioLevelLength + kVideoRotationLength), rtp_sender_->RtpHeaderExtensionTotalLength()); EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime)); + kRtpExtensionAbsoluteSendTime)); EXPECT_EQ(RtpUtility::Word32Align(kRtpOneByteHeaderLength + kAudioLevelLength + kVideoRotationLength), rtp_sender_->RtpHeaderExtensionTotalLength()); - EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension( - kRtpExtensionAudioLevel)); + EXPECT_EQ(0, + rtp_sender_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel)); EXPECT_EQ( RtpUtility::Word32Align(kRtpOneByteHeaderLength + kVideoRotationLength), rtp_sender_->RtpHeaderExtensionTotalLength()); @@ -334,7 +335,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacket) { webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length); webrtc::RTPHeader rtp_header; - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, nullptr); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, nullptr); ASSERT_TRUE(valid_rtp_header); ASSERT_FALSE(rtp_parser.RTCP()); @@ -354,7 +355,8 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithTransmissionOffsetExtension) { EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kTimeOffset)); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); size_t length = static_cast<size_t>(rtp_sender_->BuildRTPheader( packet_, kPayload, kMarkerBit, kTimestamp, 0)); @@ -368,7 +370,7 @@ TEST_F(RtpSenderTestWithoutPacer, RtpHeaderExtensionMap map; map.Register(kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); ASSERT_FALSE(rtp_parser.RTCP()); @@ -379,7 +381,7 @@ TEST_F(RtpSenderTestWithoutPacer, // Parse without map extension webrtc::RTPHeader rtp_header2; - const bool valid_rtp_header2 = rtp_parser.Parse(rtp_header2, nullptr); + const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr); ASSERT_TRUE(valid_rtp_header2); VerifyRTPHeaderCommon(rtp_header2); @@ -393,7 +395,8 @@ TEST_F(RtpSenderTestWithoutPacer, const int kNegTimeOffset = -500; EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kNegTimeOffset)); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); size_t length = static_cast<size_t>(rtp_sender_->BuildRTPheader( packet_, kPayload, kMarkerBit, kTimestamp, 0)); @@ -407,7 +410,7 @@ TEST_F(RtpSenderTestWithoutPacer, RtpHeaderExtensionMap map; map.Register(kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); ASSERT_FALSE(rtp_parser.RTCP()); @@ -419,8 +422,9 @@ TEST_F(RtpSenderTestWithoutPacer, TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAbsoluteSendTimeExtension) { EXPECT_EQ(0, rtp_sender_->SetAbsoluteSendTime(kAbsoluteSendTime)); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); size_t length = static_cast<size_t>(rtp_sender_->BuildRTPheader( packet_, kPayload, kMarkerBit, kTimestamp, 0)); @@ -433,7 +437,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAbsoluteSendTimeExtension) { RtpHeaderExtensionMap map; map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); ASSERT_FALSE(rtp_parser.RTCP()); @@ -444,7 +448,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAbsoluteSendTimeExtension) { // Parse without map extension webrtc::RTPHeader rtp_header2; - const bool valid_rtp_header2 = rtp_parser.Parse(rtp_header2, nullptr); + const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr); ASSERT_TRUE(valid_rtp_header2); VerifyRTPHeaderCommon(rtp_header2); @@ -472,7 +476,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithVideoRotation_MarkerBit) { webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length); webrtc::RTPHeader rtp_header; - ASSERT_TRUE(rtp_parser.Parse(rtp_header, &map)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header, &map)); ASSERT_FALSE(rtp_parser.RTCP()); VerifyRTPHeaderCommon(rtp_header); EXPECT_EQ(length, rtp_header.headerLength); @@ -500,7 +504,7 @@ TEST_F(RtpSenderTestWithoutPacer, webrtc::RtpUtility::RtpHeaderParser rtp_parser(packet_, length); webrtc::RTPHeader rtp_header; - ASSERT_TRUE(rtp_parser.Parse(rtp_header, &map)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header, &map)); ASSERT_FALSE(rtp_parser.RTCP()); VerifyRTPHeaderCommon(rtp_header, false); EXPECT_EQ(length, rtp_header.headerLength); @@ -508,8 +512,8 @@ TEST_F(RtpSenderTestWithoutPacer, } TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAudioLevelExtension) { - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAudioLevel, kAudioLevelExtensionId)); + EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, + kAudioLevelExtensionId)); size_t length = static_cast<size_t>(rtp_sender_->BuildRTPheader( packet_, kPayload, kMarkerBit, kTimestamp, 0)); @@ -521,12 +525,12 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAudioLevelExtension) { webrtc::RTPHeader rtp_header; // Updating audio level is done in RTPSenderAudio, so simulate it here. - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true, kAudioLevel); RtpHeaderExtensionMap map; map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); ASSERT_FALSE(rtp_parser.RTCP()); @@ -538,7 +542,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithAudioLevelExtension) { // Parse without map extension webrtc::RTPHeader rtp_header2; - const bool valid_rtp_header2 = rtp_parser.Parse(rtp_header2, nullptr); + const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr); ASSERT_TRUE(valid_rtp_header2); VerifyRTPHeaderCommon(rtp_header2); @@ -554,11 +558,13 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithHeaderExtensions) { EXPECT_EQ(0, rtp_sender_->SetTransportSequenceNumber(kTransportSequenceNumber)); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAudioLevel, kAudioLevelExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); + EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, + kAudioLevelExtensionId)); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( kRtpExtensionTransportSequenceNumber, kTransportSequenceNumberExtensionId)); @@ -573,7 +579,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithHeaderExtensions) { webrtc::RTPHeader rtp_header; // Updating audio level is done in RTPSenderAudio, so simulate it here. - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true, kAudioLevel); RtpHeaderExtensionMap map; @@ -583,7 +589,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithHeaderExtensions) { map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId); map.Register(kRtpExtensionTransportSequenceNumber, kTransportSequenceNumberExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); ASSERT_FALSE(rtp_parser.RTCP()); @@ -602,7 +608,7 @@ TEST_F(RtpSenderTestWithoutPacer, BuildRTPPacketWithHeaderExtensions) { // Parse without map extension webrtc::RTPHeader rtp_header2; - const bool valid_rtp_header2 = rtp_parser.Parse(rtp_header2, nullptr); + const bool valid_rtp_header2 = rtp_parser.Parse(&rtp_header2, nullptr); ASSERT_TRUE(valid_rtp_header2); VerifyRTPHeaderCommon(rtp_header2); @@ -626,9 +632,11 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) { rtp_sender_->SetStorePacketsStatus(true, 10); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); rtp_sender_->SetTargetBitrate(300000); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); int rtp_length_int = rtp_sender_->BuildRTPheader( @@ -659,7 +667,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) { map.Register(kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId); map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); // Verify transmission time offset. @@ -676,9 +684,11 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) { rtp_sender_->SetStorePacketsStatus(true, 10); EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); rtp_sender_->SetTargetBitrate(300000); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); int rtp_length_int = rtp_sender_->BuildRTPheader( @@ -717,7 +727,7 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) { map.Register(kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId); map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId); - const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map); + const bool valid_rtp_header = rtp_parser.Parse(&rtp_header, &map); ASSERT_TRUE(valid_rtp_header); // Verify transmission time offset. @@ -740,10 +750,12 @@ TEST_F(RtpSenderTest, SendPadding) { rtp_sender_->SetStorePacketsStatus(true, 10); size_t rtp_header_len = kRtpHeaderSize; EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId)); + kRtpExtensionTransmissionTimeOffset, + kTransmissionTimeOffsetExtensionId)); rtp_header_len += 4; // 4 bytes extension. - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); rtp_header_len += 4; // 4 bytes extension. rtp_header_len += 4; // 4 extra bytes common to all extension headers. @@ -815,8 +827,8 @@ TEST_F(RtpSenderTest, SendPadding) { // Send a regular video packet again. capture_time_ms = fake_clock_.TimeInMilliseconds(); - rtp_length_int = rtp_sender_->BuildRTPheader( - packet_, kPayload, kMarkerBit, timestamp, capture_time_ms); + rtp_length_int = rtp_sender_->BuildRTPheader(packet_, kPayload, kMarkerBit, + timestamp, capture_time_ms); ASSERT_NE(-1, rtp_length_int); rtp_length = static_cast<size_t>(rtp_length_int); @@ -830,8 +842,8 @@ TEST_F(RtpSenderTest, SendPadding) { EXPECT_EQ(++total_packets_sent, transport_.packets_sent_); EXPECT_EQ(rtp_length, transport_.last_sent_packet_len_); // Parse sent packet. - ASSERT_TRUE(rtp_parser->Parse(transport_.last_sent_packet_, rtp_length, - &rtp_header)); + ASSERT_TRUE( + rtp_parser->Parse(transport_.last_sent_packet_, rtp_length, &rtp_header)); // Verify sequence number and timestamp. EXPECT_EQ(seq_num, rtp_header.sequenceNumber); @@ -858,8 +870,9 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) { uint16_t seq_num = kSeqNum; rtp_sender_->SetStorePacketsStatus(true, 10); int32_t rtp_header_len = kRtpHeaderSize; - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId)); + EXPECT_EQ( + 0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime, + kAbsoluteSendTimeExtensionId)); rtp_header_len += 4; // 4 bytes extension. rtp_header_len += 4; // 4 extra bytes common to all extension headers. @@ -876,8 +889,8 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) { kAbsoluteSendTimeExtensionId); rtp_sender_->SetTargetBitrate(300000); const size_t kNumPayloadSizes = 10; - const size_t kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700, 750, - 800, 850, 900, 950}; + const size_t kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700, + 750, 800, 850, 900, 950}; // Send 10 packets of increasing size. for (size_t i = 0; i < kNumPayloadSizes; ++i) { int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); @@ -921,10 +934,10 @@ TEST_F(RtpSenderTestWithoutPacer, SendGenericVideo) { RtpUtility::RtpHeaderParser rtp_parser(transport_.last_sent_packet_, transport_.last_sent_packet_len_); webrtc::RTPHeader rtp_header; - ASSERT_TRUE(rtp_parser.Parse(rtp_header)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header)); - const uint8_t* payload_data = GetPayloadData(rtp_header, - transport_.last_sent_packet_); + const uint8_t* payload_data = + GetPayloadData(rtp_header, transport_.last_sent_packet_); uint8_t generic_header = *payload_data++; ASSERT_EQ(sizeof(payload) + sizeof(generic_header), @@ -946,7 +959,7 @@ TEST_F(RtpSenderTestWithoutPacer, SendGenericVideo) { RtpUtility::RtpHeaderParser rtp_parser2(transport_.last_sent_packet_, transport_.last_sent_packet_len_); - ASSERT_TRUE(rtp_parser.Parse(rtp_header)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header)); payload_data = GetPayloadData(rtp_header, transport_.last_sent_packet_); generic_header = *payload_data++; @@ -1043,9 +1056,8 @@ TEST_F(RtpSenderTest, BitrateCallbacks) { char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC"; const uint8_t payload_type = 127; - ASSERT_EQ( - 0, - rtp_sender_->RegisterPayload(payload_name, payload_type, 90000, 0, 1500)); + ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000, + 0, 1500)); uint8_t payload[] = {47, 11, 32, 93, 89}; rtp_sender_->SetStorePacketsStatus(true, 1); uint32_t ssrc = rtp_sender_->SSRC(); @@ -1057,13 +1069,8 @@ TEST_F(RtpSenderTest, BitrateCallbacks) { // Send a few frames. for (uint32_t i = 0; i < kNumPackets; ++i) { ASSERT_EQ(0, - rtp_sender_->SendOutgoingData(kVideoFrameKey, - payload_type, - 1234, - 4321, - payload, - sizeof(payload), - 0)); + rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234, + 4321, payload, sizeof(payload), 0)); fake_clock_.AdvanceTimeMilliseconds(kPacketInterval); } @@ -1100,8 +1107,7 @@ class RtpSenderAudioTest : public RtpSenderTest { TEST_F(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) { class TestCallback : public StreamDataCountersCallback { public: - TestCallback() - : StreamDataCountersCallback(), ssrc_(0), counters_() {} + TestCallback() : StreamDataCountersCallback(), ssrc_(0), counters_() {} virtual ~TestCallback() {} void DataCountersUpdated(const StreamDataCounters& counters, @@ -1127,7 +1133,6 @@ TEST_F(RtpSenderTestWithoutPacer, StreamDataCountersCallbacks) { MatchPacketCounter(counters.retransmitted, counters_.retransmitted); EXPECT_EQ(counters.fec.packets, counters_.fec.packets); } - } callback; const uint8_t kRedPayloadType = 96; @@ -1212,10 +1217,10 @@ TEST_F(RtpSenderAudioTest, SendAudio) { RtpUtility::RtpHeaderParser rtp_parser(transport_.last_sent_packet_, transport_.last_sent_packet_len_); webrtc::RTPHeader rtp_header; - ASSERT_TRUE(rtp_parser.Parse(rtp_header)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header)); - const uint8_t* payload_data = GetPayloadData(rtp_header, - transport_.last_sent_packet_); + const uint8_t* payload_data = + GetPayloadData(rtp_header, transport_.last_sent_packet_); ASSERT_EQ(sizeof(payload), GetPayloadDataLength(rtp_header, transport_.last_sent_packet_len_)); @@ -1225,8 +1230,8 @@ TEST_F(RtpSenderAudioTest, SendAudio) { TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) { EXPECT_EQ(0, rtp_sender_->SetAudioLevel(kAudioLevel)); - EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension( - kRtpExtensionAudioLevel, kAudioLevelExtensionId)); + EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel, + kAudioLevelExtensionId)); char payload_name[RTP_PAYLOAD_NAME_SIZE] = "PAYLOAD_NAME"; const uint8_t payload_type = 127; @@ -1241,21 +1246,22 @@ TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) { RtpUtility::RtpHeaderParser rtp_parser(transport_.last_sent_packet_, transport_.last_sent_packet_len_); webrtc::RTPHeader rtp_header; - ASSERT_TRUE(rtp_parser.Parse(rtp_header)); + ASSERT_TRUE(rtp_parser.Parse(&rtp_header)); - const uint8_t* payload_data = GetPayloadData(rtp_header, - transport_.last_sent_packet_); + const uint8_t* payload_data = + GetPayloadData(rtp_header, transport_.last_sent_packet_); ASSERT_EQ(sizeof(payload), GetPayloadDataLength(rtp_header, transport_.last_sent_packet_len_)); EXPECT_EQ(0, memcmp(payload, payload_data, sizeof(payload))); - uint8_t extension[] = { 0xbe, 0xde, 0x00, 0x01, - (kAudioLevelExtensionId << 4) + 0, // ID + length. - kAudioLevel, // Data. - 0x00, 0x00 // Padding. - }; + uint8_t extension[] = { + 0xbe, 0xde, 0x00, 0x01, + (kAudioLevelExtensionId << 4) + 0, // ID + length. + kAudioLevel, // Data. + 0x00, 0x00 // Padding. + }; EXPECT_EQ(0, memcmp(extension, payload_data - sizeof(extension), sizeof(extension))); @@ -1270,14 +1276,14 @@ TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) { TEST_F(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) { char payload_name[RTP_PAYLOAD_NAME_SIZE] = "telephone-event"; uint8_t payload_type = 126; - ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 0, - 0, 0)); + ASSERT_EQ(0, + rtp_sender_->RegisterPayload(payload_name, payload_type, 0, 0, 0)); // For Telephone events, payload is not added to the registered payload list, // it will register only the payload used for audio stream. // Registering the payload again for audio stream with different payload name. - strcpy(payload_name, "payload_name"); - ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 8000, - 1, 0)); + const char kPayloadName[] = "payload_name"; + ASSERT_EQ( + 0, rtp_sender_->RegisterPayload(kPayloadName, payload_type, 8000, 1, 0)); int64_t capture_time_ms = fake_clock_.TimeInMilliseconds(); // DTMF event key=9, duration=500 and attenuationdB=10 rtp_sender_->SendTelephoneEvent(9, 500, 10); @@ -1298,8 +1304,7 @@ TEST_F(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) { ASSERT_TRUE(rtp_parser.get() != nullptr); webrtc::RTPHeader rtp_header; ASSERT_TRUE(rtp_parser->Parse(transport_.last_sent_packet_, - transport_.last_sent_packet_len_, - &rtp_header)); + transport_.last_sent_packet_len_, &rtp_header)); // Marker Bit should be set to 1 for first packet. EXPECT_TRUE(rtp_header.markerBit); @@ -1307,8 +1312,7 @@ TEST_F(RtpSenderAudioTest, CheckMarkerBitForTelephoneEvents) { capture_time_ms + 4000, 0, nullptr, 0, nullptr)); ASSERT_TRUE(rtp_parser->Parse(transport_.last_sent_packet_, - transport_.last_sent_packet_len_, - &rtp_header)); + transport_.last_sent_packet_len_, &rtp_header)); // Marker Bit should be set to 0 for rest of the packets. EXPECT_FALSE(rtp_header.markerBit); } @@ -1321,19 +1325,13 @@ TEST_F(RtpSenderTestWithoutPacer, BytesReportedCorrectly) { rtp_sender_->SetRtxPayloadType(kPayloadType - 1, kPayloadType); rtp_sender_->SetRtxStatus(kRtxRetransmitted | kRtxRedundantPayloads); - ASSERT_EQ( - 0, - rtp_sender_->RegisterPayload(kPayloadName, kPayloadType, 90000, 0, 1500)); + ASSERT_EQ(0, rtp_sender_->RegisterPayload(kPayloadName, kPayloadType, 90000, + 0, 1500)); uint8_t payload[] = {47, 11, 32, 93, 89}; - ASSERT_EQ(0, - rtp_sender_->SendOutgoingData(kVideoFrameKey, - kPayloadType, - 1234, - 4321, - payload, - sizeof(payload), - 0)); + ASSERT_EQ( + 0, rtp_sender_->SendOutgoingData(kVideoFrameKey, kPayloadType, 1234, 4321, + payload, sizeof(payload), 0)); // Will send 2 full-size padding packets. rtp_sender_->TimeToSendPadding(1); @@ -1353,17 +1351,17 @@ TEST_F(RtpSenderTestWithoutPacer, BytesReportedCorrectly) { EXPECT_EQ(rtx_stats.transmitted.padding_bytes, 2 * kMaxPaddingSize); EXPECT_EQ(rtp_stats.transmitted.TotalBytes(), - rtp_stats.transmitted.payload_bytes + - rtp_stats.transmitted.header_bytes + - rtp_stats.transmitted.padding_bytes); + rtp_stats.transmitted.payload_bytes + + rtp_stats.transmitted.header_bytes + + rtp_stats.transmitted.padding_bytes); EXPECT_EQ(rtx_stats.transmitted.TotalBytes(), - rtx_stats.transmitted.payload_bytes + - rtx_stats.transmitted.header_bytes + - rtx_stats.transmitted.padding_bytes); + rtx_stats.transmitted.payload_bytes + + rtx_stats.transmitted.header_bytes + + rtx_stats.transmitted.padding_bytes); - EXPECT_EQ(transport_.total_bytes_sent_, - rtp_stats.transmitted.TotalBytes() + - rtx_stats.transmitted.TotalBytes()); + EXPECT_EQ( + transport_.total_bytes_sent_, + rtp_stats.transmitted.TotalBytes() + rtx_stats.transmitted.TotalBytes()); } TEST_F(RtpSenderTestWithoutPacer, RespectsNackBitrateLimit) { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc index 66062771de..5a565dfa99 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -18,7 +18,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/trace_event.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" @@ -42,13 +42,13 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender) _retransmissionSettings(kRetransmitBaseLayer), // Generic FEC - _fec(), - _fecEnabled(false), - _payloadTypeRED(-1), - _payloadTypeFEC(-1), + fec_(), + fec_enabled_(false), + red_payload_type_(-1), + fec_payload_type_(-1), delta_fec_params_(), key_fec_params_(), - producer_fec_(&_fec), + producer_fec_(&fec_), _fecOverheadRate(clock, NULL), _videoBitrate(clock, NULL) { memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); @@ -104,7 +104,7 @@ void RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, StorageType storage) { if (_rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length, capture_time_ms, storage, - RtpPacketSender::kNormalPriority) == 0) { + RtpPacketSender::kLowPriority) == 0) { _videoBitrate.Update(payload_length + rtp_header_length); TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Video::PacketNormal", "timestamp", capture_timestamp, @@ -130,7 +130,7 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, // Only protect while creating RED and FEC packets, not when sending. CriticalSectionScoped cs(crit_.get()); red_packet.reset(producer_fec_.BuildRedPacket( - data_buffer, payload_length, rtp_header_length, _payloadTypeRED)); + data_buffer, payload_length, rtp_header_length, red_payload_type_)); if (protect) { producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, payload_length, rtp_header_length); @@ -140,7 +140,7 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, next_fec_sequence_number = _rtpSender.AllocateSequenceNumber(num_fec_packets); fec_packets = producer_fec_.GetFecPackets( - _payloadTypeRED, _payloadTypeFEC, next_fec_sequence_number, + red_payload_type_, fec_payload_type_, next_fec_sequence_number, rtp_header_length); RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); if (_retransmissionSettings & kRetransmitFECPackets) @@ -150,7 +150,7 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, if (_rtpSender.SendToNetwork( red_packet->data(), red_packet->length() - rtp_header_length, rtp_header_length, capture_time_ms, media_packet_storage, - RtpPacketSender::kNormalPriority) == 0) { + RtpPacketSender::kLowPriority) == 0) { _videoBitrate.Update(red_packet->length()); TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Video::PacketRed", "timestamp", capture_timestamp, @@ -162,7 +162,7 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, if (_rtpSender.SendToNetwork( fec_packet->data(), fec_packet->length() - rtp_header_length, rtp_header_length, capture_time_ms, fec_storage, - RtpPacketSender::kNormalPriority) == 0) { + RtpPacketSender::kLowPriority) == 0) { _fecOverheadRate.Update(fec_packet->length()); TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "Video::PacketFec", "timestamp", capture_timestamp, @@ -180,9 +180,9 @@ void RTPSenderVideo::SetGenericFECStatus(const bool enable, const uint8_t payloadTypeRED, const uint8_t payloadTypeFEC) { CriticalSectionScoped cs(crit_.get()); - _fecEnabled = enable; - _payloadTypeRED = payloadTypeRED; - _payloadTypeFEC = payloadTypeFEC; + fec_enabled_ = enable; + red_payload_type_ = payloadTypeRED; + fec_payload_type_ = payloadTypeFEC; memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); memset(&key_fec_params_, 0, sizeof(key_fec_params_)); delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; @@ -190,18 +190,18 @@ void RTPSenderVideo::SetGenericFECStatus(const bool enable, kFecMaskRandom; } -void RTPSenderVideo::GenericFECStatus(bool& enable, - uint8_t& payloadTypeRED, - uint8_t& payloadTypeFEC) const { +void RTPSenderVideo::GenericFECStatus(bool* enable, + uint8_t* payloadTypeRED, + uint8_t* payloadTypeFEC) const { CriticalSectionScoped cs(crit_.get()); - enable = _fecEnabled; - payloadTypeRED = _payloadTypeRED; - payloadTypeFEC = _payloadTypeFEC; + *enable = fec_enabled_; + *payloadTypeRED = red_payload_type_; + *payloadTypeFEC = fec_payload_type_; } size_t RTPSenderVideo::FECPacketOverhead() const { CriticalSectionScoped cs(crit_.get()); - if (_fecEnabled) { + if (fec_enabled_) { // Overhead is FEC headers plus RED for FEC header plus anything in RTP // header beyond the 12 bytes base header (CSRC list, extensions...) // This reason for the header extensions to be included here is that @@ -247,7 +247,7 @@ int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType, frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; producer_fec_.SetFecParameters(fec_params, 0); storage = packetizer->GetStorageType(_retransmissionSettings); - fec_enabled = _fecEnabled; + fec_enabled = fec_enabled_; } // Register CVO rtp header extension at the first time when we receive a frame @@ -304,7 +304,7 @@ int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType, size_t packetSize = payloadSize + rtp_header_length; RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize); RTPHeader rtp_header; - rtp_parser.Parse(rtp_header); + rtp_parser.Parse(&rtp_header); _rtpSender.UpdateVideoRotation(dataBuffer, packetSize, rtp_header, rtpHdr->rotation); } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h index f412542d86..e59321ab93 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h @@ -16,7 +16,7 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" @@ -67,9 +67,9 @@ class RTPSenderVideo { const uint8_t payloadTypeRED, const uint8_t payloadTypeFEC); - void GenericFECStatus(bool& enable, - uint8_t& payloadTypeRED, - uint8_t& payloadTypeFEC) const; + void GenericFECStatus(bool* enable, + uint8_t* payloadTypeRED, + uint8_t* payloadTypeFEC) const; void SetFecParameters(const FecProtectionParams* delta_params, const FecProtectionParams* key_params); @@ -82,7 +82,7 @@ class RTPSenderVideo { int SelectiveRetransmissions() const; void SetSelectiveRetransmissions(uint8_t settings); -private: + private: void SendVideoPacket(uint8_t* dataBuffer, const size_t payloadLength, const size_t rtpHeaderLength, @@ -110,10 +110,10 @@ private: int32_t _retransmissionSettings GUARDED_BY(crit_); // FEC - ForwardErrorCorrection _fec; - bool _fecEnabled GUARDED_BY(crit_); - int8_t _payloadTypeRED GUARDED_BY(crit_); - int8_t _payloadTypeFEC GUARDED_BY(crit_); + ForwardErrorCorrection fec_; + bool fec_enabled_ GUARDED_BY(crit_); + int8_t red_payload_type_ GUARDED_BY(crit_); + int8_t fec_payload_type_ GUARDED_BY(crit_); FecProtectionParams delta_fec_params_ GUARDED_BY(crit_); FecProtectionParams key_fec_params_ GUARDED_BY(crit_); ProducerFec producer_fec_ GUARDED_BY(crit_); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc index bf0b30a064..0f0ad835b1 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc @@ -10,38 +10,10 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" -#include <assert.h> -#include <math.h> // ceil -#include <string.h> // memcpy - -#if defined(_WIN32) -// Order for these headers are important -#include <winsock2.h> // timeval -#include <windows.h> // FILETIME -#include <MMSystem.h> // timeGetTime -#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC)) -#include <sys/time.h> // gettimeofday -#include <time.h> -#endif -#if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400)) -#include <stdio.h> -#endif +#include <string.h> #include "webrtc/base/logging.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" -#include "webrtc/system_wrappers/include/tick_util.h" - -#if (defined(_DEBUG) && defined(_WIN32) && (_MSC_VER >= 1400)) -#define DEBUG_PRINT(...) \ - { \ - char msg[256]; \ - sprintf(msg, __VA_ARGS__); \ - OutputDebugString(msg); \ - } -#else -// special fix for visual 2003 -#define DEBUG_PRINT(exp) ((void)0) -#endif // defined(_DEBUG) && defined(_WIN32) namespace webrtc { @@ -77,50 +49,18 @@ enum { }; /* - * Time routines. - */ - -uint32_t GetCurrentRTP(Clock* clock, uint32_t freq) { - const bool use_global_clock = (clock == NULL); - Clock* local_clock = clock; - if (use_global_clock) { - local_clock = Clock::GetRealTimeClock(); - } - uint32_t secs = 0, frac = 0; - local_clock->CurrentNtp(secs, frac); - if (use_global_clock) { - delete local_clock; - } - return ConvertNTPTimeToRTP(secs, frac, freq); -} - -uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, uint32_t NTPfrac, uint32_t freq) { - float ftemp = (float)NTPfrac / (float)NTP_FRAC; - uint32_t tmp = (uint32_t)(ftemp * freq); - return NTPsec * freq + tmp; -} - -uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) { - int freq = 1000; - float ftemp = (float)NTPfrac / (float)NTP_FRAC; - uint32_t tmp = (uint32_t)(ftemp * freq); - uint32_t MStime = NTPsec * freq + tmp; - return MStime; -} - -/* * Misc utility routines */ #if defined(_WIN32) bool StringCompare(const char* str1, const char* str2, const uint32_t length) { - return (_strnicmp(str1, str2, length) == 0) ? true : false; + return _strnicmp(str1, str2, length) == 0; } #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) bool StringCompare(const char* str1, const char* str2, const uint32_t length) { - return (strncasecmp(str1, str2, length) == 0) ? true : false; + return strncasecmp(str1, str2, length) == 0; } #endif @@ -131,10 +71,6 @@ size_t Word32Align(size_t size) { return size; } -uint32_t pow2(uint8_t exp) { - return 1 << exp; -} - RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData, const size_t rtpDataLength) : _ptrRTPDataBegin(rtpData), @@ -244,7 +180,7 @@ bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const { return true; } -bool RtpHeaderParser::Parse(RTPHeader& header, +bool RtpHeaderParser::Parse(RTPHeader* header, RtpHeaderExtensionMap* ptrExtensionMap) const { const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin; if (length < kRtpMinParseLength) { @@ -283,39 +219,39 @@ bool RtpHeaderParser::Parse(RTPHeader& header, return false; } - header.markerBit = M; - header.payloadType = PT; - header.sequenceNumber = sequenceNumber; - header.timestamp = RTPTimestamp; - header.ssrc = SSRC; - header.numCSRCs = CC; - header.paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0; + header->markerBit = M; + header->payloadType = PT; + header->sequenceNumber = sequenceNumber; + header->timestamp = RTPTimestamp; + header->ssrc = SSRC; + header->numCSRCs = CC; + header->paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0; for (uint8_t i = 0; i < CC; ++i) { uint32_t CSRC = ByteReader<uint32_t>::ReadBigEndian(ptr); ptr += 4; - header.arrOfCSRCs[i] = CSRC; + header->arrOfCSRCs[i] = CSRC; } - header.headerLength = 12 + CSRCocts; + header->headerLength = 12 + CSRCocts; // If in effect, MAY be omitted for those packets for which the offset // is zero. - header.extension.hasTransmissionTimeOffset = false; - header.extension.transmissionTimeOffset = 0; + header->extension.hasTransmissionTimeOffset = false; + header->extension.transmissionTimeOffset = 0; // May not be present in packet. - header.extension.hasAbsoluteSendTime = false; - header.extension.absoluteSendTime = 0; + header->extension.hasAbsoluteSendTime = false; + header->extension.absoluteSendTime = 0; // May not be present in packet. - header.extension.hasAudioLevel = false; - header.extension.voiceActivity = false; - header.extension.audioLevel = 0; + header->extension.hasAudioLevel = false; + header->extension.voiceActivity = false; + header->extension.audioLevel = 0; // May not be present in packet. - header.extension.hasVideoRotation = false; - header.extension.videoRotation = 0; + header->extension.hasVideoRotation = false; + header->extension.videoRotation = 0; if (X) { /* RTP header extension, RFC 3550. @@ -332,7 +268,7 @@ bool RtpHeaderParser::Parse(RTPHeader& header, return false; } - header.headerLength += 4; + header->headerLength += 4; uint16_t definedByProfile = ByteReader<uint16_t>::ReadBigEndian(ptr); ptr += 2; @@ -352,15 +288,16 @@ bool RtpHeaderParser::Parse(RTPHeader& header, ptrRTPDataExtensionEnd, ptr); } - header.headerLength += XLen; + header->headerLength += XLen; } - if (header.headerLength + header.paddingLength > static_cast<size_t>(length)) + if (header->headerLength + header->paddingLength > + static_cast<size_t>(length)) return false; return true; } void RtpHeaderParser::ParseOneByteExtensionHeader( - RTPHeader& header, + RTPHeader* header, const RtpHeaderExtensionMap* ptrExtensionMap, const uint8_t* ptrRTPDataExtensionEnd, const uint8_t* ptr) const { @@ -377,8 +314,8 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( // Note that 'len' is the header extension element length, which is the // number of bytes - 1. - const uint8_t id = (*ptr & 0xf0) >> 4; - const uint8_t len = (*ptr & 0x0f); + const int id = (*ptr & 0xf0) >> 4; + const int len = (*ptr & 0x0f); ptr++; if (id == 15) { @@ -390,8 +327,7 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( RTPExtensionType type; if (ptrExtensionMap->GetType(id, &type) != 0) { // If we encounter an unknown extension, just skip over it. - LOG(LS_WARNING) << "Failed to find extension id: " - << static_cast<int>(id); + LOG(LS_WARNING) << "Failed to find extension id: " << id; } else { switch (type) { case kRtpExtensionTransmissionTimeOffset: { @@ -406,9 +342,9 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( // | ID | len=2 | transmission offset | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - header.extension.transmissionTimeOffset = + header->extension.transmissionTimeOffset = ByteReader<int32_t, 3>::ReadBigEndian(ptr); - header.extension.hasTransmissionTimeOffset = true; + header->extension.hasTransmissionTimeOffset = true; break; } case kRtpExtensionAudioLevel: { @@ -422,9 +358,9 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( // | ID | len=0 |V| level | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // - header.extension.audioLevel = ptr[0] & 0x7f; - header.extension.voiceActivity = (ptr[0] & 0x80) != 0; - header.extension.hasAudioLevel = true; + header->extension.audioLevel = ptr[0] & 0x7f; + header->extension.voiceActivity = (ptr[0] & 0x80) != 0; + header->extension.hasAudioLevel = true; break; } case kRtpExtensionAbsoluteSendTime: { @@ -438,9 +374,9 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( // | ID | len=2 | absolute send time | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - header.extension.absoluteSendTime = + header->extension.absoluteSendTime = ByteReader<uint32_t, 3>::ReadBigEndian(ptr); - header.extension.hasAbsoluteSendTime = true; + header->extension.hasAbsoluteSendTime = true; break; } case kRtpExtensionVideoRotation: { @@ -454,14 +390,14 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | ID | len=0 |0 0 0 0 C F R R| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - header.extension.hasVideoRotation = true; - header.extension.videoRotation = ptr[0]; + header->extension.hasVideoRotation = true; + header->extension.videoRotation = ptr[0]; break; } case kRtpExtensionTransportSequenceNumber: { if (len != 1) { - LOG(LS_WARNING) - << "Incorrect peer connection sequence number len: " << len; + LOG(LS_WARNING) << "Incorrect transport sequence number len: " + << len; return; } // 0 1 2 @@ -472,8 +408,8 @@ void RtpHeaderParser::ParseOneByteExtensionHeader( uint16_t sequence_number = ptr[0] << 8; sequence_number += ptr[1]; - header.extension.transportSequenceNumber = sequence_number; - header.extension.hasTransportSequenceNumber = true; + header->extension.transportSequenceNumber = sequence_number; + header->extension.hasTransportSequenceNumber = true; break; } default: { @@ -502,5 +438,4 @@ uint8_t RtpHeaderParser::ParsePaddingBytes( return num_zero_bytes; } } // namespace RtpUtility - } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.h b/webrtc/modules/rtp_rtcp/source/rtp_utility.h index af20f97e82..23c175356a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.h @@ -11,10 +11,11 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_UTILITY_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_UTILITY_H_ -#include <stddef.h> // size_t, ptrdiff_t +#include <map> -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" +#include "webrtc/base/deprecation.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/typedefs.h" @@ -29,71 +30,48 @@ RtpAudioFeedback* NullObjectRtpAudioFeedback(); ReceiveStatistics* NullObjectReceiveStatistics(); namespace RtpUtility { - // January 1970, in NTP seconds. - const uint32_t NTP_JAN_1970 = 2208988800UL; - - // Magic NTP fractional unit. - const double NTP_FRAC = 4.294967296E+9; - - struct Payload - { - char name[RTP_PAYLOAD_NAME_SIZE]; - bool audio; - PayloadUnion typeSpecific; - }; - - typedef std::map<int8_t, Payload*> PayloadTypeMap; - - // Return the current RTP timestamp from the NTP timestamp - // returned by the specified clock. - uint32_t GetCurrentRTP(Clock* clock, uint32_t freq); - - // Return the current RTP absolute timestamp. - uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, - uint32_t NTPfrac, - uint32_t freq); - - uint32_t pow2(uint8_t exp); - - // Returns true if |newTimestamp| is older than |existingTimestamp|. - // |wrapped| will be set to true if there has been a wraparound between the - // two timestamps. - bool OldTimestamp(uint32_t newTimestamp, - uint32_t existingTimestamp, - bool* wrapped); - - bool StringCompare(const char* str1, - const char* str2, - const uint32_t length); - - // Round up to the nearest size that is a multiple of 4. - size_t Word32Align(size_t size); - - class RtpHeaderParser { - public: - RtpHeaderParser(const uint8_t* rtpData, size_t rtpDataLength); - ~RtpHeaderParser(); - - bool RTCP() const; - bool ParseRtcp(RTPHeader* header) const; - bool Parse(RTPHeader& parsedPacket, - RtpHeaderExtensionMap* ptrExtensionMap = NULL) const; - - private: - void ParseOneByteExtensionHeader( - RTPHeader& parsedPacket, - const RtpHeaderExtensionMap* ptrExtensionMap, - const uint8_t* ptrRTPDataExtensionEnd, - const uint8_t* ptr) const; - - uint8_t ParsePaddingBytes( - const uint8_t* ptrRTPDataExtensionEnd, - const uint8_t* ptr) const; - - const uint8_t* const _ptrRTPDataBegin; - const uint8_t* const _ptrRTPDataEnd; - }; + +struct Payload { + char name[RTP_PAYLOAD_NAME_SIZE]; + bool audio; + PayloadUnion typeSpecific; +}; + +typedef std::map<int8_t, Payload*> PayloadTypeMap; + +bool StringCompare(const char* str1, const char* str2, const uint32_t length); + +// Round up to the nearest size that is a multiple of 4. +size_t Word32Align(size_t size); + +class RtpHeaderParser { + public: + RtpHeaderParser(const uint8_t* rtpData, size_t rtpDataLength); + ~RtpHeaderParser(); + + bool RTCP() const; + bool ParseRtcp(RTPHeader* header) const; + bool Parse(RTPHeader* parsedPacket, + RtpHeaderExtensionMap* ptrExtensionMap = nullptr) const; + RTC_DEPRECATED bool Parse( + RTPHeader& parsedPacket, // NOLINT(runtime/references) + RtpHeaderExtensionMap* ptrExtensionMap = nullptr) const { + return Parse(&parsedPacket, ptrExtensionMap); + } + + private: + void ParseOneByteExtensionHeader(RTPHeader* parsedPacket, + const RtpHeaderExtensionMap* ptrExtensionMap, + const uint8_t* ptrRTPDataExtensionEnd, + const uint8_t* ptr) const; + + uint8_t ParsePaddingBytes(const uint8_t* ptrRTPDataExtensionEnd, + const uint8_t* ptr) const; + + const uint8_t* const _ptrRTPDataBegin; + const uint8_t* const _ptrRTPDataEnd; +}; } // namespace RtpUtility } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_UTILITY_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_UTILITY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/ssrc_database.cc b/webrtc/modules/rtp_rtcp/source/ssrc_database.cc index 6fb7c4701a..fb02b7ef12 100644 --- a/webrtc/modules/rtp_rtcp/source/ssrc_database.cc +++ b/webrtc/modules/rtp_rtcp/source/ssrc_database.cc @@ -10,110 +10,51 @@ #include "webrtc/modules/rtp_rtcp/source/ssrc_database.h" -#include <assert.h> -#include <stdlib.h> - +#include "webrtc/base/checks.h" +#include "webrtc/system_wrappers/include/clock.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" -#ifdef _WIN32 - #include <windows.h> - #include <MMSystem.h> //timeGetTime - -// TODO(hellner): investigate if it is necessary to disable these warnings. - #pragma warning(disable:4311) - #pragma warning(disable:4312) -#else - #include <stdio.h> - #include <string.h> - #include <time.h> - #include <sys/time.h> -#endif - namespace webrtc { -SSRCDatabase* -SSRCDatabase::StaticInstance(CountOperation count_operation) -{ - SSRCDatabase* impl = - GetStaticInstance<SSRCDatabase>(count_operation); - return impl; +namespace { +uint64_t Seed() { + return Clock::GetRealTimeClock()->TimeInMicroseconds(); } +} // namespace -SSRCDatabase* -SSRCDatabase::GetSSRCDatabase() -{ - return StaticInstance(kAddRef); +SSRCDatabase* SSRCDatabase::GetSSRCDatabase() { + return GetStaticInstance<SSRCDatabase>(kAddRef); } -void -SSRCDatabase::ReturnSSRCDatabase() -{ - StaticInstance(kRelease); +void SSRCDatabase::ReturnSSRCDatabase() { + GetStaticInstance<SSRCDatabase>(kRelease); } -uint32_t -SSRCDatabase::CreateSSRC() -{ - CriticalSectionScoped lock(_critSect); +uint32_t SSRCDatabase::CreateSSRC() { + CriticalSectionScoped lock(crit_.get()); - uint32_t ssrc = GenerateRandom(); - - while(_ssrcMap.find(ssrc) != _ssrcMap.end()) - { - ssrc = GenerateRandom(); + while (true) { // Try until get a new ssrc. + // 0 and 0xffffffff are invalid values for SSRC. + uint32_t ssrc = random_.Rand(1u, 0xfffffffe); + if (ssrcs_.insert(ssrc).second) { + return ssrc; } - _ssrcMap[ssrc] = 0; - - return ssrc; + } } -int32_t -SSRCDatabase::RegisterSSRC(const uint32_t ssrc) -{ - CriticalSectionScoped lock(_critSect); - _ssrcMap[ssrc] = 0; - return 0; +void SSRCDatabase::RegisterSSRC(uint32_t ssrc) { + CriticalSectionScoped lock(crit_.get()); + ssrcs_.insert(ssrc); } -int32_t -SSRCDatabase::ReturnSSRC(const uint32_t ssrc) -{ - CriticalSectionScoped lock(_critSect); - _ssrcMap.erase(ssrc); - return 0; +void SSRCDatabase::ReturnSSRC(uint32_t ssrc) { + CriticalSectionScoped lock(crit_.get()); + ssrcs_.erase(ssrc); } SSRCDatabase::SSRCDatabase() -{ - // we need to seed the random generator, otherwise we get 26500 each time, hardly a random value :) -#ifdef _WIN32 - srand(timeGetTime()); -#else - struct timeval tv; - struct timezone tz; - gettimeofday(&tv, &tz); - srand(tv.tv_usec); -#endif + : crit_(CriticalSectionWrapper::CreateCriticalSection()), random_(Seed()) {} - _critSect = CriticalSectionWrapper::CreateCriticalSection(); +SSRCDatabase::~SSRCDatabase() { } -SSRCDatabase::~SSRCDatabase() -{ - _ssrcMap.clear(); - delete _critSect; -} - -uint32_t SSRCDatabase::GenerateRandom() -{ - uint32_t ssrc = 0; - do - { - ssrc = rand(); - ssrc = ssrc <<16; - ssrc += rand(); - - } while (ssrc == 0 || ssrc == 0xffffffff); - - return ssrc; -} } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/ssrc_database.h b/webrtc/modules/rtp_rtcp/source/ssrc_database.h index 7129d0de76..7a3133638d 100644 --- a/webrtc/modules/rtp_rtcp/source/ssrc_database.h +++ b/webrtc/modules/rtp_rtcp/source/ssrc_database.h @@ -11,43 +11,41 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ -#include <map> +#include <set> +#include "webrtc/base/random.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/system_wrappers/include/static_instance.h" #include "webrtc/typedefs.h" namespace webrtc { class CriticalSectionWrapper; -class SSRCDatabase -{ -public: - static SSRCDatabase* GetSSRCDatabase(); - static void ReturnSSRCDatabase(); +class SSRCDatabase { + public: + static SSRCDatabase* GetSSRCDatabase(); + static void ReturnSSRCDatabase(); - uint32_t CreateSSRC(); - int32_t RegisterSSRC(const uint32_t ssrc); - int32_t ReturnSSRC(const uint32_t ssrc); + uint32_t CreateSSRC(); + void RegisterSSRC(uint32_t ssrc); + void ReturnSSRC(uint32_t ssrc); -protected: - SSRCDatabase(); - virtual ~SSRCDatabase(); + protected: + SSRCDatabase(); + virtual ~SSRCDatabase(); - static SSRCDatabase* CreateInstance() { return new SSRCDatabase(); } + static SSRCDatabase* CreateInstance() { return new SSRCDatabase(); } -private: - // Friend function to allow the SSRC destructor to be accessed from the - // template class. - friend SSRCDatabase* GetStaticInstance<SSRCDatabase>( - CountOperation count_operation); - static SSRCDatabase* StaticInstance(CountOperation count_operation); + private: + // Friend function to allow the SSRC destructor to be accessed from the + // template class. + friend SSRCDatabase* GetStaticInstance<SSRCDatabase>( + CountOperation count_operation); - uint32_t GenerateRandom(); - - std::map<uint32_t, uint32_t> _ssrcMap; - - CriticalSectionWrapper* _critSect; + rtc::scoped_ptr<CriticalSectionWrapper> crit_; + Random random_ GUARDED_BY(crit_); + std::set<uint32_t> ssrcs_ GUARDED_BY(crit_); }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ diff --git a/webrtc/modules/rtp_rtcp/source/time_util.h b/webrtc/modules/rtp_rtcp/source/time_util.h new file mode 100644 index 0000000000..5b544ddf9a --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/time_util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/system_wrappers/include/ntp_time.h" + +namespace webrtc { + +// Converts NTP timestamp to RTP timestamp. +inline uint32_t NtpToRtp(NtpTime ntp, uint32_t freq) { + uint32_t tmp = (static_cast<uint64_t>(ntp.fractions()) * freq) >> 32; + return ntp.seconds() * freq + tmp; +} +// Return the current RTP timestamp from the NTP timestamp +// returned by the specified clock. +inline uint32_t CurrentRtp(const Clock& clock, uint32_t freq) { + return NtpToRtp(NtpTime(clock), freq); +} + +// Helper function for compact ntp representation: +// RFC 3550, Section 4. Time Format. +// Wallclock time is represented using the timestamp format of +// the Network Time Protocol (NTP). +// ... +// In some fields where a more compact representation is +// appropriate, only the middle 32 bits are used; that is, the low 16 +// bits of the integer part and the high 16 bits of the fractional part. +inline uint32_t CompactNtp(NtpTime ntp) { + return (ntp.seconds() << 16) | (ntp.fractions() >> 16); +} +// Converts interval between compact ntp timestamps to milliseconds. +// This interval can be upto ~18.2 hours (2^16 seconds). +inline uint32_t CompactNtpIntervalToMs(uint32_t compact_ntp_interval) { + return static_cast<uint64_t>(compact_ntp_interval) * 1000 / (1 << 16); +} + +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ diff --git a/webrtc/modules/rtp_rtcp/source/time_util_unittest.cc b/webrtc/modules/rtp_rtcp/source/time_util_unittest.cc new file mode 100644 index 0000000000..7efb83ccad --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/time_util_unittest.cc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015 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. + */ +#include "webrtc/modules/rtp_rtcp/source/time_util.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace webrtc { + +TEST(TimeUtilTest, CompactNtp) { + const uint32_t kNtpSec = 0x12345678; + const uint32_t kNtpFrac = 0x23456789; + const NtpTime kNtp(kNtpSec, kNtpFrac); + const uint32_t kNtpMid = 0x56782345; + EXPECT_EQ(kNtpMid, CompactNtp(kNtp)); +} + +TEST(TimeUtilTest, CompactNtpToMs) { + const NtpTime ntp1(0x12345, 0x23456); + const NtpTime ntp2(0x12654, 0x64335); + uint32_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); + uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); + + uint32_t ntp_to_ms_diff = CompactNtpIntervalToMs(ntp_diff); + + EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); +} + +TEST(TimeUtilTest, CompactNtpToMsWithWrap) { + const NtpTime ntp1(0x1ffff, 0x23456); + const NtpTime ntp2(0x20000, 0x64335); + uint32_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); + + // While ntp2 > ntp1, there compact ntp presentation happen to be opposite. + // That shouldn't be a problem as long as unsigned arithmetic is used. + ASSERT_GT(ntp2.ToMs(), ntp1.ToMs()); + ASSERT_LT(CompactNtp(ntp2), CompactNtp(ntp1)); + + uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); + uint32_t ntp_to_ms_diff = CompactNtpIntervalToMs(ntp_diff); + + EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); +} + +TEST(TimeUtilTest, CompactNtpToMsLarge) { + const NtpTime ntp1(0x10000, 0x23456); + const NtpTime ntp2(0x1ffff, 0x64335); + uint32_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); + // Ntp difference close to maximum of ~18 hours should convert correctly too. + ASSERT_GT(ms_diff, 18u * 3600 * 1000); + uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); + uint32_t ntp_to_ms_diff = CompactNtpIntervalToMs(ntp_diff); + + EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); +} +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/tmmbr_help.cc b/webrtc/modules/rtp_rtcp/source/tmmbr_help.cc index fb1ed625ed..f994ff7049 100644 --- a/webrtc/modules/rtp_rtcp/source/tmmbr_help.cc +++ b/webrtc/modules/rtp_rtcp/source/tmmbr_help.cc @@ -11,8 +11,10 @@ #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" #include <assert.h> -#include <limits> #include <string.h> + +#include <limits> + #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" namespace webrtc { diff --git a/webrtc/modules/rtp_rtcp/source/video_codec_information.h b/webrtc/modules/rtp_rtcp/source/video_codec_information.h index 456b3bb934..7b819d060f 100644 --- a/webrtc/modules/rtp_rtcp/source/video_codec_information.h +++ b/webrtc/modules/rtp_rtcp/source/video_codec_information.h @@ -15,14 +15,13 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" namespace webrtc { -class VideoCodecInformation -{ -public: - virtual void Reset() = 0; +class VideoCodecInformation { + public: + virtual void Reset() = 0; - virtual RtpVideoCodecTypes Type() = 0; - virtual ~VideoCodecInformation(){}; + virtual RtpVideoCodecTypes Type() = 0; + virtual ~VideoCodecInformation() {} }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_VIDEO_CODEC_INFORMATION_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_VIDEO_CODEC_INFORMATION_H_ diff --git a/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.cc b/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.cc index feed784839..9721a7e9ac 100644 --- a/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.cc +++ b/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.cc @@ -37,9 +37,8 @@ PartitionTreeNode::PartitionTreeNode(PartitionTreeNode* parent, PartitionTreeNode* PartitionTreeNode::CreateRootNode(const size_t* size_vector, size_t num_partitions) { - PartitionTreeNode* root_node = - new PartitionTreeNode(NULL, &size_vector[1], num_partitions - 1, - size_vector[0]); + PartitionTreeNode* root_node = new PartitionTreeNode( + NULL, &size_vector[1], num_partitions - 1, size_vector[0]); root_node->set_packet_start(true); return root_node; } @@ -54,7 +53,7 @@ int PartitionTreeNode::Cost(size_t penalty) { if (num_partitions_ == 0) { // This is a solution node. cost = std::max(max_parent_size_, this_size_int()) - - std::min(min_parent_size_, this_size_int()); + std::min(min_parent_size_, this_size_int()); } else { cost = std::max(max_parent_size_, this_size_int()) - min_parent_size_; } @@ -68,9 +67,7 @@ bool PartitionTreeNode::CreateChildren(size_t max_size) { if (this_size_ + size_vector_[0] <= max_size) { assert(!children_[kLeftChild]); children_[kLeftChild] = - new PartitionTreeNode(this, - &size_vector_[1], - num_partitions_ - 1, + new PartitionTreeNode(this, &size_vector_[1], num_partitions_ - 1, this_size_ + size_vector_[0]); children_[kLeftChild]->set_max_parent_size(max_parent_size_); children_[kLeftChild]->set_min_parent_size(min_parent_size_); @@ -80,10 +77,8 @@ bool PartitionTreeNode::CreateChildren(size_t max_size) { } if (this_size_ > 0) { assert(!children_[kRightChild]); - children_[kRightChild] = new PartitionTreeNode(this, - &size_vector_[1], - num_partitions_ - 1, - size_vector_[0]); + children_[kRightChild] = new PartitionTreeNode( + this, &size_vector_[1], num_partitions_ - 1, size_vector_[0]); children_[kRightChild]->set_max_parent_size( std::max(max_parent_size_, this_size_int())); children_[kRightChild]->set_min_parent_size( @@ -148,7 +143,8 @@ PartitionTreeNode* PartitionTreeNode::GetOptimalNode(size_t max_size, Vp8PartitionAggregator::Vp8PartitionAggregator( const RTPFragmentationHeader& fragmentation, - size_t first_partition_idx, size_t last_partition_idx) + size_t first_partition_idx, + size_t last_partition_idx) : root_(NULL), num_partitions_(last_partition_idx - first_partition_idx + 1), size_vector_(new size_t[num_partitions_]), @@ -158,14 +154,14 @@ Vp8PartitionAggregator::Vp8PartitionAggregator( for (size_t i = 0; i < num_partitions_; ++i) { size_vector_[i] = fragmentation.fragmentationLength[i + first_partition_idx]; - largest_partition_size_ = std::max(largest_partition_size_, - size_vector_[i]); + largest_partition_size_ = + std::max(largest_partition_size_, size_vector_[i]); } root_ = PartitionTreeNode::CreateRootNode(size_vector_, num_partitions_); } Vp8PartitionAggregator::~Vp8PartitionAggregator() { - delete [] size_vector_; + delete[] size_vector_; delete root_; } @@ -190,14 +186,16 @@ Vp8PartitionAggregator::FindOptimalConfiguration(size_t max_size, assert(packet_index > 0); assert(temp_node != NULL); config_vector[i - 1] = packet_index - 1; - if (temp_node->packet_start()) --packet_index; + if (temp_node->packet_start()) + --packet_index; temp_node = temp_node->parent(); } return config_vector; } void Vp8PartitionAggregator::CalcMinMax(const ConfigVec& config, - int* min_size, int* max_size) const { + int* min_size, + int* max_size) const { if (*min_size < 0) { *min_size = std::numeric_limits<int>::max(); } @@ -263,8 +261,8 @@ size_t Vp8PartitionAggregator::CalcNumberOfFragments( } assert(num_fragments > 0); // TODO(mflodman) Assert disabled since it's falsely triggered, see issue 293. - //assert(large_partition_size / num_fragments + 1 <= max_payload_size); + // assert(large_partition_size / num_fragments + 1 <= max_payload_size); return num_fragments; } -} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h b/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h index 53b678f3b9..ccd22e5be2 100644 --- a/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h +++ b/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h @@ -14,7 +14,7 @@ #include <vector> #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -132,6 +132,6 @@ class Vp8PartitionAggregator { RTC_DISALLOW_COPY_AND_ASSIGN(Vp8PartitionAggregator); }; -} // namespace +} // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_VP8_PARTITION_AGGREGATOR_H_ diff --git a/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator_unittest.cc b/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator_unittest.cc index 4650c94047..726d83ec50 100644 --- a/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator_unittest.cc @@ -209,4 +209,4 @@ TEST(Vp8PartitionAggregator, TestCalcNumberOfFragments) { 1600, kMTU, 1, 900, 1000)); } -} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/BWEStandAlone.cc b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/BWEStandAlone.cc deleted file mode 100644 index 711be4a623..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/BWEStandAlone.cc +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -// BWEStandAlone.cpp : Defines the entry point for the console application. -// - -#include <stdio.h> -#include <string> - -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/system_wrappers/include/trace.h" -#include "webrtc/test/channel_transport/udp_transport.h" - -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h" -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h" - -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h" - -//#include "vld.h" - -class myTransportCB: public UdpTransportData -{ -public: - myTransportCB (RtpRtcp *rtpMod) : _rtpMod(rtpMod) {}; -protected: - // Inherited from UdpTransportData - void IncomingRTPPacket(const int8_t* incomingRtpPacket, - const size_t rtpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) override; - - void IncomingRTCPPacket(const int8_t* incomingRtcpPacket, - const size_t rtcpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) override; - -private: - RtpRtcp *_rtpMod; -}; - -void myTransportCB::IncomingRTPPacket(const int8_t* incomingRtpPacket, - const size_t rtpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) -{ - printf("Receiving RTP from IP %s, port %u\n", fromIP, fromPort); - _rtpMod->IncomingPacket((uint8_t *) incomingRtpPacket, rtpPacketLength); -} - -void myTransportCB::IncomingRTCPPacket(const int8_t* incomingRtcpPacket, - const size_t rtcpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) -{ - printf("Receiving RTCP from IP %s, port %u\n", fromIP, fromPort); - _rtpMod->IncomingPacket((uint8_t *) incomingRtcpPacket, rtcpPacketLength); -} - - -int main(int argc, char* argv[]) -{ - bool isSender = false; - bool isReceiver = false; - uint16_t port; - std::string ip; - TestSenderReceiver *sendrec = new TestSenderReceiver(); - TestLoadGenerator *gen; - - if (argc == 2) - { - // receiver only - isReceiver = true; - - // read port - port = atoi(argv[1]); - } - else if (argc == 3) - { - // sender and receiver - isSender = true; - isReceiver = true; - - // read IP - ip = argv[1]; - - // read port - port = atoi(argv[2]); - } - - Trace::CreateTrace(); - Trace::SetTraceFile("BWEStandAloneTrace.txt"); - Trace::set_level_filter(webrtc::kTraceAll); - - sendrec->InitReceiver(port); - - sendrec->Start(); - - if (isSender) - { - const uint32_t startRateKbps = 1000; - //gen = new CBRGenerator(sendrec, 1000, 500); - gen = new CBRFixFRGenerator(sendrec, startRateKbps, 90000, 30, 0.2); - //gen = new PeriodicKeyFixFRGenerator(sendrec, startRateKbps, 90000, 30, 0.2, 7, 300); - //const uint16_t numFrameRates = 5; - //const uint8_t frameRates[numFrameRates] = {30, 15, 20, 23, 25}; - //gen = new CBRVarFRGenerator(sendrec, 1000, frameRates, numFrameRates, 90000, 4.0, 0.1, 0.2); - //gen = new CBRFrameDropGenerator(sendrec, startRateKbps, 90000, 0.2); - sendrec->SetLoadGenerator(gen); - sendrec->InitSender(startRateKbps, ip.c_str(), port); - gen->Start(); - } - - while (1) - { - } - - if (isSender) - { - gen->Stop(); - delete gen; - } - - delete sendrec; - - //uint8_t numberOfSocketThreads = 1; - //UdpTransport* transport = UdpTransport::Create(0, numberOfSocketThreads); - - //RtpRtcp* rtp = RtpRtcp::CreateRtpRtcp(1, false); - //if (rtp->InitSender() != 0) - //{ - // exit(1); - //} - //if (rtp->RegisterSendTransport(transport) != 0) - //{ - // exit(1); - //} - -// transport->InitializeSendSockets("192.168.200.39", 8000); - //transport->InitializeSendSockets("127.0.0.1", 10000); - //transport->InitializeSourcePorts(8000); - - - return(0); - // myTransportCB *tp = new myTransportCB(rtp); - // transport->InitializeReceiveSockets(tp, 10000, "0.0.0.0"); - // transport->StartReceiving(500); - - // int8_t data[100]; - // for (int i = 0; i < 100; data[i] = i++); - - // for (int i = 0; i < 100; i++) - // { - // transport->SendRaw(data, 100, false); - // } - - - - // int32_t totTime = 0; - // while (totTime < 10000) - // { - // transport->Process(); - // int32_t wTime = transport->TimeUntilNextProcess(); - // totTime += wTime; - // Sleep(wTime); - // } - - - //if (transport) - //{ - // // Destroy the Socket Transport module - // transport->StopReceiving(); - // transport->InitializeReceiveSockets(NULL,0);// deregister callback - // UdpTransport::Destroy(transport); - // transport = NULL; - // } - - // if (tp) - // { - // delete tp; - // tp = NULL; - // } - - // if (rtp) - // { - // RtpRtcp::DestroyRtpRtcp(rtp); - // rtp = NULL; - // } - - - //return 0; -} diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.cc b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.cc deleted file mode 100644 index fe54d67ee7..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.cc +++ /dev/null @@ -1,1055 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h" - -#include <math.h> -#include <stdio.h> - -#include <algorithm> -#include <sstream> - -#ifdef MATLAB -#include "engine.h" -#endif - -#include "webrtc/system_wrappers/include/critical_section_wrapper.h" -#include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/system_wrappers/include/tick_util.h" - -using namespace webrtc; - -#ifdef MATLAB -MatlabEngine eng; - -MatlabLine::MatlabLine(int maxLen /*= -1*/, const char *plotAttrib /*= NULL*/, const char *name /*= NULL*/) -: -_xArray(NULL), -_yArray(NULL), -_maxLen(maxLen), -_plotAttribute(), -_name() -{ - if (_maxLen > 0) - { - _xArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); - _yArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); - } - - if (plotAttrib) - { - _plotAttribute = plotAttrib; - } - - if (name) - { - _name = name; - } -} - -MatlabLine::~MatlabLine() -{ - if (_xArray != NULL) - { - mxDestroyArray(_xArray); - } - if (_yArray != NULL) - { - mxDestroyArray(_yArray); - } -} - -void MatlabLine::Append(double x, double y) -{ - if (_maxLen > 0 && _xData.size() > static_cast<uint32_t>(_maxLen)) - { - _xData.resize(_maxLen); - _yData.resize(_maxLen); - } - - _xData.push_front(x); - _yData.push_front(y); -} - - -// append y-data with running integer index as x-data -void MatlabLine::Append(double y) -{ - if (_xData.empty()) - { - // first element is index 0 - Append(0, y); - } - else - { - // take last x-value and increment - double temp = _xData.back(); // last x-value - Append(temp + 1, y); - } -} - - -void MatlabLine::SetMaxLen(int maxLen) -{ - if (maxLen <= 0) - { - // means no maxLen - _maxLen = -1; - } - else - { - _maxLen = maxLen; - - if (_xArray != NULL) - { - mxDestroyArray(_xArray); - mxDestroyArray(_yArray); - } - _xArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); - _yArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); - - maxLen = ((unsigned int)maxLen <= _xData.size()) ? maxLen : (int)_xData.size(); - _xData.resize(maxLen); - _yData.resize(maxLen); - - //// reserve the right amount of memory - //_xData.reserve(_maxLen); - //_yData.reserve(_maxLen); - } -} - -void MatlabLine::SetAttribute(char *plotAttrib) -{ - _plotAttribute = plotAttrib; -} - -void MatlabLine::SetName(char *name) -{ - _name = name; -} - -void MatlabLine::GetPlotData(mxArray** xData, mxArray** yData) -{ - // Make sure we have enough Matlab allocated memory. - // Assuming both arrays (x and y) are of the same size. - if (_xData.empty()) - { - return; // No data - } - unsigned int size = 0; - if (_xArray != NULL) - { - size = (unsigned int)mxGetNumberOfElements(_xArray); - } - if (size < _xData.size()) - { - if (_xArray != NULL) - { - mxDestroyArray(_xArray); - mxDestroyArray(_yArray); - } - _xArray = mxCreateDoubleMatrix(1, _xData.size(), mxREAL); - _yArray = mxCreateDoubleMatrix(1, _yData.size(), mxREAL); - } - - if (!_xData.empty()) - { - double* x = mxGetPr(_xArray); - - std::list<double>::iterator it = _xData.begin(); - - for (int i = 0; it != _xData.end(); it++, i++) - { - x[i] = *it; - } - } - - if (!_yData.empty()) - { - double* y = mxGetPr(_yArray); - - std::list<double>::iterator it = _yData.begin(); - - for (int i = 0; it != _yData.end(); it++, i++) - { - y[i] = *it; - } - } - *xData = _xArray; - *yData = _yArray; -} - -std::string MatlabLine::GetXName() -{ - std::ostringstream xString; - xString << "x_" << _name; - return xString.str(); -} - -std::string MatlabLine::GetYName() -{ - std::ostringstream yString; - yString << "y_" << _name; - return yString.str(); -} - -std::string MatlabLine::GetPlotString() -{ - - std::ostringstream s; - - if (_xData.size() == 0) - { - s << "[0 1], [0 1]"; // To get an empty plot - } - else - { - s << GetXName() << "(1:" << _xData.size() << "),"; - s << GetYName() << "(1:" << _yData.size() << ")"; - } - - s << ", '"; - s << _plotAttribute; - s << "'"; - - return s.str(); -} - -std::string MatlabLine::GetRefreshString() -{ - std::ostringstream s; - - if (_xData.size() > 0) - { - s << "set(h,'xdata',"<< GetXName() <<"(1:" << _xData.size() << "),'ydata',"<< GetYName() << "(1:" << _yData.size() << "));"; - } - else - { - s << "set(h,'xdata',[NaN],'ydata',[NaN]);"; - } - return s.str(); -} - -std::string MatlabLine::GetLegendString() -{ - return ("'" + _name + "'"); -} - -bool MatlabLine::hasLegend() -{ - return (!_name.empty()); -} - - -// remove data points, but keep attributes -void MatlabLine::Reset() -{ - _xData.clear(); - _yData.clear(); -} - - -void MatlabLine::UpdateTrendLine(MatlabLine * sourceData, double slope, double offset) -{ - Reset(); // reset data, not attributes and name - - double thexMin = sourceData->xMin(); - double thexMax = sourceData->xMax(); - Append(thexMin, thexMin * slope + offset); - Append(thexMax, thexMax * slope + offset); -} - -double MatlabLine::xMin() -{ - if (!_xData.empty()) - { - std::list<double>::iterator theStart = _xData.begin(); - std::list<double>::iterator theEnd = _xData.end(); - return(*min_element(theStart, theEnd)); - } - return (0.0); -} - -double MatlabLine::xMax() -{ - if (!_xData.empty()) - { - std::list<double>::iterator theStart = _xData.begin(); - std::list<double>::iterator theEnd = _xData.end(); - return(*max_element(theStart, theEnd)); - } - return (0.0); -} - -double MatlabLine::yMin() -{ - if (!_yData.empty()) - { - std::list<double>::iterator theStart = _yData.begin(); - std::list<double>::iterator theEnd = _yData.end(); - return(*min_element(theStart, theEnd)); - } - return (0.0); -} - -double MatlabLine::yMax() -{ - if (!_yData.empty()) - { - std::list<double>::iterator theStart = _yData.begin(); - std::list<double>::iterator theEnd = _yData.end(); - return(*max_element(theStart, theEnd)); - } - return (0.0); -} - - - -MatlabTimeLine::MatlabTimeLine(int horizonSeconds /*= -1*/, const char *plotAttrib /*= NULL*/, - const char *name /*= NULL*/, - int64_t refTimeMs /* = -1*/) - : -_timeHorizon(horizonSeconds), -MatlabLine(-1, plotAttrib, name) // infinite number of elements -{ - if (refTimeMs < 0) - _refTimeMs = TickTime::MillisecondTimestamp(); - else - _refTimeMs = refTimeMs; -} - -void MatlabTimeLine::Append(double y) -{ - MatlabLine::Append(static_cast<double>(TickTime::MillisecondTimestamp() - _refTimeMs) / 1000.0, y); - - PurgeOldData(); -} - - -void MatlabTimeLine::PurgeOldData() -{ - if (_timeHorizon > 0) - { - // remove old data - double historyLimit = static_cast<double>(TickTime::MillisecondTimestamp() - _refTimeMs) / 1000.0 - - _timeHorizon; // remove data points older than this - - std::list<double>::reverse_iterator ritx = _xData.rbegin(); - uint32_t removeCount = 0; - while (ritx != _xData.rend()) - { - if (*ritx >= historyLimit) - { - break; - } - ritx++; - removeCount++; - } - if (removeCount == 0) - { - return; - } - - // remove the range [begin, it). - //if (removeCount > 10) - //{ - // printf("Removing %lu elements\n", removeCount); - //} - _xData.resize(_xData.size() - removeCount); - _yData.resize(_yData.size() - removeCount); - } -} - - -int64_t MatlabTimeLine::GetRefTime() -{ - return(_refTimeMs); -} - - - - -MatlabPlot::MatlabPlot() -: -_figHandle(-1), -_smartAxis(false), -_critSect(CriticalSectionWrapper::CreateCriticalSection()), -_timeToPlot(false), -_plotting(false), -_enabled(true), -_firstPlot(true), -_legendEnabled(true), -_donePlottingEvent(EventWrapper::Create()) -{ - CriticalSectionScoped cs(_critSect); - - _xlim[0] = 0; - _xlim[1] = 0; - _ylim[0] = 0; - _ylim[1] = 0; - -#ifdef PLOT_TESTING - _plotStartTime = -1; - _plotDelay = 0; -#endif - -} - - -MatlabPlot::~MatlabPlot() -{ - _critSect->Enter(); - - // delete all line objects - while (!_line.empty()) - { - delete *(_line.end() - 1); - _line.pop_back(); - } - - delete _critSect; - delete _donePlottingEvent; -} - - -int MatlabPlot::AddLine(int maxLen /*= -1*/, const char *plotAttrib /*= NULL*/, const char *name /*= NULL*/) -{ - CriticalSectionScoped cs(_critSect); - if (!_enabled) - { - return -1; - } - - MatlabLine *newLine = new MatlabLine(maxLen, plotAttrib, name); - _line.push_back(newLine); - - return (static_cast<int>(_line.size() - 1)); // index of newly inserted line -} - - -int MatlabPlot::AddTimeLine(int maxLen /*= -1*/, const char *plotAttrib /*= NULL*/, const char *name /*= NULL*/, - int64_t refTimeMs /*= -1*/) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return -1; - } - - MatlabTimeLine *newLine = new MatlabTimeLine(maxLen, plotAttrib, name, refTimeMs); - _line.push_back(newLine); - - return (static_cast<int>(_line.size() - 1)); // index of newly inserted line -} - - -int MatlabPlot::GetLineIx(const char *name) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return -1; - } - - // search the list for a matching line name - std::vector<MatlabLine*>::iterator it = _line.begin(); - bool matchFound = false; - int lineIx = 0; - - for (; it != _line.end(); it++, lineIx++) - { - if ((*it)->_name == name) - { - matchFound = true; - break; - } - } - - if (matchFound) - { - return (lineIx); - } - else - { - return (-1); - } -} - - -void MatlabPlot::Append(int lineIndex, double x, double y) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return; - } - - // sanity for index - if (lineIndex < 0 || lineIndex >= static_cast<int>(_line.size())) - { - throw "Line index out of range"; - exit(1); - } - - return (_line[lineIndex]->Append(x, y)); -} - - -void MatlabPlot::Append(int lineIndex, double y) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return; - } - - // sanity for index - if (lineIndex < 0 || lineIndex >= static_cast<int>(_line.size())) - { - throw "Line index out of range"; - exit(1); - } - - return (_line[lineIndex]->Append(y)); -} - - -int MatlabPlot::Append(const char *name, double x, double y) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return -1; - } - - // search the list for a matching line name - int lineIx = GetLineIx(name); - - if (lineIx < 0) //(!matchFound) - { - // no match; append new line - lineIx = AddLine(-1, NULL, name); - } - - // append data to line - Append(lineIx, x, y); - return (lineIx); -} - -int MatlabPlot::Append(const char *name, double y) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return -1; - } - - // search the list for a matching line name - int lineIx = GetLineIx(name); - - if (lineIx < 0) //(!matchFound) - { - // no match; append new line - lineIx = AddLine(-1, NULL, name); - } - - // append data to line - Append(lineIx, y); - return (lineIx); -} - -int MatlabPlot::Length(char *name) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return -1; - } - - int ix = GetLineIx(name); - if (ix >= 0) - { - return (static_cast<int>(_line[ix]->_xData.size())); - } - else - { - return (-1); - } -} - - -void MatlabPlot::SetPlotAttribute(char *name, char *plotAttrib) -{ - CriticalSectionScoped cs(_critSect); - - if (!_enabled) - { - return; - } - - int lineIx = GetLineIx(name); - - if (lineIx >= 0) - { - _line[lineIx]->SetAttribute(plotAttrib); - } -} - -// Must be called under critical section _critSect -void MatlabPlot::UpdateData(Engine* ep) -{ - if (!_enabled) - { - return; - } - - for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) - { - mxArray* xData = NULL; - mxArray* yData = NULL; - (*it)->GetPlotData(&xData, &yData); - if (xData != NULL) - { - std::string xName = (*it)->GetXName(); - std::string yName = (*it)->GetYName(); - _critSect->Leave(); -#ifdef MATLAB6 - mxSetName(xData, xName.c_str()); - mxSetName(yData, yName.c_str()); - engPutArray(ep, xData); - engPutArray(ep, yData); -#else - int ret = engPutVariable(ep, xName.c_str(), xData); - assert(ret == 0); - ret = engPutVariable(ep, yName.c_str(), yData); - assert(ret == 0); -#endif - _critSect->Enter(); - } - } -} - -bool MatlabPlot::GetPlotCmd(std::ostringstream & cmd, Engine* ep) -{ - _critSect->Enter(); - - if (!DataAvailable()) - { - return false; - } - - if (_firstPlot) - { - GetPlotCmd(cmd); - _firstPlot = false; - } - else - { - GetRefreshCmd(cmd); - } - - UpdateData(ep); - - _critSect->Leave(); - - return true; -} - -// Call inside critsect -void MatlabPlot::GetPlotCmd(std::ostringstream & cmd) -{ - // we have something to plot - // empty the stream - cmd.str(""); // (this seems to be the only way) - - cmd << "figure; h" << _figHandle << "= plot("; - - // first line - std::vector<MatlabLine*>::iterator it = _line.begin(); - cmd << (*it)->GetPlotString(); - - it++; - - // remaining lines - for (; it != _line.end(); it++) - { - cmd << ", "; - cmd << (*it)->GetPlotString(); - } - - cmd << "); "; - - if (_legendEnabled) - { - GetLegendCmd(cmd); - } - - if (_smartAxis) - { - double xMin = _xlim[0]; - double xMax = _xlim[1]; - double yMax = _ylim[1]; - for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) - { - xMax = std::max(xMax, (*it)->xMax()); - xMin = std::min(xMin, (*it)->xMin()); - - yMax = std::max(yMax, (*it)->yMax()); - yMax = std::max(yMax, fabs((*it)->yMin())); - } - _xlim[0] = xMin; - _xlim[1] = xMax; - _ylim[0] = -yMax; - _ylim[1] = yMax; - - cmd << "axis([" << _xlim[0] << ", " << _xlim[1] << ", " << _ylim[0] << ", " << _ylim[1] << "]);"; - } - - int i=1; - for (it = _line.begin(); it != _line.end(); i++, it++) - { - cmd << "set(h" << _figHandle << "(" << i << "), 'Tag', " << (*it)->GetLegendString() << ");"; - } -} - -// Call inside critsect -void MatlabPlot::GetRefreshCmd(std::ostringstream & cmd) -{ - cmd.str(""); // (this seems to be the only way) - std::vector<MatlabLine*>::iterator it = _line.begin(); - for (it = _line.begin(); it != _line.end(); it++) - { - cmd << "h = findobj(0, 'Tag', " << (*it)->GetLegendString() << ");"; - cmd << (*it)->GetRefreshString(); - } - //if (_legendEnabled) - //{ - // GetLegendCmd(cmd); - //} -} - -void MatlabPlot::GetLegendCmd(std::ostringstream & cmd) -{ - std::vector<MatlabLine*>::iterator it = _line.begin(); - bool anyLegend = false; - for (; it != _line.end(); it++) - { - anyLegend = anyLegend || (*it)->hasLegend(); - } - if (anyLegend) - { - // create the legend - - cmd << "legend(h" << _figHandle << ",{"; - - - // iterate lines - int i = 0; - for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) - { - if (i > 0) - { - cmd << ", "; - } - cmd << (*it)->GetLegendString(); - i++; - } - - cmd << "}, 2); "; // place legend in upper-left corner - } -} - -// Call inside critsect -bool MatlabPlot::DataAvailable() -{ - if (!_enabled) - { - return false; - } - - for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) - { - (*it)->PurgeOldData(); - } - - return true; -} - -void MatlabPlot::Plot() -{ - CriticalSectionScoped cs(_critSect); - - _timeToPlot = true; - -#ifdef PLOT_TESTING - _plotStartTime = TickTime::MillisecondTimestamp(); -#endif -} - - -void MatlabPlot::Reset() -{ - CriticalSectionScoped cs(_critSect); - - _enabled = true; - - for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) - { - (*it)->Reset(); - } - -} - -void MatlabPlot::SetFigHandle(int handle) -{ - CriticalSectionScoped cs(_critSect); - - if (handle > 0) - _figHandle = handle; -} - -bool -MatlabPlot::TimeToPlot() -{ - CriticalSectionScoped cs(_critSect); - return _enabled && _timeToPlot; -} - -void -MatlabPlot::Plotting() -{ - CriticalSectionScoped cs(_critSect); - _plotting = true; -} - -void -MatlabPlot::DonePlotting() -{ - CriticalSectionScoped cs(_critSect); - _timeToPlot = false; - _plotting = false; - _donePlottingEvent->Set(); -} - -void -MatlabPlot::DisablePlot() -{ - _critSect->Enter(); - while (_plotting) - { - _critSect->Leave(); - _donePlottingEvent->Wait(WEBRTC_EVENT_INFINITE); - _critSect->Enter(); - } - _enabled = false; -} - -int MatlabPlot::MakeTrend(const char *sourceName, const char *trendName, double slope, double offset, const char *plotAttrib) -{ - CriticalSectionScoped cs(_critSect); - - int sourceIx; - int trendIx; - - sourceIx = GetLineIx(sourceName); - if (sourceIx < 0) - { - // could not find source - return (-1); - } - - trendIx = GetLineIx(trendName); - if (trendIx < 0) - { - // no trend found; add new line - trendIx = AddLine(2 /*maxLen*/, plotAttrib, trendName); - } - - _line[trendIx]->UpdateTrendLine(_line[sourceIx], slope, offset); - - return (trendIx); - -} - - -MatlabEngine::MatlabEngine() -: -_critSect(CriticalSectionWrapper::CreateCriticalSection()), -_eventPtr(NULL), -_running(false), -_numPlots(0) -{ - _eventPtr = EventWrapper::Create(); - - _plotThread = ThreadWrapper::CreateThread(MatlabEngine::PlotThread, this, - kLowPriority, "MatlabPlot"); - _running = true; - _plotThread->Start(); -} - -MatlabEngine::~MatlabEngine() -{ - _critSect->Enter(); - - if (_plotThread) - { - _running = false; - _eventPtr->Set(); - - _plotThread->Stop(); - } - - _plots.clear(); - - delete _eventPtr; - _eventPtr = NULL; - - _critSect->Leave(); - delete _critSect; - -} - -MatlabPlot * MatlabEngine::NewPlot(MatlabPlot *newPlot) -{ - CriticalSectionScoped cs(_critSect); - - //MatlabPlot *newPlot = new MatlabPlot(); - - if (newPlot) - { - newPlot->SetFigHandle(++_numPlots); // first plot is number 1 - _plots.push_back(newPlot); - } - - return (newPlot); - -} - - -void MatlabEngine::DeletePlot(MatlabPlot *plot) -{ - CriticalSectionScoped cs(_critSect); - - if (plot == NULL) - { - return; - } - - std::vector<MatlabPlot *>::iterator it; - for (it = _plots.begin(); it < _plots.end(); it++) - { - if (plot == *it) - { - break; - } - } - - assert (plot == *it); - - (*it)->DisablePlot(); - - _plots.erase(it); - --_numPlots; - - delete plot; -} - - -bool MatlabEngine::PlotThread(void *obj) -{ - if (!obj) - { - return (false); - } - - MatlabEngine *eng = (MatlabEngine *) obj; - - Engine *ep = engOpen(NULL); - if (!ep) - { - throw "Cannot open Matlab engine"; - return (false); - } - - engSetVisible(ep, true); - engEvalString(ep, "close all;"); - - while (eng->_running) - { - eng->_critSect->Enter(); - - // iterate through all plots - for (unsigned int ix = 0; ix < eng->_plots.size(); ix++) - { - MatlabPlot *plot = eng->_plots[ix]; - if (plot->TimeToPlot()) - { - plot->Plotting(); - eng->_critSect->Leave(); - std::ostringstream cmd; - - if (engEvalString(ep, cmd.str().c_str())) - { - // engine dead - return (false); - } - - // empty the stream - cmd.str(""); // (this seems to be the only way) - if (plot->GetPlotCmd(cmd, ep)) - { - // things to plot, we have already accessed what we need in the plot - plot->DonePlotting(); - - int64_t start = TickTime::MillisecondTimestamp(); - // plot it - int ret = engEvalString(ep, cmd.str().c_str()); - printf("time=%I64i\n", TickTime::MillisecondTimestamp() - start); - if (ret) - { - // engine dead - return (false); - } - -#ifdef PLOT_TESTING - if(plot->_plotStartTime >= 0) - { - plot->_plotDelay = TickTime::MillisecondTimestamp() - plot->_plotStartTime; - plot->_plotStartTime = -1; - } -#endif - } - eng->_critSect->Enter(); - } - } - - eng->_critSect->Leave(); - // wait a while - eng->_eventPtr->Wait(66); // 33 ms - } - - if (ep) - { - engClose(ep); - ep = NULL; - } - - return (true); - -} - -#endif // MATLAB diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h deleted file mode 100644 index 3ed89f8f91..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2011 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 WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_MATLABPLOT_H_ -#define WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_MATLABPLOT_H_ - -#include <list> -#include <string> -#include <vector> - -#include "webrtc/typedefs.h" -#include "webrtc/system_wrappers/include/thread_wrapper.h" - -namespace webrtc { -class CriticalSectionWrapper; -class EventWrapper; -} - -//#define PLOT_TESTING - -#ifdef MATLAB - -typedef struct engine Engine; -typedef struct mxArray_tag mxArray; - -class MatlabLine -{ - friend class MatlabPlot; - -public: - MatlabLine(int maxLen = -1, const char *plotAttrib = NULL, const char *name = NULL); - ~MatlabLine(); - virtual void Append(double x, double y); - virtual void Append(double y); - void SetMaxLen(int maxLen); - void SetAttribute(char *plotAttrib); - void SetName(char *name); - void Reset(); - virtual void PurgeOldData() {}; - - void UpdateTrendLine(MatlabLine * sourceData, double slope, double offset); - - double xMin(); - double xMax(); - double yMin(); - double yMax(); - -protected: - void GetPlotData(mxArray** xData, mxArray** yData); - std::string GetXName(); - std::string GetYName(); - std::string GetPlotString(); - std::string GetRefreshString(); - std::string GetLegendString(); - bool hasLegend(); - std::list<double> _xData; - std::list<double> _yData; - mxArray* _xArray; - mxArray* _yArray; - int _maxLen; - std::string _plotAttribute; - std::string _name; -}; - - -class MatlabTimeLine : public MatlabLine -{ -public: - MatlabTimeLine(int horizonSeconds = -1, const char *plotAttrib = NULL, const char *name = NULL, - int64_t refTimeMs = -1); - ~MatlabTimeLine() {}; - void Append(double y); - void PurgeOldData(); - int64_t GetRefTime(); - -private: - int64_t _refTimeMs; - int _timeHorizon; -}; - - -class MatlabPlot -{ - friend class MatlabEngine; - -public: - MatlabPlot(); - ~MatlabPlot(); - - int AddLine(int maxLen = -1, const char *plotAttrib = NULL, const char *name = NULL); - int AddTimeLine(int maxLen = -1, const char *plotAttrib = NULL, const char *name = NULL, - int64_t refTimeMs = -1); - int GetLineIx(const char *name); - void Append(int lineIndex, double x, double y); - void Append(int lineIndex, double y); - int Append(const char *name, double x, double y); - int Append(const char *name, double y); - int Length(char *name); - void SetPlotAttribute(char *name, char *plotAttrib); - void Plot(); - void Reset(); - void SmartAxis(bool status = true) { _smartAxis = status; }; - void SetFigHandle(int handle); - void EnableLegend(bool enable) { _legendEnabled = enable; }; - - bool TimeToPlot(); - void Plotting(); - void DonePlotting(); - void DisablePlot(); - - int MakeTrend(const char *sourceName, const char *trendName, double slope, double offset, const char *plotAttrib = NULL); - -#ifdef PLOT_TESTING - int64_t _plotStartTime; - int64_t _plotDelay; -#endif - -private: - void UpdateData(Engine* ep); - bool GetPlotCmd(std::ostringstream & cmd, Engine* ep); - void GetPlotCmd(std::ostringstream & cmd); // call inside crit sect - void GetRefreshCmd(std::ostringstream & cmd); // call inside crit sect - void GetLegendCmd(std::ostringstream & cmd); - bool DataAvailable(); - - std::vector<MatlabLine *> _line; - int _figHandle; - bool _smartAxis; - double _xlim[2]; - double _ylim[2]; - webrtc::CriticalSectionWrapper *_critSect; - bool _timeToPlot; - bool _plotting; - bool _enabled; - bool _firstPlot; - bool _legendEnabled; - webrtc::EventWrapper* _donePlottingEvent; -}; - - -class MatlabEngine -{ -public: - MatlabEngine(); - ~MatlabEngine(); - - MatlabPlot * NewPlot(MatlabPlot *newPlot); - void DeletePlot(MatlabPlot *plot); - -private: - static bool PlotThread(void *obj); - - std::vector<MatlabPlot *> _plots; - webrtc::CriticalSectionWrapper *_critSect; - webrtc::EventWrapper *_eventPtr; - rtc::scoped_ptr<webrtc::ThreadWrapper> _plotThread; - bool _running; - int _numPlots; -}; - -#endif //MATLAB - -#endif // WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_MATLABPLOT_H_ diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.cc b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.cc deleted file mode 100644 index 0e3e87976c..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.cc +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h" - -#include <stdio.h> - -#include <algorithm> - -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h" -#include "webrtc/system_wrappers/include/critical_section_wrapper.h" -#include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/system_wrappers/include/tick_util.h" - - -bool SenderThreadFunction(void *obj) -{ - if (obj == NULL) - { - return false; - } - TestLoadGenerator *_genObj = static_cast<TestLoadGenerator *>(obj); - - return _genObj->GeneratorLoop(); -} - - -TestLoadGenerator::TestLoadGenerator(TestSenderReceiver *sender, int32_t rtpSampleRate) -: -_critSect(CriticalSectionWrapper::CreateCriticalSection()), -_eventPtr(NULL), -_bitrateKbps(0), -_sender(sender), -_running(false), -_rtpSampleRate(rtpSampleRate) -{ -} - -TestLoadGenerator::~TestLoadGenerator () -{ - if (_running) - { - Stop(); - } - - delete _critSect; -} - -int32_t TestLoadGenerator::SetBitrate (int32_t newBitrateKbps) -{ - CriticalSectionScoped cs(_critSect); - - if (newBitrateKbps < 0) - { - return -1; - } - - _bitrateKbps = newBitrateKbps; - - printf("New bitrate = %i kbps\n", _bitrateKbps); - - return _bitrateKbps; -} - - -int32_t TestLoadGenerator::Start (const char *threadName) -{ - CriticalSectionScoped cs(_critSect); - - _eventPtr = EventWrapper::Create(); - - _genThread = ThreadWrapper::CreateThread(SenderThreadFunction, this, - threadName); - _running = true; - - _genThread->Start(); - _genThread->SetPriority(kRealtimePriority); - - return 0; -} - - -int32_t TestLoadGenerator::Stop () -{ - _critSect.Enter(); - - if (_genThread) - { - _running = false; - _eventPtr->Set(); - - _genThread->Stop(); - _genThread.reset(); - - delete _eventPtr; - _eventPtr = NULL; - } - - _critSect.Leave(); - return (0); -} - - -int TestLoadGenerator::generatePayload () -{ - return(generatePayload( static_cast<uint32_t>( TickTime::MillisecondTimestamp() * _rtpSampleRate / 1000 ))); -} - - -int TestLoadGenerator::sendPayload (const uint32_t timeStamp, - const uint8_t* payloadData, - const size_t payloadSize, - const webrtc::FrameType frameType /*= webrtc::kVideoFrameDelta*/) -{ - - return (_sender->SendOutgoingData(timeStamp, payloadData, payloadSize, frameType)); -} - - -CBRGenerator::CBRGenerator (TestSenderReceiver *sender, - size_t payloadSizeBytes, - int32_t bitrateKbps, - int32_t rtpSampleRate) -: -//_eventPtr(NULL), -_payloadSizeBytes(payloadSizeBytes), -_payload(new uint8_t[payloadSizeBytes]), -TestLoadGenerator(sender, rtpSampleRate) -{ - SetBitrate (bitrateKbps); -} - -CBRGenerator::~CBRGenerator () -{ - if (_running) - { - Stop(); - } - - if (_payload) - { - delete [] _payload; - } - -} - -bool CBRGenerator::GeneratorLoop () -{ - double periodMs; - int64_t nextSendTime = TickTime::MillisecondTimestamp(); - - - // no critSect - while (_running) - { - // send data (critSect inside) - generatePayload( static_cast<uint32_t>(nextSendTime * _rtpSampleRate / 1000) ); - - // calculate wait time - periodMs = 8.0 * _payloadSizeBytes / ( _bitrateKbps ); - - nextSendTime = static_cast<int64_t>(nextSendTime + periodMs); - - int32_t waitTime = static_cast<int32_t>(nextSendTime - TickTime::MillisecondTimestamp()); - if (waitTime < 0) - { - waitTime = 0; - } - // wait - _eventPtr->Wait(static_cast<int32_t>(waitTime)); - } - - return true; -} - -int CBRGenerator::generatePayload ( uint32_t timestamp ) -{ - CriticalSectionScoped cs(_critSect); - - //uint8_t *payload = new uint8_t[_payloadSizeBytes]; - - int ret = sendPayload(timestamp, _payload, _payloadSizeBytes); - - //delete [] payload; - return ret; -} - - - - -///////////////////// - -CBRFixFRGenerator::CBRFixFRGenerator (TestSenderReceiver *sender, int32_t bitrateKbps, - int32_t rtpSampleRate, int32_t frameRateFps /*= 30*/, - double spread /*= 0.0*/) -: -//_eventPtr(NULL), -_payloadSizeBytes(0), -_payload(NULL), -_payloadAllocLen(0), -_frameRateFps(frameRateFps), -_spreadFactor(spread), -TestLoadGenerator(sender, rtpSampleRate) -{ - SetBitrate (bitrateKbps); -} - -CBRFixFRGenerator::~CBRFixFRGenerator () -{ - if (_running) - { - Stop(); - } - - if (_payload) - { - delete [] _payload; - _payloadAllocLen = 0; - } - -} - -bool CBRFixFRGenerator::GeneratorLoop () -{ - double periodMs; - int64_t nextSendTime = TickTime::MillisecondTimestamp(); - - _critSect.Enter(); - - if (_frameRateFps <= 0) - { - return false; - } - - _critSect.Leave(); - - // no critSect - while (_running) - { - _critSect.Enter(); - - // calculate payload size - _payloadSizeBytes = nextPayloadSize(); - - if (_payloadSizeBytes > 0) - { - - if (_payloadAllocLen < _payloadSizeBytes * (1 + _spreadFactor)) - { - // re-allocate _payload - if (_payload) - { - delete [] _payload; - _payload = NULL; - } - - _payloadAllocLen = static_cast<int32_t>((_payloadSizeBytes * (1 + _spreadFactor) * 3) / 2 + .5); // 50% extra to avoid frequent re-alloc - _payload = new uint8_t[_payloadAllocLen]; - } - - - // send data (critSect inside) - generatePayload( static_cast<uint32_t>(nextSendTime * _rtpSampleRate / 1000) ); - } - - _critSect.Leave(); - - // calculate wait time - periodMs = 1000.0 / _frameRateFps; - nextSendTime = static_cast<int64_t>(nextSendTime + periodMs + 0.5); - - int32_t waitTime = static_cast<int32_t>(nextSendTime - TickTime::MillisecondTimestamp()); - if (waitTime < 0) - { - waitTime = 0; - } - // wait - _eventPtr->Wait(waitTime); - } - - return true; -} - -size_t CBRFixFRGenerator::nextPayloadSize() -{ - const double periodMs = 1000.0 / _frameRateFps; - return static_cast<size_t>(_bitrateKbps * periodMs / 8 + 0.5); -} - -int CBRFixFRGenerator::generatePayload ( uint32_t timestamp ) -{ - CriticalSectionScoped cs(_critSect); - - double factor = ((double) rand() - RAND_MAX/2) / RAND_MAX; // [-0.5; 0.5] - factor = 1 + 2 * _spreadFactor * factor; // [1 - _spreadFactor ; 1 + _spreadFactor] - - size_t thisPayloadBytes = static_cast<size_t>(_payloadSizeBytes * factor); - // sanity - if (thisPayloadBytes > _payloadAllocLen) - { - thisPayloadBytes = _payloadAllocLen; - } - - int ret = sendPayload(timestamp, _payload, thisPayloadBytes); - return ret; -} - - -///////////////////// - -PeriodicKeyFixFRGenerator::PeriodicKeyFixFRGenerator (TestSenderReceiver *sender, int32_t bitrateKbps, - int32_t rtpSampleRate, int32_t frameRateFps /*= 30*/, - double spread /*= 0.0*/, double keyFactor /*= 4.0*/, uint32_t keyPeriod /*= 300*/) -: -_keyFactor(keyFactor), -_keyPeriod(keyPeriod), -_frameCount(0), -CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, frameRateFps, spread) -{ -} - -size_t PeriodicKeyFixFRGenerator::nextPayloadSize() -{ - // calculate payload size for a delta frame - size_t payloadSizeBytes = static_cast<size_t>(1000 * _bitrateKbps / - (8.0 * _frameRateFps * (1.0 + (_keyFactor - 1.0) / _keyPeriod)) + 0.5); - - if (_frameCount % _keyPeriod == 0) - { - // this is a key frame, scale the payload size - payloadSizeBytes = - static_cast<size_t>(_keyFactor * _payloadSizeBytes + 0.5); - } - _frameCount++; - - return payloadSizeBytes; -} - -//////////////////// - -CBRVarFRGenerator::CBRVarFRGenerator(TestSenderReceiver *sender, int32_t bitrateKbps, const uint8_t* frameRates, - uint16_t numFrameRates, int32_t rtpSampleRate, double avgFrPeriodMs, - double frSpreadFactor, double spreadFactor) -: -_avgFrPeriodMs(avgFrPeriodMs), -_frSpreadFactor(frSpreadFactor), -_frameRates(NULL), -_numFrameRates(numFrameRates), -_frChangeTimeMs(TickTime::MillisecondTimestamp() + _avgFrPeriodMs), -CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, frameRates[0], spreadFactor) -{ - _frameRates = new uint8_t[_numFrameRates]; - memcpy(_frameRates, frameRates, _numFrameRates); -} - -CBRVarFRGenerator::~CBRVarFRGenerator() -{ - delete [] _frameRates; -} - -void CBRVarFRGenerator::ChangeFrameRate() -{ - const int64_t nowMs = TickTime::MillisecondTimestamp(); - if (nowMs < _frChangeTimeMs) - { - return; - } - // Time to change frame rate - uint16_t frIndex = static_cast<uint16_t>(static_cast<double>(rand()) / RAND_MAX - * (_numFrameRates - 1) + 0.5) ; - assert(frIndex < _numFrameRates); - _frameRateFps = _frameRates[frIndex]; - // Update the next frame rate change time - double factor = ((double) rand() - RAND_MAX/2) / RAND_MAX; // [-0.5; 0.5] - factor = 1 + 2 * _frSpreadFactor * factor; // [1 - _frSpreadFactor ; 1 + _frSpreadFactor] - _frChangeTimeMs = nowMs + static_cast<int64_t>(1000.0 * factor * - _avgFrPeriodMs + 0.5); - - printf("New frame rate: %d\n", _frameRateFps); -} - -size_t CBRVarFRGenerator::nextPayloadSize() -{ - ChangeFrameRate(); - return CBRFixFRGenerator::nextPayloadSize(); -} - -//////////////////// - -CBRFrameDropGenerator::CBRFrameDropGenerator(TestSenderReceiver *sender, int32_t bitrateKbps, - int32_t rtpSampleRate, double spreadFactor) -: -_accBits(0), -CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, 30, spreadFactor) -{ -} - -CBRFrameDropGenerator::~CBRFrameDropGenerator() -{ -} - -size_t CBRFrameDropGenerator::nextPayloadSize() -{ - _accBits -= 1000 * _bitrateKbps / _frameRateFps; - if (_accBits < 0) - { - _accBits = 0; - } - if (_accBits > 0.3 * _bitrateKbps * 1000) - { - //printf("drop\n"); - return 0; - } - else - { - //printf("keep\n"); - const double periodMs = 1000.0 / _frameRateFps; - size_t frameSize = - static_cast<size_t>(_bitrateKbps * periodMs / 8 + 0.5); - frameSize = - std::max(frameSize, static_cast<size_t>(300 * periodMs / 8 + 0.5)); - _accBits += frameSize * 8; - return frameSize; - } -} diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h deleted file mode 100644 index bd83962fa3..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2011 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 WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_TESTLOADGENERATOR_H_ -#define WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_TESTLOADGENERATOR_H_ - -#include <stdlib.h> - -#include "webrtc/modules/interface/module_common_types.h" -#include "webrtc/system_wrappers/include/thread_wrapper.h" -#include "webrtc/typedefs.h" - -class TestSenderReceiver; -namespace webrtc { -class CriticalSectionWrapper; -class EventWrapper; -} - -class TestLoadGenerator -{ -public: - TestLoadGenerator (TestSenderReceiver *sender, int32_t rtpSampleRate = 90000); - virtual ~TestLoadGenerator (); - - int32_t SetBitrate (int32_t newBitrateKbps); - virtual int32_t Start (const char *threadName = NULL); - virtual int32_t Stop (); - virtual bool GeneratorLoop () = 0; - -protected: - virtual int generatePayload ( uint32_t timestamp ) = 0; - int generatePayload (); - int sendPayload (const uint32_t timeStamp, - const uint8_t* payloadData, - const size_t payloadSize, - const webrtc::FrameType frameType = webrtc::kVideoFrameDelta); - - webrtc::CriticalSectionWrapper* _critSect; - webrtc::EventWrapper *_eventPtr; - rtc::scoped_ptr<webrtc::ThreadWrapper> _genThread; - int32_t _bitrateKbps; - TestSenderReceiver *_sender; - bool _running; - int32_t _rtpSampleRate; -}; - - -class CBRGenerator : public TestLoadGenerator -{ -public: - CBRGenerator (TestSenderReceiver *sender, - size_t payloadSizeBytes, - int32_t bitrateKbps, - int32_t rtpSampleRate = 90000); - virtual ~CBRGenerator (); - - virtual int32_t Start () {return (TestLoadGenerator::Start("CBRGenerator"));}; - - virtual bool GeneratorLoop (); - -protected: - virtual int generatePayload ( uint32_t timestamp ); - - size_t _payloadSizeBytes; - uint8_t *_payload; -}; - - -class CBRFixFRGenerator : public TestLoadGenerator // constant bitrate and fixed frame rate -{ -public: - CBRFixFRGenerator (TestSenderReceiver *sender, int32_t bitrateKbps, int32_t rtpSampleRate = 90000, - int32_t frameRateFps = 30, double spread = 0.0); - virtual ~CBRFixFRGenerator (); - - virtual int32_t Start () {return (TestLoadGenerator::Start("CBRFixFRGenerator"));}; - - virtual bool GeneratorLoop (); - -protected: - virtual size_t nextPayloadSize (); - virtual int generatePayload ( uint32_t timestamp ); - - size_t _payloadSizeBytes; - uint8_t *_payload; - size_t _payloadAllocLen; - int32_t _frameRateFps; - double _spreadFactor; -}; - -class PeriodicKeyFixFRGenerator : public CBRFixFRGenerator // constant bitrate and fixed frame rate with periodically large frames -{ -public: - PeriodicKeyFixFRGenerator (TestSenderReceiver *sender, int32_t bitrateKbps, int32_t rtpSampleRate = 90000, - int32_t frameRateFps = 30, double spread = 0.0, double keyFactor = 4.0, uint32_t keyPeriod = 300); - virtual ~PeriodicKeyFixFRGenerator () {} - -protected: - virtual size_t nextPayloadSize (); - - double _keyFactor; - uint32_t _keyPeriod; - uint32_t _frameCount; -}; - -// Probably better to inherit CBRFixFRGenerator from CBRVarFRGenerator, but since -// the fix FR version already existed this was easier. -class CBRVarFRGenerator : public CBRFixFRGenerator // constant bitrate and variable frame rate -{ -public: - CBRVarFRGenerator(TestSenderReceiver *sender, int32_t bitrateKbps, const uint8_t* frameRates, - uint16_t numFrameRates, int32_t rtpSampleRate = 90000, double avgFrPeriodMs = 5.0, - double frSpreadFactor = 0.05, double spreadFactor = 0.0); - - ~CBRVarFRGenerator(); - -protected: - virtual void ChangeFrameRate(); - virtual size_t nextPayloadSize (); - - double _avgFrPeriodMs; - double _frSpreadFactor; - uint8_t* _frameRates; - uint16_t _numFrameRates; - int64_t _frChangeTimeMs; -}; - -class CBRFrameDropGenerator : public CBRFixFRGenerator // constant bitrate and variable frame rate -{ -public: - CBRFrameDropGenerator(TestSenderReceiver *sender, int32_t bitrateKbps, - int32_t rtpSampleRate = 90000, double spreadFactor = 0.0); - - ~CBRFrameDropGenerator(); - -protected: - virtual size_t nextPayloadSize(); - - double _accBits; -}; - -#endif // WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_TESTLOADGENERATOR_H_ diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.cc b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.cc deleted file mode 100644 index 47f2880638..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.cc +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 2011 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. - */ - -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h" - -#include <stdio.h> -#include <stdlib.h> - -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h" -#include "webrtc/system_wrappers/include/critical_section_wrapper.h" -#include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/system_wrappers/include/tick_util.h" -#include "webrtc/test/channel_transport/udp_transport.h" - -#define NR_OF_SOCKET_BUFFERS 500 - - -bool ProcThreadFunction(void *obj) -{ - if (obj == NULL) - { - return false; - } - TestSenderReceiver *theObj = static_cast<TestSenderReceiver *>(obj); - - return theObj->ProcLoop(); -} - - -TestSenderReceiver::TestSenderReceiver (void) -: -_critSect(CriticalSectionWrapper::CreateCriticalSection()), -_eventPtr(NULL), -_running(false), -_payloadType(0), -_loadGenerator(NULL), -_isSender(false), -_isReceiver(false), -_sendRecCB(NULL), -_lastBytesReceived(0), -_lastTime(-1) -{ - // RTP/RTCP module - _rtp = RtpRtcp::CreateRtpRtcp(0, false); - if (!_rtp) - { - throw "Could not create RTP/RTCP module"; - exit(1); - } - - if (_rtp->InitReceiver() != 0) - { - throw "_rtp->InitReceiver()"; - exit(1); - } - - if (_rtp->InitSender() != 0) - { - throw "_rtp->InitSender()"; - exit(1); - } - - // SocketTransport module - uint8_t numberOfThreads = 1; - _transport = UdpTransport::Create(0, numberOfThreads); - if (!_transport) - { - throw "Could not create transport module"; - exit(1); - } -} - -TestSenderReceiver::~TestSenderReceiver (void) -{ - - Stop(); // N.B. without critSect - - _critSect->Enter(); - - if (_rtp) - { - RtpRtcp::DestroyRtpRtcp(_rtp); - _rtp = NULL; - } - - if (_transport) - { - UdpTransport::Destroy(_transport); - _transport = NULL; - } - - delete _critSect; - -} - - -int32_t TestSenderReceiver::InitReceiver (const uint16_t rtpPort, - const uint16_t rtcpPort, - const int8_t payloadType /*= 127*/) -{ - CriticalSectionScoped cs(_critSect); - - // init transport - if (_transport->InitializeReceiveSockets(this, rtpPort/*, 0, NULL, 0, true*/) != 0) - { - throw "_transport->InitializeReceiveSockets"; - exit(1); - } - - if (_rtp->RegisterIncomingRTPCallback(this) != 0) - { - throw "_rtp->RegisterIncomingRTPCallback"; - exit(1); - } - - if (_rtp->RegisterIncomingDataCallback(this) != 0) - { - throw "_rtp->RegisterIncomingRTPCallback"; - exit(1); - } - - if (_rtp->SetRTCPStatus(RtcpMode::kReducedSize) != 0) { - throw "_rtp->SetRTCPStatus"; - exit(1); - } - - if (_rtp->SetTMMBRStatus(true) != 0) - { - throw "_rtp->SetTMMBRStatus"; - exit(1); - } - - if (_rtp->RegisterReceivePayload("I420", payloadType, 90000) != 0) - { - throw "_rtp->RegisterReceivePayload"; - exit(1); - } - - _isReceiver = true; - - return (0); -} - - -int32_t TestSenderReceiver::Start() -{ - CriticalSectionScoped cs(_critSect); - - _eventPtr = EventWrapper::Create(); - - if (_rtp->SetSendingStatus(true) != 0) - { - throw "_rtp->SetSendingStatus"; - exit(1); - } - - _procThread = ThreadWrapper::CreateThread(ProcThreadFunction, this, - "TestSenderReceiver"); - - _running = true; - - if (_isReceiver) - { - if (_transport->StartReceiving(NR_OF_SOCKET_BUFFERS) != 0) - { - throw "_transport->StartReceiving"; - exit(1); - } - } - - _procThread->Start(); - _procThread->SetPriority(kRealtimePriority); - - return 0; - -} - - -int32_t TestSenderReceiver::Stop () -{ - CriticalSectionScoped cs(_critSect); - - _transport->StopReceiving(); - - if (_procThread) - { - _running = false; - _eventPtr->Set(); - - _procThread->Stop(); - _procThread.reset(); - - delete _eventPtr; - } - - return (0); -} - - -bool TestSenderReceiver::ProcLoop(void) -{ - - // process RTP/RTCP module - _rtp->Process(); - - // process SocketTransport module - _transport->Process(); - - // no critSect - while (_running) - { - // ask RTP/RTCP module for wait time - int32_t rtpWait = _rtp->TimeUntilNextProcess(); - - // ask SocketTransport module for wait time - int32_t tpWait = _transport->TimeUntilNextProcess(); - - int32_t minWait = (rtpWait < tpWait) ? rtpWait: tpWait; - minWait = (minWait > 0) ? minWait : 0; - // wait - _eventPtr->Wait(minWait); - - // process RTP/RTCP module - _rtp->Process(); - - // process SocketTransport module - _transport->Process(); - - } - - return true; -} - - -int32_t TestSenderReceiver::ReceiveBitrateKbps () -{ - size_t bytesSent; - uint32_t packetsSent; - size_t bytesReceived; - uint32_t packetsReceived; - - if (_rtp->DataCountersRTP(&bytesSent, &packetsSent, &bytesReceived, &packetsReceived) == 0) - { - int64_t now = TickTime::MillisecondTimestamp(); - int32_t kbps = 0; - if (now > _lastTime) - { - if (_lastTime > 0) - { - // 8 * bytes / ms = kbps - kbps = static_cast<int32_t>( - (8 * (bytesReceived - _lastBytesReceived)) / (now - _lastTime)); - } - _lastTime = now; - _lastBytesReceived = bytesReceived; - } - return (kbps); - } - - return (-1); -} - - -int32_t TestSenderReceiver::SetPacketTimeout(const uint32_t timeoutMS) -{ - return (_rtp->SetPacketTimeout(timeoutMS, 0 /* RTCP timeout */)); -} - - -int32_t TestSenderReceiver::OnReceivedPayloadData(const uint8_t* payloadData, - const size_t payloadSize, - const webrtc::WebRtcRTPHeader* rtpHeader) -{ - //printf("OnReceivedPayloadData\n"); - return (0); -} - - -void TestSenderReceiver::IncomingRTPPacket(const int8_t* incomingRtpPacket, - const size_t rtpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) -{ - _rtp->IncomingPacket((uint8_t *) incomingRtpPacket, rtpPacketLength); -} - - - -void TestSenderReceiver::IncomingRTCPPacket(const int8_t* incomingRtcpPacket, - const size_t rtcpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) -{ - _rtp->IncomingPacket((uint8_t *) incomingRtcpPacket, rtcpPacketLength); -} - - - - - -/////////////////// - - -int32_t TestSenderReceiver::InitSender (const uint32_t startBitrateKbps, - const int8_t* ipAddr, - const uint16_t rtpPort, - const uint16_t rtcpPort /*= 0*/, - const int8_t payloadType /*= 127*/) -{ - CriticalSectionScoped cs(_critSect); - - _payloadType = payloadType; - - // check load generator valid - if (_loadGenerator) - { - _loadGenerator->SetBitrate(startBitrateKbps); - } - - if (_rtp->RegisterSendTransport(_transport) != 0) - { - throw "_rtp->RegisterSendTransport"; - exit(1); - } - if (_rtp->RegisterSendPayload("I420", _payloadType, 90000) != 0) - { - throw "_rtp->RegisterSendPayload"; - exit(1); - } - - if (_rtp->RegisterIncomingVideoCallback(this) != 0) - { - throw "_rtp->RegisterIncomingVideoCallback"; - exit(1); - } - - if (_rtp->SetRTCPStatus(RtcpMode::kReducedSize) != 0) { - throw "_rtp->SetRTCPStatus"; - exit(1); - } - - if (_rtp->SetSendBitrate(startBitrateKbps*1000, 0, MAX_BITRATE_KBPS) != 0) - { - throw "_rtp->SetSendBitrate"; - exit(1); - } - - - // SocketTransport - if (_transport->InitializeSendSockets(ipAddr, rtpPort, rtcpPort)) - { - throw "_transport->InitializeSendSockets"; - exit(1); - } - - _isSender = true; - - return (0); -} - - - -int32_t -TestSenderReceiver::SendOutgoingData(const uint32_t timeStamp, - const uint8_t* payloadData, - const size_t payloadSize, - const webrtc::FrameType frameType /*= webrtc::kVideoFrameDelta*/) -{ - return (_rtp->SendOutgoingData(frameType, _payloadType, timeStamp, payloadData, payloadSize)); -} - - -int32_t TestSenderReceiver::SetLoadGenerator(TestLoadGenerator *generator) -{ - CriticalSectionScoped cs(_critSect); - - _loadGenerator = generator; - return(0); - -} - -void TestSenderReceiver::OnNetworkChanged(const int32_t id, - const uint32_t minBitrateBps, - const uint32_t maxBitrateBps, - const uint8_t fractionLost, - const uint16_t roundTripTimeMs, - const uint16_t bwEstimateKbitMin, - const uint16_t bwEstimateKbitMax) -{ - if (_loadGenerator) - { - _loadGenerator->SetBitrate(maxBitrateBps/1000); - } - - if (_sendRecCB) - { - _sendRecCB->OnOnNetworkChanged(maxBitrateBps, - fractionLost, - roundTripTimeMs, - bwEstimateKbitMin, - bwEstimateKbitMax); - } -} diff --git a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h b/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h deleted file mode 100644 index f394412a73..0000000000 --- a/webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2011 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 WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_TESTSENDERRECEIVER_H_ -#define WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_TESTSENDERRECEIVER_H_ - -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" -#include "webrtc/system_wrappers/include/thread_wrapper.h" -#include "webrtc/test/channel_transport/udp_transport.h" -#include "webrtc/typedefs.h" - -class TestLoadGenerator; -namespace webrtc { -class CriticalSectionWrapper; -class EventWrapper; -} - -using namespace webrtc; - -#define MAX_BITRATE_KBPS 50000 - - -class SendRecCB -{ -public: - virtual void OnOnNetworkChanged(const uint32_t bitrateTarget, - const uint8_t fractionLost, - const uint16_t roundTripTimeMs, - const uint16_t bwEstimateKbitMin, - const uint16_t bwEstimateKbitMax) = 0; - - virtual ~SendRecCB() {}; -}; - - -class TestSenderReceiver : public RtpFeedback, public RtpData, public UdpTransportData, public RtpVideoFeedback -{ - -public: - TestSenderReceiver (void); - - ~TestSenderReceiver (void); - - void SetCallback (SendRecCB *cb) { _sendRecCB = cb; }; - - int32_t Start(); - - int32_t Stop(); - - bool ProcLoop(); - - ///////////////////////////////////////////// - // Receiver methods - - int32_t InitReceiver (const uint16_t rtpPort, - const uint16_t rtcpPort = 0, - const int8_t payloadType = 127); - - int32_t ReceiveBitrateKbps (); - - int32_t SetPacketTimeout(const uint32_t timeoutMS); - - // Inherited from RtpFeedback - int32_t OnInitializeDecoder(const int32_t id, - const int8_t payloadType, - const int8_t payloadName[RTP_PAYLOAD_NAME_SIZE], - const uint32_t frequency, - const uint8_t channels, - const uint32_t rate) override { - return 0; - } - - void OnIncomingSSRCChanged(const int32_t id, const uint32_t SSRC) override { - } - - void OnIncomingCSRCChanged(const int32_t id, - const uint32_t CSRC, - const bool added) override {} - - // Inherited from RtpData - int32_t OnReceivedPayloadData( - const uint8_t* payloadData, - const size_t payloadSize, - const webrtc::WebRtcRTPHeader* rtpHeader) override; - - // Inherited from UdpTransportData - void IncomingRTPPacket(const int8_t* incomingRtpPacket, - const size_t rtpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) override; - - void IncomingRTCPPacket(const int8_t* incomingRtcpPacket, - const size_t rtcpPacketLength, - const int8_t* fromIP, - const uint16_t fromPort) override; - - ///////////////////////////////// - // Sender methods - - int32_t InitSender (const uint32_t startBitrateKbps, - const int8_t* ipAddr, - const uint16_t rtpPort, - const uint16_t rtcpPort = 0, - const int8_t payloadType = 127); - - int32_t SendOutgoingData(const uint32_t timeStamp, - const uint8_t* payloadData, - const size_t payloadSize, - const webrtc::FrameType frameType = webrtc::kVideoFrameDelta); - - int32_t SetLoadGenerator(TestLoadGenerator *generator); - - uint32_t BitrateSent() { return (_rtp->BitrateSent()); }; - - - // Inherited from RtpVideoFeedback - virtual void OnReceivedIntraFrameRequest(const int32_t id, - const uint8_t message = 0) {}; - - virtual void OnNetworkChanged(const int32_t id, - const uint32_t minBitrateBps, - const uint32_t maxBitrateBps, - const uint8_t fractionLost, - const uint16_t roundTripTimeMs, - const uint16_t bwEstimateKbitMin, - const uint16_t bwEstimateKbitMax); - -private: - RtpRtcp* _rtp; - UdpTransport* _transport; - webrtc::CriticalSectionWrapper* _critSect; - webrtc::EventWrapper *_eventPtr; - rtc::scoped_ptr<webrtc::ThreadWrapper> _procThread; - bool _running; - int8_t _payloadType; - TestLoadGenerator* _loadGenerator; - bool _isSender; - bool _isReceiver; - SendRecCB * _sendRecCB; - size_t _lastBytesReceived; - int64_t _lastTime; - -}; - -#endif // WEBRTC_MODULES_RTP_RTCP_TEST_BWESTANDALONE_TESTSENDERRECEIVER_H_ diff --git a/webrtc/modules/rtp_rtcp/test/bwe_standalone.gypi b/webrtc/modules/rtp_rtcp/test/bwe_standalone.gypi deleted file mode 100644 index e45daec77d..0000000000 --- a/webrtc/modules/rtp_rtcp/test/bwe_standalone.gypi +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (c) 2011 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. - -{ - 'targets': [ - { - 'target_name': 'bwe_standalone', - 'type': 'executable', - 'dependencies': [ - 'matlab_plotting', - 'rtp_rtcp', - 'udp_transport', - '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', - ], - 'sources': [ - 'BWEStandAlone/BWEStandAlone.cc', - 'BWEStandAlone/TestLoadGenerator.cc', - 'BWEStandAlone/TestLoadGenerator.h', - 'BWEStandAlone/TestSenderReceiver.cc', - 'BWEStandAlone/TestSenderReceiver.h', - ], # source - 'conditions': [ - ['OS=="linux"', { - 'cflags': [ - '-fexceptions', # enable exceptions - ], - }, - ], - ], - }, - - { - 'target_name': 'matlab_plotting', - 'type': 'static_library', - 'dependencies': [ - 'matlab_plotting_include', - '<(webrtc_root)/system_wrappers/system_wrappers.gyp:system_wrappers', - ], - 'include_dirs': [ - '/opt/matlab2010a/extern/include', - ], - 'export_dependent_settings': [ - 'matlab_plotting_include', - ], - 'sources': [ - 'BWEStandAlone/MatlabPlot.cc', - 'BWEStandAlone/MatlabPlot.h', - ], - 'link_settings': { - 'ldflags' : [ - '-L/opt/matlab2010a/bin/glnxa64', - '-leng', - '-lmx', - '-Wl,-rpath,/opt/matlab2010a/bin/glnxa64', - ], - }, - 'defines': [ - 'MATLAB', - ], - 'conditions': [ - ['OS=="linux"', { - 'cflags': [ - '-fexceptions', # enable exceptions - ], - }, - ], - ], - }, - - { - 'target_name': 'matlab_plotting_include', - 'type': 'none', - 'direct_dependent_settings': { - 'include_dirs': [ - 'BWEStandAlone', - ], - }, - }, - ], -} diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc index 0270e55802..1d4d6d04a5 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc @@ -9,14 +9,14 @@ */ #include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h" -#include "webrtc/test/null_transport.h" #include <algorithm> #include <vector> -using namespace webrtc; +#include "webrtc/test/null_transport.h" namespace webrtc { + void LoopBackTransport::SetSendModule(RtpRtcp* rtp_rtcp_module, RTPPayloadRegistry* payload_registry, RtpReceiver* receiver, @@ -76,7 +76,6 @@ int32_t TestRtpReceiver::OnReceivedPayloadData( payload_size_ = payload_size; return 0; } -} // namespace webrtc class RtpRtcpAPITest : public ::testing::Test { protected: @@ -187,3 +186,5 @@ TEST_F(RtpRtcpAPITest, RtxReceiver) { rtx_header.payloadType = 0; EXPECT_TRUE(rtp_payload_registry_->IsRtx(rtx_header)); } + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h index 73334a8b26..d8040f7902 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h @@ -7,16 +7,18 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ +#ifndef WEBRTC_MODULES_RTP_RTCP_TEST_TESTAPI_TEST_API_H_ +#define WEBRTC_MODULES_RTP_RTCP_TEST_TESTAPI_TEST_API_H_ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_receiver.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/transport.h" namespace webrtc { @@ -68,3 +70,4 @@ class TestRtpReceiver : public NullRtpData { }; } // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_TEST_TESTAPI_TEST_API_H_ diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc index 745386d485..634969b311 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_audio.cc @@ -15,12 +15,12 @@ #include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h" -using namespace webrtc; - +namespace webrtc { +namespace { #define test_rate 64000u class VerifyingAudioReceiver : public NullRtpData { @@ -64,7 +64,7 @@ class RTPCallback : public NullRtpFeedback { int32_t OnInitializeDecoder(const int8_t payloadType, const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate) override { if (payloadType == 96) { EXPECT_EQ(test_rate, rate) << @@ -165,7 +165,7 @@ TEST_F(RtpRtcpAudioTest, Basic) { module1->SetStartTimestamp(test_timestamp); // Test detection at the end of a DTMF tone. - //EXPECT_EQ(0, module2->SetTelephoneEventForwardToDecoder(true)); + // EXPECT_EQ(0, module2->SetTelephoneEventForwardToDecoder(true)); EXPECT_EQ(0, module1->SetSendingStatus(true)); @@ -241,7 +241,7 @@ TEST_F(RtpRtcpAudioTest, RED) { EXPECT_EQ(0, module1->SetSendREDPayloadType(voice_codec.pltype)); int8_t red = 0; - EXPECT_EQ(0, module1->SendREDPayloadType(red)); + EXPECT_EQ(0, module1->SendREDPayloadType(&red)); EXPECT_EQ(voice_codec.pltype, red); EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload( voice_codec.plname, @@ -278,7 +278,7 @@ TEST_F(RtpRtcpAudioTest, RED) { &fragmentation)); EXPECT_EQ(0, module1->SetSendREDPayloadType(-1)); - EXPECT_EQ(-1, module1->SendREDPayloadType(red)); + EXPECT_EQ(-1, module1->SendREDPayloadType(&red)); } TEST_F(RtpRtcpAudioTest, DTMF) { @@ -334,7 +334,7 @@ TEST_F(RtpRtcpAudioTest, DTMF) { // Send RTP packets for 16 tones a 160 ms 100ms // pause between = 2560ms + 1600ms = 4160ms - for (;timeStamp <= 250 * 160; timeStamp += 160) { + for (; timeStamp <= 250 * 160; timeStamp += 160) { EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96, timeStamp, -1, test, 4)); fake_clock.AdvanceTimeMilliseconds(20); @@ -342,10 +342,13 @@ TEST_F(RtpRtcpAudioTest, DTMF) { } EXPECT_EQ(0, module1->SendTelephoneEventOutband(32, 9000, 10)); - for (;timeStamp <= 740 * 160; timeStamp += 160) { + for (; timeStamp <= 740 * 160; timeStamp += 160) { EXPECT_EQ(0, module1->SendOutgoingData(webrtc::kAudioFrameSpeech, 96, timeStamp, -1, test, 4)); fake_clock.AdvanceTimeMilliseconds(20); module1->Process(); } } + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc index e9d81122b1..6c60bf1f6d 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_rtcp.cc @@ -14,13 +14,14 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h" #include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h" -using namespace webrtc; +namespace webrtc { +namespace { const uint64_t kTestPictureId = 12345678; const uint8_t kSliPictureId = 156; @@ -29,30 +30,29 @@ class RtcpCallback : public RtcpIntraFrameObserver { public: void SetModule(RtpRtcp* module) { _rtpRtcpModule = module; - }; + } virtual void OnRTCPPacketTimeout(const int32_t id) { } virtual void OnLipSyncUpdate(const int32_t id, - const int32_t audioVideoOffset) { - }; - virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) { - }; + const int32_t audioVideoOffset) {} + virtual void OnReceivedIntraFrameRequest(uint32_t ssrc) {} virtual void OnReceivedSLI(uint32_t ssrc, uint8_t pictureId) { EXPECT_EQ(kSliPictureId & 0x3f, pictureId); - }; + } virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t pictureId) { EXPECT_EQ(kTestPictureId, pictureId); - }; - virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {}; + } + virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {} + private: RtpRtcp* _rtpRtcpModule; }; class TestRtpFeedback : public NullRtpFeedback { public: - TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {} + explicit TestRtpFeedback(RtpRtcp* rtp_rtcp) : rtp_rtcp_(rtp_rtcp) {} virtual ~TestRtpFeedback() {} void OnIncomingSSRCChanged(const uint32_t ssrc) override { @@ -266,3 +266,6 @@ TEST_F(RtpRtcpRtcpTest, RemoteRTCPStatRemote) { EXPECT_EQ(test_sequence_number, report_blocks[0].extendedHighSeqNum); EXPECT_EQ(0u, report_blocks[0].fractionLost); } + +} // namespace +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_video.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_video.cc index 30a6a1c303..16ea540bd5 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api_video.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api_video.cc @@ -15,9 +15,9 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h" #include "webrtc/modules/rtp_rtcp/test/testAPI/test_api.h" diff --git a/webrtc/modules/rtp_rtcp/test/testFec/average_residual_loss_xor_codes.h b/webrtc/modules/rtp_rtcp/test/testFec/average_residual_loss_xor_codes.h index 2e8d676e47..6c233bba17 100644 --- a/webrtc/modules/rtp_rtcp/test/testFec/average_residual_loss_xor_codes.h +++ b/webrtc/modules/rtp_rtcp/test/testFec/average_residual_loss_xor_codes.h @@ -7,8 +7,10 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ +#ifndef WEBRTC_MODULES_RTP_RTCP_TEST_TESTFEC_AVERAGE_RESIDUAL_LOSS_XOR_CODES_H_ +#define WEBRTC_MODULES_RTP_RTCP_TEST_TESTFEC_AVERAGE_RESIDUAL_LOSS_XOR_CODES_H_ -namespace { +namespace webrtc { // Maximum number of media packets allowed in this test. The burst mask types // are currently defined up to (kMaxMediaPacketsTest, kMaxMediaPacketsTest). @@ -185,4 +187,5 @@ const float kMaxResidualLossBurstyMask[kNumberCodes] = { 0.009657f }; -} // namespace +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_TEST_TESTFEC_AVERAGE_RESIDUAL_LOSS_XOR_CODES_H_ diff --git a/webrtc/modules/rtp_rtcp/test/testFec/test_fec.cc b/webrtc/modules/rtp_rtcp/test/testFec/test_fec.cc index a8eafdd27e..b164b7e04c 100644 --- a/webrtc/modules/rtp_rtcp/test/testFec/test_fec.cc +++ b/webrtc/modules/rtp_rtcp/test/testFec/test_fec.cc @@ -22,43 +22,49 @@ #include <list> #include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/rtp_rtcp/source/fec_private_tables_bursty.h" +#include "webrtc/base/random.h" +#include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" - -#include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/test/testsupport/fileutils.h" -//#define VERBOSE_OUTPUT +// #define VERBOSE_OUTPUT namespace webrtc { +namespace fec_private_tables { +extern const uint8_t** kPacketMaskBurstyTbl[12]; +} namespace test { +using fec_private_tables::kPacketMaskBurstyTbl; void ReceivePackets( ForwardErrorCorrection::ReceivedPacketList* toDecodeList, ForwardErrorCorrection::ReceivedPacketList* receivedPacketList, - uint32_t numPacketsToDecode, float reorderRate, float duplicateRate) { + size_t numPacketsToDecode, + float reorderRate, + float duplicateRate, + Random* random) { assert(toDecodeList->empty()); assert(numPacketsToDecode <= receivedPacketList->size()); ForwardErrorCorrection::ReceivedPacketList::iterator it; - for (uint32_t i = 0; i < numPacketsToDecode; i++) { + for (size_t i = 0; i < numPacketsToDecode; i++) { it = receivedPacketList->begin(); // Reorder packets. - float randomVariable = static_cast<float>(rand()) / RAND_MAX; + float randomVariable = random->Rand<float>(); while (randomVariable < reorderRate) { ++it; if (it == receivedPacketList->end()) { --it; break; } - randomVariable = static_cast<float>(rand()) / RAND_MAX; + randomVariable = random->Rand<float>(); } ForwardErrorCorrection::ReceivedPacket* receivedPacket = *it; toDecodeList->push_back(receivedPacket); // Duplicate packets. - randomVariable = static_cast<float>(rand()) / RAND_MAX; + randomVariable = random->Rand<float>(); while (randomVariable < duplicateRate) { ForwardErrorCorrection::ReceivedPacket* duplicatePacket = new ForwardErrorCorrection::ReceivedPacket; @@ -69,7 +75,7 @@ void ReceivePackets( duplicatePacket->pkt->length = receivedPacket->pkt->length; toDecodeList->push_back(duplicatePacket); - randomVariable = static_cast<float>(rand()) / RAND_MAX; + randomVariable = random->Rand<float>(); } receivedPacketList->erase(it); } @@ -77,12 +83,8 @@ void ReceivePackets( TEST(FecTest, FecTest) { // TODO(marpan): Split this function into subroutines/helper functions. - enum { - kMaxNumberMediaPackets = 48 - }; - enum { - kMaxNumberFecPackets = 48 - }; + enum { kMaxNumberMediaPackets = 48 }; + enum { kMaxNumberFecPackets = 48 }; const uint32_t kNumMaskBytesL0 = 2; const uint32_t kNumMaskBytesL1 = 6; @@ -91,15 +93,12 @@ TEST(FecTest, FecTest) { const bool kUseUnequalProtection = true; // FEC mask types. - const FecMaskType kMaskTypes[] = { kFecMaskRandom, kFecMaskBursty }; + const FecMaskType kMaskTypes[] = {kFecMaskRandom, kFecMaskBursty}; const int kNumFecMaskTypes = sizeof(kMaskTypes) / sizeof(*kMaskTypes); - // TODO(pbos): Fix this. Hack to prevent a warning - // ('-Wunneeded-internal-declaration') from clang. - (void) kPacketMaskBurstyTbl; - // Maximum number of media packets allowed for the mask type. - const uint16_t kMaxMediaPackets[] = {kMaxNumberMediaPackets, + const uint16_t kMaxMediaPackets[] = { + kMaxNumberMediaPackets, sizeof(kPacketMaskBurstyTbl) / sizeof(*kPacketMaskBurstyTbl)}; ASSERT_EQ(12, kMaxMediaPackets[1]) << "Max media packets for bursty mode not " @@ -115,7 +114,7 @@ TEST(FecTest, FecTest) { ForwardErrorCorrection::Packet* mediaPacket = NULL; // Running over only one loss rate to limit execution time. - const float lossRate[] = { 0.5f }; + const float lossRate[] = {0.5f}; const uint32_t lossRateSize = sizeof(lossRate) / sizeof(*lossRate); const float reorderRate = 0.1f; const float duplicateRate = 0.1f; @@ -127,7 +126,7 @@ TEST(FecTest, FecTest) { // Seed the random number generator, storing the seed to file in order to // reproduce past results. const unsigned int randomSeed = static_cast<unsigned int>(time(NULL)); - srand(randomSeed); + Random random(randomSeed); std::string filename = webrtc::test::OutputPath() + "randomSeedLog.txt"; FILE* randomSeedFile = fopen(filename.c_str(), "a"); fprintf(randomSeedFile, "%u\n", randomSeed); @@ -135,15 +134,13 @@ TEST(FecTest, FecTest) { randomSeedFile = NULL; uint16_t seqNum = 0; - uint32_t timeStamp = static_cast<uint32_t>(rand()); - const uint32_t ssrc = static_cast<uint32_t>(rand()); + uint32_t timeStamp = random.Rand<uint32_t>(); + const uint32_t ssrc = random.Rand(1u, 0xfffffffe); // Loop over the mask types: random and bursty. for (int mask_type_idx = 0; mask_type_idx < kNumFecMaskTypes; ++mask_type_idx) { - for (uint32_t lossRateIdx = 0; lossRateIdx < lossRateSize; ++lossRateIdx) { - printf("Loss rate: %.2f, Mask type %d \n", lossRate[lossRateIdx], mask_type_idx); @@ -159,14 +156,12 @@ TEST(FecTest, FecTest) { for (uint32_t numFecPackets = 1; numFecPackets <= numMediaPackets && numFecPackets <= packetMaskMax; numFecPackets++) { - // Loop over numImpPackets: usually <= (0.3*numMediaPackets). // For this test we check up to ~ (numMediaPackets / 4). uint32_t maxNumImpPackets = numMediaPackets / 4 + 1; for (uint32_t numImpPackets = 0; numImpPackets <= maxNumImpPackets && - numImpPackets <= packetMaskMax; + numImpPackets <= packetMaskMax; numImpPackets++) { - uint8_t protectionFactor = static_cast<uint8_t>(numFecPackets * 255 / numMediaPackets); @@ -181,10 +176,11 @@ TEST(FecTest, FecTest) { mask_table, packetMask); #ifdef VERBOSE_OUTPUT - printf("%u media packets, %u FEC packets, %u numImpPackets, " - "loss rate = %.2f \n", - numMediaPackets, numFecPackets, numImpPackets, - lossRate[lossRateIdx]); + printf( + "%u media packets, %u FEC packets, %u numImpPackets, " + "loss rate = %.2f \n", + numMediaPackets, numFecPackets, numImpPackets, + lossRate[lossRateIdx]); printf("Packet mask matrix \n"); #endif @@ -232,16 +228,15 @@ TEST(FecTest, FecTest) { for (uint32_t i = 0; i < numMediaPackets; ++i) { mediaPacket = new ForwardErrorCorrection::Packet; mediaPacketList.push_back(mediaPacket); - mediaPacket->length = static_cast<size_t>( - (static_cast<float>(rand()) / RAND_MAX) * - (IP_PACKET_SIZE - 12 - 28 - - ForwardErrorCorrection::PacketOverhead())); - if (mediaPacket->length < 12) { - mediaPacket->length = 12; - } + const uint32_t kMinPacketSize = 12; + const uint32_t kMaxPacketSize = static_cast<uint32_t>( + IP_PACKET_SIZE - 12 - 28 - + ForwardErrorCorrection::PacketOverhead()); + mediaPacket->length = random.Rand(kMinPacketSize, kMaxPacketSize); + // Generate random values for the first 2 bytes. - mediaPacket->data[0] = static_cast<uint8_t>(rand() % 256); - mediaPacket->data[1] = static_cast<uint8_t>(rand() % 256); + mediaPacket->data[0] = random.Rand<uint8_t>(); + mediaPacket->data[1] = random.Rand<uint8_t>(); // The first two bits are assumed to be 10 by the // FEC encoder. In fact the FEC decoder will set the @@ -266,7 +261,7 @@ TEST(FecTest, FecTest) { ByteWriter<uint32_t>::WriteBigEndian(&mediaPacket->data[8], ssrc); // Generate random values for payload for (size_t j = 12; j < mediaPacket->length; ++j) { - mediaPacket->data[j] = static_cast<uint8_t>(rand() % 256); + mediaPacket->data[j] = random.Rand<uint8_t>(); } seqNum++; } @@ -289,8 +284,7 @@ TEST(FecTest, FecTest) { while (mediaPacketListItem != mediaPacketList.end()) { mediaPacket = *mediaPacketListItem; // We want a value between 0 and 1. - const float lossRandomVariable = - (static_cast<float>(rand()) / (RAND_MAX)); + const float lossRandomVariable = random.Rand<float>(); if (lossRandomVariable >= lossRate[lossRateIdx]) { mediaLossMask[mediaPacketIdx] = 1; @@ -315,8 +309,7 @@ TEST(FecTest, FecTest) { uint32_t fecPacketIdx = 0; while (fecPacketListItem != fecPacketList.end()) { fecPacket = *fecPacketListItem; - const float lossRandomVariable = - (static_cast<float>(rand()) / (RAND_MAX)); + const float lossRandomVariable = random.Rand<float>(); if (lossRandomVariable >= lossRate[lossRateIdx]) { fecLossMask[fecPacketIdx] = 1; receivedPacket = new ForwardErrorCorrection::ReceivedPacket; @@ -387,18 +380,15 @@ TEST(FecTest, FecTest) { // For error-checking frame completion. bool fecPacketReceived = false; while (!receivedPacketList.empty()) { - uint32_t numPacketsToDecode = static_cast<uint32_t>( - (static_cast<float>(rand()) / RAND_MAX) * - receivedPacketList.size() + 0.5); - if (numPacketsToDecode < 1) { - numPacketsToDecode = 1; - } + size_t numPacketsToDecode = random.Rand( + 1u, static_cast<uint32_t>(receivedPacketList.size())); ReceivePackets(&toDecodeList, &receivedPacketList, - numPacketsToDecode, reorderRate, duplicateRate); + numPacketsToDecode, reorderRate, duplicateRate, + &random); if (fecPacketReceived == false) { ForwardErrorCorrection::ReceivedPacketList::iterator - toDecodeIt = toDecodeList.begin(); + toDecodeIt = toDecodeList.begin(); while (toDecodeIt != toDecodeList.end()) { receivedPacket = *toDecodeIt; if (receivedPacket->is_fec) { @@ -418,11 +408,11 @@ TEST(FecTest, FecTest) { if (mediaLossMask[mediaPacketIdx] == 1) { // Should have recovered this packet. ForwardErrorCorrection::RecoveredPacketList::iterator - recoveredPacketListItem = recoveredPacketList.begin(); + recoveredPacketListItem = recoveredPacketList.begin(); - ASSERT_FALSE( - recoveredPacketListItem == recoveredPacketList.end()) - << "Insufficient number of recovered packets."; + ASSERT_FALSE(recoveredPacketListItem == + recoveredPacketList.end()) + << "Insufficient number of recovered packets."; mediaPacket = *mediaPacketListItem; ForwardErrorCorrection::RecoveredPacket* recoveredPacket = *recoveredPacketListItem; @@ -462,7 +452,7 @@ TEST(FecTest, FecTest) { // Delete received packets we didn't pass to DecodeFEC(), due to // early frame completion. ForwardErrorCorrection::ReceivedPacketList::iterator - receivedPacketIt = receivedPacketList.begin(); + receivedPacketIt = receivedPacketList.begin(); while (receivedPacketIt != receivedPacketList.end()) { receivedPacket = *receivedPacketIt; delete receivedPacket; @@ -476,11 +466,11 @@ TEST(FecTest, FecTest) { } timeStamp += 90000 / 30; } // loop over numImpPackets - } // loop over FecPackets - } // loop over numMediaPackets + } // loop over FecPackets + } // loop over numMediaPackets delete[] packetMask; } // loop over loss rates - } // loop over mask types + } // loop over mask types // Have DecodeFEC free allocated memory. fec.ResetState(&recoveredPacketList); diff --git a/webrtc/modules/rtp_rtcp/test/testFec/test_packet_masks_metrics.cc b/webrtc/modules/rtp_rtcp/test/testFec/test_packet_masks_metrics.cc index 843a7f77f5..466214c740 100644 --- a/webrtc/modules/rtp_rtcp/test/testFec/test_packet_masks_metrics.cc +++ b/webrtc/modules/rtp_rtcp/test/testFec/test_packet_masks_metrics.cc @@ -59,13 +59,6 @@ enum { kMaxNumberMediaPackets = 48 }; // Maximum number of media packets allowed for each mask type. const uint16_t kMaxMediaPackets[] = {kMaxNumberMediaPackets, 12}; -// Maximum number of media packets allowed in this test. The burst mask types -// are currently defined up to (k=12,m=12). -const int kMaxMediaPacketsTest = 12; - -// Maximum number of FEC codes considered in this test. -const int kNumberCodes = kMaxMediaPacketsTest * (kMaxMediaPacketsTest + 1) / 2; - // Maximum gap size for characterizing the consecutiveness of the loss. const int kMaxGapSize = 2 * kMaxMediaPacketsTest; @@ -407,7 +400,7 @@ class FecPacketMaskMetricsTest : public ::testing::Test { // Loop over all loss configurations for the symbol sequence of length // |tot_num_packets|. In this version we process up to (k=12, m=12) codes, // and get exact expressions for the residual loss. - // TODO (marpan): For larger codes, loop over some random sample of loss + // TODO(marpan): For larger codes, loop over some random sample of loss // configurations, sampling driven by the underlying statistical loss model // (importance sampling). @@ -427,7 +420,7 @@ class FecPacketMaskMetricsTest : public ::testing::Test { // Map configuration number to a loss state. for (int j = 0; j < tot_num_packets; j++) { - state[j]=0; // Received state. + state[j] = 0; // Received state. int bit_value = i >> (tot_num_packets - j - 1) & 1; if (bit_value == 1) { state[j] = 1; // Lost state. @@ -860,9 +853,9 @@ TEST_F(FecPacketMaskMetricsTest, FecXorVsRS) { EXPECT_GE(kMetricsXorBursty[code_index].average_residual_loss[k], kMetricsReedSolomon[code_index].average_residual_loss[k]); } - // TODO (marpan): There are some cases (for high loss rates and/or - // burst loss models) where XOR is better than RS. Is there some pattern - // we can identify and enforce as a constraint? + // TODO(marpan): There are some cases (for high loss rates and/or + // burst loss models) where XOR is better than RS. Is there some pattern + // we can identify and enforce as a constraint? } } } @@ -874,7 +867,7 @@ TEST_F(FecPacketMaskMetricsTest, FecXorVsRS) { TEST_F(FecPacketMaskMetricsTest, FecTrendXorVsRsLossRate) { SetLossModels(); SetCodeParams(); - // TODO (marpan): Examine this further to see if the condition can be strictly + // TODO(marpan): Examine this further to see if the condition can be strictly // satisfied (i.e., scale = 1.0) for all codes with different/better masks. double scale = 0.90; int num_loss_rates = sizeof(kAverageLossRate) / @@ -898,7 +891,7 @@ TEST_F(FecPacketMaskMetricsTest, FecTrendXorVsRsLossRate) { kMetricsXorRandom[code_index].average_residual_loss[k+1]; EXPECT_GE(diff_rs_xor_random_loss1, scale * diff_rs_xor_random_loss2); } - // TODO (marpan): Investigate the cases for the bursty mask where + // TODO(marpan): Investigate the cases for the bursty mask where // this trend is not strictly satisfied. } } @@ -937,7 +930,7 @@ TEST_F(FecPacketMaskMetricsTest, FecBehaviorViaProtectionLevelAndLength) { EXPECT_LT( kMetricsReedSolomon[code_index2].average_residual_loss[k], kMetricsReedSolomon[code_index1].average_residual_loss[k]); - // TODO (marpan): There are some corner cases where this is not + // TODO(marpan): There are some corner cases where this is not // satisfied with the current packet masks. Look into updating // these cases to see if this behavior should/can be satisfied, // with overall lower residual loss for those XOR codes. @@ -963,7 +956,7 @@ TEST_F(FecPacketMaskMetricsTest, FecVarianceBehaviorXorVsRs) { SetCodeParams(); // The condition is not strictly satisfied with the current masks, // i.e., for some codes, the variance of XOR may be slightly higher than RS. - // TODO (marpan): Examine this further to see if the condition can be strictly + // TODO(marpan): Examine this further to see if the condition can be strictly // satisfied (i.e., scale = 1.0) for all codes with different/better masks. double scale = 0.95; for (int code_index = 0; code_index < max_num_codes_; code_index++) { @@ -998,7 +991,7 @@ TEST_F(FecPacketMaskMetricsTest, FecXorBurstyPerfectRecoveryConsecutiveLoss) { // bursty mask type, for random loss models at low loss rates. // The XOR codes with bursty mask types are generally better than the one with // random mask type, for bursty loss models and/or high loss rates. -// TODO (marpan): Enable this test when some of the packet masks are updated. +// TODO(marpan): Enable this test when some of the packet masks are updated. // Some isolated cases of the codes don't pass this currently. /* TEST_F(FecPacketMaskMetricsTest, FecXorRandomVsBursty) { |