From 1da1ce0da5fcc029dbc2a134a9760e1b398b02d7 Mon Sep 17 00:00:00 2001 From: "pwestin@webrtc.org" Date: Thu, 13 Oct 2011 15:19:55 +0000 Subject: [PATCH] First implementation of simulcast, adds VP8 simulcast to video engine. Changed API to RTP module Expanded Auto test with a test for simulcast Made the video codec tests compile Added the vp8_simulcast files to this cl Added missing auto test file Review URL: http://webrtc-codereview.appspot.com/188001 git-svn-id: http://webrtc.googlecode.com/svn/trunk@736 4adac7df-926f-26a2-2b94-8c16560cd09d --- src/common_types.h | 25 +- src/modules/interface/module_common_types.h | 5 + src/modules/rtp_rtcp/interface/rtp_rtcp.h | 136 +- .../rtp_rtcp/interface/rtp_rtcp_defines.h | 13 +- .../rtp_rtcp/source/bandwidth_management.cc | 93 +- .../rtp_rtcp/source/bandwidth_management.h | 28 +- src/modules/rtp_rtcp/source/rtcp_receiver.cc | 22 +- src/modules/rtp_rtcp/source/rtcp_receiver.h | 15 +- src/modules/rtp_rtcp/source/rtp_format_vp8.cc | 12 +- src/modules/rtp_rtcp/source/rtp_receiver.cc | 12 +- src/modules/rtp_rtcp/source/rtp_receiver.h | 19 +- .../rtp_rtcp/source/rtp_receiver_video.cc | 12 +- .../rtp_rtcp/source/rtp_receiver_video.h | 116 +- src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 1889 ++++++++++------- src/modules/rtp_rtcp/source/rtp_rtcp_impl.h | 167 +- src/modules/utility/source/video_coder.cc | 2 +- src/modules/utility/source/video_coder.h | 2 +- .../codecs/i420/main/interface/i420.h | 2 +- .../codecs/i420/main/source/i420.cc | 2 +- .../codecs/interface/video_codec_interface.h | 6 +- .../test_framework/normal_async_test.cc | 2 +- .../codecs/test_framework/performance_test.cc | 2 +- .../codecs/test_framework/unit_test.cc | 44 +- .../codecs/vp8/main/interface/vp8.h | 3 +- .../codecs/vp8/main/interface/vp8_simulcast.h | 144 ++ .../codecs/vp8/main/source/vp8.cc | 42 +- .../codecs/vp8/main/source/vp8.gypi | 3 + .../codecs/vp8/main/source/vp8_simulcast.cc | 317 +++ .../main/interface/video_coding.h | 5 +- .../main/interface/video_coding_defines.h | 2 +- .../main/source/codec_database.cc | 48 +- .../video_coding/main/source/codec_database.h | 3 +- .../main/source/generic_encoder.cc | 59 +- .../main/source/generic_encoder.h | 6 +- .../main/source/video_coding_impl.cc | 33 +- .../main/source/video_coding_impl.h | 9 +- .../main/test/codec_database_test.cc | 6 +- .../main/test/generic_codec_test.cc | 4 +- .../main/test/generic_codec_test.h | 2 +- .../video_coding/main/test/media_opt_test.cc | 23 +- .../video_coding/main/test/mt_rx_tx_test.cc | 19 +- .../video_coding/main/test/normal_test.cc | 8 +- .../video_coding/main/test/normal_test.h | 2 +- .../video_coding/main/test/rtp_player.cc | 5 +- .../video_coding/main/test/test_callbacks.cc | 10 +- .../video_coding/main/test/test_callbacks.h | 4 +- .../main/interface/vie_rtp_rtcp.h | 16 +- src/video_engine/main/source/vie_base_impl.cc | 1 - src/video_engine/main/source/vie_capturer.cc | 9 +- src/video_engine/main/source/vie_capturer.h | 7 +- src/video_engine/main/source/vie_channel.cc | 420 +++- src/video_engine/main/source/vie_channel.h | 16 +- .../main/source/vie_channel_manager.cc | 23 +- .../main/source/vie_codec_impl.cc | 20 +- src/video_engine/main/source/vie_encoder.cc | 226 +- src/video_engine/main/source/vie_encoder.h | 35 +- src/video_engine/main/source/vie_receiver.cc | 49 +- src/video_engine/main/source/vie_receiver.h | 33 +- .../main/source/vie_rtp_rtcp_impl.cc | 28 +- .../main/source/vie_rtp_rtcp_impl.h | 9 +- src/video_engine/main/source/vie_sender.cc | 7 +- src/video_engine/main/source/vie_sender.h | 4 +- .../interface/tb_external_transport.h | 3 + .../test/AutoTest/interface/vie_autotest.h | 1 + .../AutoTest/source/tb_external_transport.cc | 50 +- .../test/AutoTest/source/vie_autotest_main.cc | 14 +- .../AutoTest/source/vie_autotest_simulcast.cc | 554 +++++ .../main/test/AutoTest/vie_auto_test.gypi | 1 + src/voice_engine/main/source/channel.cc | 82 +- 69 files changed, 3374 insertions(+), 1617 deletions(-) create mode 100644 src/modules/video_coding/codecs/vp8/main/interface/vp8_simulcast.h create mode 100644 src/modules/video_coding/codecs/vp8/main/source/vp8_simulcast.cc create mode 100644 src/video_engine/main/test/AutoTest/source/vie_autotest_simulcast.cc diff --git a/src/common_types.h b/src/common_types.h index 8b0b8a59c1..a3c12d9a0a 100644 --- a/src/common_types.h +++ b/src/common_types.h @@ -485,6 +485,7 @@ enum RawVideoType // Video codec enum { kConfigParameterSize = 128}; enum { kPayloadNameSize = 32}; +enum { kMaxSimulcastStreams = 4}; // H.263 specific struct VideoCodecH263 @@ -530,9 +531,10 @@ struct VideoCodecH264 // VP8 specific struct VideoCodecVP8 { - bool pictureLossIndicationOn; - bool feedbackModeOn; - VideoCodecComplexity complexity; + bool pictureLossIndicationOn; + bool feedbackModeOn; + VideoCodecComplexity complexity; + unsigned char numberOfTemporalLayers; }; // MPEG-4 specific @@ -570,6 +572,19 @@ union VideoCodecUnion VideoCodecGeneric Generic; }; +/* +* Simulcast is when the same stream is encoded multiple times with different +* settings such as resolution. +*/ +struct SimulcastStream +{ + unsigned short width; + unsigned short height; + unsigned char numberOfTemporalLayers; + unsigned int maxBitrate; + unsigned int qpMax; // minimum quality +}; + // Common video codec properties struct VideoCodec { @@ -588,8 +603,8 @@ struct VideoCodec VideoCodecUnion codecSpecific; unsigned int qpMax; + unsigned char numberOfSimulcastStreams; + SimulcastStream simulcastStream[kMaxSimulcastStreams]; }; - } // namespace webrtc - #endif // WEBRTC_COMMON_TYPES_H diff --git a/src/modules/interface/module_common_types.h b/src/modules/interface/module_common_types.h index 6e35a9d3be..99e1b68950 100644 --- a/src/modules/interface/module_common_types.h +++ b/src/modules/interface/module_common_types.h @@ -42,9 +42,12 @@ struct RTPVideoHeaderH263 bool bits; // H.263 mode B, Xor the lasy byte of previus packet with the // first byte of this packet }; + enum {kNoPictureId = -1}; enum {kNoTl0PicIdx = -1}; enum {kNoTemporalIdx = -1}; +enum {kNoSimulcastIdx = 0}; + struct RTPVideoHeaderVP8 { void InitRTPVideoHeaderVP8() @@ -89,6 +92,8 @@ struct RTPVideoHeader WebRtc_UWord16 height; bool isFirstPacket; // first packet in frame + WebRtc_UWord8 simulcastIdx; // Index if the simulcast encoder creating + // this frame, 0 if not using simulcast. RTPVideoCodecTypes codec; RTPVideoTypeHeader codecHeader; }; diff --git a/src/modules/rtp_rtcp/interface/rtp_rtcp.h b/src/modules/rtp_rtcp/interface/rtp_rtcp.h index 3f4bf4210f..12fdda1b06 100644 --- a/src/modules/rtp_rtcp/interface/rtp_rtcp.h +++ b/src/modules/rtp_rtcp/interface/rtp_rtcp.h @@ -161,22 +161,38 @@ public: WebRtc_UWord8 &sampleTimeSeconds) = 0; /* - * set codec name and payload type - * - * payloadName - payload name of codec - * payloadType - payload type of codec - * frequency - (audio specific) frequency of codec - * channels - (audio specific) number of channels in codec (1 = mono, 2 = stereo) - * rate - (audio) rate of codec - * (video) maxBitrate of codec, bits/sec + * set voice codec name and payload type * * return -1 on failure else 0 */ - virtual WebRtc_Word32 RegisterReceivePayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 frequency = 0, - const WebRtc_UWord8 channels = 1, - const WebRtc_UWord32 rate = 0) = 0; + virtual WebRtc_Word32 RegisterReceivePayload( + const CodecInst& voiceCodec) = 0; + + /* + * set video codec name and payload type + * + * return -1 on failure else 0 + */ + virtual WebRtc_Word32 RegisterReceivePayload( + const VideoCodec& videoCodec) = 0; + + /* + * get payload type for a voice codec + * + * return -1 on failure else 0 + */ + virtual WebRtc_Word32 ReceivePayloadType( + const CodecInst& voiceCodec, + WebRtc_Word8* plType) = 0; + + /* + * get payload type for a video codec + * + * return -1 on failure else 0 + */ + virtual WebRtc_Word32 ReceivePayloadType( + const VideoCodec& videoCodec, + WebRtc_Word8* plType) = 0; /* * Remove a registerd payload type from list of accepted payloads @@ -185,40 +201,8 @@ public: * * return -1 on failure else 0 */ - virtual WebRtc_Word32 DeRegisterReceivePayload(const WebRtc_Word8 payloadType) = 0; - - /* - * get configured payload type - * - * payloadName - payload name of codec - * frequency - frequency of codec, ignored for video - * payloadType - payload type of codec, ignored for video - * channels - number of channels in codec (1 = mono, 2 = stereo) - * rate - (audio) rate of codec (ignored if set to 0) - * - * return -1 on failure else 0 - */ - virtual WebRtc_Word32 ReceivePayloadType(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - WebRtc_Word8* payloadType, - const WebRtc_UWord32 rate = 0) const = 0; - - /* - * get configured payload - * - * payloadType - payload type of codec - * payloadName - payload name of codec - * frequency - frequency of codec - * channels - number of channels in codec (1 = mono, 2 = stereo) - * - * return -1 on failure else 0 - */ - virtual WebRtc_Word32 ReceivePayload(const WebRtc_Word8 payloadType, - WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels, - WebRtc_UWord32* rate = NULL) const = 0; + virtual WebRtc_Word32 DeRegisterReceivePayload( + const WebRtc_Word8 payloadType) = 0; /* * Get last received remote timestamp @@ -248,21 +232,6 @@ public: */ virtual WebRtc_Word32 RemoteCSRCs( WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize]) const = 0; - /* - * get Current incoming payload - * - * payloadName - payload name of codec - * payloadType - payload type of codec - * frequency - frequency of codec - * channels - number of channels in codec (2 = stereo) - * - * return -1 on failure else 0 - */ - virtual WebRtc_Word32 RemotePayload(WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_Word8* payloadType, - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels) const = 0; - /* * get the currently configured SSRC filter * @@ -289,8 +258,8 @@ public: * * return -1 on failure else 0 */ - virtual WebRtc_Word32 IncomingPacket( const WebRtc_UWord8* incomingPacket, - const WebRtc_UWord16 packetLength) = 0; + virtual WebRtc_Word32 IncomingPacket(const WebRtc_UWord8* incomingPacket, + const WebRtc_UWord16 packetLength) = 0; /* @@ -300,11 +269,11 @@ public: * * return -1 on failure else 0 */ - virtual WebRtc_Word32 IncomingAudioNTP(const WebRtc_UWord32 audioReceivedNTPsecs, - const WebRtc_UWord32 audioReceivedNTPfrac, - const WebRtc_UWord32 audioRTCPArrivalTimeSecs, - const WebRtc_UWord32 audioRTCPArrivalTimeFrac) = 0; - + virtual WebRtc_Word32 IncomingAudioNTP( + const WebRtc_UWord32 audioReceivedNTPsecs, + const WebRtc_UWord32 audioReceivedNTPfrac, + const WebRtc_UWord32 audioRTCPArrivalTimeSecs, + const WebRtc_UWord32 audioRTCPArrivalTimeFrac) = 0; /************************************************************************** * @@ -391,9 +360,10 @@ public: * * return -1 on failure else 0 */ - virtual WebRtc_Word32 RTPKeepaliveStatus(bool* enable, - WebRtc_Word8* unknownPayloadType, - WebRtc_UWord16* deltaTransmitTimeMS) const = 0; + virtual WebRtc_Word32 RTPKeepaliveStatus( + bool* enable, + WebRtc_Word8* unknownPayloadType, + WebRtc_UWord16* deltaTransmitTimeMS) const = 0; /* * check if RTPKeepaliveStatus is enabled @@ -403,20 +373,18 @@ public: /* * set codec name and payload type * - * payloadName - payload name of codec - * payloadType - payload type of codec - * frequency - frequency of codec - * channels - number of channels in codec (1 = mono, 2 = stereo) - * rate - (audio) rate of codec - * (video) maxBitrate of codec, bits/sec + * return -1 on failure else 0 + */ + virtual WebRtc_Word32 RegisterSendPayload( + const CodecInst& voiceCodec) = 0; + + /* + * set codec name and payload type * * return -1 on failure else 0 */ - virtual WebRtc_Word32 RegisterSendPayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 frequency = 0, - const WebRtc_UWord8 channels = 1, - const WebRtc_UWord32 rate = 0) = 0; + virtual WebRtc_Word32 RegisterSendPayload( + const VideoCodec& videoCodec) = 0; /* * Unregister a send payload @@ -548,7 +516,7 @@ public: const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader* fragmentation = NULL, - const RTPVideoTypeHeader* rtpTypeHdr = NULL) = 0; + const RTPVideoHeader* rtpVideoHdr = NULL) = 0; /************************************************************************** * diff --git a/src/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/src/modules/rtp_rtcp/interface/rtp_rtcp_defines.h index c2f4cb33cb..6ceb02bf82 100644 --- a/src/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/src/modules/rtp_rtcp/interface/rtp_rtcp_defines.h @@ -210,17 +210,14 @@ class RtpVideoFeedback { public: // this function should call codec module to inform it about the request - virtual void OnReceivedIntraFrameRequest( - const WebRtc_Word32 id, - const WebRtc_UWord8 message = 0) = 0; + virtual void OnReceivedIntraFrameRequest(const WebRtc_Word32 id, + const FrameType type, + const WebRtc_UWord8 streamIdx) = 0; virtual void OnNetworkChanged(const WebRtc_Word32 id, - const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, + const WebRtc_UWord32 bitrateBps, const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax) = 0; + const WebRtc_UWord16 roundTripTimeMs) = 0; protected: virtual ~RtpVideoFeedback() {} diff --git a/src/modules/rtp_rtcp/source/bandwidth_management.cc b/src/modules/rtp_rtcp/source/bandwidth_management.cc index 8dab36e3e3..919730bc63 100644 --- a/src/modules/rtp_rtcp/source/bandwidth_management.cc +++ b/src/modules/rtp_rtcp/source/bandwidth_management.cc @@ -18,25 +18,18 @@ namespace webrtc { BandwidthManagement::BandwidthManagement(const WebRtc_Word32 id) : _id(id), - _critsect(*CriticalSectionWrapper::CreateCriticalSection()), - _lastPacketLossExtendedHighSeqNum(0), _lastReportAllLost(false), _lastLoss(0), _accumulateLostPacketsQ8(0), _accumulateExpectedPackets(0), - _bitRate(0), _minBitRateConfigured(0), _maxBitRateConfigured(0), - _last_fraction_loss(0), _last_round_trip_time(0), - - // bandwidth estimate _bwEstimateIncoming(0), - _bwEstimateIncomingMax(0), _smoothedFractionLostQ4(-1), // indicate uninitialized _sFLFactorQ4(14) // 0.875 in Q4 { @@ -68,7 +61,7 @@ BandwidthManagement::SetSendBitrate(const WebRtc_UWord32 startBitrate, } WebRtc_Word32 -BandwidthManagement::MaxConfiguredBitrate(WebRtc_UWord16& maxBitrateKbit) +BandwidthManagement::MaxConfiguredBitrate(WebRtc_UWord16* maxBitrateKbit) { CriticalSectionScoped cs(_critsect); @@ -76,57 +69,48 @@ BandwidthManagement::MaxConfiguredBitrate(WebRtc_UWord16& maxBitrateKbit) { return -1; } - maxBitrateKbit = (WebRtc_UWord16)(_maxBitRateConfigured/1000); + *maxBitrateKbit = (WebRtc_UWord16)(_maxBitRateConfigured/1000); return 0; } WebRtc_Word32 -BandwidthManagement::UpdateBandwidthEstimate(const WebRtc_UWord16 bandWidthMinKbit, - const WebRtc_UWord16 bandWidthMaxKbit, - WebRtc_UWord32& newBitrate, - WebRtc_UWord8& fractionLost, - WebRtc_UWord16& roundTripTime) +BandwidthManagement::UpdateBandwidthEstimate(const WebRtc_UWord16 bandWidthKbit, + WebRtc_UWord32* newBitrate, + WebRtc_UWord8* fractionLost, + WebRtc_UWord16* roundTripTime) { - newBitrate = 0; + *newBitrate = 0; CriticalSectionScoped cs(_critsect); - _bwEstimateIncoming = bandWidthMinKbit*1000; - _bwEstimateIncomingMax = bandWidthMaxKbit*1000; + _bwEstimateIncoming = bandWidthKbit*1000; if(_bitRate == 0) { // BandwidthManagement off return -1; } - if (_bwEstimateIncoming > 0 && _bitRate > _bwEstimateIncoming) { _bitRate = _bwEstimateIncoming; - } - else + } else { return -1; } - newBitrate = _bitRate; - fractionLost = _last_fraction_loss; - roundTripTime = _last_round_trip_time; + *newBitrate = _bitRate; + *fractionLost = _last_fraction_loss; + *roundTripTime = _last_round_trip_time; return 0; } -WebRtc_Word32 -BandwidthManagement::UpdatePacketLoss(const WebRtc_UWord32 lastReceivedExtendedHighSeqNum, - const bool defaultCodec, - const WebRtc_UWord8 lossInput, - const WebRtc_UWord16 rtt, - WebRtc_UWord32& newBitrate, - WebRtc_UWord16& bwEstimateKbitMin, - WebRtc_UWord16& bwEstimateKbitMax) +WebRtc_Word32 BandwidthManagement::UpdatePacketLoss( + const WebRtc_UWord32 lastReceivedExtendedHighSeqNum, + const WebRtc_UWord16 rtt, + WebRtc_UWord8* loss, + WebRtc_UWord32* newBitrate) { CriticalSectionScoped cs(_critsect); - WebRtc_UWord8 loss = lossInput; // Local copy to modify. - - _last_fraction_loss = loss; + _last_fraction_loss = *loss; _last_round_trip_time = rtt; if(_bitRate == 0) @@ -147,13 +131,13 @@ BandwidthManagement::UpdatePacketLoss(const WebRtc_UWord32 lastReceivedExtendedH // Check if this report and the last was 100% loss, then report // 100% loss even though seqNumDiff is small. // If not, go on with the checks. - if (!(_lastReportAllLost && loss == 255)) + if (!(_lastReportAllLost && *loss == 255)) { - _lastReportAllLost = (loss == 255); + _lastReportAllLost = (*loss == 255); // Calculate number of lost packets. // loss = 256 * numLostPackets / expectedPackets. - const int numLostPacketsQ8 = loss * seqNumDiff; + const int numLostPacketsQ8 = *loss * seqNumDiff; // Accumulate reports. _accumulateLostPacketsQ8 += numLostPacketsQ8; @@ -164,7 +148,7 @@ BandwidthManagement::UpdatePacketLoss(const WebRtc_UWord32 lastReceivedExtendedH const int limitNumPackets = 10; if (_accumulateExpectedPackets >= limitNumPackets) { - loss = _accumulateLostPacketsQ8 / _accumulateExpectedPackets; + *loss = _accumulateLostPacketsQ8 / _accumulateExpectedPackets; // Reset accumulators _accumulateLostPacketsQ8 = 0; @@ -174,34 +158,24 @@ BandwidthManagement::UpdatePacketLoss(const WebRtc_UWord32 lastReceivedExtendedH { // Report same loss as before and keep the accumulators until // the next report. - loss = _lastLoss; + *loss = _lastLoss; } } } - // Keep for next time. - _lastLoss = loss; + _lastLoss = *loss; // Remember the sequence number until next time _lastPacketLossExtendedHighSeqNum = lastReceivedExtendedHighSeqNum; - bwEstimateKbitMax = static_cast(_bwEstimateIncomingMax / 1000); - bwEstimateKbitMin = static_cast(_bwEstimateIncoming / 1000); - - newBitrate = 0; - - if (defaultCodec) - { - return 0; - } - WebRtc_UWord32 bitRate = ShapeSimple(loss, rtt); - if(bitRate == 0) + WebRtc_UWord32 bitRate = ShapeSimple(*loss, rtt); + if (bitRate == 0) { // no change return -1; } _bitRate = bitRate; - newBitrate = bitRate; + *newBitrate = bitRate; return 0; } @@ -210,8 +184,9 @@ BandwidthManagement::UpdatePacketLoss(const WebRtc_UWord32 lastReceivedExtendedH */ // protected -WebRtc_Word32 -BandwidthManagement::CalcTFRCbps(WebRtc_Word16 avgPackSizeBytes, WebRtc_Word32 rttMs, WebRtc_Word32 packetLoss) +WebRtc_Word32 BandwidthManagement::CalcTFRCbps(WebRtc_Word16 avgPackSizeBytes, + WebRtc_Word32 rttMs, + WebRtc_Word32 packetLoss) { if (avgPackSizeBytes <= 0 || rttMs <= 0 || packetLoss <= 0) { @@ -235,8 +210,8 @@ BandwidthManagement::CalcTFRCbps(WebRtc_Word16 avgPackSizeBytes, WebRtc_Word32 r * Simple bandwidth estimation. Depends a lot on bwEstimateIncoming and packetLoss. */ // protected -WebRtc_UWord32 -BandwidthManagement::ShapeSimple(WebRtc_Word32 packetLoss, WebRtc_Word32 rtt) +WebRtc_UWord32 BandwidthManagement::ShapeSimple(WebRtc_Word32 packetLoss, + WebRtc_Word32 rtt) { WebRtc_UWord32 newBitRate = 0; bool reducing = false; @@ -292,18 +267,14 @@ BandwidthManagement::ShapeSimple(WebRtc_Word32 packetLoss, WebRtc_Word32 rtt) { newBitRate = _bwEstimateIncoming; } - if (newBitRate > _maxBitRateConfigured) { newBitRate = _maxBitRateConfigured; } - if (newBitRate < _minBitRateConfigured) { newBitRate = _minBitRateConfigured; } - return newBitRate; } - } // namespace webrtc diff --git a/src/modules/rtp_rtcp/source/bandwidth_management.h b/src/modules/rtp_rtcp/source/bandwidth_management.h index 62a3f4e1a4..c4ab939bdb 100644 --- a/src/modules/rtp_rtcp/source/bandwidth_management.h +++ b/src/modules/rtp_rtcp/source/bandwidth_management.h @@ -26,27 +26,26 @@ public: BandwidthManagement(const WebRtc_Word32 id); ~BandwidthManagement(); - WebRtc_Word32 UpdateBandwidthEstimate(const WebRtc_UWord16 bandWidthMinKbit, - const WebRtc_UWord16 bandWidthMaxKbit, - WebRtc_UWord32& newBitrate, - WebRtc_UWord8& fractionLost, - WebRtc_UWord16& roundTripTime); + // Call when we receive a RTCP message with TMMBR or REMB + WebRtc_Word32 UpdateBandwidthEstimate(const WebRtc_UWord16 bandWidthKbit, + WebRtc_UWord32* newBitrate, + WebRtc_UWord8* fractionLost, + WebRtc_UWord16* roundTripTime); - WebRtc_Word32 UpdatePacketLoss(const WebRtc_UWord32 lastReceivedExtendedHighSeqNum, - const bool defaultCodec, - const WebRtc_UWord8 lossInput, - const WebRtc_UWord16 rtt, - WebRtc_UWord32& newBitrate, - WebRtc_UWord16& bwEstimateKbitMin, - WebRtc_UWord16& bwEstimateKbitMax); + // Call when we receive a RTCP message with a ReceiveBlock + WebRtc_Word32 UpdatePacketLoss( + const WebRtc_UWord32 lastReceivedExtendedHighSeqNum, + const WebRtc_UWord16 rtt, + WebRtc_UWord8* loss, + WebRtc_UWord32* newBitrate); - WebRtc_Word32 AvailableBandwidth(WebRtc_UWord16& bandwidthKbit) const; + WebRtc_Word32 AvailableBandwidth(WebRtc_UWord16* bandwidthKbit) const; WebRtc_Word32 SetSendBitrate(const WebRtc_UWord32 startBitrate, const WebRtc_UWord16 minBitrateKbit, const WebRtc_UWord16 maxBitrateKbit); - WebRtc_Word32 MaxConfiguredBitrate(WebRtc_UWord16& maxBitrateKbit); + WebRtc_Word32 MaxConfiguredBitrate(WebRtc_UWord16* maxBitrateKbit); protected: WebRtc_UWord32 ShapeSimple(WebRtc_Word32 packetLoss, WebRtc_Word32 rtt); @@ -77,7 +76,6 @@ private: // bandwidth estimate WebRtc_UWord32 _bwEstimateIncoming; - WebRtc_UWord32 _bwEstimateIncomingMax; WebRtc_Word16 _smoothedFractionLostQ4; WebRtc_Word16 _sFLFactorQ4; // forgetting factor for _smoothedFractionLostQ4 }; diff --git a/src/modules/rtp_rtcp/source/rtcp_receiver.cc b/src/modules/rtp_rtcp/source/rtcp_receiver.cc index d5caf57269..4132367d9a 100644 --- a/src/modules/rtp_rtcp/source/rtcp_receiver.cc +++ b/src/modules/rtp_rtcp/source/rtcp_receiver.cc @@ -1155,7 +1155,7 @@ RTCPReceiver::HandleREMBItem(RTCPUtility::RTCPParserV2& rtcpParser, rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRemb; rtcpPacketInformation.receiverEstimatedMaxBitrate = rtcpPacket.REMB.BitRate; - // TODO send up SSRCs and do a sanity check + // TODO(pwestin) send up SSRCs and do a sanity check } // no need for critsect we have _criticalSectionRTCPReceiver @@ -1235,13 +1235,14 @@ RTCPReceiver::HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser, } void -RTCPReceiver::OnReceivedIntraFrameRequest(const WebRtc_UWord8 message) const +RTCPReceiver::OnReceivedIntraFrameRequest(const FrameType frameType, + const WebRtc_UWord8 streamIdx) const { CriticalSectionScoped lock(_criticalSectionFeedbacks); if(_cbVideoFeedback) { - _cbVideoFeedback->OnReceivedIntraFrameRequest(_id, message); + _cbVideoFeedback->OnReceivedIntraFrameRequest(_id, frameType, streamIdx); } } @@ -1280,8 +1281,7 @@ RTCPReceiver::TriggerCallbacksFromRTCPPacket(RTCPPacketInformation& rtcpPacketIn _rtpRtcp.OnPacketLossStatisticsUpdate( rtcpPacketInformation.fractionLost, rtcpPacketInformation.roundTripTime, - rtcpPacketInformation.lastReceivedExtendedHighSeqNum, - rtcpPacketInformation.jitter); + rtcpPacketInformation.lastReceivedExtendedHighSeqNum); } } if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSr) @@ -1318,13 +1318,19 @@ RTCPReceiver::TriggerCallbacksFromRTCPPacket(RTCPPacketInformation& rtcpPacketIn { WEBRTC_TRACE(kTraceStateInfo, kTraceRtpRtcp, _id, "SIG [RTCP] Incoming FIR to id:%d", _id); } - // we need use a bounce it up to handle default channel - _rtpRtcp.OnReceivedIntraFrameRequest(0); + _rtpRtcp.OnReceivedIntraFrameRequest(&_rtpRtcp); } if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpSli) { // we need use a bounce it up to handle default channel - _rtpRtcp.OnReceivedSliceLossIndication(rtcpPacketInformation.sliPictureId); + _rtpRtcp.OnReceivedSliceLossIndication( + rtcpPacketInformation.sliPictureId); + } + if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRemb) + { + // We need to bounce this to the default channel + _rtpRtcp.OnReceivedEstimatedMaxBitrate( + rtcpPacketInformation.receiverEstimatedMaxBitrate); } if (rtcpPacketInformation.rtcpPacketTypeFlags & kRtcpRpsi) { diff --git a/src/modules/rtp_rtcp/source/rtcp_receiver.h b/src/modules/rtp_rtcp/source/rtcp_receiver.h index 47640e8235..244c87eb47 100644 --- a/src/modules/rtp_rtcp/source/rtcp_receiver.h +++ b/src/modules/rtp_rtcp/source/rtcp_receiver.h @@ -72,24 +72,27 @@ public: WebRtc_Word32 SenderInfoReceived(RTCPSenderInfo* senderInfo) const; - void OnReceivedIntraFrameRequest(const WebRtc_UWord8 message) const; + void OnReceivedIntraFrameRequest(const FrameType frameType, + const WebRtc_UWord8 streamIdx) const; + void OnReceivedSliceLossIndication(const WebRtc_UWord8 pitureID) const; - void OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pitureID) const; + void OnReceivedReferencePictureSelectionIndication( + const WebRtc_UWord64 pitureID) const; // get statistics WebRtc_Word32 StatisticsReceived(const WebRtc_UWord32 remoteSSRC, - RTCPReportBlock* receiveBlock) const; + RTCPReportBlock* receiveBlock) const; // Get TMMBR WebRtc_Word32 TMMBRReceived(const WebRtc_UWord32 size, - const WebRtc_UWord32 accNumCandidates, - TMMBRSet* candidateSet) const; + const WebRtc_UWord32 accNumCandidates, + TMMBRSet* candidateSet) const; bool UpdateRTCPReceiveInformationTimers(); void UpdateBandwidthEstimate(const WebRtc_UWord16 bwEstimateKbit); WebRtc_Word32 BoundingSet(bool &tmmbrOwner, - TMMBRSet*& boundingSetRec); + TMMBRSet*& boundingSetRec); WebRtc_Word32 SetPacketTimeout(const WebRtc_UWord32 timeoutMS); void PacketTimeout(); diff --git a/src/modules/rtp_rtcp/source/rtp_format_vp8.cc b/src/modules/rtp_rtcp/source/rtp_format_vp8.cc index 1e8f336b62..e94f410267 100644 --- a/src/modules/rtp_rtcp/source/rtp_format_vp8.cc +++ b/src/modules/rtp_rtcp/source/rtp_format_vp8.cc @@ -318,11 +318,11 @@ int RtpFormatVp8::WriteTIDFields(WebRtc_UWord8* x_field, int RtpFormatVp8::PayloadDescriptorExtraLength() const { - if (!beginning_) + int length_bytes = 0; + if (beginning_) { - return 0; + length_bytes = PictureIdLength(); } - int length_bytes = PictureIdLength(); if (TL0PicIdxFieldPresent()) ++length_bytes; if (TIDFieldPresent()) ++length_bytes; if (length_bytes > 0) ++length_bytes; // Include the extension field. @@ -339,10 +339,7 @@ int RtpFormatVp8::PictureIdLength() const { return 1; } - else - { - return 2; - } + return 2; } bool RtpFormatVp8::XFieldPresent() const @@ -359,5 +356,4 @@ bool RtpFormatVp8::TL0PicIdxFieldPresent() const { return (hdr_info_.tl0PicIdx != kNoTl0PicIdx); } - } // namespace webrtc diff --git a/src/modules/rtp_rtcp/source/rtp_receiver.cc b/src/modules/rtp_rtcp/source/rtp_receiver.cc index d5d3102c27..4788ae53cf 100644 --- a/src/modules/rtp_rtcp/source/rtp_receiver.cc +++ b/src/modules/rtp_rtcp/source/rtp_receiver.cc @@ -512,12 +512,12 @@ RTPReceiver::DeRegisterReceivePayload(const WebRtc_Word8 payloadType) return -1; } -WebRtc_Word32 -RTPReceiver::ReceivePayloadType(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - WebRtc_Word8* payloadType, - const WebRtc_UWord32 rate) const +WebRtc_Word32 RTPReceiver::ReceivePayloadType( + const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate, + WebRtc_Word8* payloadType) const { if(payloadType == NULL) { diff --git a/src/modules/rtp_rtcp/source/rtp_receiver.h b/src/modules/rtp_rtcp/source/rtp_receiver.h index 899468b352..2e9d277183 100644 --- a/src/modules/rtp_rtcp/source/rtp_receiver.h +++ b/src/modules/rtp_rtcp/source/rtp_receiver.h @@ -59,17 +59,18 @@ public: WebRtc_Word32 DeRegisterReceivePayload(const WebRtc_Word8 payloadType); - WebRtc_Word32 ReceivePayloadType(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - WebRtc_Word8* payloadType, - const WebRtc_UWord32 rate) const; + WebRtc_Word32 ReceivePayloadType( + const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate, + WebRtc_Word8* payloadType) const; WebRtc_Word32 ReceivePayload(const WebRtc_Word8 payloadType, - WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels, - WebRtc_UWord32* rate) const; + WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], + WebRtc_UWord32* frequency, + WebRtc_UWord8* channels, + WebRtc_UWord32* rate) const; WebRtc_Word32 RemotePayload(WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], WebRtc_Word8* payloadType, diff --git a/src/modules/rtp_rtcp/source/rtp_receiver_video.cc b/src/modules/rtp_rtcp/source/rtp_receiver_video.cc index 279047daa2..90acb5ee0c 100644 --- a/src/modules/rtp_rtcp/source/rtp_receiver_video.cc +++ b/src/modules/rtp_rtcp/source/rtp_receiver_video.cc @@ -86,17 +86,17 @@ RTPReceiverVideo::RegisterIncomingVideoCallback(RtpVideoFeedback* incomingMessag } void -RTPReceiverVideo::UpdateBandwidthManagement(const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, +RTPReceiverVideo::UpdateBandwidthManagement(const WebRtc_UWord32 bitrateBps, const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax) + const WebRtc_UWord16 roundTripTimeMs) { CriticalSectionScoped lock(_criticalSectionFeedback); if(_cbVideoFeedback) { - _cbVideoFeedback->OnNetworkChanged(_id, minBitrateBps, maxBitrateBps, fractionLost, roundTripTimeMs, bwEstimateKbitMin, bwEstimateKbitMax); + _cbVideoFeedback->OnNetworkChanged(_id, + bitrateBps, + fractionLost, + roundTripTimeMs); } } diff --git a/src/modules/rtp_rtcp/source/rtp_receiver_video.h b/src/modules/rtp_rtcp/source/rtp_receiver_video.h index f71cd9bd33..c77b525110 100644 --- a/src/modules/rtp_rtcp/source/rtp_receiver_video.h +++ b/src/modules/rtp_rtcp/source/rtp_receiver_video.h @@ -38,32 +38,33 @@ public: WebRtc_Word32 Init(); - WebRtc_Word32 RegisterIncomingVideoCallback(RtpVideoFeedback* incomingMessagesCallback); + WebRtc_Word32 RegisterIncomingVideoCallback( + RtpVideoFeedback* incomingMessagesCallback); - void UpdateBandwidthManagement(const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, + void UpdateBandwidthManagement(const WebRtc_UWord32 bitrateBps, const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax); + const WebRtc_UWord16 roundTripTimeMs); - ModuleRTPUtility::Payload* RegisterReceiveVideoPayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 maxRate); + ModuleRTPUtility::Payload* RegisterReceiveVideoPayload( + const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], + const WebRtc_Word8 payloadType, + const WebRtc_UWord32 maxRate); - WebRtc_Word32 ParseVideoCodecSpecific(WebRtcRTPHeader* rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadDataLength, - const RtpVideoCodecTypes videoType, - const bool isRED, - const WebRtc_UWord8* incomingRtpPacket, - const WebRtc_UWord16 incomingRtpPacketSize); + WebRtc_Word32 ParseVideoCodecSpecific( + WebRtcRTPHeader* rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadDataLength, + const RtpVideoCodecTypes videoType, + const bool isRED, + const WebRtc_UWord8* incomingRtpPacket, + const WebRtc_UWord16 incomingRtpPacketSize); WebRtc_Word32 SetH263InverseLogic(const bool enable); - WebRtc_Word32 ReceiveRecoveredPacketCallback(WebRtcRTPHeader* rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadDataLength); + WebRtc_Word32 ReceiveRecoveredPacketCallback( + WebRtcRTPHeader* rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadDataLength); void SetPacketOverHead(WebRtc_UWord16 packetOverHead); @@ -72,54 +73,59 @@ protected: WebRtc_UWord16 EstimateBandwidth( const WebRtc_UWord16 bufferLength); - virtual WebRtc_Word32 CallbackOfReceivedPayloadData(const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadSize, - const WebRtcRTPHeader* rtpHeader) = 0; + virtual WebRtc_Word32 CallbackOfReceivedPayloadData( + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadSize, + const WebRtcRTPHeader* rtpHeader) = 0; virtual WebRtc_UWord32 TimeStamp() const = 0; virtual WebRtc_UWord16 SequenceNumber() const = 0; - virtual WebRtc_UWord32 PayloadTypeToPayload(const WebRtc_UWord8 payloadType, - ModuleRTPUtility::Payload*& payload) const = 0; + virtual WebRtc_UWord32 PayloadTypeToPayload( + const WebRtc_UWord8 payloadType, + ModuleRTPUtility::Payload*& payload) const = 0; - virtual bool RetransmitOfOldPacket(const WebRtc_UWord16 sequenceNumber, - const WebRtc_UWord32 rtpTimeStamp) const = 0; + virtual bool RetransmitOfOldPacket( + const WebRtc_UWord16 sequenceNumber, + const WebRtc_UWord32 rtpTimeStamp) const = 0; virtual WebRtc_Word8 REDPayloadType() const = 0; WebRtc_Word32 SetCodecType(const RtpVideoCodecTypes videoType, - WebRtcRTPHeader* rtpHeader) const; + WebRtcRTPHeader* rtpHeader) const; - WebRtc_Word32 ParseVideoCodecSpecificSwitch(WebRtcRTPHeader* rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadDataLength, - const RtpVideoCodecTypes videoType); + WebRtc_Word32 ParseVideoCodecSpecificSwitch( + WebRtcRTPHeader* rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadDataLength, + const RtpVideoCodecTypes videoType); WebRtc_Word32 ReceiveGenericCodec(WebRtcRTPHeader *rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadDataLength); + + WebRtc_Word32 ReceiveH263Codec(WebRtcRTPHeader *rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadDataLength); + + WebRtc_Word32 ReceiveH2631998Codec(WebRtcRTPHeader *rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadDataLength); + + WebRtc_Word32 ReceiveH263CodecCommon( + ModuleRTPUtility::RTPPayload& parsedPacket, + WebRtcRTPHeader* rtpHeader); + + WebRtc_Word32 ReceiveMPEG4Codec(WebRtcRTPHeader *rtpHeader, const WebRtc_UWord8* payloadData, const WebRtc_UWord16 payloadDataLength); - WebRtc_Word32 ReceiveH263Codec(WebRtcRTPHeader *rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadDataLength); - - WebRtc_Word32 ReceiveH2631998Codec(WebRtcRTPHeader *rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadDataLength); - - WebRtc_Word32 ReceiveH263CodecCommon(ModuleRTPUtility::RTPPayload& parsedPacket, - WebRtcRTPHeader* rtpHeader); - - WebRtc_Word32 ReceiveMPEG4Codec(WebRtcRTPHeader *rtpHeader, + WebRtc_Word32 ReceiveVp8Codec(WebRtcRTPHeader *rtpHeader, const WebRtc_UWord8* payloadData, const WebRtc_UWord16 payloadDataLength); - WebRtc_Word32 ReceiveVp8Codec(WebRtcRTPHeader *rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadDataLength); - WebRtc_Word32 BuildRTPheader(const WebRtcRTPHeader* rtpHeader, - WebRtc_UWord8* dataBuffer) const; + WebRtc_UWord8* dataBuffer) const; private: WebRtc_Word32 _id; @@ -128,24 +134,24 @@ private: CriticalSectionWrapper& _criticalSectionFeedback; RtpVideoFeedback* _cbVideoFeedback; - CriticalSectionWrapper& _criticalSectionReceiverVideo; + CriticalSectionWrapper& _criticalSectionReceiverVideo; // bandwidth - bool _completeFrame; + bool _completeFrame; WebRtc_UWord32 _packetStartTimeMs; WebRtc_UWord16 _receivedBW[BW_HISTORY_SIZE]; WebRtc_UWord16 _estimatedBW; // FEC - bool _currentFecFrameDecoded; - ReceiverFEC* _receiveFEC; + bool _currentFecFrameDecoded; + ReceiverFEC* _receiveFEC; // H263 - bool _h263InverseLogic; + bool _h263InverseLogic; // BWE - OverUseDetector _overUseDetector; - BitRateStats _videoBitRate; + OverUseDetector _overUseDetector; + BitRateStats _videoBitRate; WebRtc_Word64 _lastBitRateChange; WebRtc_UWord16 _packetOverHead; }; diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index dd8fb15f3f..eb07420e35 100644 --- a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -40,10 +40,16 @@ RtpRtcp::CreateRtpRtcp(const WebRtc_Word32 id, { if(audio) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id, "CreateRtpRtcp(audio)"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + id, + "CreateRtpRtcp(audio)"); } else { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id, "CreateRtpRtcp(video)"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + id, + "CreateRtpRtcp(video)"); } return new ModuleRtpRtcpImpl(id, audio); } @@ -52,7 +58,10 @@ void RtpRtcp::DestroyRtpRtcp(RtpRtcp* module) { if(module) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, static_cast(module)->Id(), "DestroyRtpRtcp()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + static_cast(module)->Id(), + "DestroyRtpRtcp()"); delete static_cast(module); } } @@ -75,7 +84,6 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id, _defaultModule(NULL), _audioModule(NULL), _videoModule(NULL), - _childModules(), _deadOrAliveActive(false), _deadOrAliveTimeoutMS(0), _deadOrAliveLastTimer(0), @@ -87,12 +95,13 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const WebRtc_Word32 id, _nackMethod(kNackOff), _nackLastTimeSent(0), _nackLastSeqNumberSent(0), - _keyFrameReqMethod(kKeyFrameReqFirRtp), - _lastChildBitrateUpdate(0) + _simulcast(false), + _keyFrameReqMethod(kKeyFrameReqFirRtp) #ifdef MATLAB ,_plot1(NULL) #endif { + _sendVideoCodec.codecType = kVideoCodecUnknown; // make sure that RTCP objects are aware of our SSRC WebRtc_UWord32 SSRC = _rtpSender.SSRC(); _rtcpSender.SetSSRC(SSRC); @@ -106,22 +115,22 @@ ModuleRtpRtcpImpl::~ModuleRtpRtcpImpl() // make sure to unregister this module from other modules - const bool defaultInstance(_childModules.Empty()?false:true); + const bool defaultInstance(_childModules.empty()?false:true); if(defaultInstance) { // deregister for the default module // will go in to the child modules and remove it self - ListItem* item = _childModules.First(); - while (item) + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); - _childModules.Erase(item); + RtpRtcp* module = *it; + _childModules.erase(it); if(module) { module->DeRegisterDefaultModule(); } - item = _childModules.First(); + it = _childModules.begin(); } } else { @@ -155,18 +164,24 @@ ModuleRtpRtcpImpl::Version(WebRtc_Word8* version, WebRtc_UWord32& remainingBufferInBytes, WebRtc_UWord32& position) const { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Version(bufferLength:%d)", remainingBufferInBytes); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "Version(bufferLength:%d)", + remainingBufferInBytes); return GetVersion(version, remainingBufferInBytes, position); } -WebRtc_Word32 -RtpRtcp::GetVersion(WebRtc_Word8* version, - WebRtc_UWord32& remainingBufferInBytes, - WebRtc_UWord32& position) +WebRtc_Word32 RtpRtcp::GetVersion(WebRtc_Word8* version, + WebRtc_UWord32& remainingBufferInBytes, + WebRtc_UWord32& position) { if(version == NULL) { - WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1, "Invalid in argument to Version()"); + WEBRTC_TRACE(kTraceWarning, + kTraceRtpRtcp, + -1, + "Invalid in argument to Version()"); return -1; } WebRtc_Word8 ourVersion[] = "Module RTP RTCP 1.3.0"; @@ -185,7 +200,10 @@ RtpRtcp::GetVersion(WebRtc_Word8* version, WebRtc_Word32 ModuleRtpRtcpImpl::ChangeUniqueId(const WebRtc_Word32 id) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ChangeUniqueId(new id:%d)", id); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "ChangeUniqueId(new id:%d)", id); _id = id; @@ -197,15 +215,25 @@ ModuleRtpRtcpImpl::ChangeUniqueId(const WebRtc_Word32 id) } // default encoder that we need to multiplex out -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterDefaultModule(RtpRtcp* module) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterDefaultModule(RtpRtcp* module) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterDefaultModule(module:0x%x)", module); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterDefaultModule(module:0x%x)", module); if(module == NULL) { return -1; } + if(module == this) + { + WEBRTC_TRACE(kTraceError, + kTraceRtpRtcp, + _id, + "RegisterDefaultModule can't register self as default"); + return -1; + } CriticalSectionScoped lock(_criticalSectionModulePtrs); if(_defaultModule) @@ -220,7 +248,10 @@ ModuleRtpRtcpImpl::RegisterDefaultModule(RtpRtcp* module) WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterDefaultModule() { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DeRegisterDefaultModule()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DeRegisterDefaultModule()"); CriticalSectionScoped lock(_criticalSectionModulePtrs); if(_defaultModule) @@ -233,73 +264,84 @@ ModuleRtpRtcpImpl::DeRegisterDefaultModule() bool ModuleRtpRtcpImpl::DefaultModuleRegistered() { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DefaultModuleRegistered()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DefaultModuleRegistered()"); CriticalSectionScoped lock(_criticalSectionModulePtrs); if(_defaultModule) { return true; } - else - { - return false; - } + return false; } -WebRtc_UWord32 -ModuleRtpRtcpImpl::NumberChildModules() +WebRtc_UWord32 ModuleRtpRtcpImpl::NumberChildModules() { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "NumberChildModules"); CriticalSectionScoped lock(_criticalSectionModulePtrs); CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback); - // we use two locks for protecting _childModules one (_criticalSectionModulePtrsFeedback) for incoming - // messages (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs for all outgoing messages sending packets etc + // we use two locks for protecting _childModules one + // (_criticalSectionModulePtrsFeedback) for incoming messages + // (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs for + // all outgoing messages sending packets etc - return _childModules.GetSize(); + return _childModules.size(); } void ModuleRtpRtcpImpl::RegisterChildModule(RtpRtcp* module) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterChildModule(module:0x%x)", module); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterChildModule(module:0x%x)", + module); CriticalSectionScoped lock(_criticalSectionModulePtrs); CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback); - // we use two locks for protecting _childModules one (_criticalSectionModulePtrsFeedback) for incoming - // messages (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs for all outgoing messages sending packets etc - - _childModules.PushFront(module); + // we use two locks for protecting _childModules one + // (_criticalSectionModulePtrsFeedback) for incoming + // messages (BitrateSent and UpdateTMMBR) and _criticalSectionModulePtrs + // for all outgoing messages sending packets etc + _childModules.push_back((ModuleRtpRtcpImpl*)module); } -void -ModuleRtpRtcpImpl::DeRegisterChildModule(RtpRtcp* removeModule) +void ModuleRtpRtcpImpl::DeRegisterChildModule(RtpRtcp* removeModule) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DeRegisterChildModule(module:0x%x)", removeModule); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DeRegisterChildModule(module:0x%x)", removeModule); CriticalSectionScoped lock(_criticalSectionModulePtrs); CriticalSectionScoped doubleLock(_criticalSectionModulePtrsFeedback); - ListItem* item = _childModules.First(); - while (item) + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); + RtpRtcp* module = *it; if(module == removeModule) { - _childModules.Erase(item); + _childModules.erase(it); return; } - item = _childModules.Next(item); + it++; } } // Lip-sync between voice-video engine, -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterSyncModule(RtpRtcp* audioModule) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSyncModule(RtpRtcp* audioModule) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterSyncModule(module:0x%x)", audioModule); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterSyncModule(module:0x%x)", + audioModule); if(audioModule == NULL) { @@ -314,15 +356,17 @@ ModuleRtpRtcpImpl::RegisterSyncModule(RtpRtcp* audioModule) return _audioModule->RegisterVideoModule(this); } -WebRtc_Word32 -ModuleRtpRtcpImpl::DeRegisterSyncModule() +WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterSyncModule() { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DeRegisterSyncModule()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DeRegisterSyncModule()"); CriticalSectionScoped lock(_criticalSectionModulePtrs); if(_audioModule) { - ModuleRtpRtcpImpl* audioModule=_audioModule; + ModuleRtpRtcpImpl* audioModule = _audioModule; _audioModule = NULL; _receivedNTPsecsAudio = 0; _receivedNTPfracAudio = 0; @@ -336,7 +380,11 @@ ModuleRtpRtcpImpl::DeRegisterSyncModule() WebRtc_Word32 ModuleRtpRtcpImpl::RegisterVideoModule(RtpRtcp* videoModule) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterVideoModule(module:0x%x)", videoModule); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterVideoModule(module:0x%x)", + videoModule); if(videoModule == NULL) { @@ -351,10 +399,12 @@ ModuleRtpRtcpImpl::RegisterVideoModule(RtpRtcp* videoModule) return 0; } -void -ModuleRtpRtcpImpl::DeRegisterVideoModule() +void ModuleRtpRtcpImpl::DeRegisterVideoModule() { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DeRegisterVideoModule()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DeRegisterVideoModule()"); CriticalSectionScoped lock(_criticalSectionModulePtrs); if(_videoModule) @@ -365,9 +415,9 @@ ModuleRtpRtcpImpl::DeRegisterVideoModule() } } -// returns the number of milliseconds until the module want a worker thread to call Process -WebRtc_Word32 -ModuleRtpRtcpImpl::TimeUntilNextProcess() +// returns the number of milliseconds until the module want a worker thread +// to call Process +WebRtc_Word32 ModuleRtpRtcpImpl::TimeUntilNextProcess() { const WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS(); return kRtpRtcpMaxIdleTimeProcess - (now -_lastProcessTime); @@ -375,8 +425,7 @@ ModuleRtpRtcpImpl::TimeUntilNextProcess() // Process any pending tasks such as timeouts // non time critical events -WebRtc_Word32 -ModuleRtpRtcpImpl::Process() +WebRtc_Word32 ModuleRtpRtcpImpl::Process() { _lastProcessTime = ModuleRTPUtility::GetTimeInMS(); @@ -388,10 +437,11 @@ ModuleRtpRtcpImpl::Process() ProcessDeadOrAliveTimer(); - if(_rtcpSender.TimeToSendRTCPReport()) + const bool defaultInstance(_childModules.empty() ? false : true); + if(!defaultInstance &&_rtcpSender.TimeToSendRTCPReport()) { WebRtc_UWord16 RTT = 0; - _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL,NULL,NULL); + _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); _rtcpSender.SendRTCP(kRtcpReport, 0, 0, RTT); } if(_rtpSender.RTPKeepalive()) @@ -414,8 +464,7 @@ ModuleRtpRtcpImpl::Process() * Receiver */ -WebRtc_Word32 -ModuleRtpRtcpImpl::InitReceiver() +WebRtc_Word32 ModuleRtpRtcpImpl::InitReceiver() { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "InitReceiver()"); @@ -434,17 +483,17 @@ ModuleRtpRtcpImpl::InitReceiver() return ret; } -void -ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() +void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() { if(_deadOrAliveActive) { const WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS(); if(now > _deadOrAliveTimeoutMS +_deadOrAliveLastTimer) { + // RTCP is alive if we have received a report the last 12 seconds _deadOrAliveLastTimer += _deadOrAliveTimeoutMS; - bool RTCPalive = false; // RTCP is alive if we have received a report the last 12 seconds + bool RTCPalive = false; if(_rtcpReceiver.LastReceived() + 12000 > now) { RTCPalive = true; @@ -454,26 +503,32 @@ ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() } } - // Set periodic dead or alive notification -WebRtc_Word32 -ModuleRtpRtcpImpl::SetPeriodicDeadOrAliveStatus(const bool enable, - const WebRtc_UWord8 sampleTimeSeconds) +WebRtc_Word32 ModuleRtpRtcpImpl::SetPeriodicDeadOrAliveStatus( + const bool enable, + const WebRtc_UWord8 sampleTimeSeconds) { if(enable) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetPeriodicDeadOrAliveStatus(enable, %d)", sampleTimeSeconds); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetPeriodicDeadOrAliveStatus(enable, %d)", + sampleTimeSeconds); }else { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetPeriodicDeadOrAliveStatus(disable)"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetPeriodicDeadOrAliveStatus(disable)"); } - if(sampleTimeSeconds == 0) { return -1; } _deadOrAliveActive = enable; _deadOrAliveTimeoutMS = sampleTimeSeconds*1000; - _deadOrAliveLastTimer = ModuleRTPUtility::GetTimeInMS(); // trigger the first after one period + // trigger the first after one period + _deadOrAliveLastTimer = ModuleRTPUtility::GetTimeInMS(); return 0; } @@ -481,7 +536,10 @@ WebRtc_Word32 ModuleRtpRtcpImpl::PeriodicDeadOrAliveStatus(bool &enable, WebRtc_UWord8 &sampleTimeSeconds) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "PeriodicDeadOrAliveStatus()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "PeriodicDeadOrAliveStatus()"); enable = _deadOrAliveActive; sampleTimeSeconds = (WebRtc_UWord8)(_deadOrAliveTimeoutMS/1000); @@ -492,7 +550,12 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SetPacketTimeout(const WebRtc_UWord32 RTPtimeoutMS, const WebRtc_UWord32 RTCPtimeoutMS) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetPacketTimeout(%u,%u)",RTPtimeoutMS, RTCPtimeoutMS); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetPacketTimeout(%u,%u)", + RTPtimeoutMS, + RTCPtimeoutMS); if(_rtpReceiver.SetPacketTimeout(RTPtimeoutMS) == 0) { @@ -501,63 +564,82 @@ ModuleRtpRtcpImpl::SetPacketTimeout(const WebRtc_UWord32 RTPtimeoutMS, return -1; } -// set codec name and payload type -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterReceivePayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - const WebRtc_UWord32 rate) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceivePayload( + const CodecInst& voiceCodec) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterReceivePayload()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterReceivePayload(voiceCodec)"); - return _rtpReceiver.RegisterReceivePayload(payloadName, payloadType, frequency, channels, rate); + return _rtpReceiver.RegisterReceivePayload( + voiceCodec.plname, + voiceCodec.pltype, + voiceCodec.plfreq, + voiceCodec.channels, + (voiceCodec.rate < 0) ? 0 : voiceCodec.rate); +} + +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterReceivePayload( + const VideoCodec& videoCodec) +{ + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterReceivePayload(videoCodec)"); + + return _rtpReceiver.RegisterReceivePayload(videoCodec.plName, + videoCodec.plType, + 90000, + 0, + videoCodec.maxBitrate); +} + +WebRtc_Word32 ModuleRtpRtcpImpl::ReceivePayloadType( + const CodecInst& voiceCodec, + WebRtc_Word8* plType) +{ + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "ReceivePayloadType(voiceCodec)"); + + return _rtpReceiver.ReceivePayloadType( + voiceCodec.plname, + voiceCodec.plfreq, + voiceCodec.channels, + (voiceCodec.rate < 0) ? 0 : voiceCodec.rate, + plType); +} + +WebRtc_Word32 ModuleRtpRtcpImpl::ReceivePayloadType( + const VideoCodec& videoCodec, + WebRtc_Word8* plType) +{ + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "ReceivePayloadType(videoCodec)"); + + return _rtpReceiver.ReceivePayloadType(videoCodec.plName, + 90000, + 0, + videoCodec.maxBitrate, + plType); } WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterReceivePayload(const WebRtc_Word8 payloadType) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DeRegisterReceivePayload(%d)", payloadType); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DeRegisterReceivePayload(%d)", + payloadType); return _rtpReceiver.DeRegisterReceivePayload(payloadType); } - // get configured payload type -WebRtc_Word32 -ModuleRtpRtcpImpl::ReceivePayloadType(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - WebRtc_Word8* payloadType, - const WebRtc_UWord32 rate) const -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ReceivePayloadType()"); - - return _rtpReceiver.ReceivePayloadType(payloadName, frequency, channels, payloadType, rate); -} - -WebRtc_Word32 -ModuleRtpRtcpImpl::ReceivePayload(const WebRtc_Word8 payloadType, - WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels, - WebRtc_UWord32* rate) const -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ReceivePayload()"); - - return _rtpReceiver.ReceivePayload(payloadType, payloadName, frequency, channels, rate); -} - -WebRtc_Word32 -ModuleRtpRtcpImpl::RemotePayload(WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_Word8* payloadType, - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels) const -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemotePayload()"); - - return _rtpReceiver.RemotePayload(payloadName, payloadType, frequency, channels); -} - // get the currently configured SSRC filter WebRtc_Word32 ModuleRtpRtcpImpl::SSRCFilter(WebRtc_UWord32& allowedSSRC) const @@ -568,23 +650,30 @@ ModuleRtpRtcpImpl::SSRCFilter(WebRtc_UWord32& allowedSSRC) const } // set a SSRC to be used as a filter for incoming RTP streams -WebRtc_Word32 -ModuleRtpRtcpImpl::SetSSRCFilter(const bool enable, const WebRtc_UWord32 allowedSSRC) +WebRtc_Word32 ModuleRtpRtcpImpl::SetSSRCFilter( + const bool enable, + const WebRtc_UWord32 allowedSSRC) { if(enable) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSSRCFilter(enable, 0x%x)", allowedSSRC); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetSSRCFilter(enable, 0x%x)", + allowedSSRC); }else { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSSRCFilter(disable)"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetSSRCFilter(disable)"); } return _rtpReceiver.SetSSRCFilter(enable, allowedSSRC); } // Get last received remote timestamp -WebRtc_UWord32 -ModuleRtpRtcpImpl::RemoteTimestamp() const +WebRtc_UWord32 ModuleRtpRtcpImpl::RemoteTimestamp() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteTimestamp()"); @@ -595,14 +684,16 @@ ModuleRtpRtcpImpl::RemoteTimestamp() const WebRtc_Word32 ModuleRtpRtcpImpl::EstimatedRemoteTimeStamp(WebRtc_UWord32& timestamp) const { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "EstimatedRemoteTimeStamp()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "EstimatedRemoteTimeStamp()"); return _rtpReceiver.EstimatedRemoteTimeStamp(timestamp); } // Get incoming SSRC -WebRtc_UWord32 -ModuleRtpRtcpImpl::RemoteSSRC() const +WebRtc_UWord32 ModuleRtpRtcpImpl::RemoteSSRC() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteSSRC()"); @@ -623,40 +714,56 @@ WebRtc_Word32 ModuleRtpRtcpImpl::IncomingPacket(const WebRtc_UWord8* incomingPacket, const WebRtc_UWord16 incomingPacketLength) { - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "IncomingPacket(packetLength:%u)", incomingPacketLength); + WEBRTC_TRACE(kTraceStream, + kTraceRtpRtcp, + _id, + "IncomingPacket(packetLength:%u)", + incomingPacketLength); // minimum RTP is 12 bytes // minimum RTCP is 8 bytes (RTCP BYE) if(incomingPacketLength < 8 || incomingPacket == NULL) { - WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id, "IncomingPacket invalid buffer or length"); + WEBRTC_TRACE(kTraceDebug, + kTraceRtpRtcp, + _id, + "IncomingPacket invalid buffer or length"); return -1; } // check RTP version const WebRtc_UWord8 version = incomingPacket[0] >> 6 ; if(version != 2) { - WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id, "IncomingPacket invalid RTP version"); + WEBRTC_TRACE(kTraceDebug, + kTraceRtpRtcp, + _id, + "IncomingPacket invalid RTP version"); return -1; } - ModuleRTPUtility::RTPHeaderParser rtpParser(incomingPacket, incomingPacketLength); + ModuleRTPUtility::RTPHeaderParser rtpParser(incomingPacket, + incomingPacketLength); if(rtpParser.RTCP()) { + // Allow receive of non-compound RTCP packets. RTCPUtility::RTCPParserV2 rtcpParser(incomingPacket, incomingPacketLength, - true); // Allow receive of non-compound RTCP packets. + true); const bool validRTCPHeader = rtcpParser.IsValid(); if(!validRTCPHeader) { - WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id, "IncomingPacket invalid RTCP packet"); + WEBRTC_TRACE(kTraceDebug, + kTraceRtpRtcp, + _id, + "IncomingPacket invalid RTCP packet"); return -1; } RTCPHelp::RTCPPacketInformation rtcpPacketInformation; - WebRtc_Word32 retVal = _rtcpReceiver.IncomingRTCPPacket(rtcpPacketInformation, - &rtcpParser); + WebRtc_Word32 retVal = _rtcpReceiver.IncomingRTCPPacket( + rtcpPacketInformation, + &rtcpParser); if(retVal == 0) { _rtcpReceiver.TriggerCallbacksFromRTCPPacket(rtcpPacketInformation); @@ -671,7 +778,10 @@ ModuleRtpRtcpImpl::IncomingPacket(const WebRtc_UWord8* incomingPacket, const bool validRTPHeader = rtpParser.Parse(rtpHeader); if(!validRTPHeader) { - WEBRTC_TRACE(kTraceDebug, kTraceRtpRtcp, _id, "IncomingPacket invalid RTP header"); + WEBRTC_TRACE(kTraceDebug, + kTraceRtpRtcp, + _id, + "IncomingPacket invalid RTP header"); return -1; } return _rtpReceiver.IncomingRTPPacket(&rtpHeader, @@ -680,11 +790,11 @@ ModuleRtpRtcpImpl::IncomingPacket(const WebRtc_UWord8* incomingPacket, } } -WebRtc_Word32 -ModuleRtpRtcpImpl::IncomingAudioNTP(const WebRtc_UWord32 audioReceivedNTPsecs, - const WebRtc_UWord32 audioReceivedNTPfrac, - const WebRtc_UWord32 audioRTCPArrivalTimeSecs, - const WebRtc_UWord32 audioRTCPArrivalTimeFrac) +WebRtc_Word32 ModuleRtpRtcpImpl::IncomingAudioNTP( + const WebRtc_UWord32 audioReceivedNTPsecs, + const WebRtc_UWord32 audioReceivedNTPfrac, + const WebRtc_UWord32 audioRTCPArrivalTimeSecs, + const WebRtc_UWord32 audioRTCPArrivalTimeFrac) { _receivedNTPsecsAudio = audioReceivedNTPsecs; _receivedNTPfracAudio = audioReceivedNTPfrac; @@ -693,48 +803,70 @@ ModuleRtpRtcpImpl::IncomingAudioNTP(const WebRtc_UWord32 audioReceivedNTPsecs, return 0; } -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterIncomingDataCallback(RtpData* incomingDataCallback) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingDataCallback( + RtpData* incomingDataCallback) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterIncomingDataCallback(incomingDataCallback:0x%x)", incomingDataCallback); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterIncomingDataCallback(incomingDataCallback:0x%x)", + incomingDataCallback); return _rtpReceiver.RegisterIncomingDataCallback(incomingDataCallback); } -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterIncomingRTPCallback(RtpFeedback* incomingMessagesCallback) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingRTPCallback( + RtpFeedback* incomingMessagesCallback) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterIncomingRTPCallback(incomingMessagesCallback:0x%x)",incomingMessagesCallback); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterIncomingRTPCallback(incomingMessagesCallback:0x%x)", + incomingMessagesCallback); return _rtpReceiver.RegisterIncomingRTPCallback(incomingMessagesCallback); } -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterIncomingRTCPCallback(RtcpFeedback* incomingMessagesCallback) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingRTCPCallback( + RtcpFeedback* incomingMessagesCallback) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterIncomingRTCPCallback(incomingMessagesCallback:0x%x)",incomingMessagesCallback); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterIncomingRTCPCallback(incomingMessagesCallback:0x%x)", + incomingMessagesCallback); return _rtcpReceiver.RegisterIncomingRTCPCallback(incomingMessagesCallback); } -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterIncomingVideoCallback(RtpVideoFeedback* incomingMessagesCallback) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterIncomingVideoCallback( + RtpVideoFeedback* incomingMessagesCallback) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterIncomingVideoCallback(incomingMessagesCallback:0x%x)",incomingMessagesCallback); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterIncomingVideoCallback(incomingMessagesCallback:0x%x)", + incomingMessagesCallback); - if(_rtcpReceiver.RegisterIncomingVideoCallback(incomingMessagesCallback) == 0) + if (_rtcpReceiver.RegisterIncomingVideoCallback(incomingMessagesCallback) + == 0) { - return _rtpReceiver.RegisterIncomingVideoCallback(incomingMessagesCallback); + return _rtpReceiver.RegisterIncomingVideoCallback( + incomingMessagesCallback); } return -1; } -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterAudioCallback(RtpAudioFeedback* messagesCallback) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterAudioCallback( + RtpAudioFeedback* messagesCallback) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterAudioCallback(messagesCallback:0x%x)",messagesCallback); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterAudioCallback(messagesCallback:0x%x)", + messagesCallback); - if(_rtpSender.RegisterAudioCallback(messagesCallback) == 0) + if (_rtpSender.RegisterAudioCallback(messagesCallback) == 0) { return _rtpReceiver.RegisterIncomingAudioCallback(messagesCallback); } @@ -745,8 +877,7 @@ ModuleRtpRtcpImpl::RegisterAudioCallback(RtpAudioFeedback* messagesCallback) * Sender */ -WebRtc_Word32 -ModuleRtpRtcpImpl::InitSender() +WebRtc_Word32 ModuleRtpRtcpImpl::InitSender() { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "InitSender()"); @@ -759,15 +890,15 @@ ModuleRtpRtcpImpl::InitSender() } WebRtc_Word32 retVal = _rtcpSender.Init(); - // make sure that RTCP objects are aware of our SSRC (it could have changed due to collision) + // make sure that RTCP objects are aware of our SSRC + // (it could have changed due to collision) WebRtc_UWord32 SSRC = _rtpSender.SSRC(); _rtcpReceiver.SetSSRC(SSRC); _rtcpSender.SetSSRC(SSRC); return retVal; } -bool -ModuleRtpRtcpImpl::RTPKeepalive() const +bool ModuleRtpRtcpImpl::RTPKeepalive() const { WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "RTPKeepalive()"); @@ -781,69 +912,115 @@ ModuleRtpRtcpImpl::RTPKeepaliveStatus(bool* enable, { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTPKeepaliveStatus()"); - return _rtpSender.RTPKeepaliveStatus(enable, unknownPayloadType, deltaTransmitTimeMS); + return _rtpSender.RTPKeepaliveStatus(enable, + unknownPayloadType, + deltaTransmitTimeMS); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetRTPKeepaliveStatus(bool enable, WebRtc_Word8 unknownPayloadType, WebRtc_UWord16 deltaTransmitTimeMS) +WebRtc_Word32 ModuleRtpRtcpImpl::SetRTPKeepaliveStatus( + bool enable, + WebRtc_Word8 unknownPayloadType, + WebRtc_UWord16 deltaTransmitTimeMS) { if (enable) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTPKeepaliveStatus(enable, payloadType:%d deltaTransmitTimeMS:%u)",unknownPayloadType,deltaTransmitTimeMS); + WEBRTC_TRACE( + kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetRTPKeepaliveStatus(true, plType:%d deltaTransmitTimeMS:%u)", + unknownPayloadType, + deltaTransmitTimeMS); // check the transmit keepalive delta time [1,60] if (deltaTransmitTimeMS < 1000 || deltaTransmitTimeMS > 60000) { - WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tinvalid deltaTransmitTimeSeconds (%d)", deltaTransmitTimeMS); - return (-1); + WEBRTC_TRACE(kTraceError, + kTraceRtpRtcp, + _id, + "\tinvalid deltaTransmitTimeSeconds (%d)", + deltaTransmitTimeMS); + return -1; } // check the payload time [0,127] if (unknownPayloadType < 0 ) { - WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, "\tinvalid unknownPayloadType (%d)", unknownPayloadType); - return (-1); + WEBRTC_TRACE(kTraceError, + kTraceRtpRtcp, + _id, + "\tinvalid unknownPayloadType (%d)", + unknownPayloadType); + return -1; } - // enable RTP keepalive mechanism - return _rtpSender.EnableRTPKeepalive(unknownPayloadType, deltaTransmitTimeMS); - + return _rtpSender.EnableRTPKeepalive(unknownPayloadType, + deltaTransmitTimeMS); }else { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTPKeepaliveStatus(disable)"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetRTPKeepaliveStatus(disable)"); return _rtpSender.DisableRTPKeepalive(); } } -// set codec name and payload type -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterSendPayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - const WebRtc_UWord32 rate) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendPayload( + const CodecInst& voiceCodec) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterSendPayload(payloadName:%s payloadType:%d frequency:%u)", payloadName, payloadType, frequency); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterSendPayload(plName:%s plType:%d frequency:%u)", + voiceCodec.plname, + voiceCodec.pltype, + voiceCodec.plfreq); - return _rtpSender.RegisterPayload(payloadName, payloadType, frequency, channels, rate); + return _rtpSender.RegisterPayload( + voiceCodec.plname, + voiceCodec.pltype, + voiceCodec.plfreq, + voiceCodec.channels, + (voiceCodec.rate < 0) ? 0 : voiceCodec.rate); +} + +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendPayload( + const VideoCodec& videoCodec) +{ + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterSendPayload(plName:%s plType:%d)", + videoCodec.plName, + videoCodec.plType); + + _sendVideoCodec = videoCodec; + _simulcast = (videoCodec.numberOfSimulcastStreams > 1) ? true : false; + return _rtpSender.RegisterPayload(videoCodec.plName, + videoCodec.plType, + 90000, + 0, + videoCodec.maxBitrate); } WebRtc_Word32 ModuleRtpRtcpImpl::DeRegisterSendPayload(const WebRtc_Word8 payloadType) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "DeRegisterSendPayload(%d)", payloadType); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "DeRegisterSendPayload(%d)", payloadType); return _rtpSender.DeRegisterSendPayload(payloadType); } -WebRtc_Word8 -ModuleRtpRtcpImpl::SendPayloadType() const +WebRtc_Word8 ModuleRtpRtcpImpl::SendPayloadType() const { return _rtpSender.SendPayloadType(); } -WebRtc_UWord32 -ModuleRtpRtcpImpl::StartTimestamp() const +WebRtc_UWord32 ModuleRtpRtcpImpl::StartTimestamp() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "StartTimestamp()"); @@ -854,13 +1031,16 @@ ModuleRtpRtcpImpl::StartTimestamp() const WebRtc_Word32 ModuleRtpRtcpImpl::SetStartTimestamp(const WebRtc_UWord32 timestamp) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetStartTimestamp(%d)", timestamp); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetStartTimestamp(%d)", + timestamp); return _rtpSender.SetStartTimestamp(timestamp, true); } -WebRtc_UWord16 -ModuleRtpRtcpImpl::SequenceNumber() const +WebRtc_UWord16 ModuleRtpRtcpImpl::SequenceNumber() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SequenceNumber()"); @@ -868,16 +1048,18 @@ ModuleRtpRtcpImpl::SequenceNumber() const } // Set SequenceNumber, default is a random number -WebRtc_Word32 -ModuleRtpRtcpImpl::SetSequenceNumber(const WebRtc_UWord16 seqNum) +WebRtc_Word32 ModuleRtpRtcpImpl::SetSequenceNumber(const WebRtc_UWord16 seqNum) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSequenceNumber(%d)",seqNum); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetSequenceNumber(%d)", + seqNum); return _rtpSender.SetSequenceNumber(seqNum); } -WebRtc_UWord32 -ModuleRtpRtcpImpl::SSRC() const +WebRtc_UWord32 ModuleRtpRtcpImpl::SSRC() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SSRC()"); @@ -918,24 +1100,28 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize], const WebRtc_UWord8 arrLength) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetCSRCs(arrLength:%d)", arrLength); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetCSRCs(arrLength:%d)", + arrLength); - const bool defaultInstance(_childModules.Empty()?false:true); + const bool defaultInstance(_childModules.empty() ? false : true); if(defaultInstance) { // for default we need to update all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while (item) + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); + RtpRtcp* module = *it; if(module) { module->SetCSRCs(arrOfCSRC, arrLength); } - item = _childModules.Next(item); + it++; } return 0; @@ -950,16 +1136,14 @@ ModuleRtpRtcpImpl::SetCSRCs(const WebRtc_UWord32 arrOfCSRC[kRtpCsrcSize], } } -WebRtc_UWord32 -ModuleRtpRtcpImpl::PacketCountSent() const +WebRtc_UWord32 ModuleRtpRtcpImpl::PacketCountSent() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "PacketCountSent()"); return _rtpSender.Packets(); } -WebRtc_UWord32 -ModuleRtpRtcpImpl::ByteCountSent() const +WebRtc_UWord32 ModuleRtpRtcpImpl::ByteCountSent() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ByteCountSent()"); @@ -973,8 +1157,7 @@ int ModuleRtpRtcpImpl::CurrentSendFrequencyHz() const return _rtpSender.SendPayloadFrequency(); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) +WebRtc_Word32 ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) { if(sending) { @@ -1008,16 +1191,14 @@ ModuleRtpRtcpImpl::SetSendingStatus(const bool sending) return 0; } -bool -ModuleRtpRtcpImpl::Sending() const +bool ModuleRtpRtcpImpl::Sending() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Sending()"); return _rtcpSender.Sending(); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetSendingMediaStatus(const bool sending) +WebRtc_Word32 ModuleRtpRtcpImpl::SetSendingMediaStatus(const bool sending) { if(sending) { @@ -1030,38 +1211,37 @@ ModuleRtpRtcpImpl::SetSendingMediaStatus(const bool sending) return 0; } -bool -ModuleRtpRtcpImpl::SendingMedia() const +bool ModuleRtpRtcpImpl::SendingMedia() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "Sending()"); - const bool haveChildModules(_childModules.Empty()?false:true); - + const bool haveChildModules(_childModules.empty() ? false : true); if(!haveChildModules) { return _rtpSender.SendingMedia(); } - else + + CriticalSectionScoped lock(_criticalSectionModulePtrs); + std::list::const_iterator it = _childModules.begin(); + while (it != _childModules.end()) { - CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - if(item) + RTPSender& rtpSender = (*it)->_rtpSender; + if (rtpSender.SendingMedia()) { - RTPSender& rtpSender = static_cast(item->GetItem())->_rtpSender; - if (rtpSender.SendingMedia()) - { - return true; - } - item = _childModules.Next(item); + return true; } + it++; } return false; } -WebRtc_Word32 -ModuleRtpRtcpImpl::RegisterSendTransport(Transport* outgoingTransport) +WebRtc_Word32 ModuleRtpRtcpImpl::RegisterSendTransport( + Transport* outgoingTransport) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RegisterSendTransport(0x%x)", outgoingTransport); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RegisterSendTransport(0x%x)", outgoingTransport); if(_rtpSender.RegisterSendTransport(outgoingTransport) == 0) { @@ -1077,42 +1257,76 @@ ModuleRtpRtcpImpl::SendOutgoingData(const FrameType frameType, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader* fragmentation, - const RTPVideoTypeHeader* rtpTypeHdr) + const RTPVideoHeader* rtpVideoHdr) { - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, - "SendOutgoingData(frameType:%d payloadType:%d timeStamp:%u payloadSize:%u)", - frameType, payloadType, timeStamp, payloadSize); + WEBRTC_TRACE( + kTraceStream, + kTraceRtpRtcp, + _id, + "SendOutgoingData(frameType:%d payloadType:%d timeStamp:%u size:%u)", + frameType, payloadType, timeStamp, payloadSize); - if(_rtcpSender.TimeToSendRTCPReport(kVideoFrameKey == frameType)) - { - WebRtc_UWord16 RTT = 0; - _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL,NULL,NULL); - _rtcpSender.SendRTCP(kRtcpReport, 0, 0, RTT); - } - - const bool haveChildModules(_childModules.Empty()?false:true); - - WebRtc_Word32 retVal = -1; + const bool haveChildModules(_childModules.empty() ? false : true); if(!haveChildModules) { - retVal = _rtpSender.SendOutgoingData(frameType, - payloadType, - timeStamp, - payloadData, - payloadSize, - fragmentation, - NULL, - rtpTypeHdr); + // Don't sent RTCP from default module + if(_rtcpSender.TimeToSendRTCPReport(kVideoFrameKey == frameType)) + { + WebRtc_UWord16 RTT = 0; + _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); + _rtcpSender.SendRTCP(kRtcpReport, 0, 0, RTT); + } + return _rtpSender.SendOutgoingData(frameType, + payloadType, + timeStamp, + payloadData, + payloadSize, + fragmentation, + NULL, + &(rtpVideoHdr->codecHeader)); + } + WebRtc_Word32 retVal = -1; + if (_simulcast) + { + if (rtpVideoHdr == NULL) + { + return -1; + } + int idx = 0; + CriticalSectionScoped lock(_criticalSectionModulePtrs); + std::list::iterator it = _childModules.begin(); + for (; idx < rtpVideoHdr->simulcastIdx; idx++) + { + it++; + if (it == _childModules.end()) + { + return -1; + } + } + RTPSender& rtpSender = (*it)->_rtpSender; + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SendOutgoingData(SimulcastIdx:%u size:%u, ssrc:0x%x)", + idx, payloadSize, rtpSender.SSRC()); + return rtpSender.SendOutgoingData(frameType, + payloadType, + timeStamp, + payloadData, + payloadSize, + fragmentation, + NULL, + &(rtpVideoHdr->codecHeader)); } else { CriticalSectionScoped lock(_criticalSectionModulePtrs); - + // TODO(pwestin) remove codecInfo from SendOutgoingData VideoCodecInformation* codecInfo = NULL; - ListItem* item = _childModules.First(); - if(item) + std::list::iterator it = _childModules.begin(); + if (it != _childModules.end()) { - RTPSender& rtpSender = static_cast(item->GetItem())->_rtpSender; + RTPSender& rtpSender = (*it)->_rtpSender; retVal = rtpSender.SendOutgoingData(frameType, payloadType, timeStamp, @@ -1120,15 +1334,15 @@ ModuleRtpRtcpImpl::SendOutgoingData(const FrameType frameType, payloadSize, fragmentation, NULL, - rtpTypeHdr); + &(rtpVideoHdr->codecHeader)); - item = _childModules.Next(item); + it++; } // send to all remaining "child" modules - while(item) + while (it != _childModules.end()) { - RTPSender& rtpSender = static_cast(item->GetItem())->_rtpSender; + RTPSender& rtpSender = (*it)->_rtpSender; retVal = rtpSender.SendOutgoingData(frameType, payloadType, timeStamp, @@ -1136,9 +1350,9 @@ ModuleRtpRtcpImpl::SendOutgoingData(const FrameType frameType, payloadSize, fragmentation, codecInfo, - rtpTypeHdr); + &(rtpVideoHdr->codecHeader)); - item = _childModules.Next(item); + it++; } } return retVal; @@ -1152,31 +1366,35 @@ ModuleRtpRtcpImpl::MaxPayloadLength() const return _rtpSender.MaxPayloadLength(); } -WebRtc_UWord16 -ModuleRtpRtcpImpl::MaxDataPayloadLength() const +WebRtc_UWord16 ModuleRtpRtcpImpl::MaxDataPayloadLength() const { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "MaxDataPayloadLength()"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "MaxDataPayloadLength()"); WebRtc_UWord16 minDataPayloadLength = IP_PACKET_SIZE-28; // Assuming IP/UDP - const bool defaultInstance(_childModules.Empty() ? false : true); + const bool defaultInstance(_childModules.empty() ? false : true); if (defaultInstance) { // for default we need to update all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while(item) + std::list::const_iterator it = + _childModules.begin(); + while (it != _childModules.end()) { - RtpRtcp* module = static_cast(item->GetItem()); + RtpRtcp* module = *it; if (module) { - WebRtc_UWord16 dataPayloadLength = module->MaxDataPayloadLength(); + WebRtc_UWord16 dataPayloadLength = + module->MaxDataPayloadLength(); if (dataPayloadLength < minDataPayloadLength) { minDataPayloadLength = dataPayloadLength; } } - item = _childModules.Next(item); + it++; } } @@ -1185,16 +1403,20 @@ ModuleRtpRtcpImpl::MaxDataPayloadLength() const { minDataPayloadLength = dataPayloadLength; } - return minDataPayloadLength; } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetTransportOverhead(const bool TCP, - const bool IPV6, - const WebRtc_UWord8 authenticationOverhead) +WebRtc_Word32 ModuleRtpRtcpImpl::SetTransportOverhead( + const bool TCP, + const bool IPV6, + const WebRtc_UWord8 authenticationOverhead) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetTransportOverhead(TCP:%d, IPV6:%d authenticationOverhead:%u)",TCP,IPV6,authenticationOverhead); + WEBRTC_TRACE( + kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetTransportOverhead(TCP:%d, IPV6:%d authenticationOverhead:%u)", + TCP, IPV6, authenticationOverhead); WebRtc_UWord16 packetOverHead = 0; if(IPV6) @@ -1241,14 +1463,14 @@ ModuleRtpRtcpImpl::SetMaxTransferUnit(const WebRtc_UWord16 MTU) WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Invalid in argument to SetMaxTransferUnit(%u)",MTU); return -1; } - return _rtpSender.SetMaxPayloadLength(MTU - _packetOverHead, _packetOverHead); + return _rtpSender.SetMaxPayloadLength(MTU - _packetOverHead, + _packetOverHead); } /* * RTCP */ -RTCPMethod -ModuleRtpRtcpImpl::RTCP() const +RTCPMethod ModuleRtpRtcpImpl::RTCP() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RTCP()"); @@ -1260,8 +1482,7 @@ ModuleRtpRtcpImpl::RTCP() const } // configure RTCP status i.e on/off -WebRtc_Word32 -ModuleRtpRtcpImpl::SetRTCPStatus(const RTCPMethod method) +WebRtc_Word32 ModuleRtpRtcpImpl::SetRTCPStatus(const RTCPMethod method) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetRTCPStatus(%d)",method); @@ -1271,9 +1492,9 @@ ModuleRtpRtcpImpl::SetRTCPStatus(const RTCPMethod method) } return -1; } + // only for internal test -WebRtc_UWord32 -ModuleRtpRtcpImpl::LastSendReport(WebRtc_UWord32& lastRTCPTime) +WebRtc_UWord32 ModuleRtpRtcpImpl::LastSendReport(WebRtc_UWord32& lastRTCPTime) { return _rtcpSender.LastSendReport(lastRTCPTime); } @@ -1467,7 +1688,12 @@ ModuleRtpRtcpImpl::ReportBlockStatistics(WebRtc_UWord8 *fraction_lost, { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "ReportBlockStatistics()"); WebRtc_Word32 missing = 0; - WebRtc_Word32 ret = _rtpReceiver.Statistics(fraction_lost,cum_lost,ext_max,jitter, NULL, &missing, true); + WebRtc_Word32 ret = _rtpReceiver.Statistics(fraction_lost, + cum_lost,ext_max, + jitter, + NULL, + &missing, + true); #ifdef MATLAB if (_plot1 == NULL) @@ -1482,8 +1708,7 @@ ModuleRtpRtcpImpl::ReportBlockStatistics(WebRtc_UWord8 *fraction_lost, return ret; } -WebRtc_Word32 -ModuleRtpRtcpImpl::RemoteRTCPStat( RTCPSenderInfo* senderInfo) +WebRtc_Word32 ModuleRtpRtcpImpl::RemoteRTCPStat( RTCPSenderInfo* senderInfo) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RemoteRTCPStat()"); @@ -1520,31 +1745,34 @@ ModuleRtpRtcpImpl::RemoveRTCPReportBlock(const WebRtc_UWord32 SSRC) /* * (REMB) Receiver Estimated Max Bitrate */ -bool -ModuleRtpRtcpImpl::REMB() const +bool ModuleRtpRtcpImpl::REMB() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "REMB()"); return _rtcpSender.REMB(); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetREMBStatus(const bool enable) +WebRtc_Word32 ModuleRtpRtcpImpl::SetREMBStatus(const bool enable) { if(enable) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetREMBStatus(enable)"); - }else + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetREMBStatus(enable)"); + } else { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetREMBStatus(disable)"); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetREMBStatus(disable)"); } return _rtcpSender.SetREMBStatus(enable); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetREMBData(const WebRtc_UWord32 bitrate, - const WebRtc_UWord8 numberOfSSRC, - const WebRtc_UWord32* SSRC) +WebRtc_Word32 ModuleRtpRtcpImpl::SetREMBData(const WebRtc_UWord32 bitrate, + const WebRtc_UWord8 numberOfSSRC, + const WebRtc_UWord32* SSRC) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetREMBData(bitrate:%d,?,?)", bitrate); return _rtcpSender.SetREMBData(bitrate, numberOfSSRC, SSRC); @@ -1553,16 +1781,14 @@ ModuleRtpRtcpImpl::SetREMBData(const WebRtc_UWord32 bitrate, /* * (TMMBR) Temporary Max Media Bit Rate */ -bool -ModuleRtpRtcpImpl::TMMBR() const +bool ModuleRtpRtcpImpl::TMMBR() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TMMBR()"); return _rtcpSender.TMMBR(); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetTMMBRStatus(const bool enable) +WebRtc_Word32 ModuleRtpRtcpImpl::SetTMMBRStatus(const bool enable) { if(enable) { @@ -1607,21 +1833,21 @@ ModuleRtpRtcpImpl::RequestTMMBR(const WebRtc_UWord32 estimatedBW, */ // Is Negative acknowledgement requests on/off? -NACKMethod -ModuleRtpRtcpImpl::NACK() const +NACKMethod ModuleRtpRtcpImpl::NACK() const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "NACK()"); NACKMethod childMethod = kNackOff; - const bool defaultInstance(_childModules.Empty() ? false : true); + const bool defaultInstance(_childModules.empty() ? false : true); if (defaultInstance) { // for default we need to check all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while(item) + std::list::const_iterator it = + _childModules.begin(); + while (it != _childModules.end()) { - RtpRtcp* module = static_cast(item->GetItem()); + RtpRtcp* module = *it; if (module) { NACKMethod nackMethod = module->NACK(); @@ -1631,7 +1857,7 @@ ModuleRtpRtcpImpl::NACK() const break; } } - item = _childModules.Next(item); + it++; } } @@ -1644,10 +1870,12 @@ ModuleRtpRtcpImpl::NACK() const } // Turn negative acknowledgement requests on/off -WebRtc_Word32 -ModuleRtpRtcpImpl::SetNACKStatus(NACKMethod method) +WebRtc_Word32 ModuleRtpRtcpImpl::SetNACKStatus(NACKMethod method) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetNACKStatus(%u)",method); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetNACKStatus(%u)",method); _nackMethod = method; _rtpReceiver.SetNACKStatus(method); @@ -1659,7 +1887,10 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList, const WebRtc_UWord16 size) { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendNACK(size:%u)", size); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SendNACK(size:%u)", size); if(size > NACK_PACKETS_MAX_SIZE) { @@ -1708,8 +1939,9 @@ ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList, } // Store the sent packets, needed to answer to a Negative acknowledgement requests -WebRtc_Word32 -ModuleRtpRtcpImpl::SetStorePacketsStatus(const bool enable, const WebRtc_UWord16 numberToStore) +WebRtc_Word32 ModuleRtpRtcpImpl::SetStorePacketsStatus( + const bool enable, + const WebRtc_UWord16 numberToStore) { if(enable) { @@ -1718,7 +1950,6 @@ ModuleRtpRtcpImpl::SetStorePacketsStatus(const bool enable, const WebRtc_UWord16 { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetStorePacketsStatus(disable)"); } - return _rtpSender.SetStorePacketsStatus(enable, numberToStore); } @@ -1727,9 +1958,10 @@ ModuleRtpRtcpImpl::SetStorePacketsStatus(const bool enable, const WebRtc_UWord16 */ // Outband TelephoneEvent detection -WebRtc_Word32 ModuleRtpRtcpImpl::SetTelephoneEventStatus(const bool enable, - const bool forwardToDecoder, - const bool detectEndOfTone) +WebRtc_Word32 ModuleRtpRtcpImpl::SetTelephoneEventStatus( + const bool enable, + const bool forwardToDecoder, + const bool detectEndOfTone) { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetTelephoneEventStatus(enable:%d forwardToDecoder:%d detectEndOfTone:%d)", enable, forwardToDecoder, detectEndOfTone); @@ -1763,60 +1995,79 @@ ModuleRtpRtcpImpl::SendTelephoneEventOutband(const WebRtc_UWord8 key, return _rtpSender.SendTelephoneEvent(key, timeMs, level); } -bool -ModuleRtpRtcpImpl::SendTelephoneEventActive(WebRtc_Word8& telephoneEvent) const -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendTelephoneEventActive()"); +bool ModuleRtpRtcpImpl::SendTelephoneEventActive( + WebRtc_Word8& telephoneEvent) const { + + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SendTelephoneEventActive()"); return _rtpSender.SendTelephoneEventActive(telephoneEvent); } - // set audio packet size, used to determine when it's time to send a DTMF packet in silence (CNG) -WebRtc_Word32 -ModuleRtpRtcpImpl::SetAudioPacketSize(const WebRtc_UWord16 packetSizeSamples) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetAudioPacketSize(%u)", packetSizeSamples); +// set audio packet size, used to determine when it's time to send a DTMF +// packet in silence (CNG) +WebRtc_Word32 ModuleRtpRtcpImpl::SetAudioPacketSize( + const WebRtc_UWord16 packetSizeSamples) { + + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetAudioPacketSize(%u)", + packetSizeSamples); return _rtpSender.SetAudioPacketSize(packetSizeSamples); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetRTPAudioLevelIndicationStatus(const bool enable, - const WebRtc_UWord8 ID) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, - "SetRTPAudioLevelIndicationStatus(enable=%d, ID=%u)", enable, ID); +WebRtc_Word32 ModuleRtpRtcpImpl::SetRTPAudioLevelIndicationStatus( + const bool enable, + const WebRtc_UWord8 ID) { + + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetRTPAudioLevelIndicationStatus(enable=%d, ID=%u)", + enable, + ID); return _rtpSender.SetAudioLevelIndicationStatus(enable, ID); } -WebRtc_Word32 -ModuleRtpRtcpImpl::GetRTPAudioLevelIndicationStatus(bool& enable, - WebRtc_UWord8& ID) const -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "GetRTPAudioLevelIndicationStatus()"); +WebRtc_Word32 ModuleRtpRtcpImpl::GetRTPAudioLevelIndicationStatus( + bool& enable, + WebRtc_UWord8& ID) const { + + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "GetRTPAudioLevelIndicationStatus()"); return _rtpSender.AudioLevelIndicationStatus(enable, ID); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetAudioLevel(const WebRtc_UWord8 level_dBov) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetAudioLevel(level_dBov:%u)", level_dBov); +WebRtc_Word32 ModuleRtpRtcpImpl::SetAudioLevel(const WebRtc_UWord8 level_dBov) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetAudioLevel(level_dBov:%u)", + level_dBov); return _rtpSender.SetAudioLevel(level_dBov); } // Set payload type for Redundant Audio Data RFC 2198 -WebRtc_Word32 -ModuleRtpRtcpImpl::SetSendREDPayloadType(const WebRtc_Word8 payloadType) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSendREDPayloadType(%d)", payloadType); +WebRtc_Word32 ModuleRtpRtcpImpl::SetSendREDPayloadType( + const WebRtc_Word8 payloadType) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetSendREDPayloadType(%d)", + payloadType); return _rtpSender.SetRED(payloadType); } // Get payload type for Redundant Audio Data RFC 2198 WebRtc_Word32 -ModuleRtpRtcpImpl::SendREDPayloadType(WebRtc_Word8& payloadType) const -{ +ModuleRtpRtcpImpl::SendREDPayloadType(WebRtc_Word8& payloadType) const { WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendREDPayloadType()"); return _rtpSender.RED(payloadType); @@ -1826,76 +2077,80 @@ ModuleRtpRtcpImpl::SendREDPayloadType(WebRtc_Word8& payloadType) const /* * Video */ -RtpVideoCodecTypes -ModuleRtpRtcpImpl::ReceivedVideoCodec() const -{ +RtpVideoCodecTypes ModuleRtpRtcpImpl::ReceivedVideoCodec() const { return _rtpReceiver.VideoCodecType(); } -RtpVideoCodecTypes -ModuleRtpRtcpImpl::SendVideoCodec() const -{ +RtpVideoCodecTypes ModuleRtpRtcpImpl::SendVideoCodec() const { return _rtpSender.VideoCodecType(); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetSendBitrate(const WebRtc_UWord32 startBitrate, - const WebRtc_UWord16 minBitrateKbit, - const WebRtc_UWord16 maxBitrateKbit) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetSendBitrate start:%ubit/s min:%uKbit/s max:%uKbit/s", startBitrate, minBitrateKbit, maxBitrateKbit); +WebRtc_Word32 ModuleRtpRtcpImpl::SetSendBitrate( + const WebRtc_UWord32 startBitrate, + const WebRtc_UWord16 minBitrateKbit, + const WebRtc_UWord16 maxBitrateKbit) { - const bool defaultInstance(_childModules.Empty()?false:true); + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetSendBitrate start:%ubit/s min:%uKbit/s max:%uKbit/s", + startBitrate, minBitrateKbit, maxBitrateKbit); - if(defaultInstance) - { + const bool defaultInstance(_childModules.empty() ? false : true); + + if (defaultInstance) { // for default we need to update all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while (item) - { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); - if(module) - { - module->SetSendBitrate(startBitrate, minBitrateKbit, maxBitrateKbit); + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + RtpRtcp* module = *it; + if (module) { + module->SetSendBitrate(startBitrate, + minBitrateKbit, + maxBitrateKbit); } - item = _childModules.Next(item); + it++; } } _rtpSender.SetTargetSendBitrate(startBitrate); - return _bandwidthManagement.SetSendBitrate(startBitrate, minBitrateKbit, maxBitrateKbit); + return _bandwidthManagement.SetSendBitrate(startBitrate, + minBitrateKbit, + maxBitrateKbit); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetKeyFrameRequestMethod(const KeyFrameRequestMethod method) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetKeyFrameRequestMethod(method:%u)",method); +WebRtc_Word32 ModuleRtpRtcpImpl::SetKeyFrameRequestMethod( + const KeyFrameRequestMethod method) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetKeyFrameRequestMethod(method:%u)", + method); _keyFrameReqMethod = method; return 0; } -WebRtc_Word32 -ModuleRtpRtcpImpl::RequestKeyFrame(const FrameType frameType) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "RequestKeyFrame(frameType:%d)",frameType); +WebRtc_Word32 ModuleRtpRtcpImpl::RequestKeyFrame(const FrameType frameType) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "RequestKeyFrame(frameType:%d)", + frameType); - switch(_keyFrameReqMethod) - { + switch (_keyFrameReqMethod) { case kKeyFrameReqFirRtp: return _rtpSender.SendRTPIntraRequest(); case kKeyFrameReqPliRtcp: return _rtcpSender.SendRTCP(kRtcpPli); - case kKeyFrameReqFirRtcp: - { + case kKeyFrameReqFirRtcp: { // conference scenario WebRtc_UWord16 RTT = 0; - _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL,NULL,NULL); - return _rtcpSender.SendRTCP(kRtcpFir, 0,NULL, RTT); + _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); + return _rtcpSender.SendRTCP(kRtcpFir, 0, NULL, RTT); } default: assert(false); @@ -1903,178 +2158,172 @@ ModuleRtpRtcpImpl::RequestKeyFrame(const FrameType frameType) } } -WebRtc_Word32 -ModuleRtpRtcpImpl::SendRTCPSliceLossIndication(const WebRtc_UWord8 pictureID) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SendRTCPSliceLossIndication (pictureID:%d)", pictureID); - return _rtcpSender.SendRTCP(kRtcpSli, 0,0,0, pictureID); +WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCPSliceLossIndication( + const WebRtc_UWord8 pictureID) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SendRTCPSliceLossIndication (pictureID:%d)", + pictureID); + return _rtcpSender.SendRTCP(kRtcpSli, 0, 0, 0, pictureID); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetCameraDelay(const WebRtc_Word32 delayMS) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetCameraDelay(%d)",delayMS); - const bool defaultInstance(_childModules.Empty()?false:true); +WebRtc_Word32 ModuleRtpRtcpImpl::SetCameraDelay(const WebRtc_Word32 delayMS) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetCameraDelay(%d)", + delayMS); + const bool defaultInstance(_childModules.empty() ? false : true); - if(defaultInstance) - { + if (defaultInstance) { CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while (item) - { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); - if(module) - { + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + RtpRtcp* module = *it; + if (module) { module->SetCameraDelay(delayMS); } - item = _childModules.Next(item); + it++; } return 0; - } else - { - return _rtcpSender.SetCameraDelay(delayMS); } + return _rtcpSender.SetCameraDelay(delayMS); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetGenericFECStatus(const bool enable, - const WebRtc_UWord8 payloadTypeRED, - const WebRtc_UWord8 payloadTypeFEC) -{ - if(enable) - { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetGenericFECStatus(enable, %u)", payloadTypeRED); - } else - { - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetGenericFECStatus(disable)"); +WebRtc_Word32 ModuleRtpRtcpImpl::SetGenericFECStatus( + const bool enable, + const WebRtc_UWord8 payloadTypeRED, + const WebRtc_UWord8 payloadTypeFEC) { + if (enable) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetGenericFECStatus(enable, %u)", + payloadTypeRED); + } else { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetGenericFECStatus(disable)"); } - return _rtpSender.SetGenericFECStatus(enable, payloadTypeRED, payloadTypeFEC); + return _rtpSender.SetGenericFECStatus(enable, + payloadTypeRED, + payloadTypeFEC); } -WebRtc_Word32 -ModuleRtpRtcpImpl::GenericFECStatus(bool& enable, WebRtc_UWord8& payloadTypeRED, WebRtc_UWord8& payloadTypeFEC) -{ +WebRtc_Word32 ModuleRtpRtcpImpl::GenericFECStatus( + bool& enable, + WebRtc_UWord8& payloadTypeRED, + WebRtc_UWord8& payloadTypeFEC) { + WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "GenericFECStatus()"); bool childEnabled = false; - const bool defaultInstance(_childModules.Empty() ? false : true); - if (defaultInstance) - { + const bool defaultInstance(_childModules.empty() ? false : true); + if (defaultInstance) { // for default we need to check all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while(item) - { - RtpRtcp* module = static_cast(item->GetItem()); - if (module) - { + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + RtpRtcp* module = *it; + if (module) { bool enabled = false; WebRtc_UWord8 dummyPTypeRED = 0; WebRtc_UWord8 dummyPTypeFEC = 0; - if (module->GenericFECStatus(enabled, dummyPTypeRED, dummyPTypeFEC) == 0 && enabled) - { + if (module->GenericFECStatus(enabled, + dummyPTypeRED, + dummyPTypeFEC) == 0 && enabled) { childEnabled = true; break; } } - item = _childModules.Next(item); + it++; } } - - WebRtc_Word32 retVal = _rtpSender.GenericFECStatus(enable, payloadTypeRED, payloadTypeFEC); - if (childEnabled) - { + WebRtc_Word32 retVal = _rtpSender.GenericFECStatus(enable, + payloadTypeRED, + payloadTypeFEC); + if (childEnabled) { // returns true if enabled for any child module enable = childEnabled; } return retVal; } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetFECCodeRate(const WebRtc_UWord8 keyFrameCodeRate, - const WebRtc_UWord8 deltaFrameCodeRate) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetFECCodeRate(%u, %u)", keyFrameCodeRate, deltaFrameCodeRate); +WebRtc_Word32 ModuleRtpRtcpImpl::SetFECCodeRate( + const WebRtc_UWord8 keyFrameCodeRate, + const WebRtc_UWord8 deltaFrameCodeRate) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetFECCodeRate(%u, %u)", + keyFrameCodeRate, + deltaFrameCodeRate); - const bool defaultInstance(_childModules.Empty()?false:true); - if (defaultInstance) - { + const bool defaultInstance(_childModules.empty() ? false : true); + if (defaultInstance) { // for default we need to update all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while (item) - { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); - if (module) - { + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + RtpRtcp* module = *it; + if (module) { module->SetFECCodeRate(keyFrameCodeRate, deltaFrameCodeRate); } - item = _childModules.Next(item); + it++; } return 0; - - } else - { - return _rtpSender.SetFECCodeRate(keyFrameCodeRate, deltaFrameCodeRate); } + return _rtpSender.SetFECCodeRate(keyFrameCodeRate, deltaFrameCodeRate); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetFECUepProtection(const bool keyUseUepProtection, - const bool deltaUseUepProtection) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, - "SetFECUepProtection(%d, %d)", keyUseUepProtection, +WebRtc_Word32 ModuleRtpRtcpImpl::SetFECUepProtection( + const bool keyUseUepProtection, + const bool deltaUseUepProtection) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, _id, + "SetFECUepProtection(%d, %d)", + keyUseUepProtection, deltaUseUepProtection); - const bool defaultInstance(_childModules.Empty()?false:true); - if (defaultInstance) - { + const bool defaultInstance(_childModules.empty()?false:true); + if (defaultInstance) { // for default we need to update all child modules too CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while (item) - { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); - if (module) - { + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + RtpRtcp* module = *it; + if (module) { module->SetFECUepProtection(keyUseUepProtection, deltaUseUepProtection); } - item = _childModules.Next(item); + it++; } return 0; - - } else - { - return _rtpSender.SetFECUepProtection(keyUseUepProtection, - deltaUseUepProtection); } + return _rtpSender.SetFECUepProtection(keyUseUepProtection, + deltaUseUepProtection); } -void -ModuleRtpRtcpImpl::SetRemoteSSRC(const WebRtc_UWord32 SSRC) -{ +void ModuleRtpRtcpImpl::SetRemoteSSRC(const WebRtc_UWord32 SSRC) { // inform about the incoming SSRC _rtcpSender.SetRemoteSSRC(SSRC); _rtcpReceiver.SetRemoteSSRC(SSRC); // check for a SSRC collision - if(_rtpSender.SSRC() == SSRC && !_collisionDetected ) // loopback - { + if (_rtpSender.SSRC() == SSRC && !_collisionDetected) { // if we detect a collision change the SSRC but only once _collisionDetected = true; WebRtc_UWord32 newSSRC =_rtpSender.GenerateNewSSRC(); - if(newSSRC == 0) - { + if (newSSRC == 0) { // configured via API ignore return; } - if(kRtcpOff != _rtcpSender.Status()) - { + if (kRtcpOff != _rtcpSender.Status()) { // send RTCP bye on the current SSRC _rtcpSender.SendRTCP(kRtcpBye); } @@ -2086,86 +2335,78 @@ ModuleRtpRtcpImpl::SetRemoteSSRC(const WebRtc_UWord32 SSRC) } } -WebRtc_UWord32 -ModuleRtpRtcpImpl::BitrateReceivedNow() const -{ +WebRtc_UWord32 ModuleRtpRtcpImpl::BitrateReceivedNow() const { return _rtpReceiver.BitrateNow(); } -WebRtc_UWord32 -ModuleRtpRtcpImpl::BitrateSent() const -{ - const bool defaultInstance(_childModules.Empty()?false:true); +WebRtc_UWord32 ModuleRtpRtcpImpl::BitrateSent() const { + const bool defaultInstance(_childModules.empty() ? false : true); - if(defaultInstance) - { + if (defaultInstance) { // for default we need to update the send bitrate CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); - ListItem* item = _childModules.First(); WebRtc_UWord32 bitrate = 0; - while (item) - { - RtpRtcp* module = (RtpRtcp*)item->GetItem(); - if(module) - { - bitrate = (module->BitrateSent() > bitrate) ?module->BitrateSent():bitrate; + std::list::const_iterator it = + _childModules.begin(); + while (it != _childModules.end()) { + RtpRtcp* module = *it; + if (module) { + bitrate = std::max(module->BitrateSent(), bitrate); } - item = _childModules.Next(item); + it++; } return bitrate; - } else - { - return _rtpSender.BitrateLast(); } + return _rtpSender.BitrateLast(); } // for lip sync -void -ModuleRtpRtcpImpl::OnReceivedNTP() -{ +void ModuleRtpRtcpImpl::OnReceivedNTP() { // don't do anything if we are the audio module // video module is responsible for sync - - if(!_audio) - { + if (!_audio) { WebRtc_Word32 diff = 0; WebRtc_UWord32 receivedNTPsecs = 0; WebRtc_UWord32 receivedNTPfrac= 0; WebRtc_UWord32 RTCPArrivalTimeSecs= 0; WebRtc_UWord32 RTCPArrivalTimeFrac= 0; - if(0 == _rtcpReceiver.NTP(&receivedNTPsecs, &receivedNTPfrac, &RTCPArrivalTimeSecs, &RTCPArrivalTimeFrac)) - { + if (0 == _rtcpReceiver.NTP(&receivedNTPsecs, + &receivedNTPfrac, + &RTCPArrivalTimeSecs, + &RTCPArrivalTimeFrac)) { CriticalSectionScoped lock(_criticalSectionModulePtrs); - if(_audioModule) - { - if(0 != _audioModule->RemoteNTP(&_receivedNTPsecsAudio, - &_receivedNTPfracAudio, - &_RTCPArrivalTimeSecsAudio, - &_RTCPArrivalTimeFracAudio)) - { + if (_audioModule) { + if (0 != _audioModule->RemoteNTP(&_receivedNTPsecsAudio, + &_receivedNTPfracAudio, + &_RTCPArrivalTimeSecsAudio, + &_RTCPArrivalTimeFracAudio)) { // failed ot get audio NTP return; } } - if(_receivedNTPfracAudio != 0) - { + if (_receivedNTPfracAudio != 0) { // ReceivedNTPxxx is NTP at sender side when sent. // RTCPArrivalTimexxx is NTP at receiver side when received. - // can't use ConvertNTPTimeToMS since calculation can be negative + // can't use ConvertNTPTimeToMS since calculation can be + // negative - WebRtc_Word32 NTPdiff = (WebRtc_Word32)((_receivedNTPsecsAudio - receivedNTPsecs)*1000); // ms - NTPdiff += (WebRtc_Word32)(_receivedNTPfracAudio/FracMS - receivedNTPfrac/FracMS); // ms + WebRtc_Word32 NTPdiff = (WebRtc_Word32) + ((_receivedNTPsecsAudio - receivedNTPsecs)*1000); // ms + NTPdiff += (WebRtc_Word32) + (_receivedNTPfracAudio/FracMS - receivedNTPfrac/FracMS); - WebRtc_Word32 RTCPdiff = (WebRtc_Word32)((_RTCPArrivalTimeSecsAudio - RTCPArrivalTimeSecs)*1000); // ms - RTCPdiff += (WebRtc_Word32)((_RTCPArrivalTimeFracAudio/FracMS - RTCPArrivalTimeFrac/FracMS)); // ms + WebRtc_Word32 RTCPdiff = (WebRtc_Word32) + ((_RTCPArrivalTimeSecsAudio - RTCPArrivalTimeSecs)*1000); + RTCPdiff += (WebRtc_Word32) + (_RTCPArrivalTimeFracAudio/FracMS - + RTCPArrivalTimeFrac/FracMS); diff = NTPdiff - RTCPdiff; // if diff is + video is behind - if(diff < -1000 || diff > 1000) - { + if (diff < -1000 || diff > 1000) { // unresonable ignore value. diff = 0; return; @@ -2179,21 +2420,18 @@ ModuleRtpRtcpImpl::OnReceivedNTP() } // our local BW estimate is updated -void -ModuleRtpRtcpImpl::OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit) -{ +void ModuleRtpRtcpImpl::OnBandwidthEstimateUpdate( + WebRtc_UWord16 bandWidthKbit) { + WebRtc_UWord32 maxBitrateKbit = _rtpReceiver.MaxConfiguredBitrate()/1000; - if(maxBitrateKbit) - { + if (maxBitrateKbit) { // the app has set a max bitrate - if(maxBitrateKbit < bandWidthKbit) - { + if (maxBitrateKbit < bandWidthKbit) { // cap TMMBR at max configured bitrate bandWidthKbit = (WebRtc_UWord16)maxBitrateKbit; } } - if(_rtcpSender.TMMBR()) - { + if (_rtcpSender.TMMBR()) { /* Maximum total media bit rate: The upper limit on total media bit rate for a given media stream at a particular receiver and for its selected protocol @@ -2223,16 +2461,16 @@ ModuleRtpRtcpImpl::OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit) } } -RateControlRegion -ModuleRtpRtcpImpl::OnOverUseStateUpdate(const RateControlInput& rateControlInput) -{ +RateControlRegion ModuleRtpRtcpImpl::OnOverUseStateUpdate( + const RateControlInput& rateControlInput) { + bool firstOverUse = false; - const RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput, firstOverUse); - if (firstOverUse && _rtcpSender.Status() == kRtcpNonCompound) - { + RateControlRegion region = _rtcpSender.UpdateOverUseState(rateControlInput, + firstOverUse); + if (firstOverUse && _rtcpSender.Status() == kRtcpNonCompound) { // Send TMMBR immediately WebRtc_UWord16 RTT = 0; - _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL,NULL,NULL); + _rtcpReceiver.RTT(_rtpReceiver.SSRC(), &RTT, NULL, NULL, NULL); // About to send TMMBR, first run remote rate control // to get a target bit rate. _rtcpSender.CalculateNewTargetBitrate(RTT); @@ -2242,37 +2480,103 @@ ModuleRtpRtcpImpl::OnOverUseStateUpdate(const RateControlInput& rateControlInput } // bad state of RTP receiver request a keyframe -void -ModuleRtpRtcpImpl::OnRequestIntraFrame(const FrameType frameType) -{ +void ModuleRtpRtcpImpl::OnRequestIntraFrame(const FrameType frameType) { RequestKeyFrame(frameType); } -void -ModuleRtpRtcpImpl::OnReceivedIntraFrameRequest(const WebRtc_UWord8 message) -{ - if(_defaultModule) - { +void ModuleRtpRtcpImpl::OnReceivedIntraFrameRequest(const RtpRtcp* caller) { + if (_defaultModule) { CriticalSectionScoped lock(_criticalSectionModulePtrs); - if(_defaultModule) - { + if (_defaultModule) { // if we use a default module pass this info to the default module - _defaultModule->OnReceivedIntraFrameRequest(message); + _defaultModule->OnReceivedIntraFrameRequest(caller); return; } } - _rtcpReceiver.OnReceivedIntraFrameRequest(message); + + WebRtc_UWord8 streamIdx = 0; + FrameType frameType = kVideoFrameKey; + if (_simulcast) { + CriticalSectionScoped lock(_criticalSectionModulePtrs); + // loop though child modules and count idx + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + ModuleRtpRtcpImpl* childModule = *it; + if (childModule == caller) { + break; + } + streamIdx++; + it++; + } + } + _rtcpReceiver.OnReceivedIntraFrameRequest(frameType, streamIdx); +} + +void ModuleRtpRtcpImpl::OnReceivedEstimatedMaxBitrate( + const WebRtc_UWord32 maxBitrate) { + + // We received a REMB + if (_defaultModule) { + CriticalSectionScoped lock(_criticalSectionModulePtrs); + if (_defaultModule) { + // if we use a default module pass this info to the default module + _defaultModule->OnReceivedEstimatedMaxBitrate(maxBitrate); + return; + } + } + WebRtc_UWord32 newBitrate = 0; + WebRtc_UWord8 fractionLost = 0; + WebRtc_UWord16 roundTripTime = 0; + WebRtc_UWord16 bwEstimateKbit = WebRtc_UWord16(maxBitrate / 1000); + if (_bandwidthManagement.UpdateBandwidthEstimate(bwEstimateKbit, + &newBitrate, + &fractionLost, + &roundTripTime) == 0) { + // might trigger a OnNetworkChanged in video callback + _rtpReceiver.UpdateBandwidthManagement(newBitrate, + fractionLost, + roundTripTime); + if (newBitrate <= 0) { + return; + } + const bool defaultInstance = !_childModules.empty(); + if (!defaultInstance) { + return; + } + CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); + std::list::iterator it = _childModules.begin(); + WebRtc_UWord8 idx = 0; + while (it != _childModules.end()) { + // sanity + if (idx >= (_sendVideoCodec.numberOfSimulcastStreams - 1)) { + return; + } + ModuleRtpRtcpImpl* module = *it; + // update all child modules + if (newBitrate >= _sendVideoCodec.simulcastStream[idx].maxBitrate) { + module->_bandwidthManagement.SetSendBitrate( + _sendVideoCodec.simulcastStream[idx].maxBitrate, 0, 0); + module->_rtpSender.SetTargetSendBitrate( + _sendVideoCodec.simulcastStream[idx].maxBitrate); + + newBitrate -= _sendVideoCodec.simulcastStream[idx].maxBitrate; + } else { + module->_bandwidthManagement.SetSendBitrate(newBitrate, 0, 0); + module->_rtpSender.SetTargetSendBitrate(newBitrate); + newBitrate -= newBitrate; + } + idx++; + } + } } // received a request for a new SLI -void -ModuleRtpRtcpImpl::OnReceivedSliceLossIndication(const WebRtc_UWord8 pictureID) -{ - if(_defaultModule) - { +void ModuleRtpRtcpImpl::OnReceivedSliceLossIndication( + const WebRtc_UWord8 pictureID) { + + if (_defaultModule) { CriticalSectionScoped lock(_criticalSectionModulePtrs); - if(_defaultModule) - { + if (_defaultModule) { // if we use a default module pass this info to the default module _defaultModule->OnReceivedSliceLossIndication(pictureID); return; @@ -2282,51 +2586,48 @@ ModuleRtpRtcpImpl::OnReceivedSliceLossIndication(const WebRtc_UWord8 pictureID) } // received a new refereence frame -void -ModuleRtpRtcpImpl::OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pictureID) -{ - if(_defaultModule) - { +void ModuleRtpRtcpImpl::OnReceivedReferencePictureSelectionIndication( + const WebRtc_UWord64 pictureID) { + + if (_defaultModule) { CriticalSectionScoped lock(_criticalSectionModulePtrs); - if(_defaultModule) - { + if (_defaultModule) { // if we use a default module pass this info to the default module - _defaultModule->OnReceivedReferencePictureSelectionIndication(pictureID); + _defaultModule->OnReceivedReferencePictureSelectionIndication( + pictureID); return; } } _rtcpReceiver.OnReceivedReferencePictureSelectionIndication(pictureID); } -void -ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(const WebRtc_UWord16 bwEstimateMinKbit, - const WebRtc_UWord16 bwEstimateMaxKbit) -{ - if(_defaultModule) - { +void ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate( + const WebRtc_UWord16 bwEstimateKbit) { + // We received a TMMBR + if (_defaultModule) { CriticalSectionScoped lock(_criticalSectionModulePtrs); - if(_defaultModule) - { + if (_defaultModule) { // if we use a default module pass this info to the default module - _defaultModule->OnReceivedBandwidthEstimateUpdate(bwEstimateMinKbit, bwEstimateMaxKbit); + _defaultModule->OnReceivedBandwidthEstimateUpdate(bwEstimateKbit); return; } } - if(_audio) - { - _rtcpReceiver.UpdateBandwidthEstimate(bwEstimateMinKbit); - }else - { + if (_audio) { + _rtcpReceiver.UpdateBandwidthEstimate(bwEstimateKbit); + } else { WebRtc_UWord32 newBitrate = 0; WebRtc_UWord8 fractionLost = 0; WebRtc_UWord16 roundTripTime = 0; - if(_bandwidthManagement.UpdateBandwidthEstimate(bwEstimateMinKbit, bwEstimateMaxKbit, newBitrate, fractionLost,roundTripTime) == 0) - { + if (_bandwidthManagement.UpdateBandwidthEstimate(bwEstimateKbit, + &newBitrate, + &fractionLost, + &roundTripTime) == 0) { // video callback - _rtpReceiver.UpdateBandwidthManagement(newBitrate, newBitrate, fractionLost, roundTripTime, bwEstimateMinKbit, bwEstimateMaxKbit); - const bool defaultInstance = !_childModules.Empty(); - if((newBitrate > 0) && !defaultInstance) - { + _rtpReceiver.UpdateBandwidthManagement(newBitrate, + fractionLost, + roundTripTime); + const bool defaultInstance = !_childModules.empty(); + if ((newBitrate > 0) && !defaultInstance) { // update bitrate _rtpSender.SetTargetSendBitrate(newBitrate); } @@ -2335,154 +2636,178 @@ ModuleRtpRtcpImpl::OnReceivedBandwidthEstimateUpdate(const WebRtc_UWord16 bwEsti } // bw estimation -void -ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate(const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTime, - const WebRtc_UWord32 lastReceivedExtendedHighSeqNum, - const WebRtc_UWord32 jitter) -{ - WebRtc_UWord32 newBitrate = 0; - WebRtc_UWord8 filteredFractionLost = fractionLost; - WebRtc_UWord16 filteredRoundTripTime = roundTripTime; - WebRtc_UWord16 bwEstimateKbitMin = 0; - WebRtc_UWord16 bwEstimateKbitMax = 0; +// We received a RTCP report block +void ModuleRtpRtcpImpl::OnPacketLossStatisticsUpdate( + const WebRtc_UWord8 fractionLost, + const WebRtc_UWord16 roundTripTime, + const WebRtc_UWord32 lastReceivedExtendedHighSeqNum) { - const bool defaultInstance(_childModules.Empty()?false:true); - { - if(_bandwidthManagement.UpdatePacketLoss(lastReceivedExtendedHighSeqNum, - defaultInstance, - fractionLost, - roundTripTime, - newBitrate, - bwEstimateKbitMin, - bwEstimateKbitMax) != 0) - { + const bool defaultInstance(_childModules.empty() ? false : true); + if (!defaultInstance) { + WebRtc_UWord32 newBitrate = 0; + WebRtc_UWord8 loss = fractionLost; // local copy since it can change + if (_bandwidthManagement.UpdatePacketLoss( + lastReceivedExtendedHighSeqNum, + roundTripTime, + &loss, + &newBitrate) != 0) { // ignore this update - newBitrate = 0; + return; } - } - if(newBitrate != 0 && - !defaultInstance) - { // We need to do update RTP sender before calling default module in // case we'll strip any layers. - _rtpSender.SetTargetSendBitrate(newBitrate); - - if(_defaultModule) - { + if (!_simulcast) { + // the default module will inform all child modules about + // their bitrate + _rtpSender.SetTargetSendBitrate(newBitrate); + } + if (_defaultModule) { // if we have a default module update it CriticalSectionScoped lock(_criticalSectionModulePtrs); - if(_defaultModule) // we need to check again inside the critsect - { - // if we use a default module pass this info to the default module - _defaultModule->OnPacketLossStatisticsUpdate(filteredFractionLost, - filteredRoundTripTime, - lastReceivedExtendedHighSeqNum, - jitter); + if (_defaultModule) { // we need to check again inside the critsect + // if we use a default module pass this info to the + // default module + _defaultModule->OnPacketLossStatisticsUpdate( + loss, // send in the filtered loss + roundTripTime, + lastReceivedExtendedHighSeqNum); } return; } - // video callback - _rtpReceiver.UpdateBandwidthManagement(newBitrate, newBitrate, filteredFractionLost, filteredRoundTripTime, bwEstimateKbitMin, bwEstimateKbitMax); - } - else if (defaultInstance) - { - // Check if it's time to update bitrate - WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS(); - if((now - _lastChildBitrateUpdate) > (3*RTCP_INTERVAL_VIDEO_MS/2)) - { + // No default module check if we should trigger OnNetworkChanged + // via video callback + _rtpReceiver.UpdateBandwidthManagement(newBitrate, + fractionLost, + roundTripTime); + } else { + if (!_simulcast) { WebRtc_UWord32 minBitrateBps = 0xffffffff; WebRtc_UWord32 maxBitrateBps = 0; { - // Time to update bitrate estimate, // get min and max for the sending channels CriticalSectionScoped lock(_criticalSectionModulePtrs); - ListItem* item = _childModules.First(); - while(item) - { + std::list::iterator it = + _childModules.begin(); + while (it != _childModules.end()) { // Get child RTP sender and ask for bitrate estimate - ModuleRtpRtcpImpl* childModule = - static_cast(item->GetItem()); - if (childModule->Sending()) - { - RTPSender& childRtpSender = - static_cast(item->GetItem())->_rtpSender; - WebRtc_UWord32 childEstimateBps = 1000*childRtpSender.TargetSendBitrateKbit(); - if (childEstimateBps < minBitrateBps) - { + ModuleRtpRtcpImpl* childModule = *it; + if (childModule->Sending()) { + RTPSender& childRtpSender = (*it)->_rtpSender; + const WebRtc_UWord32 childEstimateBps = + 1000 * childRtpSender.TargetSendBitrateKbit(); + if (childEstimateBps < minBitrateBps) { minBitrateBps = childEstimateBps; } - if (childEstimateBps > maxBitrateBps) - { + if (childEstimateBps > maxBitrateBps) { maxBitrateBps = childEstimateBps; } } - item = _childModules.Next(item); + it++; } + } // end critsect + _bandwidthManagement.SetSendBitrate(minBitrateBps, 0, 0); + // Update default module bitrate. Don't care about min max. + // Check if we should trigger OnNetworkChanged via video callback + // TODO(pwestin) for this to work better fractionLost shoudl be the + // weighted average loss from all childs + _rtpReceiver.UpdateBandwidthManagement(minBitrateBps, + fractionLost, + roundTripTime); + } else { + // default and simulcast + WebRtc_UWord32 newBitrate = 0; + WebRtc_UWord8 loss = fractionLost; // local copy + if (_bandwidthManagement.UpdatePacketLoss(0, // we can't use this + roundTripTime, + &loss, + &newBitrate) != 0) { + // ignore this update + return; } - // Limit the bitrate with TMMBR. - if(bwEstimateKbitMin && bwEstimateKbitMin 0) - { - // video callback - _rtpReceiver.UpdateBandwidthManagement(minBitrateBps, maxBitrateBps, filteredFractionLost, filteredRoundTripTime, bwEstimateKbitMin, bwEstimateKbitMax); - } - _lastChildBitrateUpdate = now; - } + CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); + std::list::iterator it = _childModules.begin(); + WebRtc_UWord8 idx = 0; + while (it != _childModules.end()) { + // sanity + if (idx >= (_sendVideoCodec.numberOfSimulcastStreams - 1)) { + return; + } + ModuleRtpRtcpImpl* module = *it; + // update all child modules + if (newBitrate >= + _sendVideoCodec.simulcastStream[idx].maxBitrate) { + module->_bandwidthManagement.SetSendBitrate( + _sendVideoCodec.simulcastStream[idx].maxBitrate, 0, 0); + module->_rtpSender.SetTargetSendBitrate( + _sendVideoCodec.simulcastStream[idx].maxBitrate); + newBitrate -= + _sendVideoCodec.simulcastStream[idx].maxBitrate; + } else { + module->_bandwidthManagement.SetSendBitrate(newBitrate, + 0, + 0); + module->_rtpSender.SetTargetSendBitrate(newBitrate); + newBitrate -= newBitrate; + } + idx++; + } + } } } -void -ModuleRtpRtcpImpl::OnRequestSendReport() -{ +void ModuleRtpRtcpImpl::OnRequestSendReport() { _rtcpSender.SendRTCP(kRtcpSr); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection(const WebRtc_UWord64 pictureID) -{ - return _rtcpSender.SendRTCP(kRtcpRpsi, 0,0,0, pictureID); +WebRtc_Word32 ModuleRtpRtcpImpl::SendRTCPReferencePictureSelection( + const WebRtc_UWord64 pictureID) { + return _rtcpSender.SendRTCP(kRtcpRpsi, 0, 0, 0, pictureID); } -WebRtc_UWord32 -ModuleRtpRtcpImpl::SendTimeOfSendReport(const WebRtc_UWord32 sendReport) -{ +WebRtc_UWord32 ModuleRtpRtcpImpl::SendTimeOfSendReport( + const WebRtc_UWord32 sendReport) { return _rtcpSender.SendTimeOfSendReport(sendReport); } -void -ModuleRtpRtcpImpl::OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength, - const WebRtc_UWord16* nackSequenceNumbers) -{ - if(!_rtpSender.StorePackets() || nackSequenceNumbers == NULL || nackSequenceNumbersLength == 0) - { +void ModuleRtpRtcpImpl::OnReceivedNACK( + const WebRtc_UWord16 nackSequenceNumbersLength, + const WebRtc_UWord16* nackSequenceNumbers) { + if (!_rtpSender.StorePackets() || + nackSequenceNumbers == NULL || + nackSequenceNumbersLength == 0) { return; } WebRtc_UWord16 avgRTT = 0; - _rtcpReceiver.RTT(_rtpReceiver.SSRC(), NULL, &avgRTT ,NULL,NULL); - _rtpSender.OnReceivedNACK(nackSequenceNumbersLength, nackSequenceNumbers, avgRTT); + _rtcpReceiver.RTT(_rtpReceiver.SSRC(), NULL, &avgRTT, NULL, NULL); + _rtpSender.OnReceivedNACK(nackSequenceNumbersLength, + nackSequenceNumbers, + avgRTT); } -WebRtc_Word32 -ModuleRtpRtcpImpl::LastReceivedNTP(WebRtc_UWord32& RTCPArrivalTimeSecs, // when we received the last report - WebRtc_UWord32& RTCPArrivalTimeFrac, - WebRtc_UWord32& remoteSR) // NTP inside the last received (mid 16 bits from sec and frac) -{ +WebRtc_Word32 ModuleRtpRtcpImpl::LastReceivedNTP( + WebRtc_UWord32& RTCPArrivalTimeSecs, // when we received the last report + WebRtc_UWord32& RTCPArrivalTimeFrac, + WebRtc_UWord32& remoteSR) { + // remote SR: NTP inside the last received (mid 16 bits from sec and frac) WebRtc_UWord32 NTPsecs = 0; WebRtc_UWord32 NTPfrac = 0; - if(-1 == _rtcpReceiver.NTP(&NTPsecs, &NTPfrac, &RTCPArrivalTimeSecs, &RTCPArrivalTimeFrac)) - { + if (-1 == _rtcpReceiver.NTP(&NTPsecs, + &NTPfrac, + &RTCPArrivalTimeSecs, + &RTCPArrivalTimeFrac)) { return -1; } remoteSR = ((NTPsecs & 0x0000ffff) << 16) + ((NTPfrac & 0xffff0000) >> 16); @@ -2490,36 +2815,29 @@ ModuleRtpRtcpImpl::LastReceivedNTP(WebRtc_UWord32& RTCPArrivalTimeSecs, // when } void -ModuleRtpRtcpImpl::OnReceivedTMMBR() -{ +ModuleRtpRtcpImpl::OnReceivedTMMBR() { // we received a TMMBR in a RTCP packet // answer with a TMMBN UpdateTMMBR(); } -bool -ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() -{ +bool ModuleRtpRtcpImpl::UpdateRTCPReceiveInformationTimers() { // if this returns true this channel has timed out // periodically check if this is true and if so call UpdateTMMBR return _rtcpReceiver.UpdateRTCPReceiveInformationTimers(); } -WebRtc_Word32 -ModuleRtpRtcpImpl::UpdateTMMBR() -{ +WebRtc_Word32 ModuleRtpRtcpImpl::UpdateTMMBR() { WebRtc_Word32 numBoundingSet = 0; WebRtc_Word32 newBitrates = 0; WebRtc_UWord32 minBitrateKbit = 0; WebRtc_UWord32 maxBitrateKbit = 0; - if(_defaultModule) - { + if (_defaultModule) { CriticalSectionScoped lock(_criticalSectionModulePtrs); // no callbacks allowed inside here - if(_defaultModule) - { + if (_defaultModule) { // let the default module do the update return _defaultModule->UpdateTMMBR(); } @@ -2528,94 +2846,86 @@ ModuleRtpRtcpImpl::UpdateTMMBR() WebRtc_UWord32 accNumCandidates = 0; // Find candidate set - if(!_childModules.Empty()) - { + if (!_childModules.empty()) { CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); // this module is the default module // loop over all modules using the default codec WebRtc_UWord32 size = 0; - ListItem* item = _childModules.First(); - while(item) - { - ModuleRtpRtcpImpl* module = (ModuleRtpRtcpImpl*)item->GetItem(); - WebRtc_Word32 tmpSize = module->TMMBRReceived(0,0, NULL); - if(tmpSize > 0) - { + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + ModuleRtpRtcpImpl* module = *it; + WebRtc_Word32 tmpSize = module->TMMBRReceived(0, 0, NULL); + if (tmpSize > 0) { size += tmpSize; } - item = _childModules.Next(item); + it++; } TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size); - if(candidateSet == NULL) - { + if (candidateSet == NULL) { return -1; } - item = _childModules.First(); - while(item) - { - ModuleRtpRtcpImpl* module = (ModuleRtpRtcpImpl*)item->GetItem(); - if(size > accNumCandidates && module) - { - WebRtc_Word32 accSize = module->TMMBRReceived(size, accNumCandidates, candidateSet); - if (accSize > 0) - { + it = _childModules.begin(); + while (it != _childModules.end()) { + ModuleRtpRtcpImpl* module = *it; + if (size > accNumCandidates && module) { + WebRtc_Word32 accSize = module->TMMBRReceived(size, + accNumCandidates, + candidateSet); + if (accSize > 0) { accNumCandidates = accSize; } } - item = _childModules.Next(item); + it++; } - } else - { - // this module don't use the default module and is not the default module - WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0,0,NULL); - if(size > 0) - { + } else { + // this module don't use the default module and is not the + // default module + WebRtc_Word32 size = _rtcpReceiver.TMMBRReceived(0, 0, NULL); + if (size > 0) { TMMBRSet* candidateSet = VerifyAndAllocateCandidateSet(size); // get candidate set from receiver - accNumCandidates = _rtcpReceiver.TMMBRReceived(size, accNumCandidates, candidateSet); - } - else - { + accNumCandidates = _rtcpReceiver.TMMBRReceived(size, + accNumCandidates, + candidateSet); + } else { // candidate set empty - VerifyAndAllocateCandidateSet(0); // resets candidate set + VerifyAndAllocateCandidateSet(0); // resets candidate set } } - // Find bounding set TMMBRSet* boundingSet = NULL; numBoundingSet = FindTMMBRBoundingSet(boundingSet); - if(numBoundingSet == -1) - { - WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "Failed to find TMMBR bounding set."); + if (numBoundingSet == -1) { + WEBRTC_TRACE(kTraceWarning, + kTraceRtpRtcp, + _id, + "Failed to find TMMBR bounding set."); return -1; } // Set bounding set // Inform remote clients about the new bandwidth - if(_childModules.Empty()) - { + if (_childModules.empty()) { // inform the remote client - _rtcpSender.SetTMMBN(boundingSet, _rtpSender.MaxConfiguredBitrateVideo()/1000); // might trigger a TMMBN - } else - { + _rtcpSender.SetTMMBN(boundingSet, + _rtpSender.MaxConfiguredBitrateVideo()/1000); + // might trigger a TMMBN + } else { // inform child modules using the default codec CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); - ListItem* item = _childModules.First(); - while(item) - { - ModuleRtpRtcpImpl* module = (ModuleRtpRtcpImpl*)item->GetItem(); - if( module) - { - module->SetTMMBN(boundingSet, _rtpSender.MaxConfiguredBitrateVideo()/1000); + std::list::iterator it = _childModules.begin(); + while (it != _childModules.end()) { + ModuleRtpRtcpImpl* module = *it; + if (module) { + module->SetTMMBN(boundingSet, + _rtpSender.MaxConfiguredBitrateVideo()/1000); } - item = _childModules.Next(item); + it++; } } - - if(numBoundingSet == 0) - { + if (numBoundingSet == 0) { // owner of max bitrate request has timed out // empty bounding set has been sent return 0; @@ -2628,37 +2938,38 @@ ModuleRtpRtcpImpl::UpdateTMMBR() maxBitrateKbit); // no critsect when calling out to "unknown" code - if(newBitrates == 0) // we have new bitrates - { + if (newBitrates == 0) { + // we have new bitrate // Set new max bitrate // we have a new bandwidth estimate on this channel - OnReceivedBandwidthEstimateUpdate((WebRtc_UWord16)minBitrateKbit, (WebRtc_UWord16)maxBitrateKbit); - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "Set TMMBR request min:%d kbps max:%d kbps, channel: %d", minBitrateKbit, maxBitrateKbit, _id); + OnReceivedBandwidthEstimateUpdate((WebRtc_UWord16)minBitrateKbit); + WEBRTC_TRACE(kTraceStream, + kTraceRtpRtcp, + _id, + "Set TMMBR request min:%d kbps max:%d kbps, channel: %d", + minBitrateKbit, maxBitrateKbit, _id); } return 0; } // called from RTCPsender -WebRtc_Word32 -ModuleRtpRtcpImpl::BoundingSet(bool &tmmbrOwner, - TMMBRSet*& boundingSet) -{ +WebRtc_Word32 ModuleRtpRtcpImpl::BoundingSet(bool &tmmbrOwner, + TMMBRSet*& boundingSet) { return _rtcpReceiver.BoundingSet(tmmbrOwner, boundingSet); } -WebRtc_Word32 -ModuleRtpRtcpImpl::SetH263InverseLogic(const bool enable) -{ - WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "SetH263InverseLogic(%s)", enable ? "true":"false"); +WebRtc_Word32 ModuleRtpRtcpImpl::SetH263InverseLogic(const bool enable) { + WEBRTC_TRACE(kTraceModuleCall, + kTraceRtpRtcp, + _id, + "SetH263InverseLogic(%s)", + enable ? "true":"false"); return _rtpReceiver.SetH263InverseLogic(enable); } -void -ModuleRtpRtcpImpl::SendKeyFrame() -{ +void ModuleRtpRtcpImpl::SendKeyFrame() { WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "SendKeyFrame()"); OnReceivedIntraFrameRequest(0); - return; } -} // namespace webrtc +} // namespace webrtc diff --git a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 09fb3f44bc..bfb1ed486e 100644 --- a/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/src/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -11,15 +11,14 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_IMPL_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_IMPL_H_ -#include "rtp_rtcp.h" +#include -#include "rtp_sender.h" -#include "rtp_receiver.h" +#include "bandwidth_management.h" #include "rtcp_receiver.h" #include "rtcp_sender.h" -#include "bandwidth_management.h" - -#include "list_wrapper.h" +#include "rtp_receiver.h" +#include "rtp_rtcp.h" +#include "rtp_sender.h" #ifdef MATLAB class MatlabPlot; @@ -72,43 +71,30 @@ public: // configure a timeout value virtual WebRtc_Word32 SetPacketTimeout(const WebRtc_UWord32 RTPtimeoutMS, - const WebRtc_UWord32 RTCPtimeoutMS); + const WebRtc_UWord32 RTCPtimeoutMS); // Set periodic dead or alive notification - virtual WebRtc_Word32 SetPeriodicDeadOrAliveStatus(const bool enable, - const WebRtc_UWord8 sampleTimeSeconds); + virtual WebRtc_Word32 SetPeriodicDeadOrAliveStatus( + const bool enable, + const WebRtc_UWord8 sampleTimeSeconds); // Get periodic dead or alive notification status - virtual WebRtc_Word32 PeriodicDeadOrAliveStatus(bool &enable, - WebRtc_UWord8 &sampleTimeSeconds); + virtual WebRtc_Word32 PeriodicDeadOrAliveStatus( + bool &enable, + WebRtc_UWord8 &sampleTimeSeconds); - // set codec name and payload type - virtual WebRtc_Word32 RegisterReceivePayload( const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - const WebRtc_UWord32 rate); + virtual WebRtc_Word32 RegisterReceivePayload(const CodecInst& voiceCodec); - virtual WebRtc_Word32 DeRegisterReceivePayload(const WebRtc_Word8 payloadType); + virtual WebRtc_Word32 RegisterReceivePayload(const VideoCodec& videoCodec); - // get configured payload type - virtual WebRtc_Word32 ReceivePayloadType(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - WebRtc_Word8* payloadType, - const WebRtc_UWord32 rate = 0) const; + virtual WebRtc_Word32 ReceivePayloadType(const CodecInst& voiceCodec, + WebRtc_Word8* plType); - // get configured payload - virtual WebRtc_Word32 ReceivePayload(const WebRtc_Word8 payloadType, - WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels, - WebRtc_UWord32* rate = NULL) const; + virtual WebRtc_Word32 ReceivePayloadType(const VideoCodec& videoCodec, + WebRtc_Word8* plType); - virtual WebRtc_Word32 RemotePayload(WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], - WebRtc_Word8* payloadType, - WebRtc_UWord32* frequency, - WebRtc_UWord8* channels) const; + virtual WebRtc_Word32 DeRegisterReceivePayload( + const WebRtc_Word8 payloadType); // get the currently configured SSRC filter virtual WebRtc_Word32 SSRCFilter(WebRtc_UWord32& allowedSSRC) const; @@ -164,8 +150,12 @@ public: virtual bool RTPKeepalive() const; + virtual WebRtc_Word32 RegisterSendPayload(const CodecInst& voiceCodec); + + virtual WebRtc_Word32 RegisterSendPayload(const VideoCodec& videoCodec); + // set codec name and payload type - virtual WebRtc_Word32 RegisterSendPayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], + WebRtc_Word32 RegisterSendPayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE], const WebRtc_Word8 payloadType, const WebRtc_UWord32 frequency, const WebRtc_UWord8 channels, @@ -231,7 +221,7 @@ public: const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader* fragmentation = NULL, - const RTPVideoTypeHeader* rtpTypeHdr = NULL); + const RTPVideoHeader* rtpVideoHdr = NULL); /* * RTCP @@ -365,7 +355,7 @@ public: // Send a Negative acknowledgement packet virtual WebRtc_Word32 SendNACK(const WebRtc_UWord16* nackList, - const WebRtc_UWord16 size); + const WebRtc_UWord16 size); // Store the sent packets, needed to answer to a Negative acknowledgement requests virtual WebRtc_Word32 SetStorePacketsStatus(const bool enable, const WebRtc_UWord16 numberToStore = 200); @@ -477,57 +467,60 @@ public: virtual RateControlRegion OnOverUseStateUpdate(const RateControlInput& rateControlInput); - virtual void OnReceivedNTP() ; - - // bw estimation - virtual void OnPacketLossStatisticsUpdate(const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTime, - const WebRtc_UWord32 lastReceivedExtendedHighSeqNum, - const WebRtc_UWord32 jitter); - - virtual void OnReceivedTMMBR(); - - virtual void OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit); - - virtual void OnReceivedBandwidthEstimateUpdate(const WebRtc_UWord16 bwEstimateMinKbit, - const WebRtc_UWord16 bwEstimateMaxKbit); - - // bad state of RTP receiver request a keyframe - virtual void OnRequestIntraFrame(const FrameType frameType); - // good state of RTP receiver inform sender virtual WebRtc_Word32 SendRTCPReferencePictureSelection(const WebRtc_UWord64 pictureID); - virtual void OnReceivedIntraFrameRequest(const WebRtc_UWord8 message); + virtual void OnBandwidthEstimateUpdate(WebRtc_UWord16 bandWidthKbit); + + void OnReceivedNTP() ; + + // bw estimation + void OnPacketLossStatisticsUpdate( + const WebRtc_UWord8 fractionLost, + const WebRtc_UWord16 roundTripTime, + const WebRtc_UWord32 lastReceivedExtendedHighSeqNum); + + void OnReceivedTMMBR(); + + void OnReceivedEstimatedMaxBitrate(const WebRtc_UWord32 maxBitrate); + + void OnReceivedBandwidthEstimateUpdate(const WebRtc_UWord16 bwEstimateKbit); + + // bad state of RTP receiver request a keyframe + void OnRequestIntraFrame(const FrameType frameType); + + void OnReceivedIntraFrameRequest(const RtpRtcp* caller); // received a request for a new SLI - virtual void OnReceivedSliceLossIndication(const WebRtc_UWord8 pictureID); + void OnReceivedSliceLossIndication(const WebRtc_UWord8 pictureID); // received a new refereence frame - virtual void OnReceivedReferencePictureSelectionIndication(const WebRtc_UWord64 pitureID); + void OnReceivedReferencePictureSelectionIndication( + const WebRtc_UWord64 pitureID); - virtual void OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength, - const WebRtc_UWord16* nackSequenceNumbers); + void OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength, + const WebRtc_UWord16* nackSequenceNumbers); - virtual void OnRequestSendReport(); - // only for internal testing - WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime); + void OnRequestSendReport(); protected: - virtual void RegisterChildModule(RtpRtcp* module); + void RegisterChildModule(RtpRtcp* module); - virtual void DeRegisterChildModule(RtpRtcp* module); + void DeRegisterChildModule(RtpRtcp* module); bool UpdateRTCPReceiveInformationTimers(); void ProcessDeadOrAliveTimer(); - virtual WebRtc_UWord32 BitrateReceivedNow() const; + WebRtc_UWord32 BitrateReceivedNow() const; // Get remote SequenceNumber - virtual WebRtc_UWord16 RemoteSequenceNumber() const; + WebRtc_UWord16 RemoteSequenceNumber() const; - virtual WebRtc_Word32 UpdateTMMBR(); + WebRtc_Word32 UpdateTMMBR(); + + // only for internal testing + WebRtc_UWord32 LastSendReport(WebRtc_UWord32& lastRTCPTime); RTPSender _rtpSender; RTPReceiver _rtpReceiver; @@ -543,37 +536,37 @@ private: WebRtc_UWord32 _lastProcessTime; WebRtc_UWord16 _packetOverHead; - CriticalSectionWrapper& _criticalSectionModulePtrs; - CriticalSectionWrapper& _criticalSectionModulePtrsFeedback; - ModuleRtpRtcpImpl* _defaultModule; - ModuleRtpRtcpImpl* _audioModule; - ModuleRtpRtcpImpl* _videoModule; - ListWrapper _childModules; + CriticalSectionWrapper& _criticalSectionModulePtrs; + CriticalSectionWrapper& _criticalSectionModulePtrsFeedback; + ModuleRtpRtcpImpl* _defaultModule; + ModuleRtpRtcpImpl* _audioModule; + ModuleRtpRtcpImpl* _videoModule; + std::list _childModules; // Dead or alive - bool _deadOrAliveActive; - WebRtc_UWord32 _deadOrAliveTimeoutMS; - WebRtc_UWord32 _deadOrAliveLastTimer; + bool _deadOrAliveActive; + WebRtc_UWord32 _deadOrAliveTimeoutMS; + WebRtc_UWord32 _deadOrAliveLastTimer; // receive side - BandwidthManagement _bandwidthManagement; + BandwidthManagement _bandwidthManagement; - WebRtc_UWord32 _receivedNTPsecsAudio; - WebRtc_UWord32 _receivedNTPfracAudio; - WebRtc_UWord32 _RTCPArrivalTimeSecsAudio; - WebRtc_UWord32 _RTCPArrivalTimeFracAudio; + WebRtc_UWord32 _receivedNTPsecsAudio; + WebRtc_UWord32 _receivedNTPfracAudio; + WebRtc_UWord32 _RTCPArrivalTimeSecsAudio; + WebRtc_UWord32 _RTCPArrivalTimeFracAudio; // send side NACKMethod _nackMethod; - WebRtc_UWord32 _nackLastTimeSent; - WebRtc_UWord16 _nackLastSeqNumberSent; + WebRtc_UWord32 _nackLastTimeSent; + WebRtc_UWord16 _nackLastSeqNumberSent; + bool _simulcast; + VideoCodec _sendVideoCodec; KeyFrameRequestMethod _keyFrameReqMethod; - WebRtc_UWord32 _lastChildBitrateUpdate; - #ifdef MATLAB - MatlabPlot* _plot1; + MatlabPlot* _plot1; #endif }; } // namespace webrtc diff --git a/src/modules/utility/source/video_coder.cc b/src/modules/utility/source/video_coder.cc index 3cb54ab9bc..6edcebb4c0 100644 --- a/src/modules/utility/source/video_coder.cc +++ b/src/modules/utility/source/video_coder.cc @@ -149,7 +149,7 @@ WebRtc_Word32 VideoCoder::SendData( const WebRtc_UWord8* payloadData, WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* rtpTypeHdr) + const RTPVideoHeader* /*rtpVideoHdr*/) { // Store the data in _videoEncodedData which is a pointer to videoFrame in // Encode(..) diff --git a/src/modules/utility/source/video_coder.h b/src/modules/utility/source/video_coder.h index 2f3b769c12..2b061b3dc6 100644 --- a/src/modules/utility/source/video_coder.h +++ b/src/modules/utility/source/video_coder.h @@ -64,7 +64,7 @@ private: const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& /* fragmentationHeader*/, - const RTPVideoTypeHeader* rtpTypeHdr); + const RTPVideoHeader* rtpTypeHdr); WebRtc_UWord32 _instanceID; VideoCodingModule* _vcm; diff --git a/src/modules/video_coding/codecs/i420/main/interface/i420.h b/src/modules/video_coding/codecs/i420/main/interface/i420.h index 6474e5a0a4..d50b129baf 100644 --- a/src/modules/video_coding/codecs/i420/main/interface/i420.h +++ b/src/modules/video_coding/codecs/i420/main/interface/i420.h @@ -50,7 +50,7 @@ public: virtual WebRtc_Word32 Encode(const RawImage& inputImage, const CodecSpecificInfo* /*codecSpecificInfo*/, - VideoFrameType /*frameType*/); + const VideoFrameType* /*frameTypes*/); // Register an encode complete callback object. // diff --git a/src/modules/video_coding/codecs/i420/main/source/i420.cc b/src/modules/video_coding/codecs/i420/main/source/i420.cc index 2491e114c9..3c886cc410 100644 --- a/src/modules/video_coding/codecs/i420/main/source/i420.cc +++ b/src/modules/video_coding/codecs/i420/main/source/i420.cc @@ -119,7 +119,7 @@ I420Encoder::InitEncode(const VideoCodec* codecSettings, WebRtc_Word32 I420Encoder::Encode(const RawImage& inputImage, const CodecSpecificInfo* /*codecSpecificInfo*/, - VideoFrameType /*frameTypes*/) + const VideoFrameType* /*frameTypes*/) { if (!_inited) { diff --git a/src/modules/video_coding/codecs/interface/video_codec_interface.h b/src/modules/video_coding/codecs/interface/video_codec_interface.h index be4c392837..987cb61895 100644 --- a/src/modules/video_coding/codecs/interface/video_codec_interface.h +++ b/src/modules/video_coding/codecs/interface/video_codec_interface.h @@ -31,6 +31,8 @@ struct CodecSpecificInfoVP8 WebRtc_UWord64 pictureIdRPSI; WebRtc_Word16 pictureId; // negative value to skip pictureId bool nonReference; + WebRtc_UWord8 simulcastIdx; + WebRtc_UWord8 temporalIdx; }; union CodecSpecificInfoUnion @@ -106,8 +108,8 @@ public: // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. virtual WebRtc_Word32 Encode(const RawImage& inputImage, - const CodecSpecificInfo* codecSpecificInfo = NULL, - VideoFrameType frameType = kDeltaFrame) = 0; + const CodecSpecificInfo* codecSpecificInfo, + const VideoFrameType* frameTypes) = 0; // Register an encode complete callback object. // diff --git a/src/modules/video_coding/codecs/test_framework/normal_async_test.cc b/src/modules/video_coding/codecs/test_framework/normal_async_test.cc index 15b90a9119..854724965a 100644 --- a/src/modules/video_coding/codecs/test_framework/normal_async_test.cc +++ b/src/modules/video_coding/codecs/test_framework/normal_async_test.cc @@ -447,7 +447,7 @@ NormalAsyncTest::Encode() } webrtc::CodecSpecificInfo* codecSpecificInfo = CreateEncoderSpecificInfo(); - int ret = _encoder->Encode(rawImage, codecSpecificInfo, frameType); + int ret = _encoder->Encode(rawImage, codecSpecificInfo, &frameType); if (codecSpecificInfo != NULL) { delete codecSpecificInfo; diff --git a/src/modules/video_coding/codecs/test_framework/performance_test.cc b/src/modules/video_coding/codecs/test_framework/performance_test.cc index 720c965b2d..7603c35141 100644 --- a/src/modules/video_coding/codecs/test_framework/performance_test.cc +++ b/src/modules/video_coding/codecs/test_framework/performance_test.cc @@ -268,7 +268,7 @@ bool PerformanceTest::Encode() frameType = kKeyFrame; } webrtc::CodecSpecificInfo* codecSpecificInfo = CreateEncoderSpecificInfo(); - int ret = _encoder->Encode(rawImage, codecSpecificInfo, frameType); + int ret = _encoder->Encode(rawImage, codecSpecificInfo, &frameType); if (codecSpecificInfo != NULL) { delete codecSpecificInfo; diff --git a/src/modules/video_coding/codecs/test_framework/unit_test.cc b/src/modules/video_coding/codecs/test_framework/unit_test.cc index 33adce99ba..efe2380470 100644 --- a/src/modules/video_coding/codecs/test_framework/unit_test.cc +++ b/src/modules/video_coding/codecs/test_framework/unit_test.cc @@ -233,7 +233,8 @@ UnitTest::Setup() // Ensures our initial parameters are valid. VIDEO_TEST(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK); - _encoder->Encode(image, NULL); + VideoFrameType videoFrameType = kDeltaFrame; + _encoder->Encode(image, NULL, &videoFrameType); _refEncFrameLength = WaitForEncodedFrame(); VIDEO_TEST_EXIT_ON_ERR(_refEncFrameLength > 0); _refEncFrame = new unsigned char[_refEncFrameLength]; @@ -262,7 +263,7 @@ UnitTest::Setup() _inputVideoBuffer.SetWidth(_source->GetWidth()); _inputVideoBuffer.SetHeight(_source->GetHeight()); VideoBufferToRawImage(_inputVideoBuffer, image); - _encoder->Encode(image, NULL); + _encoder->Encode(image, NULL, &videoFrameType); VIDEO_TEST_EXIT_ON_ERR(WaitForEncodedFrame() > 0); } EncodedImage encodedImage; @@ -358,6 +359,7 @@ UnitTest::Perform() RawImage inputImage; EncodedImage encodedImage; EventWrapper& sleepEvent = *EventWrapper::Create(); + VideoFrameType videoFrameType = kDeltaFrame; //----- Encoder parameter tests ----- @@ -365,7 +367,7 @@ UnitTest::Perform() // We want to revert the initialization done in Setup(). VIDEO_TEST(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK); VideoBufferToRawImage(_inputVideoBuffer, inputImage); - VIDEO_TEST(_encoder->Encode(inputImage, NULL) + VIDEO_TEST(_encoder->Encode(inputImage, NULL, &videoFrameType ) == WEBRTC_VIDEO_CODEC_UNINITIALIZED); VIDEO_TEST(_encoder->Reset() == WEBRTC_VIDEO_CODEC_UNINITIALIZED); @@ -432,7 +434,7 @@ UnitTest::Perform() // inputVideoBuffer unallocated. _inputVideoBuffer.Free(); VideoBufferToRawImage(_inputVideoBuffer, inputImage); - VIDEO_TEST(_encoder->Encode(inputImage, NULL) == + VIDEO_TEST(_encoder->Encode(inputImage, NULL, &videoFrameType) == WEBRTC_VIDEO_CODEC_ERR_PARAMETER); _inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame); _inputVideoBuffer.CopyBuffer(_lengthSourceFrame, _refFrame); @@ -444,7 +446,7 @@ UnitTest::Perform() for (int i = 1; i <= 60; i++) { VideoFrameType frameType = !(i % 2) ? kKeyFrame : kDeltaFrame; - VIDEO_TEST(_encoder->Encode(inputImage, NULL, frameType) == + VIDEO_TEST(_encoder->Encode(inputImage, NULL, &frameType) == WEBRTC_VIDEO_CODEC_OK); VIDEO_TEST(WaitForEncodedFrame() > 0); sleepEvent.Wait(10); // Allow the encoder's queue to realize it's empty. @@ -453,11 +455,12 @@ UnitTest::Perform() // Init then encode. _encodedVideoBuffer.UpdateLength(0); _encodedVideoBuffer.Reset(); - VIDEO_TEST(_encoder->Encode(inputImage, NULL) == WEBRTC_VIDEO_CODEC_OK); + VIDEO_TEST(_encoder->Encode(inputImage, NULL, &videoFrameType) == + WEBRTC_VIDEO_CODEC_OK); VIDEO_TEST(WaitForEncodedFrame() > 0); VIDEO_TEST(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK); - _encoder->Encode(inputImage, NULL); + _encoder->Encode(inputImage, NULL, &videoFrameType); frameLength = WaitForEncodedFrame(); VIDEO_TEST(frameLength > 0); VIDEO_TEST(CheckIfBitExact(_refEncFrame, _refEncFrameLength, @@ -466,11 +469,12 @@ UnitTest::Perform() // Reset then encode. _encodedVideoBuffer.UpdateLength(0); _encodedVideoBuffer.Reset(); - VIDEO_TEST(_encoder->Encode(inputImage, NULL) == WEBRTC_VIDEO_CODEC_OK); + VIDEO_TEST(_encoder->Encode(inputImage, NULL, &videoFrameType) == + WEBRTC_VIDEO_CODEC_OK); WaitForEncodedFrame(); VIDEO_TEST(_encoder->Reset() == WEBRTC_VIDEO_CODEC_OK); VIDEO_TEST(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK); - _encoder->Encode(inputImage, NULL); + _encoder->Encode(inputImage, NULL, &videoFrameType); frameLength = WaitForEncodedFrame(); VIDEO_TEST(frameLength > 0); VIDEO_TEST(CheckIfBitExact(_refEncFrame, _refEncFrameLength, @@ -479,11 +483,12 @@ UnitTest::Perform() // Release then encode. _encodedVideoBuffer.UpdateLength(0); _encodedVideoBuffer.Reset(); - VIDEO_TEST(_encoder->Encode(inputImage, NULL) == WEBRTC_VIDEO_CODEC_OK); + VIDEO_TEST(_encoder->Encode(inputImage, NULL, &videoFrameType) == + WEBRTC_VIDEO_CODEC_OK); WaitForEncodedFrame(); VIDEO_TEST(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK); VIDEO_TEST(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK); - _encoder->Encode(inputImage, NULL); + _encoder->Encode(inputImage, NULL, &videoFrameType); frameLength = WaitForEncodedFrame(); VIDEO_TEST(frameLength > 0); VIDEO_TEST(CheckIfBitExact(_refEncFrame, _refEncFrameLength, @@ -605,7 +610,8 @@ UnitTest::Perform() WEBRTC_VIDEO_CODEC_OK); RawImage tempInput(inputImage._buffer, inputImage._length/4, inputImage._size/4); - _encoder->Encode(tempInput, NULL); + VideoFrameType videoFrameType = kDeltaFrame; + _encoder->Encode(tempInput, NULL, &videoFrameType); frameLength = WaitForEncodedFrame(); VIDEO_TEST(frameLength > 0); @@ -623,7 +629,7 @@ UnitTest::Perform() VIDEO_TEST(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK); VIDEO_TEST(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK); - _encoder->Encode(inputImage, NULL); + _encoder->Encode(inputImage, NULL, &videoFrameType); frameLength = WaitForEncodedFrame(); VIDEO_TEST(frameLength > 0); @@ -690,7 +696,10 @@ UnitTest::Perform() _inputVideoBuffer.CopyBuffer(_lengthSourceFrame, _sourceBuffer); _inputVideoBuffer.SetTimeStamp(frames); VideoBufferToRawImage(_inputVideoBuffer, inputImage); - VIDEO_TEST_EXIT_ON_ERR(_encoder->Encode(inputImage, NULL) == + VideoFrameType videoFrameType = kDeltaFrame; + VIDEO_TEST_EXIT_ON_ERR(_encoder->Encode(inputImage, + NULL, + &videoFrameType) == WEBRTC_VIDEO_CODEC_OK); frameLength = WaitForEncodedFrame(); //VIDEO_TEST_EXIT_ON_ERR(frameLength); @@ -774,8 +783,11 @@ UnitTest::RateControlTests() static_cast(9e4 / static_cast(_inst.maxFramerate))); VideoBufferToRawImage(_inputVideoBuffer, inputImage); - VIDEO_TEST_EXIT_ON_ERR(_encoder->Encode(inputImage, NULL) == - WEBRTC_VIDEO_CODEC_OK); + VideoFrameType videoFrameType = kDeltaFrame; + VIDEO_TEST_EXIT_ON_ERR(_encoder->Encode(inputImage, + NULL, + &videoFrameType) == + WEBRTC_VIDEO_CODEC_OK); frameLength = WaitForEncodedFrame(); VIDEO_TEST_EXIT_ON_ERR(frameLength > 0); //VIDEO_TEST(frameLength > 0); diff --git a/src/modules/video_coding/codecs/vp8/main/interface/vp8.h b/src/modules/video_coding/codecs/vp8/main/interface/vp8.h index 1a869931c0..d1086a9c0e 100644 --- a/src/modules/video_coding/codecs/vp8/main/interface/vp8.h +++ b/src/modules/video_coding/codecs/vp8/main/interface/vp8.h @@ -87,7 +87,7 @@ public: virtual WebRtc_Word32 Encode(const RawImage& inputImage, const CodecSpecificInfo* codecSpecificInfo, - VideoFrameType frameType); + const VideoFrameType* frameTypes); // Register an encode complete callback object. // @@ -163,6 +163,7 @@ private: bool _inited; WebRtc_UWord32 _timeStamp; WebRtc_UWord16 _pictureID; + WebRtc_UWord8 _simulcastIdx; bool _pictureLossIndicationOn; bool _feedbackModeOn; bool _nextRefIsGolden; diff --git a/src/modules/video_coding/codecs/vp8/main/interface/vp8_simulcast.h b/src/modules/video_coding/codecs/vp8/main/interface/vp8_simulcast.h new file mode 100644 index 0000000000..eacc170d4e --- /dev/null +++ b/src/modules/video_coding/codecs/vp8/main/interface/vp8_simulcast.h @@ -0,0 +1,144 @@ +/* + * 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. + */ + +/* + * vp8_simulcast.h + * WEBRTC VP8 simulcast wrapper interface + * Creates up to kMaxSimulcastStreams number of VP8 encoders + * Automatically scale the input frame to the right size for all VP8 encoders + * Runtime it divides the available bitrate beteween the VP8 Encoders + */ + + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_H_ + +#include "interpolator.h" +#include "video_codec_interface.h" +#include "vp8.h" + +namespace webrtc +{ +class VP8SimulcastEncoder : public VideoEncoder +{ +public: + VP8SimulcastEncoder(); + virtual ~VP8SimulcastEncoder(); + +// Free encoder memory. +// +// Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. + virtual WebRtc_Word32 Release(); + +// Reset encoder state and prepare for a new call. +// +// Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. +// <0 - Errors: +// WEBRTC_VIDEO_CODEC_ERR_PARAMETER +// WEBRTC_VIDEO_CODEC_ERROR + virtual WebRtc_Word32 Reset(); + +// Initialize the encoder with the information from the codecSettings +// +// Input: +// - codecSettings : Codec settings +// - numberOfCores : Number of cores available for the encoder +// - maxPayloadSize : The maximum size each payload is allowed +// to have. Usually MTU - overhead. +// +// Return value : Set bit rate if OK +// <0 - Errors: +// WEBRTC_VIDEO_CODEC_ERR_PARAMETER +// WEBRTC_VIDEO_CODEC_ERR_SIZE +// WEBRTC_VIDEO_CODEC_LEVEL_EXCEEDED +// WEBRTC_VIDEO_CODEC_MEMORY +// WEBRTC_VIDEO_CODEC_ERROR + virtual WebRtc_Word32 InitEncode(const VideoCodec* codecSettings, + WebRtc_Word32 numberOfCores, + WebRtc_UWord32 maxPayloadSize); + +// Encode an I420 image (as a part of a video stream). The encoded image +// will be returned to the user through the encode complete callback. +// It can encode multiple streams based on its configuration but not more than +// kMaxSimulcastStreams. +// +// Input: +// - inputImage : Image to be encoded +// - frameTypes : Frame type to be generated by the encoder +// pointer to first frame type in array the +// caller is responsible for the length of the +// array to be no shorter than number of encoders +// configured. +// +// Return value : WEBRTC_VIDEO_CODEC_OK if OK +// <0 - Errors: +// WEBRTC_VIDEO_CODEC_ERR_PARAMETER +// WEBRTC_VIDEO_CODEC_MEMORY +// WEBRTC_VIDEO_CODEC_ERROR +// WEBRTC_VIDEO_CODEC_TIMEOUT + virtual WebRtc_Word32 Encode(const RawImage& inputImage, + const CodecSpecificInfo* codecSpecificInfo, + const VideoFrameType* frameTypes); + +// Register an encode complete callback object. +// +// Input: +// - callback : Callback object which handles encoded images. +// +// Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. + virtual WebRtc_Word32 RegisterEncodeCompleteCallback( + EncodedImageCallback* callback); + +// Inform the encoder of the new packet loss rate in the network +// +// - packetLoss : Fraction lost +// (loss rate in percent = 100 * packetLoss / 255) +// Return value : WEBRTC_VIDEO_CODEC_OK if OK +// <0 - Errors: +// WEBRTC_VIDEO_CODEC_ERROR +// + virtual WebRtc_Word32 SetPacketLoss(WebRtc_UWord32 packetLoss); + +// Inform the encoder about the new target bit rate. +// +// - newBitRate : New target bit rate +// - frameRate : The target frame rate +// +// Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. + virtual WebRtc_Word32 SetRates(WebRtc_UWord32 newBitRateKbit, + WebRtc_UWord32 frameRate); + +// Get version number for the codec. +// +// Input: +// - version : Pointer to allocated char buffer. +// - buflen : Length of provided char buffer. +// +// Output: +// - version : Version number string written to char buffer. +// +// Return value : >0 - Length of written string. +// <0 - WEBRTC_VIDEO_CODEC_ERR_SIZE + virtual WebRtc_Word32 Version(WebRtc_Word8 *version, + WebRtc_Word32 length) const; + static WebRtc_Word32 VersionStatic(WebRtc_Word8 *version, + WebRtc_Word32 length); + +private: + VP8Encoder* encoder_[kMaxSimulcastStreams]; + bool encode_stream_[kMaxSimulcastStreams]; + VideoFrameType frame_type_[kMaxSimulcastStreams]; + interpolator* interpolator_[kMaxSimulcastStreams]; + RawImage video_frame_[kMaxSimulcastStreams]; + VideoCodec video_codec_; +};// end of VP8SimulcastEncoder class +} // namespace webrtc +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_H_ + diff --git a/src/modules/video_coding/codecs/vp8/main/source/vp8.cc b/src/modules/video_coding/codecs/vp8/main/source/vp8.cc index 4a645a3e2b..005515b41e 100644 --- a/src/modules/video_coding/codecs/vp8/main/source/vp8.cc +++ b/src/modules/video_coding/codecs/vp8/main/source/vp8.cc @@ -43,6 +43,7 @@ VP8Encoder::VP8Encoder(): _inited(false), _timeStamp(0), _pictureID(0), + _simulcastIdx(0), _pictureLossIndicationOn(false), _feedbackModeOn(false), _nextRefIsGolden(true), @@ -164,8 +165,20 @@ VP8Encoder::SetRates(WebRtc_UWord32 newBitRateKbit, WebRtc_UWord32 newFrameRate) { newBitRateKbit = _maxBitRateKbit; } - _cfg->rc_target_bitrate = newBitRateKbit; // in kbit/s + _cfg->rc_target_bitrate = newBitRateKbit; // in kbit/s +/* TODO(pwestin) use number of temoral layers config + int ids[3] = {0,1,2}; + _cfg->ts_number_layers = 3; + _cfg->ts_periodicity = 3; + _cfg->ts_target_bitrate[0] = (newBitRateKbit*2/5); + _cfg->ts_target_bitrate[1] = (newBitRateKbit*3/5); + _cfg->ts_target_bitrate[2] = (newBitRateKbit); + _cfg->ts_rate_decimator[0] = 4; + _cfg->ts_rate_decimator[1] = 2; + _cfg->ts_rate_decimator[2] = 1; + memcpy(_cfg->ts_layer_id, ids, sizeof(ids)); +*/ // update frame rate if (newFrameRate != _maxFrameRate) { @@ -267,6 +280,18 @@ VP8Encoder::InitEncode(const VideoCodec* inst, { _cfg->rc_target_bitrate = inst->startBitrate; // in kbit/s } +/* TODO(pwestin) use number of temoral layers config + int ids[3] = {0,1,2}; + _cfg->ts_number_layers = 3; + _cfg->ts_periodicity = 3; + _cfg->ts_target_bitrate[0] = (inst->startBitrate*2/5); + _cfg->ts_target_bitrate[1] = (inst->startBitrate*3/5); + _cfg->ts_target_bitrate[2] = (inst->startBitrate); + _cfg->ts_rate_decimator[0] = 4; + _cfg->ts_rate_decimator[1] = 2; + _cfg->ts_rate_decimator[2] = 1; + memcpy(_cfg->ts_layer_id, ids, sizeof(ids)); +*/ // setting the time base of the codec _cfg->g_timebase.num = 1; @@ -394,7 +419,7 @@ VP8Encoder::MaxIntraTarget(WebRtc_UWord32 optimalBuffersize) WebRtc_Word32 VP8Encoder::Encode(const RawImage& inputImage, const CodecSpecificInfo* codecSpecificInfo, - VideoFrameType frameTypes) + const VideoFrameType* frameTypes) { if (!_inited) { @@ -408,14 +433,21 @@ VP8Encoder::Encode(const RawImage& inputImage, { return WEBRTC_VIDEO_CODEC_UNINITIALIZED; } - + if (codecSpecificInfo) + { + _simulcastIdx = codecSpecificInfo->codecSpecific.VP8.simulcastIdx; + } + else + { + _simulcastIdx = 0; + } // image in vpx_image_t format _raw->planes[PLANE_Y] = inputImage._buffer; _raw->planes[PLANE_U] = &inputImage._buffer[_height * _width]; _raw->planes[PLANE_V] = &inputImage._buffer[_height * _width * 5 >> 2]; int flags = 0; - if (frameTypes == kKeyFrame) + if (frameTypes && *frameTypes == kKeyFrame) { flags |= VPX_EFLAG_FORCE_KF; // will update both golden and altref _encodedImage._frameType = kKeyFrame; @@ -555,6 +587,8 @@ void VP8Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, codec_specific->codecType = kVideoCodecVP8; CodecSpecificInfoVP8 *vp8Info = &(codec_specific->codecSpecific.VP8); vp8Info->pictureId = _pictureID; + vp8Info->simulcastIdx = _simulcastIdx;; + vp8Info->temporalIdx = kNoTemporalIdx; // TODO(pwestin) need to populate this vp8Info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE); _pictureID = (_pictureID + 1) % 0x7FFF; // prepare next } diff --git a/src/modules/video_coding/codecs/vp8/main/source/vp8.gypi b/src/modules/video_coding/codecs/vp8/main/source/vp8.gypi index 0cc2b74686..0295a2c894 100644 --- a/src/modules/video_coding/codecs/vp8/main/source/vp8.gypi +++ b/src/modules/video_coding/codecs/vp8/main/source/vp8.gypi @@ -17,6 +17,7 @@ 'include_dirs': [ '../interface', '../../../../../../common_video/interface', + '../../../../../../common_video/vplib/main/interface', '../../../interface', '../../../../../interface', ], @@ -72,7 +73,9 @@ }, 'sources': [ '../interface/vp8.h', + '../interface/vp8_simulcast.h', 'vp8.cc', + 'vp8_simulcast.cc', ], }, ], # targets diff --git a/src/modules/video_coding/codecs/vp8/main/source/vp8_simulcast.cc b/src/modules/video_coding/codecs/vp8/main/source/vp8_simulcast.cc new file mode 100644 index 0000000000..f1100427bb --- /dev/null +++ b/src/modules/video_coding/codecs/vp8/main/source/vp8_simulcast.cc @@ -0,0 +1,317 @@ +/* + * 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. + */ + +/* + * vp8_simulcast.cc + * WEBRTC VP8 simulcast wrapper interface + */ + +#include "vp8_simulcast.h" + +#include + +#include "module_common_types.h" +#include "trace.h" + +namespace webrtc { + +VP8SimulcastEncoder::VP8SimulcastEncoder() { + for (int i = 0; i < kMaxSimulcastStreams; i++) { + encoder_[i] = NULL; + encode_stream_[i] = false; + frame_type_[i] = kKeyFrame; + interpolator_[i] = NULL; + } +} + +VP8SimulcastEncoder::~VP8SimulcastEncoder() { + for (int i = 0; i < kMaxSimulcastStreams; i++) { + delete encoder_[i]; + delete interpolator_[i]; + delete [] video_frame_[i]._buffer; + } +} + +WebRtc_Word32 VP8SimulcastEncoder::Release() { + for (int i = 0; i < kMaxSimulcastStreams; i++) { + delete encoder_[i]; + encoder_[i] = NULL; + delete interpolator_[i]; + interpolator_[i] = NULL; + delete [] video_frame_[i]._buffer; + video_frame_[i]._buffer = NULL; + video_frame_[i]._size = 0; + } + return 0; +} + +WebRtc_Word32 VP8SimulcastEncoder::Reset() { + for (int i = 0; i < kMaxSimulcastStreams; i++) { + if (encoder_[i]) { + encoder_[i]->Reset(); + } + } + return 0; +} + +WebRtc_Word32 VP8SimulcastEncoder::InitEncode(const VideoCodec* codecSettings, + WebRtc_Word32 numberOfCores, + WebRtc_UWord32 maxPayloadSize) { + // Store a config copy + memcpy(&video_codec_, codecSettings, sizeof(VideoCodec)); + + // local copy + VideoCodec video_codec; + memcpy(&video_codec, codecSettings, sizeof(VideoCodec)); + video_codec.numberOfSimulcastStreams = 0; + + WebRtc_UWord32 bitrate_sum = 0; + WebRtc_Word32 ret_val = 0; + for (int i = 0; i < codecSettings->numberOfSimulcastStreams; i++) { + if (encoder_[i] == NULL) { + encoder_[i] = new VP8Encoder(); + } + assert(encoder_[i]); + + if (codecSettings->startBitrate > bitrate_sum) { + frame_type_[i] = kKeyFrame; + encode_stream_[i] = true; + } else { + // no more bits + encode_stream_[i] = false; + continue; + } + bitrate_sum += codecSettings->simulcastStream[i].maxBitrate; + if (codecSettings->startBitrate >= bitrate_sum) { + video_codec.startBitrate = codecSettings->simulcastStream[i].maxBitrate; + } else { + // The last stream will get what ever is left of the budget up to its max + video_codec.startBitrate = + codecSettings->startBitrate - + (bitrate_sum - + codecSettings->simulcastStream[i].maxBitrate); + } + video_codec.maxBitrate = codecSettings->simulcastStream[i].maxBitrate; + video_codec.qpMax = codecSettings->simulcastStream[i].qpMax; + video_codec.width = codecSettings->simulcastStream[i].width; + video_codec.height = codecSettings->simulcastStream[i].height; + + WebRtc_Word32 cores = 1; + if (video_codec.width > 640 && + numberOfCores > codecSettings->numberOfSimulcastStreams) { + cores = 2; + } + ret_val = encoder_[i]->InitEncode(&video_codec, + cores, + maxPayloadSize); + if (ret_val != 0) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + -1, + "Failed to initialize VP8 simulcast idx: %d.", + i); + return ret_val; + } + if (codecSettings->width != video_codec.width || + codecSettings->height != video_codec.height) { + if (interpolator_[i] == NULL) { + interpolator_[i] = new interpolator(); + } + interpolator_[i]->Set( + codecSettings->width, + codecSettings->height, + video_codec.width, + video_codec.height, + kI420, + kI420, + kBilinear); + + if (video_frame_[i]._size < + (3u * video_codec.width * video_codec.height / 2u)) { + video_frame_[i]._size = 3 * video_codec.width * video_codec.height / 2; + delete video_frame_[i]._buffer; + video_frame_[i]._buffer = new WebRtc_UWord8[video_frame_[i]._size]; + video_frame_[i]._length = 0; + } + } + } + return ret_val; +} + +WebRtc_Word32 VP8SimulcastEncoder::Encode( + const RawImage& inputImage, + const CodecSpecificInfo* codecSpecificInfo, + const VideoFrameType* requestedFrameTypes) { + + WebRtc_Word32 ret_val = -1; + // we need a local copy since we modify it + CodecSpecificInfo info = *codecSpecificInfo; + + const int numberOfStreams = video_codec_.numberOfSimulcastStreams; + + for (int i = 0; i < numberOfStreams; i++) { + if (encode_stream_[i]) { + video_frame_[i]._timeStamp = inputImage._timeStamp; + } + if (requestedFrameTypes[i] == kKeyFrame) { + // always do a keyframe if asked to + frame_type_[i] = kKeyFrame; + } else if (frame_type_[i] == kKeyFrame) { + // don't write over a previusly requested keyframe + } else if (frame_type_[i] == kGoldenFrame) { + if (requestedFrameTypes[i] == kAltRefFrame) { + // request for both AltRef and Golden upgrade to keyframe + frame_type_[i] = kKeyFrame; + } + } else if (frame_type_[i] == kAltRefFrame) { + if (requestedFrameTypes[i] == kGoldenFrame) { + // request for both AltRef and Golden upgrade to keyframe + frame_type_[i] = kKeyFrame; + } + } else if (frame_type_[i] == kDeltaFrame) { + // if the current is delta set requested + frame_type_[i] = requestedFrameTypes[i]; + } + } + + for (int i = 0; i < numberOfStreams; i++) { + if (encoder_[i] && encode_stream_[i]) { + // need the simulcastIdx to keep track of which encoder encoded the frame + info.codecSpecific.VP8.simulcastIdx = i; + VideoFrameType requested_frame_type = frame_type_[i]; + if (interpolator_[i]) { + interpolator_[i]->Interpolate(inputImage._buffer, + video_frame_[i]._buffer, + video_frame_[i]._size); + video_frame_[i]._length = + 3 * + video_codec_.simulcastStream[i].width * + video_codec_.simulcastStream[i].height / + 2; + ret_val = encoder_[i]->Encode(video_frame_[i], + &info, + &requested_frame_type); + } else { + ret_val = encoder_[i]->Encode(inputImage, + &info, + &requested_frame_type); + } + if (ret_val < 0) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, -1, + "Encode error:%d on stream:%d", ret_val, i); + return ret_val; + } + frame_type_[i] = kDeltaFrame; + } + } + return ret_val; +} + +WebRtc_Word32 VP8SimulcastEncoder::RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) { + WebRtc_Word32 ret_val = 0; + for (int i = 0; i < kMaxSimulcastStreams; i++) { + if (encoder_[i]) { + ret_val = encoder_[i]->RegisterEncodeCompleteCallback(callback); + if (ret_val < 0) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + -1, + "RegisterEncodeCompleteCallback error:%d on stream:%d", + ret_val, + i); + return ret_val; + } + } + } + return ret_val; +} + +WebRtc_Word32 VP8SimulcastEncoder::SetPacketLoss(WebRtc_UWord32 packetLoss) { + WebRtc_Word32 ret_val = 0; + for (int i = 0; i < kMaxSimulcastStreams; i++) { + if (encoder_[i]) { + ret_val = encoder_[i]->SetPacketLoss(packetLoss); + if (ret_val < 0) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + -1, + "SetPacketLoss error:%d on stream:%d", + ret_val, + i); + return ret_val; + } + } + } + return ret_val; +} + +WebRtc_Word32 VP8SimulcastEncoder::SetRates(WebRtc_UWord32 new_bitrate, + WebRtc_UWord32 frame_rate) { + WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCoding, -1, + "VP8 simulcast SetRates(%d,%d)", new_bitrate, frame_rate); + + WebRtc_UWord32 bitrate_sum = 0; + WebRtc_Word32 ret_val = 0; + for (int i = 0; i < video_codec_.numberOfSimulcastStreams; i++) { + if (new_bitrate > bitrate_sum) { + if (!encode_stream_[i]) { + frame_type_[i] = kKeyFrame; + encode_stream_[i] = true; + } + } else { + // no more bits + encode_stream_[i] = false; + continue; + } + WebRtc_UWord32 stream_bitrate = 0; + bitrate_sum += video_codec_.simulcastStream[i].maxBitrate; + if (new_bitrate >= bitrate_sum) { + stream_bitrate = video_codec_.simulcastStream[i].maxBitrate; + } else { + stream_bitrate = + new_bitrate - + (bitrate_sum - + video_codec_.simulcastStream[i].maxBitrate); + } + ret_val = encoder_[i]->SetRates(stream_bitrate, frame_rate); + if (ret_val < 0) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + -1, + "VP8 error stream:%d SetRates(%d,%d)", + i, stream_bitrate, frame_rate); + } else { + WEBRTC_TRACE(webrtc::kTraceStateInfo, + webrtc::kTraceVideoCoding, + -1, + "VP8 stream:%d SetRates(%d,%d)", + i, stream_bitrate, frame_rate); + } + } + return ret_val; +} + +WebRtc_Word32 VP8SimulcastEncoder::VersionStatic(WebRtc_Word8 *version, + WebRtc_Word32 length) { + const WebRtc_Word8* str = "WebM/VP8 simulcast version 1.0.0\n"; + WebRtc_Word32 verLen = (WebRtc_Word32)strlen(str); + if (verLen > length) { + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; + } + strncpy(version, str, length); + return verLen; +} + +WebRtc_Word32 VP8SimulcastEncoder::Version(WebRtc_Word8 *version, + WebRtc_Word32 length) const { + return VersionStatic(version, length); +} +} // namespace webrtc diff --git a/src/modules/video_coding/main/interface/video_coding.h b/src/modules/video_coding/main/interface/video_coding.h index 6e139ca049..a6c2b0fa6d 100644 --- a/src/modules/video_coding/main/interface/video_coding.h +++ b/src/modules/video_coding/main/interface/video_coding.h @@ -237,7 +237,7 @@ public: // < 0, on error. virtual WebRtc_Word32 AddVideoFrame( const VideoFrame& videoFrame, - const VideoContentMetrics* _contentMetrics = NULL, + const VideoContentMetrics* contentMetrics = NULL, const CodecSpecificInfo* codecSpecificInfo = NULL) = 0; // Next frame encoded should be of the type frameType. @@ -248,7 +248,8 @@ public: // // Return value : VCM_OK, on success. // < 0, on error. - virtual WebRtc_Word32 FrameTypeRequest(FrameType frameType) = 0; + virtual WebRtc_Word32 FrameTypeRequest(FrameType frameType, + WebRtc_UWord8 simulcastIdx) = 0; // Frame Dropper enable. Can be used to disable the frame dropping when the encoder // over-uses its bit rate. This API is designed to be used when the encoded frames diff --git a/src/modules/video_coding/main/interface/video_coding_defines.h b/src/modules/video_coding/main/interface/video_coding_defines.h index 739440f287..bcacf9c7d4 100644 --- a/src/modules/video_coding/main/interface/video_coding_defines.h +++ b/src/modules/video_coding/main/interface/video_coding_defines.h @@ -89,7 +89,7 @@ public: const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* rtpTypeHdr) = 0; + const RTPVideoHeader* rtpVideoHdr) = 0; protected: virtual ~VCMPacketizationCallback() {} }; diff --git a/src/modules/video_coding/main/source/codec_database.cc b/src/modules/video_coding/main/source/codec_database.cc index 612b88bfc4..4583a0bb67 100644 --- a/src/modules/video_coding/main/source/codec_database.cc +++ b/src/modules/video_coding/main/source/codec_database.cc @@ -23,6 +23,7 @@ // Supported codecs #ifdef VIDEOCODEC_VP8 #include "vp8.h" + #include "vp8_simulcast.h" #endif #ifdef VIDEOCODEC_I420 #include "i420.h" @@ -91,7 +92,7 @@ VCMCodecDataBase::Version(WebRtc_Word8* version, { return ret; } - encoder = CreateEncoder(settings.codecType); + encoder = CreateEncoder(settings.codecType, false); if (encoder == NULL) { return VCM_MEMORY; @@ -133,24 +134,29 @@ VCMCodecDataBase::ResetSender() return VCM_OK; } -VCMGenericEncoder* -VCMCodecDataBase::CreateEncoder(VideoCodecType type) const -{ +VCMGenericEncoder* VCMCodecDataBase::CreateEncoder( + const VideoCodecType type, + const bool simulcast) const { + switch(type) { #ifdef VIDEOCODEC_VP8 case kVideoCodecVP8: - return new VCMGenericEncoder(*(new VP8Encoder)); - break; + if (simulcast) { + return new VCMGenericEncoder(*(new VP8SimulcastEncoder)); + } else { + return new VCMGenericEncoder(*(new VP8Encoder)); + } #endif #ifdef VIDEOCODEC_I420 case kVideoCodecI420: - return new VCMGenericEncoder(*(new I420Encoder)); - break; + if (!simulcast) { + return new VCMGenericEncoder(*(new I420Encoder)); + } + return NULL; #endif default: - return NULL; - break; + return NULL; } } @@ -203,6 +209,8 @@ VCMCodecDataBase::Codec(WebRtc_UWord8 listId, VideoCodec *settings) settings->maxFramerate = VCM_DEFAULT_FRAME_RATE; settings->width = VCM_DEFAULT_CODEC_WIDTH; settings->height = VCM_DEFAULT_CODEC_HEIGHT; + settings->numberOfSimulcastStreams = 0; + settings->codecSpecific.VP8.numberOfTemporalLayers = 1; break; } #endif @@ -222,6 +230,7 @@ VCMCodecDataBase::Codec(WebRtc_UWord8 listId, VideoCodec *settings) settings->width = VCM_DEFAULT_CODEC_WIDTH; settings->height = VCM_DEFAULT_CODEC_HEIGHT; settings->minBitrate = VCM_MIN_BITRATE; + settings->numberOfSimulcastStreams = 0; break; } #endif @@ -387,19 +396,32 @@ VCMCodecDataBase::SetEncoder(const VideoCodec* settings, } else { - _ptrEncoder = CreateEncoder(settings->codecType); + bool simulcast = false; + if (settings->numberOfSimulcastStreams > 1) + { + simulcast = true; + } + _ptrEncoder = CreateEncoder(settings->codecType, simulcast); _currentEncIsExternal = false; } - VCMencodedFrameCallback->SetPayloadType(settings->plType); if (_ptrEncoder == NULL) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + VCMId(_id), + "Failed to create encoder: %s.", + settings->plName); return NULL; } - if (_ptrEncoder->InitEncode(settings, _numberOfCores, _maxPayloadSize) < 0) { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideoCoding, + VCMId(_id), + "Failed to initialize encoder: %s.", + settings->plName); DeleteEncoder(); return NULL; } diff --git a/src/modules/video_coding/main/source/codec_database.h b/src/modules/video_coding/main/source/codec_database.h index 37943e8c61..3b37484ca7 100644 --- a/src/modules/video_coding/main/source/codec_database.h +++ b/src/modules/video_coding/main/source/codec_database.h @@ -182,7 +182,8 @@ protected: /** * Create an internal Encoder given a codec type */ - VCMGenericEncoder* CreateEncoder(VideoCodecType type) const; + VCMGenericEncoder* CreateEncoder(const VideoCodecType type, + const bool simulcast) const; void DeleteEncoder(); /* diff --git a/src/modules/video_coding/main/source/generic_encoder.cc b/src/modules/video_coding/main/source/generic_encoder.cc index e7f6e45b7a..3a6a831894 100644 --- a/src/modules/video_coding/main/source/generic_encoder.cc +++ b/src/modules/video_coding/main/source/generic_encoder.cc @@ -51,7 +51,9 @@ WebRtc_Word32 VCMGenericEncoder::Release() } WebRtc_Word32 -VCMGenericEncoder::InitEncode(const VideoCodec* settings, WebRtc_Word32 numberOfCores, WebRtc_UWord32 maxPayloadSize) +VCMGenericEncoder::InitEncode(const VideoCodec* settings, + WebRtc_Word32 numberOfCores, + WebRtc_UWord32 maxPayloadSize) { _bitRate = settings->startBitrate; _frameRate = settings->maxFramerate; @@ -66,16 +68,21 @@ VCMGenericEncoder::InitEncode(const VideoCodec* settings, WebRtc_Word32 numberOf WebRtc_Word32 VCMGenericEncoder::Encode(const VideoFrame& inputFrame, const CodecSpecificInfo* codecSpecificInfo, - FrameType frameType) + FrameType* frameType) { - RawImage rawImage(inputFrame.Buffer(), inputFrame.Length(), inputFrame.Size()); + RawImage rawImage(inputFrame.Buffer(), + inputFrame.Length(), + inputFrame.Size()); rawImage._width = inputFrame.Width(); rawImage._height = inputFrame.Height(); rawImage._timeStamp = inputFrame.TimeStamp(); - WebRtc_Word32 ret = _encoder.Encode(rawImage, codecSpecificInfo, VCMEncodedFrame::ConvertFrameType(frameType)); - - return ret; + VideoFrameType videoFrameTypes[kMaxSimulcastStreams]; + for (int i = 0; i < kMaxSimulcastStreams; i++) + { + videoFrameTypes[i] = VCMEncodedFrame::ConvertFrameType(frameType[i]); + } + return _encoder.Encode(rawImage, codecSpecificInfo, videoFrameTypes); } WebRtc_Word32 @@ -125,10 +132,15 @@ VCMGenericEncoder::SetPeriodicKeyFrames(bool enable) } WebRtc_Word32 -VCMGenericEncoder::RequestFrame(FrameType frameType) +VCMGenericEncoder::RequestFrame(FrameType* frameTypes) { RawImage image; - return _encoder.Encode(image, NULL, VCMEncodedFrame::ConvertFrameType(frameType)); + VideoFrameType videoFrameTypes[kMaxSimulcastStreams]; + for (int i = 0; i < kMaxSimulcastStreams; i++) + { + videoFrameTypes[i] = VCMEncodedFrame::ConvertFrameType(frameTypes[i]); + } + return _encoder.Encode(image, NULL, videoFrameTypes); } WebRtc_Word32 @@ -186,22 +198,22 @@ VCMEncodedFrameCallback::Encoded( WebRtc_UWord32 encodedBytes = 0; if (_sendCallback != NULL) { - encodedBytes = encodedImage._length; + encodedBytes = encodedImage._length; if (_bitStreamAfterEncoder != NULL) { fwrite(encodedImage._buffer, 1, encodedImage._length, _bitStreamAfterEncoder); } - RTPVideoTypeHeader rtpTypeHeader; - RTPVideoTypeHeader* rtpTypeHeaderPtr = &rtpTypeHeader; + RTPVideoHeader rtpVideoHeader; + RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader; if (codecSpecificInfo) { - CopyCodecSpecific(*codecSpecificInfo, &rtpTypeHeaderPtr); + CopyCodecSpecific(*codecSpecificInfo, &rtpVideoHeaderPtr); } else { - rtpTypeHeaderPtr = NULL; + rtpVideoHeaderPtr = NULL; } WebRtc_Word32 callbackReturn = _sendCallback->SendData( @@ -211,7 +223,7 @@ VCMEncodedFrameCallback::Encoded( encodedImage._buffer, encodedBytes, *fragmentationHeader, - rtpTypeHeaderPtr); + rtpVideoHeaderPtr); if (callbackReturn < 0) { return callbackReturn; @@ -227,7 +239,6 @@ VCMEncodedFrameCallback::Encoded( { return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame } - return VCM_OK; } @@ -244,13 +255,17 @@ VCMEncodedFrameCallback::SetMediaOpt(VCMMediaOptimization *mediaOpt) } void VCMEncodedFrameCallback::CopyCodecSpecific(const CodecSpecificInfo& info, - RTPVideoTypeHeader** rtp) { - switch (info.codecType) - { + RTPVideoHeader** rtp) { + switch (info.codecType) { case kVideoCodecVP8: { - (*rtp)->VP8.InitRTPVideoHeaderVP8(); - (*rtp)->VP8.pictureId = info.codecSpecific.VP8.pictureId; - (*rtp)->VP8.nonReference = info.codecSpecific.VP8.nonReference; + (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8(); + (*rtp)->codecHeader.VP8.pictureId = + info.codecSpecific.VP8.pictureId; + (*rtp)->codecHeader.VP8.nonReference = + info.codecSpecific.VP8.nonReference; + (*rtp)->codecHeader.VP8.temporalIdx = + info.codecSpecific.VP8.temporalIdx; + (*rtp)->simulcastIdx = info.codecSpecific.VP8.simulcastIdx; return; } default: { @@ -258,8 +273,6 @@ void VCMEncodedFrameCallback::CopyCodecSpecific(const CodecSpecificInfo& info, *rtp = NULL; return; } - } } - } // namespace webrtc diff --git a/src/modules/video_coding/main/source/generic_encoder.h b/src/modules/video_coding/main/source/generic_encoder.h index 26d19dff50..b0b10f3baa 100644 --- a/src/modules/video_coding/main/source/generic_encoder.h +++ b/src/modules/video_coding/main/source/generic_encoder.h @@ -59,7 +59,7 @@ private: * in info, rtp is set to NULL. */ static void CopyCodecSpecific(const CodecSpecificInfo& info, - RTPVideoTypeHeader** rtp); + RTPVideoHeader** rtp); VCMPacketizationCallback* _sendCallback; VCMMediaOptimization* _mediaOpt; @@ -103,7 +103,7 @@ public: */ WebRtc_Word32 Encode(const VideoFrame& inputFrame, const CodecSpecificInfo* codecSpecificInfo, - FrameType frameType); + FrameType* frameType); /** * Set new target bit rate and frame rate * Return Value: new bit rate if OK, otherwise <0s @@ -129,7 +129,7 @@ public: WebRtc_Word32 SetPeriodicKeyFrames(bool enable); - WebRtc_Word32 RequestFrame(FrameType frameType); + WebRtc_Word32 RequestFrame(FrameType* frameTypes); bool InternalSource() const; diff --git a/src/modules/video_coding/main/source/video_coding_impl.cc b/src/modules/video_coding/main/source/video_coding_impl.cc index b094222f69..9c1272340b 100644 --- a/src/modules/video_coding/main/source/video_coding_impl.cc +++ b/src/modules/video_coding/main/source/video_coding_impl.cc @@ -67,7 +67,6 @@ _scheduleKeyRequest(false), _sendCritSect(*CriticalSectionWrapper::CreateCriticalSection()), _encoder(), _encodedFrameCallback(), -_nextFrameType(kVideoFrameDelta), _mediaOpt(id), _sendCodecType(kVideoCodecUnknown), _sendStatsCallback(NULL), @@ -79,6 +78,10 @@ _sendStatsTimer(1000), _retransmissionTimer(10), _keyRequestTimer(500) { + for (int i = 0; i < kMaxSimulcastStreams; i++) + { + _nextFrameType[i] = kVideoFrameDelta; + } #ifdef DEBUG_DECODER_BIT_STREAM _bitStreamBeforeDecoder = fopen("decoderBitStream.bit", "wb"); #endif @@ -786,7 +789,7 @@ VideoCodingModuleImpl::SetVideoProtection(VCMVideoProtection videoProtection, // Add one raw video frame to the encoder, blocking. WebRtc_Word32 VideoCodingModuleImpl::AddVideoFrame(const VideoFrame& videoFrame, - const VideoContentMetrics* _contentMetrics, + const VideoContentMetrics* contentMetrics, const CodecSpecificInfo* codecSpecificInfo) { WEBRTC_TRACE(webrtc::kTraceModuleCall, @@ -799,12 +802,10 @@ VideoCodingModuleImpl::AddVideoFrame(const VideoFrame& videoFrame, { return VCM_UNINITIALIZED; } - - if (_nextFrameType == kFrameEmpty) + if (_nextFrameType[0] == kFrameEmpty) { return VCM_OK; } - _mediaOpt.UpdateIncomingFrameRate(); if (_mediaOpt.DropFrame()) @@ -816,12 +817,10 @@ VideoCodingModuleImpl::AddVideoFrame(const VideoFrame& videoFrame, } else { - _mediaOpt.updateContentData(_contentMetrics); - const FrameType requestedFrameType = _nextFrameType; - _nextFrameType = kVideoFrameDelta; // default frame type + _mediaOpt.updateContentData(contentMetrics); WebRtc_Word32 ret = _encoder->Encode(videoFrame, codecSpecificInfo, - requestedFrameType); + _nextFrameType); if (_encoderInputFile != NULL) { fwrite(videoFrame.Buffer(), 1, videoFrame.Length(), @@ -829,36 +828,42 @@ VideoCodingModuleImpl::AddVideoFrame(const VideoFrame& videoFrame, } if (ret < 0) { - _nextFrameType = requestedFrameType; WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCoding, VCMId(_id), "Encode error: %d", ret); return ret; } + for (int i = 0; i < kMaxSimulcastStreams; i++) + { + _nextFrameType[i] = kVideoFrameDelta; // default frame type + } } - return VCM_OK; } // Next frame encoded should be of the type frameType // Good for only one frame WebRtc_Word32 -VideoCodingModuleImpl::FrameTypeRequest(FrameType frameType) +VideoCodingModuleImpl::FrameTypeRequest(FrameType frameType, + WebRtc_UWord8 simulcastIdx) { + assert(simulcastIdx < kMaxSimulcastStreams); + WEBRTC_TRACE(webrtc::kTraceModuleCall, webrtc::kTraceVideoCoding, VCMId(_id), "FrameTypeRequest()"); + CriticalSectionScoped cs(_sendCritSect); - _nextFrameType = frameType; + _nextFrameType[simulcastIdx] = frameType; if (_encoder != NULL && _encoder->InternalSource()) { // Try to request the frame if we have an external encoder with // internal source since AddVideoFrame never will be called. if (_encoder->RequestFrame(_nextFrameType) == WEBRTC_VIDEO_CODEC_OK) { - _nextFrameType = kVideoFrameDelta; + _nextFrameType[simulcastIdx] = kVideoFrameDelta; } } return VCM_OK; diff --git a/src/modules/video_coding/main/source/video_coding_impl.h b/src/modules/video_coding/main/source/video_coding_impl.h index 8663bfe8e6..27f91b8bee 100644 --- a/src/modules/video_coding/main/source/video_coding_impl.h +++ b/src/modules/video_coding/main/source/video_coding_impl.h @@ -150,7 +150,8 @@ public: const CodecSpecificInfo* codecSpecificInfo = NULL); // Next frame encoded should be of the type frameType. - virtual WebRtc_Word32 FrameTypeRequest(FrameType frameType); + virtual WebRtc_Word32 FrameTypeRequest(FrameType frameType, + WebRtc_UWord8 simulcastIdx); //Enable frame dropper virtual WebRtc_Word32 EnableFrameDropper(bool enable); @@ -277,10 +278,10 @@ private: VCMKeyRequestMode _keyRequestMode; bool _scheduleKeyRequest; - CriticalSectionWrapper& _sendCritSect; + CriticalSectionWrapper& _sendCritSect; // Critical section for send side VCMGenericEncoder* _encoder; VCMEncodedFrameCallback _encodedFrameCallback; - FrameType _nextFrameType; + FrameType _nextFrameType[kMaxSimulcastStreams]; VCMMediaOptimization _mediaOpt; VideoCodecType _sendCodecType; VCMSendStatisticsCallback* _sendStatsCallback; @@ -292,7 +293,5 @@ private: VCMProcessTimer _retransmissionTimer; VCMProcessTimer _keyRequestTimer; }; - } // namespace webrtc - #endif // WEBRTC_MODULES_VIDEO_CODING_VIDEO_CODING_IMPL_H_ diff --git a/src/modules/video_coding/main/test/codec_database_test.cc b/src/modules/video_coding/main/test/codec_database_test.cc index 000218c8a3..34d120d9ce 100644 --- a/src/modules/video_coding/main/test/codec_database_test.cc +++ b/src/modules/video_coding/main/test/codec_database_test.cc @@ -241,7 +241,7 @@ CodecDataBaseTest::Perform(CmdArgs& args) // Try to decode a delta frame. Should get a warning since we have enabled the "require key frame" setting // and because no frame type request callback has been registered. TEST(_vcm->Decode() == VCM_MISSING_CALLBACK); - TEST(_vcm->FrameTypeRequest(kVideoFrameKey) == VCM_OK); + TEST(_vcm->FrameTypeRequest(kVideoFrameKey, 0) == VCM_OK); TEST(_vcm->AddVideoFrame(sourceFrame) == VCM_OK); TEST(_vcm->Decode() == VCM_OK); @@ -251,7 +251,7 @@ CodecDataBaseTest::Perform(CmdArgs& args) sendCodec.width = _width; sendCodec.height = _height; TEST(_vcm->RegisterReceiveCodec(&sendCodec, 1) == VCM_OK); - TEST(_vcm->FrameTypeRequest(kVideoFrameKey) == VCM_OK); + TEST(_vcm->FrameTypeRequest(kVideoFrameKey, 0) == VCM_OK); waitEvent->Wait(33); _timeStamp += (WebRtc_UWord32)(9e4 / _frameRate); sourceFrame.SetTimeStamp(_timeStamp); @@ -261,7 +261,7 @@ CodecDataBaseTest::Perform(CmdArgs& args) waitEvent->Wait(33); _timeStamp += (WebRtc_UWord32)(9e4 / _frameRate); sourceFrame.SetTimeStamp(_timeStamp); - TEST(_vcm->FrameTypeRequest(kVideoFrameKey) == VCM_OK); + TEST(_vcm->FrameTypeRequest(kVideoFrameKey, 0) == VCM_OK); TEST(_vcm->AddVideoFrame(sourceFrame) == VCM_OK); TEST(_vcm->Decode() == VCM_OK); TEST(_vcm->ResetDecoder() == VCM_OK); diff --git a/src/modules/video_coding/main/test/generic_codec_test.cc b/src/modules/video_coding/main/test/generic_codec_test.cc index 9f957840da..adb9e2512a 100644 --- a/src/modules/video_coding/main/test/generic_codec_test.cc +++ b/src/modules/video_coding/main/test/generic_codec_test.cc @@ -568,8 +568,8 @@ VCMEncComplete_KeyReqTest::SendData( const WebRtc_UWord32 timeStamp, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, - const RTPFragmentationHeader& fragmentationHeader, - const webrtc::RTPVideoTypeHeader* videoTypeHdr) + const RTPFragmentationHeader& /*fragmentationHeader*/, + const webrtc::RTPVideoHeader* /*videoHdr*/) { WebRtcRTPHeader rtpInfo; rtpInfo.header.markerBit = true; // end of frame diff --git a/src/modules/video_coding/main/test/generic_codec_test.h b/src/modules/video_coding/main/test/generic_codec_test.h index abfc239898..f8eff1aa36 100644 --- a/src/modules/video_coding/main/test/generic_codec_test.h +++ b/src/modules/video_coding/main/test/generic_codec_test.h @@ -90,7 +90,7 @@ public: const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const webrtc::RTPFragmentationHeader& fragmentationHeader, - const webrtc::RTPVideoTypeHeader* videoTypeHdr); + const webrtc::RTPVideoHeader* videoHdr); private: webrtc::VideoCodingModule& _vcm; WebRtc_UWord16 _seqNo; diff --git a/src/modules/video_coding/main/test/media_opt_test.cc b/src/modules/video_coding/main/test/media_opt_test.cc index 26b989d5c5..5ec05efdbd 100644 --- a/src/modules/video_coding/main/test/media_opt_test.cc +++ b/src/modules/video_coding/main/test/media_opt_test.cc @@ -209,15 +209,22 @@ MediaOptTest::GeneralSetup() // Registering codecs for the RTP module - // Register receive payload - _rtp->RegisterReceivePayload("VP8", VCM_VP8_PAYLOAD_TYPE); - _rtp->RegisterReceivePayload("ULPFEC", VCM_ULPFEC_PAYLOAD_TYPE); - _rtp->RegisterReceivePayload("RED", VCM_RED_PAYLOAD_TYPE); + // Register receive and send payload + VideoCodec videoCodec; + strncpy(videoCodec.plName, "VP8", 32); + videoCodec.plType = VCM_VP8_PAYLOAD_TYPE; + _rtp->RegisterReceivePayload(videoCodec); + _rtp->RegisterSendPayload(videoCodec); - // Register send payload - _rtp->RegisterSendPayload("VP8", VCM_VP8_PAYLOAD_TYPE); - _rtp->RegisterSendPayload("ULPFEC", VCM_ULPFEC_PAYLOAD_TYPE); - _rtp->RegisterSendPayload("RED", VCM_RED_PAYLOAD_TYPE); + strncpy(videoCodec.plName, "ULPFEC", 32); + videoCodec.plType = VCM_ULPFEC_PAYLOAD_TYPE; + _rtp->RegisterReceivePayload(videoCodec); + _rtp->RegisterSendPayload(videoCodec); + + strncpy(videoCodec.plName, "RED", 32); + videoCodec.plType = VCM_RED_PAYLOAD_TYPE; + _rtp->RegisterReceivePayload(videoCodec); + _rtp->RegisterSendPayload(videoCodec); if (_nackFecEnabled == 1) _rtp->SetGenericFECStatus(_nackFecEnabled, VCM_RED_PAYLOAD_TYPE, diff --git a/src/modules/video_coding/main/test/mt_rx_tx_test.cc b/src/modules/video_coding/main/test/mt_rx_tx_test.cc index 77eb0f3c0c..2e7c83a720 100644 --- a/src/modules/video_coding/main/test/mt_rx_tx_test.cc +++ b/src/modules/video_coding/main/test/mt_rx_tx_test.cc @@ -149,15 +149,24 @@ int MTRxTxTest(CmdArgs& args) return -1; } // registering codecs for the RTP module - TEST(rtp->RegisterReceivePayload("ULPFEC", VCM_ULPFEC_PAYLOAD_TYPE) == 0); - TEST(rtp->RegisterReceivePayload("RED", VCM_RED_PAYLOAD_TYPE) == 0); - TEST(rtp->RegisterReceivePayload(args.codecName.c_str(), VCM_VP8_PAYLOAD_TYPE) == 0); + VideoCodec videoCodec; + strncpy(videoCodec.plName, "ULPFEC", 32); + videoCodec.plType = VCM_ULPFEC_PAYLOAD_TYPE; + TEST(rtp->RegisterReceivePayload(videoCodec) == 0); + + strncpy(videoCodec.plName, "RED", 32); + videoCodec.plType = VCM_RED_PAYLOAD_TYPE; + TEST(rtp->RegisterReceivePayload(videoCodec) == 0); + + strncpy(videoCodec.plName, args.codecName.c_str(), 32); + videoCodec.plType = VCM_VP8_PAYLOAD_TYPE; + videoCodec.maxBitrate = 10000; + TEST(rtp->RegisterReceivePayload(videoCodec) == 0); + TEST(rtp->RegisterSendPayload(videoCodec) == 0); // inform RTP Module of error resilience features TEST(rtp->SetGenericFECStatus(fecEnabled, VCM_RED_PAYLOAD_TYPE, VCM_ULPFEC_PAYLOAD_TYPE) == 0); - TEST(rtp->RegisterSendPayload(args.codecName.c_str(), VCM_VP8_PAYLOAD_TYPE, 90000, 1, 10000) == 0); - //VCM VideoCodingModule* vcm = VideoCodingModule::Create(1); if (vcm->InitializeReceiver() < 0) diff --git a/src/modules/video_coding/main/test/normal_test.cc b/src/modules/video_coding/main/test/normal_test.cc index f0eb4b42c4..0d3ed51abc 100644 --- a/src/modules/video_coding/main/test/normal_test.cc +++ b/src/modules/video_coding/main/test/normal_test.cc @@ -77,8 +77,8 @@ VCMNTEncodeCompleteCallback::SendData( const WebRtc_UWord32 timeStamp, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, - const RTPFragmentationHeader& fragmentationHeader, - const webrtc::RTPVideoTypeHeader* videoTypeHdr) + const RTPFragmentationHeader& /*fragmentationHeader*/, + const webrtc::RTPVideoHeader* videoHdr) { // will call the VCMReceiver input packet @@ -101,9 +101,9 @@ VCMNTEncodeCompleteCallback::SendData( case kVideoCodecVP8: rtpInfo.type.Video.codec = kRTPVideoVP8; rtpInfo.type.Video.codecHeader.VP8.nonReference = - videoTypeHdr->VP8.nonReference; + videoHdr->codecHeader.VP8.nonReference; rtpInfo.type.Video.codecHeader.VP8.pictureId = - videoTypeHdr->VP8.pictureId; + videoHdr->codecHeader.VP8.pictureId; break; case kVideoCodecI420: rtpInfo.type.Video.codec = kRTPVideoI420; diff --git a/src/modules/video_coding/main/test/normal_test.h b/src/modules/video_coding/main/test/normal_test.h index 245b76dea7..7860235366 100644 --- a/src/modules/video_coding/main/test/normal_test.h +++ b/src/modules/video_coding/main/test/normal_test.h @@ -34,7 +34,7 @@ public: const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const webrtc::RTPFragmentationHeader& fragmentationHeader, - const webrtc::RTPVideoTypeHeader* videoTypeHdr); + const webrtc::RTPVideoHeader* videoHdr); // Register exisitng VCM. Currently - encode and decode with the same vcm module. void RegisterReceiverVCM(webrtc::VideoCodingModule *vcm); diff --git a/src/modules/video_coding/main/test/rtp_player.cc b/src/modules/video_coding/main/test/rtp_player.cc index 499d42637e..fb4ea36b69 100644 --- a/src/modules/video_coding/main/test/rtp_player.cc +++ b/src/modules/video_coding/main/test/rtp_player.cc @@ -205,7 +205,10 @@ WebRtc_Word32 RTPPlayer::Initialize(const ListWrapper& payloadList) PayloadCodecTuple* payloadType = static_cast(item->GetItem()); if (payloadType != NULL) { - if (_rtpModule.RegisterReceivePayload(payloadType->name.c_str(), payloadType->payloadType) < 0) + VideoCodec videoCodec; + strncpy(videoCodec.plName, payloadType->name.c_str(), 32); + videoCodec.plType = payloadType->payloadType; + if (_rtpModule.RegisterReceivePayload(videoCodec) < 0) { return -1; } diff --git a/src/modules/video_coding/main/test/test_callbacks.cc b/src/modules/video_coding/main/test/test_callbacks.cc index 28f2d25a7a..e564b180e2 100644 --- a/src/modules/video_coding/main/test/test_callbacks.cc +++ b/src/modules/video_coding/main/test/test_callbacks.cc @@ -51,7 +51,7 @@ VCMEncodeCompleteCallback::SendData( const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* videoTypeHdr) + const RTPVideoHeader* videoHdr) { // will call the VCMReceiver input packet _frameType = frameType; @@ -71,9 +71,9 @@ VCMEncodeCompleteCallback::SendData( break; case webrtc::kRTPVideoVP8: rtpInfo.type.Video.codecHeader.VP8.nonReference = - videoTypeHdr->VP8.nonReference; + videoHdr->codecHeader.VP8.nonReference; rtpInfo.type.Video.codecHeader.VP8.pictureId = - videoTypeHdr->VP8.pictureId; + videoHdr->codecHeader.VP8.pictureId; break; case webrtc::kRTPVideoI420: break; @@ -145,7 +145,7 @@ VCMRTPEncodeCompleteCallback::SendData( const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* videoTypeHdr) + const RTPVideoHeader* videoHdr) { _frameType = frameType; _encodedBytes+= payloadSize; @@ -156,7 +156,7 @@ VCMRTPEncodeCompleteCallback::SendData( payloadData, payloadSize, &fragmentationHeader, - videoTypeHdr); + videoHdr); } float diff --git a/src/modules/video_coding/main/test/test_callbacks.h b/src/modules/video_coding/main/test/test_callbacks.h index f978096596..f65f3ae4db 100644 --- a/src/modules/video_coding/main/test/test_callbacks.h +++ b/src/modules/video_coding/main/test/test_callbacks.h @@ -50,7 +50,7 @@ public: const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* videoTypeHdr); + const RTPVideoHeader* videoHdr); // Register exisitng VCM. Currently - encode and decode under same module. void RegisterReceiverVCM(VideoCodingModule *vcm) {_VCMReceiver = vcm;} // Return size of last encoded frame data (all frames in the sequence) @@ -106,7 +106,7 @@ public: const WebRtc_UWord8 payloadType, const WebRtc_UWord32 timeStamp, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* videoTypeHdr); + const RTPVideoHeader* videoHdr); // Return size of last encoded frame. Value good for one call // (resets to zero after call to inform test of frame drop) float EncodedBytes(); diff --git a/src/video_engine/main/interface/vie_rtp_rtcp.h b/src/video_engine/main/interface/vie_rtp_rtcp.h index f12d504934..c31031be09 100644 --- a/src/video_engine/main/interface/vie_rtp_rtcp.h +++ b/src/video_engine/main/interface/vie_rtp_rtcp.h @@ -47,6 +47,12 @@ enum ViEKeyFrameRequestMethod kViEKeyFrameRequestFirRtcp = 3 }; +enum StreamType +{ + kViEStreamTypeNormal = 0, // Normal media stream + kViEStreamTypeRtx = 1 // Retransmission media stream +}; + // ---------------------------------------------------------------------------- // ViERTPObserver // ---------------------------------------------------------------------------- @@ -120,13 +126,21 @@ public: // This function enables you to specify the RTP synchronization source // identifier (SSRC) explicitly. virtual int SetLocalSSRC(const int videoChannel, - const unsigned int SSRC) = 0; + const unsigned int SSRC, + const StreamType usage = kViEStreamTypeNormal, + const unsigned char simulcastIdx = 0) = 0; // This function gets the SSRC for the outgoing RTP stream for the specified // channel. virtual int GetLocalSSRC(const int videoChannel, unsigned int& SSRC) const = 0; + // This function map a incoming SSRC to a StreamType so that the engine + // can know which is the normal stream and which is the RTX + virtual int SetRemoteSSRCType(const int videoChannel, + const StreamType usage, + const unsigned int SSRC) const = 0; + // This function gets the SSRC for the incoming RTP stream for the specified // channel. virtual int GetRemoteSSRC(const int videoChannel, diff --git a/src/video_engine/main/source/vie_base_impl.cc b/src/video_engine/main/source/vie_base_impl.cc index 7d7edf829e..e1ebf34795 100644 --- a/src/video_engine/main/source/vie_base_impl.cc +++ b/src/video_engine/main/source/vie_base_impl.cc @@ -219,7 +219,6 @@ int ViEBaseImpl::CreateChannel(int& videoChannel, int originalChannel) SetLastError(kViEBaseInvalidChannelId); return -1; } - if (_channelManager.CreateChannel(videoChannel, originalChannel) == -1) { diff --git a/src/video_engine/main/source/vie_capturer.cc b/src/video_engine/main/source/vie_capturer.cc index 5de833bf3d..55dd27b49b 100644 --- a/src/video_engine/main/source/vie_capturer.cc +++ b/src/video_engine/main/source/vie_capturer.cc @@ -910,8 +910,8 @@ WebRtc_Word32 ViECapturer::InitEncode(const VideoCodec* codecSettings, */ WebRtc_Word32 ViECapturer::Encode(const RawImage& inputImage, - const CodecSpecificInfo* codecSpecificInfo, /*= NULL,*/ - VideoFrameType frameType /*= kDeltaFrame*/) + const CodecSpecificInfo* codecSpecificInfo, + const VideoFrameType* frameTypes) { CriticalSectionScoped cs(_encodingCritsect); @@ -919,14 +919,13 @@ ViECapturer::Encode(const RawImage& inputImage, if (!_captureEncoder) return WEBRTC_VIDEO_CODEC_UNINITIALIZED; - if (frameType == kKeyFrame) + if (*frameTypes == kKeyFrame) return _captureEncoder->EncodeFrameType(kVideoFrameKey); - if (frameType == kSkipFrame) + if (*frameTypes == kSkipFrame) return _captureEncoder->EncodeFrameType(kFrameEmpty); return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; - } WebRtc_Word32 ViECapturer::RegisterEncodeCompleteCallback( EncodedImageCallback* callback) diff --git a/src/video_engine/main/source/vie_capturer.h b/src/video_engine/main/source/vie_capturer.h index 6a9531798c..c681dc9d70 100644 --- a/src/video_engine/main/source/vie_capturer.h +++ b/src/video_engine/main/source/vie_capturer.h @@ -125,11 +125,10 @@ protected: WebRtc_Word32 numberOfCores, WebRtc_UWord32 maxPayloadSize); virtual WebRtc_Word32 Encode(const RawImage& inputImage, - const CodecSpecificInfo* codecSpecificInfo = - NULL, - VideoFrameType frameType = kDeltaFrame); + const CodecSpecificInfo* codecSpecificInfo, + const VideoFrameType* frameTypes); virtual WebRtc_Word32 RegisterEncodeCompleteCallback( - EncodedImageCallback* callback); + EncodedImageCallback* callback); virtual WebRtc_Word32 Release(); virtual WebRtc_Word32 Reset(); virtual WebRtc_Word32 SetPacketLoss(WebRtc_UWord32 packetLoss); diff --git a/src/video_engine/main/source/vie_channel.cc b/src/video_engine/main/source/vie_channel.cc index fa25f57070..84378f664e 100644 --- a/src/video_engine/main/source/vie_channel.cc +++ b/src/video_engine/main/source/vie_channel.cc @@ -51,7 +51,6 @@ ViEChannel::ViEChannel(WebRtc_Word32 channelId, WebRtc_Word32 engineId, _numberOfCores(numberOfCores), _numSocketThreads(kViESocketThreads), _callbackCritsect(*CriticalSectionWrapper::CreateCriticalSection()), - _dataCritsect(*CriticalSectionWrapper::CreateCriticalSection()), _rtpRtcp(*RtpRtcp::CreateRtpRtcp( ViEModuleId(engineId, channelId), false)), #ifndef WEBRTC_EXTERNAL_TRANSPORT @@ -61,8 +60,9 @@ ViEChannel::ViEChannel(WebRtc_Word32 channelId, WebRtc_Word32 engineId, #endif _vcm(*VideoCodingModule::Create( ViEModuleId(engineId, channelId))), + _vieReceiver(*(new ViEReceiver(engineId, channelId, _rtpRtcp, _vcm))), - _vieSender(*(new ViESender(engineId, channelId, _rtpRtcp))), + _vieSender(*(new ViESender(engineId, channelId))), _vieSync(*(new ViESyncModule(ViEId(engineId, channelId), _vcm, _rtpRtcp))), _moduleProcessThread(moduleProcessThread), @@ -161,7 +161,6 @@ WebRtc_Word32 ViEChannel::Init() __FUNCTION__); return -1; } - if (_rtpRtcp.RegisterIncomingRTCPCallback(this) != 0) { WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, @@ -216,8 +215,8 @@ WebRtc_Word32 ViEChannel::Init() VideoCodec videoCodec; if (_vcm.Codec(kVideoCodecVP8, &videoCodec) == VCM_OK) { - _rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType); - _rtpRtcp.RegisterReceivePayload(videoCodec.plName, videoCodec.plType); + _rtpRtcp.RegisterSendPayload(videoCodec); + _rtpRtcp.RegisterReceivePayload(videoCodec); _vcm.RegisterReceiveCodec(&videoCodec, _numberOfCores); _vcm.RegisterSendCodec(&videoCodec, _numberOfCores, _rtpRtcp.MaxDataPayloadLength()); @@ -237,9 +236,11 @@ WebRtc_Word32 ViEChannel::Init() ViEChannel::~ViEChannel() { - WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "ViEChannel Destructor, channelId: %d, engineId: %d", - _channelId, _engineId); + WEBRTC_TRACE(webrtc::kTraceMemory, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "ViEChannel Destructor, channelId: %d, engineId: %d", + _channelId, _engineId); // Make sure we don't get more callbacks from the RTP module. _rtpRtcp.RegisterIncomingRTPCallback(NULL); @@ -250,7 +251,16 @@ ViEChannel::~ViEChannel() _moduleProcessThread.DeRegisterModule(&_rtpRtcp); _moduleProcessThread.DeRegisterModule(&_vcm); _moduleProcessThread.DeRegisterModule(&_vieSync); - + while (_simulcastRtpRtcp.size() > 0) + { + std::list::iterator it = _simulcastRtpRtcp.begin(); + RtpRtcp* rtpRtcp = *it; + rtpRtcp->RegisterIncomingRTCPCallback(NULL); + rtpRtcp->RegisterSendTransport(NULL); + _moduleProcessThread.DeRegisterModule(rtpRtcp); + RtpRtcp::DestroyRtpRtcp(rtpRtcp); + _simulcastRtpRtcp.erase(it); + } if (_ptrDecodeThread) { StopDecodeThread(); @@ -261,14 +271,11 @@ ViEChannel::~ViEChannel() delete &_vieSync; delete &_callbackCritsect; - delete &_dataCritsect; // Release modules - RtpRtcp::DestroyRtpRtcp(&_rtpRtcp); #ifndef WEBRTC_EXTERNAL_TRANSPORT - UdpTransport::Destroy( - &_socketTransport); + UdpTransport::Destroy(&_socketTransport); #endif VideoCodingModule::Destroy(&_vcm); } @@ -287,8 +294,12 @@ ViEChannel::~ViEChannel() WebRtc_Word32 ViEChannel::SetSendCodec(const VideoCodec& videoCodec, bool newStream) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s: codecType: %d", __FUNCTION__, videoCodec.codecType); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: codecType: %d", + __FUNCTION__, + videoCodec.codecType); if (videoCodec.codecType == kVideoCodecRED || videoCodec.codecType == kVideoCodecULPFEC) @@ -299,7 +310,15 @@ WebRtc_Word32 ViEChannel::SetSendCodec(const VideoCodec& videoCodec, __FUNCTION__, videoCodec.codecType); return -1; } - + if (kMaxSimulcastStreams < videoCodec.numberOfSimulcastStreams) + { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: Too many simulcast streams", + __FUNCTION__); + return -1; + } // Update the RTP module with the settigns // Stop and Start the RTP module -> trigger new SSRC bool restartRtp = false; @@ -308,15 +327,168 @@ WebRtc_Word32 ViEChannel::SetSendCodec(const VideoCodec& videoCodec, restartRtp = true; _rtpRtcp.SetSendingStatus(false); } - - if (_rtpRtcp.SetSendBitrate(videoCodec.startBitrate * 1000, - videoCodec.minBitrate, videoCodec.maxBitrate) - != 0) + if (videoCodec.numberOfSimulcastStreams > 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, - ViEId(_engineId, _channelId), - "%s: could not set send bitrates", __FUNCTION__); - return -1; + WebRtc_UWord32 startBitrate = videoCodec.startBitrate * 1000; + WebRtc_UWord32 streamBitrate = std::min(startBitrate, + videoCodec.simulcastStream[0].maxBitrate); + startBitrate -= streamBitrate; + // set correct bitrate to base layer + if (_rtpRtcp.SetSendBitrate( + streamBitrate, + videoCodec.minBitrate, + videoCodec.simulcastStream[0].maxBitrate) != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: could not set send bitrates", + __FUNCTION__); + return -1; + } + // Create our simulcast RTP modules + for (int i = _simulcastRtpRtcp.size(); + i < videoCodec.numberOfSimulcastStreams - 1; + i++) + { + RtpRtcp* rtpRtcp = RtpRtcp::CreateRtpRtcp( + ViEModuleId(_engineId, _channelId), + false); + if (rtpRtcp->RegisterDefaultModule(_defaultRtpRtcp)) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: could not register default module", + __FUNCTION__); + return -1; + } + _simulcastRtpRtcp.push_back(rtpRtcp); + } + // Remove last in list if we have too many + for (int j = _simulcastRtpRtcp.size(); + j > (videoCodec.numberOfSimulcastStreams - 1); + j--) + { + RtpRtcp* rtpRtcp = _simulcastRtpRtcp.back(); + rtpRtcp->RegisterIncomingRTCPCallback(NULL); + rtpRtcp->RegisterSendTransport(NULL); + _moduleProcessThread.DeRegisterModule(rtpRtcp); + RtpRtcp::DestroyRtpRtcp(rtpRtcp); + _simulcastRtpRtcp.pop_back(); + } + VideoCodec videoCodec; + if (_vcm.Codec(kVideoCodecVP8, &videoCodec) != VCM_OK) + { + WEBRTC_TRACE(webrtc::kTraceWarning, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: VCM: failure geting default VP8 plType", + __FUNCTION__); + return -1; + } + WebRtc_UWord8 idx = 0; + // Configure all simulcast modules + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + idx++; + RtpRtcp* rtpRtcp = *it; + if (rtpRtcp->InitSender() != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: RTP::InitSender failure", + __FUNCTION__); + return -1; + } + if (rtpRtcp->InitReceiver() != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: RTP::InitReceiver failure", + __FUNCTION__); + return -1; + } + if (rtpRtcp->RegisterSendTransport((Transport*) &_vieSender) != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: RTP::RegisterSendTransport failure", + __FUNCTION__); + return -1; + } + if (_moduleProcessThread.RegisterModule(rtpRtcp) != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: RTP::RegisterModule failure", __FUNCTION__); + return -1; + } + if (rtpRtcp->SetRTCPStatus(_rtpRtcp.RTCP()) != 0) + { + WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: RTP::SetRTCPStatus failure", __FUNCTION__); + } + rtpRtcp->DeRegisterSendPayload(videoCodec.plType); + if (rtpRtcp->RegisterSendPayload(videoCodec) != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: could not register payload type", + __FUNCTION__); + return -1; + } + if (restartRtp) + { + rtpRtcp->SetSendingStatus(true); + } + // Configure all simulcast streams min and max bitrates + const WebRtc_UWord32 streamBitrate = std::min(startBitrate, + videoCodec.simulcastStream[idx].maxBitrate); + startBitrate -= streamBitrate; + if (rtpRtcp->SetSendBitrate( + streamBitrate, + videoCodec.minBitrate, + videoCodec.simulcastStream[idx].maxBitrate) != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: could not set send bitrates", + __FUNCTION__); + return -1; + } + } + _vieReceiver.RegisterSimulcastRtpRtcpModules(_simulcastRtpRtcp); + } else + { + if (!_simulcastRtpRtcp.empty()) + { + // delete all simulcast rtp modules + while (!_simulcastRtpRtcp.empty()) + { + RtpRtcp* rtpRtcp = _simulcastRtpRtcp.back(); + rtpRtcp->RegisterIncomingRTCPCallback(NULL); + rtpRtcp->RegisterSendTransport(NULL); + _moduleProcessThread.DeRegisterModule(rtpRtcp); + RtpRtcp::DestroyRtpRtcp(rtpRtcp); + _simulcastRtpRtcp.pop_back(); + } + } + // Clear any previus modules + _vieReceiver.RegisterSimulcastRtpRtcpModules(_simulcastRtpRtcp); + + if (_rtpRtcp.SetSendBitrate(videoCodec.startBitrate * 1000, + videoCodec.minBitrate, + videoCodec.maxBitrate) != 0) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: could not set send bitrates", __FUNCTION__); + return -1; + } } /* TODO Enable this if H264 is available. * This sets the wanted packetization mode. @@ -336,17 +508,16 @@ WebRtc_Word32 ViEChannel::SetSendCodec(const VideoCodec& videoCodec, } }*/ - // Don't log this error, no way to chek in advance if this plType is + // Don't log this error, no way to check in advance if this plType is // registered or not... _rtpRtcp.DeRegisterSendPayload(videoCodec.plType); - if (_rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType) != 0) + if (_rtpRtcp.RegisterSendPayload(videoCodec) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "%s: could not register payload type", __FUNCTION__); return -1; } - if (restartRtp) { _rtpRtcp.SetSendingStatus(true); @@ -360,11 +531,12 @@ WebRtc_Word32 ViEChannel::SetSendCodec(const VideoCodec& videoCodec, WebRtc_Word32 ViEChannel::SetReceiveCodec(const VideoCodec& videoCodec) { + // We will not receive simulcast streams so no need to hadle that usecase WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "%s", __FUNCTION__); _rtpRtcp.DeRegisterReceivePayload(videoCodec.plType); - if (_rtpRtcp.RegisterReceivePayload(videoCodec.plName, videoCodec.plType) + if (_rtpRtcp.RegisterReceivePayload(videoCodec) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, @@ -598,9 +770,18 @@ WebRtc_Word32 ViEChannel::SetSignalPacketLossStatus(bool enable, WebRtc_Word32 ViEChannel::SetRTCPMode(const RTCPMethod rtcpMode) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s: %d", __FUNCTION__, rtcpMode); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: %d", __FUNCTION__, rtcpMode); + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetRTCPStatus(rtcpMode); + } return _rtpRtcp.SetRTCPStatus(rtcpMode); } @@ -682,17 +863,34 @@ WebRtc_Word32 ViEChannel::ProcessNACKRequest(const bool enable) ViEId(_engineId, _channelId), "%s: Using NACK method %d", __FUNCTION__, nackMethod); _rtpRtcp.SetStorePacketsStatus(true, kNackHistorySize); + _vcm.RegisterPacketRequestCallback(this); + + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetStorePacketsStatus(true, kNackHistorySize); + } } else { + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetStorePacketsStatus(false); + } _rtpRtcp.SetStorePacketsStatus(false); _vcm.RegisterPacketRequestCallback(NULL); if (_rtpRtcp.SetNACKStatus(kNackOff) != 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, - ViEId(_engineId, _channelId), - "%s: Could not turn off NACK", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: Could not turn off NACK", __FUNCTION__); return -1; } } @@ -735,7 +933,13 @@ ViEChannel::ProcessFECRequest(const bool enable, enable); return -1; } - + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetGenericFECStatus(enable, payloadTypeRED, payloadTypeFEC); + } return 0; } @@ -820,12 +1024,32 @@ WebRtc_Word32 ViEChannel::EnableKeyFrameRequestCallback(const bool enable) // Sets SSRC for outgoing stream // ---------------------------------------------------------------------------- -WebRtc_Word32 ViEChannel::SetSSRC(const WebRtc_UWord32 SSRC) +WebRtc_Word32 ViEChannel::SetSSRC(const WebRtc_UWord32 SSRC, + const StreamType /*usage*/, + const unsigned char simulcastIdx) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s(SSRC: %u)", __FUNCTION__, SSRC); + // TODO(pwestin) add support for streamType when we add RTX + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s(SSRC: %u, idx:%u)", + __FUNCTION__, SSRC, simulcastIdx); - return _rtpRtcp.SetSSRC(SSRC); + if (simulcastIdx == 0) + { + return _rtpRtcp.SetSSRC(SSRC); + } + std::list::const_iterator it = _simulcastRtpRtcp.begin(); + for (int i = 1; i < simulcastIdx; i++) + { + it++; + if (it == _simulcastRtpRtcp.end()) + { + return -1; + } + } + RtpRtcp* rtpRtcp = *it; + return rtpRtcp->SetSSRC(SSRC); } // ---------------------------------------------------------------------------- @@ -1102,9 +1326,21 @@ WebRtc_Word32 ViEChannel::GetSendRtcpStatistics(WebRtc_UWord16& fractionLost, WebRtc_UWord32& jitterSamples, WebRtc_Word32& rttMs) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); + /* + TODO(pwestin) how do we do this for simulcast? average for all + except cumulativeLost that is the sum? + for (std::list::const_iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + } + */ WebRtc_UWord32 remoteSSRC = _rtpRtcp.RemoteSSRC(); RTCPReportBlock remoteStat; @@ -1179,20 +1415,37 @@ WebRtc_Word32 ViEChannel::GetReceivedRtcpStatistics( // ---------------------------------------------------------------------------- WebRtc_Word32 ViEChannel::GetRtpStatistics( - WebRtc_UWord32& bytesSent, WebRtc_UWord32& packetsSent, - WebRtc_UWord32& bytesReceived, WebRtc_UWord32& packetsReceived) const + WebRtc_UWord32& bytesSent, + WebRtc_UWord32& packetsSent, + WebRtc_UWord32& bytesReceived, + WebRtc_UWord32& packetsReceived) const { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); - if (_rtpRtcp.DataCountersRTP(&bytesSent, &packetsSent, &bytesReceived, + if (_rtpRtcp.DataCountersRTP(&bytesSent, + &packetsSent, + &bytesReceived, &packetsReceived) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, - ViEId(_engineId, _channelId), "%s: Could not get RTT", - __FUNCTION__); + ViEId(_engineId, _channelId), + "%s: Could not get counters", __FUNCTION__); return -1; } + for (std::list::const_iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + WebRtc_UWord32 bytesSentTemp = 0; + WebRtc_UWord32 packetsSentTemp = 0; + RtpRtcp* rtpRtcp = *it; + rtpRtcp->DataCountersRTP(&bytesSentTemp, &packetsSentTemp, NULL, NULL); + bytesSent += bytesSentTemp; + packetsSent += packetsSentTemp; + } return 0; } @@ -1706,6 +1959,14 @@ WebRtc_Word32 ViEChannel::StartSend() "%s: Could not start sending RTP", __FUNCTION__); return -1; } + for (std::list::const_iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetSendingMediaStatus(true); + rtpRtcp->SetSendingStatus(true); + } return 0; } @@ -1715,10 +1976,19 @@ WebRtc_Word32 ViEChannel::StartSend() WebRtc_Word32 ViEChannel::StopSend() { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); _rtpRtcp.SetSendingMediaStatus(false); + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetSendingMediaStatus(false); + } if (_rtpRtcp.RTPKeepalive()) { // Don't turn off sending since we'll send keep alive packets @@ -1740,6 +2010,14 @@ WebRtc_Word32 ViEChannel::StopSend() "%s: could not stop RTP sending", __FUNCTION__); return -1; } + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->ResetSendDataCountersRTP(); + rtpRtcp->SetSendingStatus(false); + } return 0; } @@ -2348,14 +2626,23 @@ WebRtc_Word32 ViEChannel::GetSendGQoS(bool& enabled, WebRtc_Word32 ViEChannel::SetMTU(WebRtc_UWord16 mtu) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); if (_rtpRtcp.SetMaxTransferUnit(mtu) != 0) { // Logging done return -1; } + for (std::list::iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->SetMaxTransferUnit(mtu); + } return 0; } @@ -2581,9 +2868,18 @@ WebRtc_Word32 ViEChannel::EnableColorEnhancement(bool enable) WebRtc_Word32 ViEChannel::RegisterSendRtpRtcpModule( RtpRtcp& sendRtpRtcpModule) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); - return _rtpRtcp.RegisterDefaultModule(&sendRtpRtcpModule); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); + + WebRtc_Word32 retVal = _rtpRtcp.RegisterDefaultModule(&sendRtpRtcpModule); + if (retVal == 0) + { + // we need to store this for the SetSendCodec call + _defaultRtpRtcp = &sendRtpRtcpModule; + } + return retVal; } // ---------------------------------------------------------------------------- @@ -2595,8 +2891,20 @@ WebRtc_Word32 ViEChannel::RegisterSendRtpRtcpModule( WebRtc_Word32 ViEChannel::DeregisterSendRtpRtcpModule() { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); + + _defaultRtpRtcp = NULL; + + for (std::list::const_iterator it = _simulcastRtpRtcp.begin(); + it != _simulcastRtpRtcp.end(); + it++) + { + RtpRtcp* rtpRtcp = *it; + rtpRtcp->DeRegisterDefaultModule(); + } return _rtpRtcp.DeRegisterDefaultModule(); } diff --git a/src/video_engine/main/source/vie_channel.h b/src/video_engine/main/source/vie_channel.h index 29e71c9200..131fd33eb4 100644 --- a/src/video_engine/main/source/vie_channel.h +++ b/src/video_engine/main/source/vie_channel.h @@ -15,11 +15,14 @@ #ifndef WEBRTC_VIDEO_ENGINE_MAIN_SOURCE_VIE_CHANNEL_H_ #define WEBRTC_VIDEO_ENGINE_MAIN_SOURCE_VIE_CHANNEL_H_ +#include + // Defines #include "vie_defines.h" #include "typedefs.h" #include "vie_network.h" +#include "vie_rtp_rtcp.h" #include "rtp_rtcp_defines.h" #include "udp_transport.h" #include "video_coding_defines.h" @@ -117,14 +120,15 @@ public: const unsigned char payloadTypeRED, const unsigned char payloadTypeFEC); - WebRtc_Word32 - SetKeyFrameRequestMethod(const KeyFrameRequestMethod method); + WebRtc_Word32 SetKeyFrameRequestMethod(const KeyFrameRequestMethod method); WebRtc_Word32 EnableTMMBR(const bool enable); WebRtc_Word32 EnableKeyFrameRequestCallback(const bool enable); - WebRtc_Word32 SetSSRC(const WebRtc_UWord32 SSRC); + WebRtc_Word32 SetSSRC(const WebRtc_UWord32 SSRC, + const StreamType usage, + const unsigned char simulcastIdx); WebRtc_Word32 GetLocalSSRC(WebRtc_UWord32& SSRC); @@ -431,11 +435,11 @@ private: // Critical sections // Used for all registered callbacks except rendering. CriticalSectionWrapper& _callbackCritsect; - // Use the same as above instead a seperate? - CriticalSectionWrapper& _dataCritsect; // Owned modules/classes RtpRtcp& _rtpRtcp; + RtpRtcp* _defaultRtpRtcp; + std::list _simulcastRtpRtcp; #ifndef WEBRTC_EXTERNAL_TRANSPORT UdpTransport& _socketTransport; #endif @@ -480,7 +484,5 @@ private: //Recording ViEFileRecorder _fileRecorder; }; - } // namespace webrtc - #endif // WEBRTC_VIDEO_ENGINE_MAIN_SOURCE_VIE_CHANNEL_H_ diff --git a/src/video_engine/main/source/vie_channel_manager.cc b/src/video_engine/main/source/vie_channel_manager.cc index 84f19ef280..5df98cca30 100644 --- a/src/video_engine/main/source/vie_channel_manager.cc +++ b/src/video_engine/main/source/vie_channel_manager.cc @@ -214,11 +214,28 @@ int ViEChannelManager::CreateChannel(int& channelId, int originalChannel) if (vieEncoder == NULL) { // The original channel doesn't exist - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId), - "%s: Original channel doesn't exist", __FUNCTION__, - originalChannel); + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId), + "%s: Original channel doesn't exist", + __FUNCTION__, + originalChannel); return -1; } + VideoCodec videoCodec; + if (vieEncoder->GetEncoder(videoCodec) == 0) + { + if (videoCodec.numberOfSimulcastStreams > 0) + { + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, originalChannel), + "%s: Can't share a simulcast encoder", + __FUNCTION__); + return -1; + } + } + // Get a free id for the new channel if (GetFreeChannelId(channelId) == false) { diff --git a/src/video_engine/main/source/vie_codec_impl.cc b/src/video_engine/main/source/vie_codec_impl.cc index 94af2f07b0..53ea4b6b9a 100644 --- a/src/video_engine/main/source/vie_codec_impl.cc +++ b/src/video_engine/main/source/vie_codec_impl.cc @@ -248,6 +248,19 @@ int ViECodecImpl::SetSendCodec(const int videoChannel, } newRtpStream = true; } + if (videoCodecInternal.numberOfSimulcastStreams > 1) + { + if (cs.ChannelUsingViEEncoder(videoChannel)) + { + // We don't allow simulcast channels to share encoder + WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, + ViEId(_instanceId, videoChannel), + "%s: Can't share simulcast encoder", + __FUNCTION__); + SetLastError(kViECodecInUse); + return -1; + } + } ViEInputManagerScoped is(_inputManager); ViEFrameProviderBase* frameProvider = NULL; @@ -958,7 +971,12 @@ bool ViECodecImpl::CodecValid(const VideoCodec& videoCodec) "Invalid minBitrate: %u", videoCodec.minBitrate); return false; } - + if (videoCodec.numberOfSimulcastStreams == 1) + { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, -1, + "Number of Simulcast streams can not be 1"); + return false; + } if (videoCodec.codecType == kVideoCodecH263) { if ((videoCodec.width == 704 && videoCodec.height == 576) diff --git a/src/video_engine/main/source/vie_encoder.cc b/src/video_engine/main/source/vie_encoder.cc index 2002e983bf..64f4fc8ca7 100644 --- a/src/video_engine/main/source/vie_encoder.cc +++ b/src/video_engine/main/source/vie_encoder.cc @@ -44,23 +44,27 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId, channelId))), _vpm(*webrtc::VideoProcessingModule::Create(ViEModuleId(engineId, channelId))), - _rtpRtcp(*RtpRtcp::CreateRtpRtcp(ViEModuleId(engineId, - channelId), - false)), + _defaultRtpRtcp(*RtpRtcp::CreateRtpRtcp( + ViEModuleId(engineId, channelId), false)), _callbackCritsect(*CriticalSectionWrapper::CreateCriticalSection()), _dataCritsect(*CriticalSectionWrapper::CreateCriticalSection()), - _paused(false), _timeLastIntraRequestMs(0), + _paused(false), _channelsDroppingDeltaFrames(0), _dropNextFrame(false), _fecEnabled(false), _nackEnabled(false), _codecObserver(NULL), _effectFilter(NULL), _moduleProcessThread(moduleProcessThread), _hasReceivedSLI(false), _pictureIdSLI(0), _hasReceivedRPSI(false), _pictureIdRPSI(0), _fileRecorder(channelId) { - WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, + WEBRTC_TRACE(webrtc::kTraceMemory, + webrtc::kTraceVideo, ViEId(engineId, channelId), "%s(engineId: %d) 0x%p - Constructor", __FUNCTION__, engineId, this); + for (int i = 0; i < kMaxSimulcastStreams; i++) + { + _timeLastIntraRequestMs[i] = 0; + } _vcm.InitializeSender(); _vpm.EnableTemporalDecimation(true); @@ -68,10 +72,10 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId, _vpm.EnableContentAnalysis(false); _moduleProcessThread.RegisterModule(&_vcm); - _rtpRtcp.InitSender(); - _rtpRtcp.RegisterIncomingVideoCallback(this); - _rtpRtcp.RegisterIncomingRTCPCallback(this); - _moduleProcessThread.RegisterModule(&_rtpRtcp); + _defaultRtpRtcp.InitSender(); + _defaultRtpRtcp.RegisterIncomingVideoCallback(this); + _defaultRtpRtcp.RegisterIncomingRTCPCallback(this); + _moduleProcessThread.RegisterModule(&_defaultRtpRtcp); // _qmCallback = new QMTestVideoSettingsCallback(); @@ -84,8 +88,8 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId, if (_vcm.Codec(webrtc::kVideoCodecVP8, &videoCodec) == VCM_OK) { _vcm.RegisterSendCodec(&videoCodec, _numberOfCores, - _rtpRtcp.MaxDataPayloadLength()); - _rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType); + _defaultRtpRtcp.MaxDataPayloadLength()); + _defaultRtpRtcp.RegisterSendPayload(videoCodec); } else { @@ -96,8 +100,8 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId, if (_vcm.Codec(webrtc::kVideoCodecI420, &videoCodec) == VCM_OK) { _vcm.RegisterSendCodec(&videoCodec, _numberOfCores, - _rtpRtcp.MaxDataPayloadLength()); - _rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType); + _defaultRtpRtcp.MaxDataPayloadLength()); + _defaultRtpRtcp.RegisterSendPayload(videoCodec); } else { @@ -136,21 +140,21 @@ ViEEncoder::~ViEEncoder() ViEId(_engineId, _channelId), "ViEEncoder Destructor 0x%p, engineId: %d", this, _engineId); - if (_rtpRtcp.NumberChildModules() > 0) + if (_defaultRtpRtcp.NumberChildModules() > 0) { assert(false); WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "Channels still attached %d, leaking memory", - _rtpRtcp.NumberChildModules()); + _defaultRtpRtcp.NumberChildModules()); return; } _moduleProcessThread.DeRegisterModule(&_vcm); _moduleProcessThread.DeRegisterModule(&_vpm); - _moduleProcessThread.DeRegisterModule(&_rtpRtcp); + _moduleProcessThread.DeRegisterModule(&_defaultRtpRtcp); delete &_vcm; delete &_vpm; - delete &_rtpRtcp; + delete &_defaultRtpRtcp; delete &_callbackCritsect; delete &_dataCritsect; delete _qmCallback; @@ -291,7 +295,7 @@ WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 plType) // If the external encoder is the current send codec use vcm internal encoder if (currentSendCodec.plType == plType) { - WebRtc_UWord16 maxDataPayloadLength = _rtpRtcp.MaxDataPayloadLength(); + WebRtc_UWord16 maxDataPayloadLength = _defaultRtpRtcp.MaxDataPayloadLength(); if (_vcm.RegisterSendCodec(¤tSendCodec, _numberOfCores, maxDataPayloadLength) != VCM_OK) { @@ -308,26 +312,33 @@ WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 plType) // SetEncoder // ---------------------------------------------------------------------------- + WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& videoCodec) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, ViEId(_engineId, _channelId), "%s: CodecType: %d, width: %u, height: %u", - __FUNCTION__, videoCodec.codecType, videoCodec.width, - videoCodec.height); + __FUNCTION__, + videoCodec.codecType, + videoCodec.width, + videoCodec.height); // Multiply startBitrate by 1000 because RTP module changed in API. - if (_rtpRtcp.SetSendBitrate(videoCodec.startBitrate * 1000, - videoCodec.minBitrate, videoCodec.maxBitrate) != 0) + if (_defaultRtpRtcp.SetSendBitrate(videoCodec.startBitrate * 1000, + videoCodec.minBitrate, + videoCodec.maxBitrate) != 0) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, - ViEId(_engineId, _channelId), - "Could not set RTP module bitrates"); + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "Could not set RTP module bitrates"); return -1; } - // Setting target width and height for VPM - if (_vpm.SetTargetResolution(videoCodec.width, videoCodec.height, videoCodec.maxFramerate) != VPM_OK) + if (_vpm.SetTargetResolution(videoCodec.width, + videoCodec.height, + videoCodec.maxFramerate) != VPM_OK) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), @@ -336,7 +347,7 @@ WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& videoCodec) } - if (_rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType) != 0) + if (_defaultRtpRtcp.RegisterSendPayload(videoCodec) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), @@ -344,7 +355,8 @@ WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& videoCodec) return -1; } - WebRtc_UWord16 maxDataPayloadLength = _rtpRtcp.MaxDataPayloadLength(); + WebRtc_UWord16 maxDataPayloadLength = + _defaultRtpRtcp.MaxDataPayloadLength(); // update QM with MaxDataPayloadLength _qmCallback->SetMaxPayloadLength(maxDataPayloadLength); @@ -363,9 +375,9 @@ WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& videoCodec) // Set this module as sending right away, let the // slave module in the channel start and stop sending... - if (_rtpRtcp.Sending() == false) + if (_defaultRtpRtcp.Sending() == false) { - if (_rtpRtcp.SetSendingStatus(true) != 0) + if (_defaultRtpRtcp.SetSendingStatus(true) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), @@ -462,14 +474,13 @@ RtpRtcp* ViEEncoder::SendRtpRtcpModule() WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "%s", __FUNCTION__); - return &_rtpRtcp; + return &_defaultRtpRtcp; } //============================================================================= // Data flow //============================================================================= - // ---------------------------------------------------------------------------- // DeliverFrame // Implements ViEFrameCallback::DeliverFrame @@ -485,7 +496,7 @@ void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, { CriticalSectionScoped cs(_dataCritsect); - if (_paused || _rtpRtcp.SendingMedia() == false) + if (_paused || _defaultRtpRtcp.SendingMedia() == false) { // We've passed or we have no channels attached, don't encode return; @@ -524,14 +535,14 @@ void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, { if (CSRC[i] == 1) { - tempCSRC[i] = _rtpRtcp.SSRC(); + tempCSRC[i] = _defaultRtpRtcp.SSRC(); } else { tempCSRC[i] = CSRC[i]; } } - _rtpRtcp.SetCSRCs(tempCSRC, (WebRtc_UWord8) numCSRCs); + _defaultRtpRtcp.SetCSRCs(tempCSRC, (WebRtc_UWord8) numCSRCs); } #ifdef VIDEOCODEC_VP8 @@ -539,7 +550,6 @@ void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, { webrtc::CodecSpecificInfo codecSpecificInfo; codecSpecificInfo.codecType = webrtc::kVideoCodecUnknown; - if (_hasReceivedSLI || _hasReceivedRPSI) { webrtc::VideoCodec currentSendCodec; @@ -565,9 +575,11 @@ void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, } else if (ret != VPM_OK) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s: Error preprocessing frame %u", __FUNCTION__, - videoFrame.TimeStamp()); + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: Error preprocessing frame %u", __FUNCTION__, + videoFrame.TimeStamp()); return; } @@ -615,7 +627,7 @@ void ViEEncoder::DelayChanged(int id, int frameDelay) WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "%s: %u", __FUNCTION__, frameDelay); - _rtpRtcp.SetCameraDelay(frameDelay); + _defaultRtpRtcp.SetCameraDelay(frameDelay); _fileRecorder.SetFrameDelay(frameDelay); } // ---------------------------------------------------------------------------- @@ -651,10 +663,12 @@ int ViEEncoder::GetPreferedFrameSettings(int &width, int &height, WebRtc_Word32 ViEEncoder::SendKeyFrame() { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); - return _vcm.FrameTypeRequest(kVideoFrameKey); + return _vcm.FrameTypeRequest(kVideoFrameKey, 0); // Simulcast idx = 0 } // ---------------------------------------------------------------------------- @@ -700,7 +714,7 @@ WebRtc_Word32 ViEEncoder::UpdateProtectionMethod() WebRtc_UWord8 dummyPTypeFEC = 0; // check if fec is enabled - WebRtc_Word32 error = _rtpRtcp.GenericFECStatus(fecEnabled, dummyPTypeRed, + WebRtc_Word32 error = _defaultRtpRtcp.GenericFECStatus(fecEnabled, dummyPTypeRed, dummyPTypeFEC); if (error) { @@ -708,7 +722,7 @@ WebRtc_Word32 ViEEncoder::UpdateProtectionMethod() } // check if nack is enabled - bool nackEnabled = (_rtpRtcp.NACK() == kNackOff) ? false : true; + bool nackEnabled = (_defaultRtpRtcp.NACK() == kNackOff) ? false : true; if (_fecEnabled == fecEnabled && _nackEnabled == nackEnabled) { // no change to current state @@ -740,7 +754,7 @@ WebRtc_Word32 ViEEncoder::UpdateProtectionMethod() webrtc::VideoCodec codec; if (_vcm.SendCodec(&codec) == 0) { - WebRtc_UWord16 maxPayLoad = _rtpRtcp.MaxDataPayloadLength(); + WebRtc_UWord16 maxPayLoad = _defaultRtpRtcp.MaxDataPayloadLength(); codec.startBitrate = _vcm.Bitrate(); if (_vcm.RegisterSendCodec(&codec, _numberOfCores, maxPayLoad) != 0) { @@ -775,7 +789,7 @@ ViEEncoder::SendData(const FrameType frameType, const WebRtc_UWord8* payloadData, const WebRtc_UWord32 payloadSize, const webrtc::RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* rtpTypeHdr) + const RTPVideoHeader* rtpVideoHdr) { { CriticalSectionScoped cs(_dataCritsect); @@ -786,19 +800,22 @@ ViEEncoder::SendData(const FrameType frameType, } if (_channelsDroppingDeltaFrames && frameType == webrtc::kVideoFrameKey) { - WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, ViEId(_engineId, - _channelId), - "%s: Sending key frame, drop next frame", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceStream, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: Sending key frame, drop next frame", + __FUNCTION__); _dropNextFrame = true; } } // New encoded data, hand over to the rtp module - WebRtc_Word32 retVal = _rtpRtcp.SendOutgoingData(frameType, payloadType, - timeStamp, payloadData, - payloadSize, - &fragmentationHeader, - rtpTypeHdr); - return retVal; + return _defaultRtpRtcp.SendOutgoingData(frameType, + payloadType, + timeStamp, + payloadData, + payloadSize, + &fragmentationHeader, + rtpVideoHdr); } //============================================================================= @@ -822,13 +839,13 @@ WebRtc_Word32 ViEEncoder::ProtectionRequest(const WebRtc_UWord8 deltaFECRate, deltaFECRate, keyFECRate, deltaUseUepProtection, keyUseUepProtection, nack); - if (_rtpRtcp.SetFECCodeRate(keyFECRate, deltaFECRate) != 0) + if (_defaultRtpRtcp.SetFECCodeRate(keyFECRate, deltaFECRate) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "%s: Could not update FEC code rate", __FUNCTION__); } - if (_rtpRtcp.SetFECUepProtection(keyUseUepProtection, + if (_defaultRtpRtcp.SetFECUepProtection(keyUseUepProtection, deltaUseUepProtection) != 0) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, @@ -922,49 +939,48 @@ void ViEEncoder::OnRPSIReceived(const WebRtc_Word32 id, // ---------------------------------------------------------------------------- void ViEEncoder::OnReceivedIntraFrameRequest(const WebRtc_Word32 id, - const WebRtc_UWord8 message) + const FrameType type, + const WebRtc_UWord8 streamIdx) { - // Key frame request from other side, signal to VCM - WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s", __FUNCTION__); + assert(streamIdx < kMaxSimulcastStreams); - if (_timeLastIntraRequestMs + kViEMinKeyRequestIntervalMs - > TickTime::MillisecondTimestamp()) + // Key frame request from other side, signal to VCM + WEBRTC_TRACE(webrtc::kTraceStateInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s", __FUNCTION__); + + WebRtc_Word64 now = TickTime::MillisecondTimestamp(); + if (_timeLastIntraRequestMs[streamIdx] + kViEMinKeyRequestIntervalMs > now) { - WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, - ViEId(_engineId, _channelId), - "%s: Not not encoding new intra due to timing", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceStream, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: Not not encoding new intra due to timing", + __FUNCTION__); return; } - // Default message == 0... - if (message == 0) - { - _vcm.FrameTypeRequest(kVideoFrameKey); - } else - { - _vcm.FrameTypeRequest((FrameType) message); - } - _timeLastIntraRequestMs = TickTime::MillisecondTimestamp(); - return; + _vcm.FrameTypeRequest(type, streamIdx); + _timeLastIntraRequestMs[streamIdx] = now; } // ---------------------------------------------------------------------------- // OnNetworkChanged // ---------------------------------------------------------------------------- void ViEEncoder::OnNetworkChanged(const WebRtc_Word32 id, - const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, + const WebRtc_UWord32 bitrateBps, const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax) + const WebRtc_UWord16 roundTripTimeMs) { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s(minBitrateBps: %u, maxBitrateBps: %u,fractionLost: %u, rttMs: %u, bwEstMinKbit: %u, bwEstMaxKbit: %u", - __FUNCTION__, minBitrateBps, maxBitrateBps, fractionLost, - roundTripTimeMs, bwEstimateKbitMin, bwEstimateKbitMax); - _vcm.SetChannelParameters(minBitrateBps / 1000, fractionLost, roundTripTimeMs); - return; + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s(bitrateBps: %u, fractionLost: %u, rttMs: %u", + __FUNCTION__, bitrateBps, fractionLost, roundTripTimeMs); + + _vcm.SetChannelParameters(bitrateBps / 1000, + fractionLost, + roundTripTimeMs); } WebRtc_Word32 ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effectFilter) @@ -974,22 +990,32 @@ WebRtc_Word32 ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effectFilter) { if (_effectFilter == NULL) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, - _channelId), - "%s: no effect filter added", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId,_channelId), + "%s: no effect filter added", + __FUNCTION__); return -1; } - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s: deregister effect filter", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: deregister effect filter", + __FUNCTION__); } else { - WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId), - "%s: register effect", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceInfo, + webrtc::kTraceVideo, + ViEId(_engineId, _channelId), + "%s: register effect", + __FUNCTION__); if (_effectFilter) { - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, - _channelId), - "%s: effect filter already added ", __FUNCTION__); + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, + ViEId(_engineId,_channelId), + "%s: effect filter already added ", + __FUNCTION__); return -1; } } diff --git a/src/video_engine/main/source/vie_encoder.h b/src/video_engine/main/source/vie_encoder.h index da9715d60b..9bbd44d042 100644 --- a/src/video_engine/main/source/vie_encoder.h +++ b/src/video_engine/main/source/vie_encoder.h @@ -61,8 +61,8 @@ public: WebRtc_Word32 GetEncoder(VideoCodec& videoCodec); WebRtc_Word32 GetCodecConfigParameters( - unsigned char configParameters[kConfigParameterSize], - unsigned char& configParametersSize); + unsigned char configParameters[kConfigParameterSize], + unsigned char& configParametersSize); // Scale or crop/pad image WebRtc_Word32 ScaleInputImage(bool enable); @@ -86,14 +86,14 @@ public: // Loss protection WebRtc_Word32 UpdateProtectionMethod(); // Implements VCMPacketizationCallback - virtual WebRtc_Word32 - SendData(const FrameType frameType, - const WebRtc_UWord8 payloadType, - const WebRtc_UWord32 timeStamp, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord32 payloadSize, - const RTPFragmentationHeader& fragmentationHeader, - const RTPVideoTypeHeader* rtpTypeHdr); + virtual WebRtc_Word32 SendData( + const FrameType frameType, + const WebRtc_UWord8 payloadType, + const WebRtc_UWord32 timeStamp, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord32 payloadSize, + const RTPFragmentationHeader& fragmentationHeader, + const RTPVideoHeader* rtpVideoHdr); // Implements VideoProtectionCallback virtual WebRtc_Word32 ProtectionRequest(const WebRtc_UWord8 deltaFECRate, const WebRtc_UWord8 keyFECRate, @@ -113,14 +113,13 @@ public: // Implements RtpVideoFeedback virtual void OnReceivedIntraFrameRequest(const WebRtc_Word32 id, - const WebRtc_UWord8 message = 0); + const FrameType type, + const WebRtc_UWord8 streamIdx); + virtual void OnNetworkChanged(const WebRtc_Word32 id, - const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, + const WebRtc_UWord32 bitrateBps, const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax); + const WebRtc_UWord16 roundTripTimeMs); // Effect filter WebRtc_Word32 RegisterEffectFilter(ViEEffectFilter* effectFilter); //Recording @@ -156,13 +155,13 @@ private: VideoCodingModule& _vcm; VideoProcessingModule& _vpm; - RtpRtcp& _rtpRtcp; + RtpRtcp& _defaultRtpRtcp; CriticalSectionWrapper& _callbackCritsect; CriticalSectionWrapper& _dataCritsect; VideoCodec _sendCodec; bool _paused; - WebRtc_Word64 _timeLastIntraRequestMs; + WebRtc_Word64 _timeLastIntraRequestMs[kMaxSimulcastStreams]; WebRtc_Word32 _channelsDroppingDeltaFrames; bool _dropNextFrame; //Loss protection diff --git a/src/video_engine/main/source/vie_receiver.cc b/src/video_engine/main/source/vie_receiver.cc index bf14d1534c..779bac346d 100644 --- a/src/video_engine/main/source/vie_receiver.cc +++ b/src/video_engine/main/source/vie_receiver.cc @@ -33,7 +33,9 @@ ViEReceiver::ViEReceiver(int engineId, int channelId, RtpRtcp& moduleRtpRtcp, VideoCodingModule& moduleVcm) : _receiveCritsect(*CriticalSectionWrapper::CreateCriticalSection()), - _engineId(engineId), _channelId(channelId), _rtpRtcp(moduleRtpRtcp), + _engineId(engineId), + _channelId(channelId), + _rtpRtcp(moduleRtpRtcp), _vcm(moduleVcm), #ifdef WEBRTC_SRTP _ptrSrtp(NULL), @@ -44,7 +46,6 @@ ViEReceiver::ViEReceiver(int engineId, int channelId, _ptrExternalDecryption(NULL), _ptrDecryptionBuffer(NULL), _rtpDump(NULL), _receiving(false) { - _rtpRtcp.RegisterIncomingVideoCallback(this); } // ---------------------------------------------------------------------------- @@ -118,6 +119,19 @@ int ViEReceiver::DeregisterExternalDecryption() return 0; } +void ViEReceiver::RegisterSimulcastRtpRtcpModules( + const std::list& rtpModules) +{ + CriticalSectionScoped cs(_receiveCritsect); + _rtpRtcpSimulcast.clear(); + if (!rtpModules.empty()) + { + _rtpRtcpSimulcast.insert(_rtpRtcpSimulcast.begin(), + rtpModules.begin(), + rtpModules.end()); + } +} + #ifdef WEBRTC_SRTP // ---------------------------------------------------------------------------- // RegisterSRTPModule @@ -217,7 +231,6 @@ void ViEReceiver::IncomingRTPPacket(const WebRtc_Word8* incomingRtpPacket, const WebRtc_UWord16 fromPort) { InsertRTPPacket(incomingRtpPacket, incomingRtpPacketLength); - return; } // ---------------------------------------------------------------------------- @@ -232,7 +245,6 @@ void ViEReceiver::IncomingRTCPPacket(const WebRtc_Word8* incomingRtcpPacket, const WebRtc_UWord16 fromPort) { InsertRTCPPacket(incomingRtcpPacket, incomingRtcpPacketLength); - return; } // ---------------------------------------------------------------------------- @@ -420,6 +432,15 @@ int ViEReceiver::InsertRTCPPacket(const WebRtc_Word8* rtcpPacket, (WebRtc_UWord16) receivedPacketLength); } } + { + CriticalSectionScoped cs(_receiveCritsect); + std::list::iterator it = _rtpRtcpSimulcast.begin(); + while (it != _rtpRtcpSimulcast.end()) + { + RtpRtcp* rtpRtcp = *it++; + rtpRtcp->IncomingPacket(receivedPacket, receivedPacketLength); + } + } return _rtpRtcp.IncomingPacket(receivedPacket, receivedPacketLength); } @@ -508,24 +529,4 @@ int ViEReceiver::StopRTPDump() } return 0; } - -// Implements RtpVideoFeedback -void ViEReceiver::OnReceivedIntraFrameRequest(const WebRtc_Word32 id, - const WebRtc_UWord8 message) -{ - // Don't do anything, action trigged on default module - return; -} - -void ViEReceiver::OnNetworkChanged(const WebRtc_Word32 id, - const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, - const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax) -{ - // Called for default module - return; -} } // namespace webrtc diff --git a/src/video_engine/main/source/vie_receiver.h b/src/video_engine/main/source/vie_receiver.h index 086b74e108..51527c0fa9 100644 --- a/src/video_engine/main/source/vie_receiver.h +++ b/src/video_engine/main/source/vie_receiver.h @@ -15,12 +15,13 @@ #ifndef WEBRTC_VIDEO_ENGINE_MAIN_SOURCE_VIE_RECEIVER_H_ #define WEBRTC_VIDEO_ENGINE_MAIN_SOURCE_VIE_RECEIVER_H_ -// Defines +#include + #include "engine_configurations.h" -#include "vie_defines.h" +#include "rtp_rtcp_defines.h" #include "typedefs.h" #include "udp_transport.h" -#include "rtp_rtcp_defines.h" +#include "vie_defines.h" #ifdef WEBRTC_SRTP class SrtpModule; @@ -35,9 +36,7 @@ class RtpRtcp; class VideoCodingModule; class Encryption; -class ViEReceiver: public UdpTransportData, - public RtpData, - public RtpVideoFeedback +class ViEReceiver: public UdpTransportData, public RtpData { public: ViEReceiver(int engineId, int channelId, RtpRtcp& moduleRtpRtcp, @@ -47,6 +46,8 @@ public: int RegisterExternalDecryption(Encryption* decryption); int DeregisterExternalDecryption(); + void RegisterSimulcastRtpRtcpModules(const std::list& rtpModules); + #ifdef WEBRTC_SRTP int RegisterSRTPModule(SrtpModule* srtpModule); int DeregisterSRTPModule(); @@ -76,21 +77,10 @@ public: int ReceivedRTCPPacket(const void* rtcpPacket, int rtcpPacketLength); // From RtpData, callback for data from RTP module - virtual WebRtc_Word32 - OnReceivedPayloadData(const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadSize, - const WebRtcRTPHeader* rtpHeader); - - // Implements RtpVideoFeedback - virtual void OnReceivedIntraFrameRequest(const WebRtc_Word32 id, - const WebRtc_UWord8 message = 0); - virtual void OnNetworkChanged(const WebRtc_Word32 id, - const WebRtc_UWord32 minBitrateBps, - const WebRtc_UWord32 maxBitrateBps, - const WebRtc_UWord8 fractionLost, - const WebRtc_UWord16 roundTripTimeMs, - const WebRtc_UWord16 bwEstimateKbitMin, - const WebRtc_UWord16 bwEstimateKbitMax); + virtual WebRtc_Word32 OnReceivedPayloadData( + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadSize, + const WebRtcRTPHeader* rtpHeader); private: int InsertRTPPacket(const WebRtc_Word8* rtpPacket, int rtpPacketLength); int InsertRTCPPacket(const WebRtc_Word8* rtcpPacket, int rtcpPacketLength); @@ -99,6 +89,7 @@ private: int _engineId; int _channelId; RtpRtcp& _rtpRtcp; + std::list _rtpRtcpSimulcast; VideoCodingModule& _vcm; #ifdef WEBRTC_SRTP diff --git a/src/video_engine/main/source/vie_rtp_rtcp_impl.cc b/src/video_engine/main/source/vie_rtp_rtcp_impl.cc index 7b6ec3787d..1a5a8bbc2e 100644 --- a/src/video_engine/main/source/vie_rtp_rtcp_impl.cc +++ b/src/video_engine/main/source/vie_rtp_rtcp_impl.cc @@ -107,10 +107,14 @@ ViERTP_RTCPImpl::~ViERTP_RTCPImpl() // ---------------------------------------------------------------------------- int ViERTP_RTCPImpl::SetLocalSSRC(const int videoChannel, - const unsigned int SSRC) + const unsigned int SSRC, + const StreamType usage, + const unsigned char simulcastIdx) { - WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, - ViEId(_instanceId, videoChannel), "%s(channel: %d, SSRC: %d)", + WEBRTC_TRACE(webrtc::kTraceApiCall, + webrtc::kTraceVideo, + ViEId(_instanceId, videoChannel), + "%s(channel: %d, SSRC: %d)", __FUNCTION__, videoChannel, SSRC); // Get the channel @@ -119,19 +123,19 @@ int ViERTP_RTCPImpl::SetLocalSSRC(const int videoChannel, if (ptrViEChannel == NULL) { // The channel doesn't exists - WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, + WEBRTC_TRACE(webrtc::kTraceError, + webrtc::kTraceVideo, ViEId(_instanceId, videoChannel), - "%s: Channel %d doesn't exist", __FUNCTION__, - videoChannel); + "%s: Channel %d doesn't exist", + __FUNCTION__, videoChannel); SetLastError(kViERtpRtcpInvalidChannelId); return -1; } - if (ptrViEChannel->SetSSRC(SSRC) != 0) + if (ptrViEChannel->SetSSRC(SSRC, usage, simulcastIdx) != 0) { SetLastError(kViERtpRtcpUnknownError); return -1; } - return 0; } @@ -171,6 +175,14 @@ int ViERTP_RTCPImpl::GetLocalSSRC(const int videoChannel, } +int ViERTP_RTCPImpl::SetRemoteSSRCType(const int videoChannel, + const StreamType usage, + const unsigned int SSRC) const +{ + // TODO(pwestin) add support for RTX + return -1; +} + // ---------------------------------------------------------------------------- // GetRemoteSSRC // diff --git a/src/video_engine/main/source/vie_rtp_rtcp_impl.h b/src/video_engine/main/source/vie_rtp_rtcp_impl.h index 9750a34f41..763128ef99 100644 --- a/src/video_engine/main/source/vie_rtp_rtcp_impl.h +++ b/src/video_engine/main/source/vie_rtp_rtcp_impl.h @@ -38,10 +38,17 @@ public: virtual int Release(); // SSRC/CSRC - virtual int SetLocalSSRC(const int videoChannel, const unsigned int SSRC); + virtual int SetLocalSSRC(const int videoChannel, + const unsigned int SSRC, + const StreamType usage, + const unsigned char simulcastIdx); virtual int GetLocalSSRC(const int videoChannel, unsigned int& SSRC) const; + virtual int SetRemoteSSRCType(const int videoChannel, + const StreamType usage, + const unsigned int SSRC) const; + virtual int GetRemoteSSRC(const int videoChannel, unsigned int& SSRC) const; virtual int GetRemoteCSRCs(const int videoChannel, diff --git a/src/video_engine/main/source/vie_sender.cc b/src/video_engine/main/source/vie_sender.cc index 46dc03165e..49b30b2863 100644 --- a/src/video_engine/main/source/vie_sender.cc +++ b/src/video_engine/main/source/vie_sender.cc @@ -11,11 +11,10 @@ /* * vie_sender.cc */ +#include #include "vie_sender.h" - #include "critical_section_wrapper.h" -#include "rtp_rtcp.h" #ifdef WEBRTC_SRTP #include "SrtpModule.h" #endif @@ -28,11 +27,9 @@ namespace webrtc { // Constructor // ---------------------------------------------------------------------------- -ViESender::ViESender(int engineId, int channelId, - RtpRtcp& rtpRtcpModule) +ViESender::ViESender(int engineId, int channelId) : _engineId(engineId), _channelId(channelId), _sendCritsect(*CriticalSectionWrapper::CreateCriticalSection()), - _rtpRtcp(rtpRtcpModule), #ifdef WEBRTC_SRTP _ptrSrtp(NULL), _ptrSrtcp(NULL), diff --git a/src/video_engine/main/source/vie_sender.h b/src/video_engine/main/source/vie_sender.h index 4d6726710f..1d241140ef 100644 --- a/src/video_engine/main/source/vie_sender.h +++ b/src/video_engine/main/source/vie_sender.h @@ -30,14 +30,13 @@ namespace webrtc { class CriticalSectionWrapper; class RtpDump; -class RtpRtcp; class Transport; class VideoCodingModule; class ViESender: public Transport { public: - ViESender(int engineId, int channelId, RtpRtcp& rtpRtcpModule); + ViESender(int engineId, int channelId); ~ViESender(); int RegisterExternalEncryption(Encryption* encryption); @@ -65,7 +64,6 @@ private: int _engineId; int _channelId; CriticalSectionWrapper& _sendCritsect; - RtpRtcp& _rtpRtcp; #ifdef WEBRTC_SRTP SrtpModule* _ptrSrtp; diff --git a/src/video_engine/main/test/AutoTest/interface/tb_external_transport.h b/src/video_engine/main/test/AutoTest/interface/tb_external_transport.h index a2f56af1c8..b515185ea3 100644 --- a/src/video_engine/main/test/AutoTest/interface/tb_external_transport.h +++ b/src/video_engine/main/test/AutoTest/interface/tb_external_transport.h @@ -37,6 +37,7 @@ public: WebRtc_Word32 SetPacketLoss(WebRtc_Word32 lossRate); // Rate in % void SetNetworkDelay(WebRtc_Word64 delayMs); + void SetSSRCFilter(WebRtc_UWord32 SSRC); void ClearStats(); void GetStats(WebRtc_Word32& numRtpPackets, @@ -88,6 +89,8 @@ private: bool _checkSSRC; WebRtc_UWord32 _lastSSRC; + bool _filterSSRC; + WebRtc_UWord32 _SSRC; bool _checkSequenceNumber; WebRtc_UWord16 _firstSequenceNumber; }; diff --git a/src/video_engine/main/test/AutoTest/interface/vie_autotest.h b/src/video_engine/main/test/AutoTest/interface/vie_autotest.h index 6ceb9d3aa8..352deb3b1f 100644 --- a/src/video_engine/main/test/AutoTest/interface/vie_autotest.h +++ b/src/video_engine/main/test/AutoTest/interface/vie_autotest.h @@ -47,6 +47,7 @@ public: int ViEExtendedTest(); int ViEAPITest(); int ViELoopbackCall(); + int ViESimulcastCall(); // custom call and helper functions int ViECustomCall(); diff --git a/src/video_engine/main/test/AutoTest/source/tb_external_transport.cc b/src/video_engine/main/test/AutoTest/source/tb_external_transport.cc index 67f2ed564f..250c38f9b0 100644 --- a/src/video_engine/main/test/AutoTest/source/tb_external_transport.cc +++ b/src/video_engine/main/test/AutoTest/source/tb_external_transport.cc @@ -12,24 +12,22 @@ // tb_external_transport.cc // -#include // rand #include "tb_external_transport.h" +#include // rand +#if defined(WEBRTC_LINUX) || defined(__linux__) +#include +#include +#endif +#if defined(WEBRTC_MAC) +#include +#endif + #include "critical_section_wrapper.h" #include "event_wrapper.h" #include "thread_wrapper.h" #include "tick_util.h" #include "vie_network.h" -#include "tick_util.h" - -#if defined(WEBRTC_LINUX) || defined(__linux__) -#include -#include -#endif - -#if defined(WEBRTC_MAC) -#include -#endif #if defined(_WIN32) #pragma warning(disable: 4355) // 'this' : used in base member initializer list @@ -52,6 +50,8 @@ tbExternalTransport::tbExternalTransport(webrtc::ViENetwork& vieNetwork) : _rtcpPackets(), _checkSSRC(false), _lastSSRC(0), + _filterSSRC(false), + _SSRC(0), _checkSequenceNumber(0), _firstSequenceNumber(0) { @@ -75,6 +75,18 @@ tbExternalTransport::~tbExternalTransport() int tbExternalTransport::SendPacket(int channel, const void *data, int len) { + if (_filterSSRC) + { + WebRtc_UWord8* ptr = (WebRtc_UWord8*)data; + WebRtc_UWord32 ssrc = ptr[8] << 24; + ssrc += ptr[9] << 16; + ssrc += ptr[10] << 8; + ssrc += ptr[11]; + if (ssrc != _SSRC) + { + return len; // return len to avoif error in trace file + } + } _statCrit.Enter(); _rtpCount++; _statCrit.Leave(); @@ -132,7 +144,13 @@ void tbExternalTransport::SetNetworkDelay(WebRtc_Word64 delayMs) { webrtc::CriticalSectionScoped cs(_crit); _networkDelayMs = delayMs; - return; +} + +void tbExternalTransport::SetSSRCFilter(WebRtc_UWord32 ssrc) +{ + webrtc::CriticalSectionScoped cs(_crit); + _filterSSRC = true; + _SSRC = ssrc; } void tbExternalTransport::ClearStats() @@ -141,7 +159,6 @@ void tbExternalTransport::ClearStats() _rtpCount = 0; _dropCount = 0; _rtcpCount = 0; - return; } void tbExternalTransport::GetStats(WebRtc_Word32& numRtpPackets, @@ -152,7 +169,6 @@ void tbExternalTransport::GetStats(WebRtc_Word32& numRtpPackets, numRtpPackets = _rtpCount; numDroppedPackets = _dropCount; numRtcpPackets = _rtcpCount; - return; } void tbExternalTransport::EnableSSRCCheck() @@ -160,6 +176,7 @@ void tbExternalTransport::EnableSSRCCheck() webrtc::CriticalSectionScoped cs(_statCrit); _checkSSRC = true; } + unsigned int tbExternalTransport::ReceivedSSRC() { webrtc::CriticalSectionScoped cs(_statCrit); @@ -258,8 +275,9 @@ bool tbExternalTransport::ViEExternalTransportProcess() // Send to ViE if (packet) { - _vieNetwork.ReceivedRTPPacket(packet->channel, - packet->packetBuffer, packet->length); + _vieNetwork.ReceivedRTCPPacket( + packet->channel, + packet->packetBuffer, packet->length); delete packet; packet = NULL; } diff --git a/src/video_engine/main/test/AutoTest/source/vie_autotest_main.cc b/src/video_engine/main/test/AutoTest/source/vie_autotest_main.cc index fdaef8f3ba..50ae66b0ae 100644 --- a/src/video_engine/main/test/AutoTest/source/vie_autotest_main.cc +++ b/src/video_engine/main/test/AutoTest/source/vie_autotest_main.cc @@ -55,6 +55,7 @@ bool ViEAutoTestMain::BeginOSIndependentTesting() ViETest::Log("\t 6. Specific extended test"); ViETest::Log("\t 7. Simple loopback call"); ViETest::Log("\t 8. Custom configure a call"); + ViETest::Log("\t 9. Simulcast in loopback"); ViETest::Log("Select type of test: "); if (_useAnswerFile) @@ -73,13 +74,6 @@ bool ViEAutoTestMain::BeginOSIndependentTesting() getchar(); } ViETest::Log(""); - - if (testType < 0 || testType > 8) - { - ViETest::Log("ERROR: Invalid selection. Try again\n"); - continue; - } - switch (testType) { case 0: @@ -257,8 +251,12 @@ bool ViEAutoTestMain::BeginOSIndependentTesting() case 8: testErrors += vieAutoTest.ViECustomCall(); break; - default: + case 9: + testErrors += vieAutoTest.ViESimulcastCall(); break; + default: + ViETest::Log("ERROR: Invalid selection. Try again\n"); + continue; } } while (testType != 0); diff --git a/src/video_engine/main/test/AutoTest/source/vie_autotest_simulcast.cc b/src/video_engine/main/test/AutoTest/source/vie_autotest_simulcast.cc new file mode 100644 index 0000000000..df1f352f47 --- /dev/null +++ b/src/video_engine/main/test/AutoTest/source/vie_autotest_simulcast.cc @@ -0,0 +1,554 @@ +/* + * 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. + */ + +// +// vie_autotest_simulcast.cc +// +// This code is also used as sample code for ViE 3.0 +// + +#include "vie_autotest_defines.h" +#include "vie_autotest.h" + +// =================================================================== +// +// BEGIN: VideoEngine 3.0 Sample Code +// + +#include "common_types.h" +#include "voe_base.h" +#include "vie_base.h" +#include "vie_capture.h" +#include "vie_codec.h" +#include "vie_network.h" +#include "vie_render.h" +#include "vie_rtp_rtcp.h" + +#include +#include "tb_external_transport.h" +#define VCM_RED_PAYLOAD_TYPE 96 +#define VCM_ULPFEC_PAYLOAD_TYPE 97 + +int VideoEngineSimulcastTest(void* window1, void* window2) +{ + //******************************************************** + // Begin create/initialize Video Engine for testing + //******************************************************** + + int error = 0; + + // + // Create a VideoEngine instance + // + webrtc::VideoEngine* ptrViE = NULL; + ptrViE = webrtc::VideoEngine::Create(); + if (ptrViE == NULL) + { + printf("ERROR in VideoEngine::Create\n"); + return -1; + } + + error = ptrViE->SetTraceFilter(webrtc::kTraceAll); + if (error == -1) + { + printf("ERROR in VideoEngine::SetTraceLevel\n"); + return -1; + } + +#ifdef WEBRTC_ANDROID + error = ptrViE->SetTraceFile("/sdcard/ViETrace.txt"); + if (error == -1) + { + printf("ERROR in VideoEngine::SetTraceFile\n"); + return -1; + } + + error = ptrViE->SetTraceFile("/sdcard/ViEEncryptedTrace.txt"); + if (error == -1) + { + printf("ERROR in VideoEngine::SetTraceFile\n"); + return -1; + } +#else + error = ptrViE->SetTraceFile("ViETrace.txt"); + if (error == -1) + { + printf("ERROR in VideoEngine::SetTraceFile\n"); + return -1; + } +#endif + // + // Init VideoEngine and create a channel + // + webrtc::ViEBase* ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE); + if (ptrViEBase == NULL) + { + printf("ERROR in ViEBase::GetInterface\n"); + return -1; + } + + error = ptrViEBase->Init(); + if (error == -1) + { + printf("ERROR in ViEBase::Init\n"); + return -1; + } + + int videoChannel = -1; + error = ptrViEBase->CreateChannel(videoChannel); + if (error == -1) + { + printf("ERROR in ViEBase::CreateChannel\n"); + return -1; + } + + // + // List available capture devices, allocate and connect. + // + webrtc::ViECapture* ptrViECapture = + webrtc::ViECapture::GetInterface(ptrViE); + if (ptrViEBase == NULL) + { + printf("ERROR in ViECapture::GetInterface\n"); + return -1; + } + + const unsigned int KMaxDeviceNameLength = 128; + const unsigned int KMaxUniqueIdLength = 256; + char deviceName[KMaxDeviceNameLength]; + memset(deviceName, 0, KMaxDeviceNameLength); + char uniqueId[KMaxUniqueIdLength]; + memset(uniqueId, 0, KMaxUniqueIdLength); + + printf("Available capture devices:\n"); + int captureIdx = 0; + for (captureIdx = 0; + captureIdx < ptrViECapture->NumberOfCaptureDevices(); + captureIdx++) + { + memset(deviceName, 0, KMaxDeviceNameLength); + memset(uniqueId, 0, KMaxUniqueIdLength); + + error = ptrViECapture->GetCaptureDevice(captureIdx, deviceName, + KMaxDeviceNameLength, uniqueId, + KMaxUniqueIdLength); + if (error == -1) + { + printf("ERROR in ViECapture::GetCaptureDevice\n"); + return -1; + } + printf("\t %d. %s\n", captureIdx + 1, deviceName); + } + printf("\nChoose capture device: "); +#ifdef WEBRTC_ANDROID + captureIdx = 0; + printf("0\n"); +#else + if (scanf("%d", &captureIdx) != 1) + { + printf("Error in scanf()\n"); + return -1; + } + getchar(); + captureIdx = captureIdx - 1; // Compensate for idx start at 1. +#endif + error = ptrViECapture->GetCaptureDevice(captureIdx, deviceName, + KMaxDeviceNameLength, uniqueId, + KMaxUniqueIdLength); + if (error == -1) + { + printf("ERROR in ViECapture::GetCaptureDevice\n"); + return -1; + } + + int captureId = 0; + error = ptrViECapture->AllocateCaptureDevice(uniqueId, KMaxUniqueIdLength, + captureId); + if (error == -1) + { + printf("ERROR in ViECapture::AllocateCaptureDevice\n"); + return -1; + } + + error = ptrViECapture->ConnectCaptureDevice(captureId, videoChannel); + if (error == -1) + { + printf("ERROR in ViECapture::ConnectCaptureDevice\n"); + return -1; + } + + error = ptrViECapture->StartCapture(captureId); + if (error == -1) + { + printf("ERROR in ViECapture::StartCapture\n"); + return -1; + } + + // + // RTP/RTCP settings + // + webrtc::ViERTP_RTCP* ptrViERtpRtcp = + webrtc::ViERTP_RTCP::GetInterface(ptrViE); + if (ptrViERtpRtcp == NULL) + { + printf("ERROR in ViERTP_RTCP::GetInterface\n"); + return -1; + } + + error = ptrViERtpRtcp->SetRTCPStatus(videoChannel, + webrtc::kRtcpCompound_RFC4585); + if (error == -1) + { + printf("ERROR in ViERTP_RTCP::SetRTCPStatus\n"); + return -1; + } + + error = ptrViERtpRtcp->SetKeyFrameRequestMethod( + videoChannel, webrtc::kViEKeyFrameRequestPliRtcp); + if (error == -1) + { + printf("ERROR in ViERTP_RTCP::SetKeyFrameRequestMethod\n"); + return -1; + } + + // + // Set up rendering + // + webrtc::ViERender* ptrViERender = webrtc::ViERender::GetInterface(ptrViE); + if (ptrViERender == NULL) + { + printf("ERROR in ViERender::GetInterface\n"); + return -1; + } + + error + = ptrViERender->AddRenderer(captureId, window1, 0, 0.0, 0.0, 1.0, 1.0); + if (error == -1) + { + printf("ERROR in ViERender::AddRenderer\n"); + return -1; + } + + error = ptrViERender->StartRender(captureId); + if (error == -1) + { + printf("ERROR in ViERender::StartRender\n"); + return -1; + } + + error = ptrViERender->AddRenderer(videoChannel, window2, 1, 0.0, 0.0, 1.0, + 1.0); + if (error == -1) + { + printf("ERROR in ViERender::AddRenderer\n"); + return -1; + } + + error = ptrViERender->StartRender(videoChannel); + if (error == -1) + { + printf("ERROR in ViERender::StartRender\n"); + return -1; + } + + // + // Setup codecs + // + webrtc::ViECodec* ptrViECodec = webrtc::ViECodec::GetInterface(ptrViE); + if (ptrViECodec == NULL) + { + printf("ERROR in ViECodec::GetInterface\n"); + return -1; + } + + // Check available codecs and prepare receive codecs + printf("\nAvailable codecs:\n"); + webrtc::VideoCodec videoCodec; + memset(&videoCodec, 0, sizeof(webrtc::VideoCodec)); + int codecIdx = 0; + for (codecIdx = 0; codecIdx < ptrViECodec->NumberOfCodecs(); codecIdx++) + { + error = ptrViECodec->GetCodec(codecIdx, videoCodec); + if (error == -1) + { + printf("ERROR in ViECodec::GetCodec\n"); + return -1; + } + // try to keep the test frame size small when I420 + if (videoCodec.codecType != webrtc::kVideoCodecVP8) + { + continue; + } + error = ptrViECodec->SetReceiveCodec(videoChannel, videoCodec); + if (error == -1) + { + printf("ERROR in ViECodec::SetReceiveCodec\n"); + return -1; + } + if (videoCodec.codecType != webrtc::kVideoCodecRED + && videoCodec.codecType != webrtc::kVideoCodecULPFEC) + { + printf("\t %d. %s\n", codecIdx + 1, videoCodec.plName); + } + break; + } + error = ptrViECodec->GetCodec(codecIdx, videoCodec); + if (error == -1) + { + printf("ERROR in ViECodec::GetCodec\n"); + return -1; + } + + // Set spatial resolution option + videoCodec.width = 1280; + videoCodec.height = 720; + + // simulcast settings + videoCodec.numberOfSimulcastStreams = 3; + videoCodec.simulcastStream[0].width = 320; + videoCodec.simulcastStream[0].height = 180; + videoCodec.simulcastStream[0].numberOfTemporalLayers = 0; + videoCodec.simulcastStream[0].maxBitrate = 100; + videoCodec.simulcastStream[0].qpMax = videoCodec.qpMax; + + videoCodec.simulcastStream[1].width = 640; + videoCodec.simulcastStream[1].height = 360; + videoCodec.simulcastStream[1].numberOfTemporalLayers = 0; + videoCodec.simulcastStream[1].maxBitrate = 500; + videoCodec.simulcastStream[1].qpMax = videoCodec.qpMax; + + videoCodec.simulcastStream[2].width = 1280; + videoCodec.simulcastStream[2].height = 720; + videoCodec.simulcastStream[2].numberOfTemporalLayers = 0; + videoCodec.simulcastStream[2].maxBitrate = 1200; + videoCodec.simulcastStream[2].qpMax = videoCodec.qpMax; + + // Set start bit rate + std::string str; + std::cout << std::endl; + std::cout << "Choose start rate (in kbps). Press enter for default: "; + std::getline(std::cin, str); + int startRate = atoi(str.c_str()); + if(startRate != 0) + { + videoCodec.startBitrate=startRate; + } + + error = ptrViECodec->SetSendCodec(videoChannel, videoCodec); + if (error == -1) + { + printf("ERROR in ViECodec::SetSendCodec\n"); + return -1; + } + // + // Address settings + // + webrtc::ViENetwork* ptrViENetwork = + webrtc::ViENetwork::GetInterface(ptrViE); + if (ptrViENetwork == NULL) + { + printf("ERROR in ViENetwork::GetInterface\n"); + return -1; + } + + // Setting External transport + tbExternalTransport extTransport(*(ptrViENetwork)); + + error = ptrViENetwork->RegisterSendTransport(videoChannel, + extTransport); + if (error == -1) + { + printf("ERROR in ViECodec::RegisterSendTransport \n"); + return -1; + } + + extTransport.SetPacketLoss(0); + + // Set network delay value + extTransport.SetNetworkDelay(10); + + extTransport.SetSSRCFilter(3); + + for (int idx = 0; idx < 3; idx++) + { + error = ptrViERtpRtcp->SetLocalSSRC(videoChannel, + idx+1, // SSRC + webrtc::kViEStreamTypeNormal, + idx); + if (error == -1) + { + printf("ERROR in ViERTP_RTCP::SetLocalSSRC(idx:%d)\n", idx); + return -1; + } + } + + error = ptrViEBase->StartReceive(videoChannel); + if (error == -1) + { + printf("ERROR in ViENetwork::StartReceive\n"); + return -1; + } + + error = ptrViEBase->StartSend(videoChannel); + if (error == -1) + { + printf("ERROR in ViENetwork::StartSend\n"); + return -1; + } + + //******************************************************** + // Engine started + //******************************************************** + + printf("\nSimulcast call started\n\n"); + do + { + printf("Enter new SSRC filter 1,2 or 3\n"); + printf("Press enter to stop..."); + str.clear(); + std::getline(std::cin, str); + if (!str.empty()) + { + int ssrc = atoi(str.c_str()); + if (ssrc > 0 && ssrc < 4) + { + extTransport.SetSSRCFilter(ssrc); + } else + { + printf("Invalid SSRC\n"); + } + } else + { + break; + } + } while (true); + + //******************************************************** + // Testing finished. Tear down Video Engine + //******************************************************** + + error = ptrViEBase->StopReceive(videoChannel); + if (error == -1) + { + printf("ERROR in ViEBase::StopReceive\n"); + return -1; + } + + error = ptrViEBase->StopSend(videoChannel); + if (error == -1) + { + printf("ERROR in ViEBase::StopSend\n"); + return -1; + } + + error = ptrViERender->StopRender(captureId); + if (error == -1) + { + printf("ERROR in ViERender::StopRender\n"); + return -1; + } + + error = ptrViERender->RemoveRenderer(captureId); + if (error == -1) + { + printf("ERROR in ViERender::RemoveRenderer\n"); + return -1; + } + + error = ptrViERender->StopRender(videoChannel); + if (error == -1) + { + printf("ERROR in ViERender::StopRender\n"); + return -1; + } + + error = ptrViERender->RemoveRenderer(videoChannel); + if (error == -1) + { + printf("ERROR in ViERender::RemoveRenderer\n"); + return -1; + } + + error = ptrViECapture->StopCapture(captureId); + if (error == -1) + { + printf("ERROR in ViECapture::StopCapture\n"); + return -1; + } + + error = ptrViECapture->DisconnectCaptureDevice(videoChannel); + if (error == -1) + { + printf("ERROR in ViECapture::DisconnectCaptureDevice\n"); + return -1; + } + + error = ptrViECapture->ReleaseCaptureDevice(captureId); + if (error == -1) + { + printf("ERROR in ViECapture::ReleaseCaptureDevice\n"); + return -1; + } + + error = ptrViEBase->DeleteChannel(videoChannel); + if (error == -1) + { + printf("ERROR in ViEBase::DeleteChannel\n"); + return -1; + } + + int remainingInterfaces = 0; + remainingInterfaces = ptrViECodec->Release(); + remainingInterfaces += ptrViECapture->Release(); + remainingInterfaces += ptrViERtpRtcp->Release(); + remainingInterfaces += ptrViERender->Release(); + remainingInterfaces += ptrViENetwork->Release(); + remainingInterfaces += ptrViEBase->Release(); + if (remainingInterfaces > 0) + { + printf("ERROR: Could not release all interfaces\n"); + return -1; + } + + bool deleted = webrtc::VideoEngine::Delete(ptrViE); + if (deleted == false) + { + printf("ERROR in VideoEngine::Delete\n"); + return -1; + } + return 0; + + // + // END: VideoEngine 3.0 Sample Code + // + // =================================================================== +} + +int ViEAutoTest::ViESimulcastCall() +{ + ViETest::Log(" "); + ViETest::Log("========================================"); + ViETest::Log(" ViE Autotest Simulcast Call\n"); + + if (VideoEngineSimulcastTest(_window1, _window2) == 0) + { + ViETest::Log(" "); + ViETest::Log(" ViE Autotest Simulcast Call Done"); + ViETest::Log("========================================"); + ViETest::Log(" "); + + return 0; + } + ViETest::Log(" "); + ViETest::Log(" ViE Autotest Simulcast Call Failed"); + ViETest::Log("========================================"); + ViETest::Log(" "); + return 1; +} diff --git a/src/video_engine/main/test/AutoTest/vie_auto_test.gypi b/src/video_engine/main/test/AutoTest/vie_auto_test.gypi index f2aeb7f67d..bcd659903c 100644 --- a/src/video_engine/main/test/AutoTest/vie_auto_test.gypi +++ b/src/video_engine/main/test/AutoTest/vie_auto_test.gypi @@ -67,6 +67,7 @@ 'source/vie_autotest_render.cc', 'source/vie_autotest_rtp_rtcp.cc', 'source/vie_autotest_custom_call.cc', + 'source/vie_autotest_simulcast.cc', # Platform dependent # Linux diff --git a/src/voice_engine/main/source/channel.cc b/src/voice_engine/main/source/channel.cc index 3d3032a50e..b0002735ff 100644 --- a/src/voice_engine/main/source/channel.cc +++ b/src/voice_engine/main/source/channel.cc @@ -1485,11 +1485,7 @@ Channel::Init() { // Open up the RTP/RTCP receiver for all supported codecs if ((_audioCodingModule.Codec(idx, codec) == -1) || - (_rtpRtcpModule.RegisterReceivePayload(codec.plname, - codec.pltype, - codec.plfreq, - codec.channels, - codec.rate) == -1)) + (_rtpRtcpModule.RegisterReceivePayload(codec) == -1)) { WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), @@ -1517,10 +1513,7 @@ Channel::Init() // Register default PT for outband 'telephone-event' if (!STR_CASE_CMP(codec.plname, "telephone-event")) { - if ((_rtpRtcpModule.RegisterSendPayload(codec.plname, - codec.pltype, - codec.plfreq, - codec.channels) == -1) || + if ((_rtpRtcpModule.RegisterSendPayload(codec) == -1) || (_audioCodingModule.RegisterReceiveCodec(codec) == -1)) { WEBRTC_TRACE(kTraceWarning, kTraceVoice, @@ -1535,10 +1528,7 @@ Channel::Init() { if ((_audioCodingModule.RegisterSendCodec(codec) == -1) || (_audioCodingModule.RegisterReceiveCodec(codec) == -1) || - (_rtpRtcpModule.RegisterSendPayload(codec.plname, - codec.pltype, - codec.plfreq, - codec.channels) == -1)) + (_rtpRtcpModule.RegisterSendPayload(codec) == -1)) { WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId,_channelId), @@ -2379,20 +2369,10 @@ Channel::SetSendCodec(const CodecInst& codec) return -1; } - if (_rtpRtcpModule.RegisterSendPayload( - codec.plname, - codec.pltype, - codec.plfreq, - codec.channels, - (codec.rate < 0 ? 0 : codec.rate)) != 0) + if (_rtpRtcpModule.RegisterSendPayload(codec) != 0) { _rtpRtcpModule.DeRegisterSendPayload(codec.pltype); - if (_rtpRtcpModule.RegisterSendPayload( - codec.plname, - codec.pltype, - codec.plfreq, - codec.channels, - (codec.rate < 0 ? 0 : codec.rate)) != 0) + if (_rtpRtcpModule.RegisterSendPayload(codec) != 0) { WEBRTC_TRACE( kTraceError, kTraceVoice, VoEId(_instanceId,_channelId), @@ -2474,12 +2454,7 @@ Channel::SetRecPayloadType(const CodecInst& codec) CodecInst rxCodec = codec; // Get payload type for the given codec - _rtpRtcpModule.ReceivePayloadType( - rxCodec.plname, - rxCodec.plfreq, - rxCodec.channels, - &pltype, - (rxCodec.rate < 0 ? 0 : rxCodec.rate)); + _rtpRtcpModule.ReceivePayloadType(rxCodec, &pltype); rxCodec.pltype = pltype; if (_rtpRtcpModule.DeRegisterReceivePayload(pltype) != 0) @@ -2501,21 +2476,11 @@ Channel::SetRecPayloadType(const CodecInst& codec) return 0; } - if (_rtpRtcpModule.RegisterReceivePayload( - codec.plname, - codec.pltype, - codec.plfreq, - codec.channels, - (codec.rate < 0 ? 0 : codec.rate)) != 0) + if (_rtpRtcpModule.RegisterReceivePayload(codec) != 0) { // First attempt to register failed => de-register and try again _rtpRtcpModule.DeRegisterReceivePayload(codec.pltype); - if (_rtpRtcpModule.RegisterReceivePayload( - codec.plname, - codec.pltype, - codec.plfreq, - codec.channels, - (codec.rate < 0 ? 0 : codec.rate)) != 0) + if (_rtpRtcpModule.RegisterReceivePayload(codec) != 0) { _engineStatisticsPtr->SetLastError( VE_RTP_RTCP_MODULE_ERROR, kTraceError, @@ -2543,12 +2508,7 @@ Channel::GetRecPayloadType(CodecInst& codec) WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::GetRecPayloadType()"); WebRtc_Word8 payloadType(-1); - if (_rtpRtcpModule.ReceivePayloadType(( - const WebRtc_Word8*)codec.plname, - codec.plfreq, - codec.channels, - &payloadType, - (codec.rate < 0 ? 0 : codec.rate)) != 0) + if (_rtpRtcpModule.ReceivePayloadType(codec, &payloadType) != 0) { _engineStatisticsPtr->SetLastError( VE_RTP_RTCP_MODULE_ERROR, kTraceError, @@ -2635,16 +2595,10 @@ Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) return -1; } - if (_rtpRtcpModule.RegisterSendPayload(codec.plname, - codec.pltype, - codec.plfreq, - codec.channels) != 0) + if (_rtpRtcpModule.RegisterSendPayload(codec) != 0) { _rtpRtcpModule.DeRegisterSendPayload(codec.pltype); - if (_rtpRtcpModule.RegisterSendPayload(codec.plname, - codec.pltype, - codec.plfreq, - codec.channels) != 0) + if (_rtpRtcpModule.RegisterSendPayload(codec) != 0) { _engineStatisticsPtr->SetLastError( VE_RTP_RTCP_MODULE_ERROR, kTraceError, @@ -4539,9 +4493,11 @@ Channel::SetSendTelephoneEventPayloadType(unsigned char type) "SetSendTelephoneEventPayloadType() invalid type"); return -1; } - const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE] = - "telephone-event"; - if (_rtpRtcpModule.RegisterSendPayload(payloadName, type, 8000) != 0) + CodecInst codec; + codec.plfreq = 8000; + codec.pltype = type; + memcpy(codec.plname, "telephone-event", 16); + if (_rtpRtcpModule.RegisterSendPayload(codec) != 0) { _engineStatisticsPtr->SetLastError( VE_RTP_RTCP_MODULE_ERROR, kTraceError, @@ -6630,11 +6586,7 @@ Channel::RegisterReceiveCodecsToRTPModule() { // Open up the RTP/RTCP receiver for all supported codecs if ((_audioCodingModule.Codec(idx, codec) == -1) || - (_rtpRtcpModule.RegisterReceivePayload(codec.plname, - codec.pltype, - codec.plfreq, - codec.channels, - codec.rate) == -1)) + (_rtpRtcpModule.RegisterReceivePayload(codec) == -1)) { WEBRTC_TRACE( kTraceWarning,