From 07bf43c67303db4ab64b44f5b849465ec7dfef75 Mon Sep 17 00:00:00 2001 From: "phoglund@webrtc.org" Date: Tue, 18 Dec 2012 15:40:53 +0000 Subject: [PATCH] Replaced the _audio parameter with a strategy. The purpose is to make _rtpReceiver mostly agnostic to if it processes audio or video, and make its delegates responsible for that. This patch makes the actual interfaces and interactions between the classes a lot clearer which will probably help straighten out the rather convoluted business logic in here. There are a number of rough edges I hope to address in coming patches. In particular, I think there are a lot of audio-specific hacks, especially when it comes to telephone event handling. I think we will see a lot of benefit once that stuff moves out of rtp_receiver altogether. The new strategy I introduced doesn't quite pull its own weight yet, but I think I will be able to remove a lot of that interface later once the responsibilities of the classes becomes move cohesive (e.g. that audio specific stuff actually lives in the audio class, and so on). Also I think it should be possible to extract payload type management to a helper class later on. BUG= TEST=vie/voe_auto_test, trybots Review URL: https://webrtc-codereview.appspot.com/1001006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3306 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../rtp_rtcp/interface/rtp_rtcp_defines.h | 1 + .../modules/rtp_rtcp/source/rtp_receiver.cc | 277 ++++++------------ webrtc/modules/rtp_rtcp/source/rtp_receiver.h | 20 +- .../rtp_rtcp/source/rtp_receiver_audio.cc | 140 ++++++++- .../rtp_rtcp/source/rtp_receiver_audio.h | 77 ++++- .../rtp_rtcp/source/rtp_receiver_strategy.cc | 31 ++ .../rtp_rtcp/source/rtp_receiver_strategy.h | 115 ++++++++ .../rtp_rtcp/source/rtp_receiver_video.cc | 65 +++- .../rtp_rtcp/source/rtp_receiver_video.h | 64 ++-- webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi | 2 + .../modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 7 +- webrtc/modules/rtp_rtcp/source/rtp_utility.cc | 12 + webrtc/modules/rtp_rtcp/source/rtp_utility.h | 12 +- 13 files changed, 581 insertions(+), 242 deletions(-) create mode 100644 webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.cc create mode 100644 webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h index 0bdbec0b4..8363d82f6 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h @@ -24,6 +24,7 @@ #define TIMEOUT_SEI_MESSAGES_MS 30000 // in milliseconds namespace webrtc{ + enum RTCPMethod { kRtcpOff = 0, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc index 43cbdcf67..51ef3ff98 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc @@ -8,17 +8,20 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "trace.h" #include "rtp_receiver.h" -#include "rtp_rtcp_defines.h" -#include "rtp_rtcp_impl.h" -#include "critical_section_wrapper.h" - #include -#include //memcpy #include // floor #include // abs +#include //memcpy + +#include "critical_section_wrapper.h" +#include "rtp_receiver_audio.h" +#include "rtp_receiver_strategy.h" +#include "rtp_receiver_video.h" +#include "rtp_rtcp_defines.h" +#include "rtp_rtcp_impl.h" +#include "trace.h" namespace webrtc { @@ -36,7 +39,6 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id, RtpAudioFeedback* incomingMessagesCallback) : Bitrate(clock), _id(id), - _audio(audio), _rtpRtcp(*owner), _criticalSectionCbs(CriticalSectionWrapper::CreateCriticalSection()), _cbRtpFeedback(NULL), @@ -48,8 +50,6 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id, _lastReceivedPayloadLength(0), _lastReceivedPayloadType(-1), _lastReceivedMediaPayloadType(-1), - _lastReceivedAudioSpecific(), - _lastReceivedVideoSpecific(), _packetTimeOutMS(0), @@ -95,16 +95,21 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id, _nackMethod(kNackOff), _RTX(false), _ssrcRTX(0) { + // TODO(phoglund): Remove hacks requiring direct access to the audio receiver + // and only instantiate one of these directly into the _rtpMediaReceiver + // field. Right now an audio receiver carries around a video handler and + // vice versa, which doesn't make sense. _rtpReceiverAudio = new RTPReceiverAudio(id, this, incomingMessagesCallback); _rtpReceiverVideo = new RTPReceiverVideo(id, this, owner); + if (audio) { + _rtpMediaReceiver = _rtpReceiverAudio; + } else { + _rtpMediaReceiver = _rtpReceiverVideo; + } + memset(_currentRemoteCSRC, 0, sizeof(_currentRemoteCSRC)); memset(_currentRemoteEnergy, 0, sizeof(_currentRemoteEnergy)); - memset(&_lastReceivedAudioSpecific, 0, sizeof(_lastReceivedAudioSpecific)); - - _lastReceivedAudioSpecific.channels = 1; - _lastReceivedVideoSpecific.maxRate = 0; - _lastReceivedVideoSpecific.videoCodecType = kRtpNoVideo; WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__); } @@ -131,13 +136,17 @@ RTPReceiver::~RTPReceiver() { RtpVideoCodecTypes RTPReceiver::VideoCodecType() const { - return _lastReceivedVideoSpecific.videoCodecType; + ModuleRTPUtility::PayloadUnion mediaSpecific; + _rtpMediaReceiver->GetLastMediaSpecificPayload(&mediaSpecific); + return mediaSpecific.Video.videoCodecType; } WebRtc_UWord32 RTPReceiver::MaxConfiguredBitrate() const { - return _lastReceivedVideoSpecific.maxRate; + ModuleRTPUtility::PayloadUnion mediaSpecific; + _rtpMediaReceiver->GetLastMediaSpecificPayload(&mediaSpecific); + return mediaSpecific.Video.maxRate; } bool @@ -201,7 +210,7 @@ void RTPReceiver::PacketTimeout() } void -RTPReceiver::ProcessDeadOrAlive(const bool RTCPalive, const WebRtc_Word64 now) +RTPReceiver::ProcessDeadOrAlive(const bool rtcpAlive, const WebRtc_Word64 now) { if(_cbRtpFeedback == NULL) { @@ -217,25 +226,10 @@ RTPReceiver::ProcessDeadOrAlive(const bool RTCPalive, const WebRtc_Word64 now) } else { - if(RTCPalive) + if(rtcpAlive) { - if(_audio) - { - // alive depends on CNG - // if last received size < 10 likely CNG - if(_lastReceivedPayloadLength < 10) // our CNG is 9 bytes - { - // potential CNG - // receiver need to check kRtpNoRtp against NetEq speechType kOutputPLCtoCNG - alive = kRtpNoRtp; - } else - { - // dead - } - } else - { - // dead for video - } + alive = _rtpMediaReceiver->ProcessDeadOrAlive( + _lastReceivedPayloadLength); }else { // no RTP packet for 1 sec and no RTCP @@ -331,19 +325,9 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload( // if same ignore sending an error if (payloadNameLength == nameLength && StringCompare(payload->name, payloadName, payloadNameLength)) { - if (_audio && - payload->audio && - payload->typeSpecific.Audio.frequency == frequency && - payload->typeSpecific.Audio.channels == channels && - (payload->typeSpecific.Audio.rate == rate || - payload->typeSpecific.Audio.rate == 0 || rate == 0)) { - payload->typeSpecific.Audio.rate = rate; - // Ensure that we update the rate if new or old is zero - return 0; - } - if (!_audio && !payload->audio) { - // update maxBitrate for video - payload->typeSpecific.Video.maxRate = rate; + if (_rtpMediaReceiver->PayloadIsCompatible(*payload, frequency, + channels, rate)) { + _rtpMediaReceiver->UpdatePayloadRate(payload, rate); return 0; } } @@ -352,38 +336,11 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload( __FUNCTION__, payloadType); return -1; } - if (_audio) { - // remove existing item, hence search for the name - // only for audio, for video we allow a codecs to use multiple pltypes - std::map::iterator audio_it = - _payloadTypeMap.begin(); - while (audio_it != _payloadTypeMap.end()) { - Payload* payload = audio_it->second; - size_t nameLength = strlen(payload->name); - if (payloadNameLength == nameLength && - StringCompare(payload->name, payloadName, payloadNameLength)) { - // we found the payload name in the list - // if audio check frequency and rate - if (payload->audio) { - if (payload->typeSpecific.Audio.frequency == frequency && - (payload->typeSpecific.Audio.rate == rate || - payload->typeSpecific.Audio.rate == 0 || rate == 0) && - payload->typeSpecific.Audio.channels == channels) { - // remove old setting - delete payload; - _payloadTypeMap.erase(audio_it); - break; - } - } else if(StringCompare(payloadName,"red",3)) { - delete payload; - _payloadTypeMap.erase(audio_it); - break; - } - } - audio_it++; - } - } + _rtpMediaReceiver->PossiblyRemoveExistingPayloadType( + &_payloadTypeMap, payloadName, payloadNameLength, frequency, channels, + rate); + Payload* payload = NULL; // save the RED payload type @@ -395,13 +352,8 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload( payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); } else { - if (_audio) { - payload = _rtpReceiverAudio->RegisterReceiveAudioPayload( - payloadName, payloadType, frequency, channels, rate); - } else { - payload = _rtpReceiverVideo->RegisterReceiveVideoPayload( - payloadName, payloadType, rate); - } + payload = _rtpMediaReceiver->CreatePayloadType( + payloadName, payloadType, frequency, channels, rate); } if (payload == NULL) { WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, @@ -512,7 +464,7 @@ WebRtc_Word32 RTPReceiver::ReceivePayload( if(payload->audio) { *frequency = payload->typeSpecific.Audio.frequency; } else { - *frequency = 90000; + *frequency = kDefaultVideoFrequency; } } if (channels) { @@ -565,7 +517,7 @@ WebRtc_Word32 RTPReceiver::RemotePayload( if (payload->audio) { *frequency = payload->typeSpecific.Audio.frequency; } else { - *frequency = 90000; + *frequency = kDefaultVideoFrequency; } } if (channels) { @@ -721,19 +673,12 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket( CheckSSRCChanged(rtp_header); bool is_red = false; - VideoPayload video_specific; - video_specific.maxRate = 0; - video_specific.videoCodecType = kRtpNoVideo; - - AudioPayload audio_specific; - audio_specific.channels = 0; - audio_specific.frequency = 0; + ModuleRTPUtility::PayloadUnion specificPayload; if (CheckPayloadChanged(rtp_header, first_payload_byte, is_red, - audio_specific, - video_specific) == -1) { + &specificPayload) == -1) { if (length - rtp_header->header.headerLength == 0) { // ok keepalive packet @@ -749,22 +694,13 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket( } CheckCSRC(rtp_header); - const WebRtc_UWord8* payload_data = - packet + rtp_header->header.headerLength; - WebRtc_UWord16 payload_data_length = - static_cast(length - rtp_header->header.headerLength); + ModuleRTPUtility::GetPayloadDataLength(rtp_header, packet_length); + + WebRtc_Word32 retVal = _rtpMediaReceiver->ParseRtpPacket( + rtp_header, specificPayload, is_red, packet, + packet_length, _clock.GetTimeInMS()); - WebRtc_Word32 retVal = 0; - if(_audio) { - retVal = _rtpReceiverAudio->ParseAudioCodecSpecific( - rtp_header, payload_data, payload_data_length, audio_specific, is_red); - } else { - retVal = _rtpReceiverVideo->ParseVideoCodecSpecific( - rtp_header, payload_data, payload_data_length, - video_specific.videoCodecType, is_red, packet, packet_length, - _clock.GetTimeInMS()); - } if(retVal < 0) { return retVal; } @@ -816,11 +752,7 @@ RTPReceiver::UpdateStatistics(const WebRtcRTPHeader* rtpHeader, const WebRtc_UWord16 bytes, const bool oldPacket) { - WebRtc_UWord32 freq = 90000; - if(_audio) - { - freq = _rtpReceiverAudio->AudioFrequency(); - } + WebRtc_UWord32 freq = _rtpMediaReceiver->GetFrequencyHz(); Bitrate::Update(bytes); @@ -918,10 +850,8 @@ bool RTPReceiver::RetransmitOfOldPacket( if (InOrderPacket(sequenceNumber)) { return false; } - WebRtc_UWord32 frequencyKHz = 90; // Video frequency. - if (_audio) { - frequencyKHz = _rtpReceiverAudio->AudioFrequency() / 1000; - } + + WebRtc_UWord32 frequencyKHz = _rtpMediaReceiver->GetFrequencyHz() / 1000; WebRtc_Word64 timeDiffMS = _clock.GetTimeInMS() - _lastReceiveTime; // Diff in time stamp since last received in order. WebRtc_Word32 rtpTimeStampDiffMS = static_cast( @@ -1025,11 +955,8 @@ WebRtc_Word32 RTPReceiver::EstimatedRemoteTimeStamp(WebRtc_UWord32& timestamp) const { CriticalSectionScoped lock(_criticalSectionRTPReceiver); - WebRtc_UWord32 freq = 90000; - if(_audio) - { - freq = _rtpReceiverAudio->AudioFrequency(); - } + WebRtc_UWord32 freq = _rtpMediaReceiver->GetFrequencyHz(); + if(_localTimeLastReceivedTimestamp == 0) { WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__); @@ -1079,7 +1006,7 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) { bool newSSRC = false; bool reInitializeDecoder = false; char payloadName[RTP_PAYLOAD_NAME_SIZE]; - WebRtc_UWord32 frequency = 90000; // default video freq + WebRtc_UWord32 frequency = kDefaultVideoFrequency; // default video freq WebRtc_UWord8 channels = 1; WebRtc_UWord32 rate = 0; @@ -1119,7 +1046,7 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) { channels = payload->typeSpecific.Audio.channels; rate = payload->typeSpecific.Audio.rate; } else { - frequency = 90000; + frequency = kDefaultVideoFrequency; } } } @@ -1149,12 +1076,17 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) { } // no criticalsection when called +// TODO(phoglund): Move as much as possible of this code path into the media +// specific receivers. Basically this method goes through a lot of trouble to +// compute something which is only used by the media specific parts later. If +// this code path moves we can get rid of some of the rtp_receiver -> +// media_specific interface (such as CheckPayloadChange, possibly get/set +// last known payload). WebRtc_Word32 RTPReceiver::CheckPayloadChanged( const WebRtcRTPHeader* rtpHeader, const WebRtc_Word8 firstPayloadByte, bool& isRED, - AudioPayload& audioSpecificPayload, - VideoPayload& videoSpecificPayload) { + ModuleRTPUtility::PayloadUnion* specificPayload) { bool reInitializeDecoder = false; char payloadName[RTP_PAYLOAD_NAME_SIZE]; @@ -1178,39 +1110,25 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged( //when we receive RED we need to check the real payload type if (payloadType == _lastReceivedPayloadType) { - if(_audio) - { - memcpy(&audioSpecificPayload, &_lastReceivedAudioSpecific, - sizeof(_lastReceivedAudioSpecific)); - } else { - memcpy(&videoSpecificPayload, &_lastReceivedVideoSpecific, - sizeof(_lastReceivedVideoSpecific)); - } + _rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload); return 0; } } - if (_audio) { - if (_rtpReceiverAudio->TelephoneEventPayloadType(payloadType)) { - // don't do callbacks for DTMF packets - isRED = false; - return 0; - } - // frequency is updated for CNG - bool cngPayloadTypeHasChanged = false; - bool isCngPayloadType = _rtpReceiverAudio->CNGPayloadType( - payloadType, &audioSpecificPayload.frequency, - &cngPayloadTypeHasChanged); + bool shouldResetStatistics = false; + bool shouldDiscardChanges = false; - if (cngPayloadTypeHasChanged) { - ResetStatistics(); - } + _rtpMediaReceiver->CheckPayloadChanged( + payloadType, specificPayload, &shouldResetStatistics, + &shouldDiscardChanges); - if (isCngPayloadType) { - // don't do callbacks for DTMF packets - isRED = false; - return 0; - } + if (shouldResetStatistics) { + ResetStatistics(); } + if (shouldDiscardChanges) { + isRED = false; + return 0; + } + std::map::iterator it = _payloadTypeMap.find(payloadType); @@ -1222,22 +1140,16 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged( assert(payload); payloadName[RTP_PAYLOAD_NAME_SIZE - 1] = 0; strncpy(payloadName, payload->name, RTP_PAYLOAD_NAME_SIZE - 1); + _lastReceivedPayloadType = payloadType; reInitializeDecoder = true; - if(payload->audio) { - memcpy(&_lastReceivedAudioSpecific, &(payload->typeSpecific.Audio), - sizeof(_lastReceivedAudioSpecific)); - memcpy(&audioSpecificPayload, &(payload->typeSpecific.Audio), - sizeof(_lastReceivedAudioSpecific)); - } else { - memcpy(&_lastReceivedVideoSpecific, &(payload->typeSpecific.Video), - sizeof(_lastReceivedVideoSpecific)); - memcpy(&videoSpecificPayload, &(payload->typeSpecific.Video), - sizeof(_lastReceivedVideoSpecific)); + _rtpMediaReceiver->SetLastMediaSpecificPayload(payload->typeSpecific); + _rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload); - if (_lastReceivedVideoSpecific.videoCodecType == kRtpFecVideo) + if(!payload->audio) { + if (VideoCodecType() == kRtpFecVideo) { // Only reset the decoder on media packets. reInitializeDecoder = false; @@ -1254,39 +1166,16 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged( ResetStatistics(); } } else { - if(_audio) - { - memcpy(&audioSpecificPayload, &_lastReceivedAudioSpecific, - sizeof(_lastReceivedAudioSpecific)); - } else - { - memcpy(&videoSpecificPayload, &_lastReceivedVideoSpecific, - sizeof(_lastReceivedVideoSpecific)); - } + _rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload); isRED = false; } } // end critsect if (reInitializeDecoder) { CriticalSectionScoped lock(_criticalSectionCbs); if (_cbRtpFeedback) { - // create new decoder instance - if(_audio) { - if (-1 == _cbRtpFeedback->OnInitializeDecoder(_id, payloadType, - payloadName, audioSpecificPayload.frequency, - audioSpecificPayload.channels, audioSpecificPayload.rate)) { - WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, - "Failed to create audio decoder for payload type:%d", - payloadType); - return -1; // Wrong payload type - } - } else { - if (-1 == _cbRtpFeedback->OnInitializeDecoder(_id, payloadType, - payloadName, 90000, 1, 0)) { - WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, - "Failed to create video decoder for payload type:%d", - payloadType); - return -1; // Wrong payload type - } + if (-1 == _rtpMediaReceiver->InvokeOnInitializeDecoder( + _cbRtpFeedback, _id, payloadType, payloadName, *specificPayload)) { + return -1; // Wrong payload type. } } } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver.h index 21c9612cb..0787f54f0 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver.h @@ -19,8 +19,6 @@ #include "rtp_header_extension.h" #include "rtp_rtcp.h" #include "rtp_rtcp_defines.h" -#include "rtp_receiver_audio.h" -#include "rtp_receiver_video.h" #include "rtcp_receiver_help.h" #include "Bitrate.h" @@ -28,6 +26,11 @@ namespace webrtc { class RtpRtcpFeedback; class ModuleRtpRtcpImpl; class Trace; +class RTPReceiverAudio; +class RTPReceiverVideo; +class RTPReceiverStrategy; + +const WebRtc_Word32 kDefaultVideoFrequency = 90000; class RTPReceiver : public Bitrate { @@ -186,8 +189,7 @@ private: WebRtc_Word32 CheckPayloadChanged(const WebRtcRTPHeader* rtpHeader, const WebRtc_Word8 firstPayloadByte, bool& isRED, - ModuleRTPUtility::AudioPayload& audioSpecific, - ModuleRTPUtility::VideoPayload& videoSpecific); + ModuleRTPUtility::PayloadUnion* payload); void UpdateNACKBitRate(WebRtc_Word32 bytes, WebRtc_UWord32 now); bool ProcessNACKBitRate(WebRtc_UWord32 now); @@ -195,9 +197,9 @@ private: private: RTPReceiverAudio* _rtpReceiverAudio; RTPReceiverVideo* _rtpReceiverVideo; + RTPReceiverStrategy* _rtpMediaReceiver; WebRtc_Word32 _id; - const bool _audio; ModuleRtpRtcpImpl& _rtpRtcp; CriticalSectionWrapper* _criticalSectionCbs; @@ -210,14 +212,11 @@ private: WebRtc_Word8 _lastReceivedPayloadType; WebRtc_Word8 _lastReceivedMediaPayloadType; - ModuleRTPUtility::AudioPayload _lastReceivedAudioSpecific; - ModuleRTPUtility::VideoPayload _lastReceivedVideoSpecific; - WebRtc_UWord32 _packetTimeOutMS; WebRtc_Word8 _redPayloadType; - std::map _payloadTypeMap; - RtpHeaderExtensionMap _rtpHeaderExtensionMap; + ModuleRTPUtility::PayloadTypeMap _payloadTypeMap; + RtpHeaderExtensionMap _rtpHeaderExtensionMap; // SSRCs WebRtc_UWord32 _SSRC; @@ -265,6 +264,7 @@ private: bool _RTX; WebRtc_UWord32 _ssrcRTX; }; + } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc index 8cd8e13f5..5d7f334de 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.cc @@ -16,6 +16,7 @@ #include "critical_section_wrapper.h" #include "rtp_receiver.h" +#include "trace.h" namespace webrtc { RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id, @@ -39,6 +40,7 @@ RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id, _lastReceivedG722(false), _cbAudioFeedback(incomingMessagesCallback) { + last_payload_.Audio.channels = 1; } WebRtc_UWord32 @@ -182,7 +184,7 @@ RTPReceiverAudio::CNGPayloadType(const WebRtc_Word8 payloadType, G7221 frame N/A */ -ModuleRTPUtility::Payload* RTPReceiverAudio::RegisterReceiveAudioPayload( +ModuleRTPUtility::Payload* RTPReceiverAudio::CreatePayloadType( const char payloadName[RTP_PAYLOAD_NAME_SIZE], const WebRtc_Word8 payloadType, const WebRtc_UWord32 frequency, @@ -248,6 +250,142 @@ void RTPReceiverAudio::SendTelephoneEvents( } } +WebRtc_Word32 RTPReceiverAudio::ParseRtpPacket( + WebRtcRTPHeader* rtpHeader, + const ModuleRTPUtility::PayloadUnion& specificPayload, + const bool isRed, + const WebRtc_UWord8* packet, + const WebRtc_UWord16 packetLength, + const WebRtc_Word64 timestampMs) { + + const WebRtc_UWord8* payloadData = + ModuleRTPUtility::GetPayloadData(rtpHeader, packet); + const WebRtc_UWord16 payloadDataLength = + ModuleRTPUtility::GetPayloadDataLength(rtpHeader, packetLength); + + return ParseAudioCodecSpecific(rtpHeader, payloadData, payloadDataLength, + specificPayload.Audio, isRed); +} + +WebRtc_Word32 RTPReceiverAudio::GetFrequencyHz() const { + return AudioFrequency(); +} + +RTPAliveType RTPReceiverAudio::ProcessDeadOrAlive( + WebRtc_UWord16 lastPayloadLength) const { + + // Our CNG is 9 bytes; if it's a likely CNG the receiver needs to check + // kRtpNoRtp against NetEq speechType kOutputPLCtoCNG. + if(lastPayloadLength < 10) // our CNG is 9 bytes + { + return kRtpNoRtp; + } else + { + return kRtpDead; + } +} + +bool RTPReceiverAudio::PayloadIsCompatible( + const ModuleRTPUtility::Payload& payload, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const { + return + payload.audio && + payload.typeSpecific.Audio.frequency == frequency && + payload.typeSpecific.Audio.channels == channels && + (payload.typeSpecific.Audio.rate == rate || + payload.typeSpecific.Audio.rate == 0 || rate == 0); +} + +void RTPReceiverAudio::UpdatePayloadRate( + ModuleRTPUtility::Payload* payload, + const WebRtc_UWord32 rate) const { + payload->typeSpecific.Audio.rate = rate; +} + +void RTPReceiverAudio::PossiblyRemoveExistingPayloadType( + ModuleRTPUtility::PayloadTypeMap* payloadTypeMap, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const size_t payloadNameLength, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const { + ModuleRTPUtility::PayloadTypeMap::iterator audio_it = payloadTypeMap->begin(); + while (audio_it != payloadTypeMap->end()) { + ModuleRTPUtility::Payload* payload = audio_it->second; + size_t nameLength = strlen(payload->name); + + if (payloadNameLength == nameLength && + ModuleRTPUtility::StringCompare(payload->name, + payloadName, payloadNameLength)) { + // we found the payload name in the list + // if audio check frequency and rate + if (payload->audio) { + if (payload->typeSpecific.Audio.frequency == frequency && + (payload->typeSpecific.Audio.rate == rate || + payload->typeSpecific.Audio.rate == 0 || rate == 0) && + payload->typeSpecific.Audio.channels == channels) { + // remove old setting + delete payload; + payloadTypeMap->erase(audio_it); + break; + } + } else if(ModuleRTPUtility::StringCompare(payloadName,"red",3)) { + delete payload; + payloadTypeMap->erase(audio_it); + break; + } + } + audio_it++; + } +} + +void RTPReceiverAudio::CheckPayloadChanged( + const WebRtc_Word8 payloadType, + ModuleRTPUtility::PayloadUnion* specificPayload, + bool* shouldResetStatistics, + bool* shouldDiscardChanges) { + *shouldDiscardChanges = false; + *shouldResetStatistics = false; + + if (TelephoneEventPayloadType(payloadType)) { + // Don't do callbacks for DTMF packets. + *shouldDiscardChanges = true; + return; + } + // frequency is updated for CNG + bool cngPayloadTypeHasChanged = false; + bool isCngPayloadType = CNGPayloadType( + payloadType, &specificPayload->Audio.frequency, + &cngPayloadTypeHasChanged); + + *shouldResetStatistics = cngPayloadTypeHasChanged; + + if (isCngPayloadType) { + // Don't do callbacks for DTMF packets. + *shouldDiscardChanges = true; + return; + } +} + +WebRtc_Word32 RTPReceiverAudio::InvokeOnInitializeDecoder( + RtpFeedback* callback, + const WebRtc_Word32 id, + const WebRtc_Word8 payloadType, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const ModuleRTPUtility::PayloadUnion& specificPayload) const { + if (-1 == callback->OnInitializeDecoder( + id, payloadType, payloadName, specificPayload.Audio.frequency, + specificPayload.Audio.channels, specificPayload.Audio.rate)) { + WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id, + "Failed to create video decoder for payload type:%d", + payloadType); + return -1; + } + return 0; +} + // we are not allowed to have any critsects when calling CallbackOfReceivedPayloadData WebRtc_Word32 RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h index 4fb63cfaf..fbe9749d6 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h @@ -13,10 +13,11 @@ #include +#include "rtp_receiver.h" +#include "rtp_receiver_strategy.h" #include "rtp_rtcp_defines.h" #include "rtp_utility.h" #include "scoped_ptr.h" - #include "typedefs.h" namespace webrtc { @@ -24,20 +25,13 @@ class CriticalSectionWrapper; class RTPReceiver; // Handles audio RTP packets. This class is thread-safe. -class RTPReceiverAudio +class RTPReceiverAudio : public RTPReceiverStrategy { public: RTPReceiverAudio(const WebRtc_Word32 id, RTPReceiver* parent, RtpAudioFeedback* incomingMessagesCallback); - ModuleRTPUtility::Payload* RegisterReceiveAudioPayload( - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const WebRtc_Word8 payloadType, - const WebRtc_UWord32 frequency, - const WebRtc_UWord8 channels, - const WebRtc_UWord32 rate); - WebRtc_UWord32 AudioFrequency() const; // Outband TelephoneEvent (DTMF) detection @@ -60,11 +54,59 @@ public: WebRtc_UWord32* frequency, bool* cngPayloadTypeHasChanged); - WebRtc_Word32 ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader, - const WebRtc_UWord8* payloadData, - const WebRtc_UWord16 payloadLength, - const ModuleRTPUtility::AudioPayload& audioSpecific, - const bool isRED); + WebRtc_Word32 ParseRtpPacket( + WebRtcRTPHeader* rtpHeader, + const ModuleRTPUtility::PayloadUnion& specificPayload, + const bool isRed, + const WebRtc_UWord8* packet, + const WebRtc_UWord16 packetLength, + const WebRtc_Word64 timestampMs); + + WebRtc_Word32 GetFrequencyHz() const; + + RTPAliveType ProcessDeadOrAlive(WebRtc_UWord16 lastPayloadLength) const; + + bool PayloadIsCompatible( + const ModuleRTPUtility::Payload& payload, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const; + + void UpdatePayloadRate( + ModuleRTPUtility::Payload* payload, + const WebRtc_UWord32 rate) const; + + ModuleRTPUtility::Payload* CreatePayloadType( + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const WebRtc_Word8 payloadType, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate); + + WebRtc_Word32 InvokeOnInitializeDecoder( + RtpFeedback* callback, + const WebRtc_Word32 id, + const WebRtc_Word8 payloadType, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const ModuleRTPUtility::PayloadUnion& specificPayload) const; + + // We do not allow codecs to have multiple payload types for audio, so we + // need to override the default behavior (which is to do nothing). + void PossiblyRemoveExistingPayloadType( + ModuleRTPUtility::PayloadTypeMap* payloadTypeMap, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const size_t payloadNameLength, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const; + + // We need to look out for special payload types here and sometimes reset + // statistics. In addition we sometimes need to tweak the frequency. + void CheckPayloadChanged( + const WebRtc_Word8 payloadType, + ModuleRTPUtility::PayloadUnion* specificPayload, + bool* shouldResetStatistics, + bool* shouldDiscardChanges); private: void SendTelephoneEvents( WebRtc_UWord8 numberOfNewEvents, @@ -72,6 +114,13 @@ private: WebRtc_UWord8 numberOfRemovedEvents, WebRtc_UWord8 removedEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS]); + WebRtc_Word32 ParseAudioCodecSpecific( + WebRtcRTPHeader* rtpHeader, + const WebRtc_UWord8* payloadData, + const WebRtc_UWord16 payloadLength, + const ModuleRTPUtility::AudioPayload& audioSpecific, + const bool isRED); + WebRtc_Word32 _id; RTPReceiver* _parent; scoped_ptr _criticalSectionRtpReceiverAudio; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.cc new file mode 100644 index 000000000..d07380296 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.cc @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" + +#include + +namespace webrtc { + +RTPReceiverStrategy::RTPReceiverStrategy() { + memset(&last_payload_, 0, sizeof(last_payload_)); +} + +void RTPReceiverStrategy::GetLastMediaSpecificPayload( + ModuleRTPUtility::PayloadUnion* payload) const { + memcpy(payload, &last_payload_, sizeof(*payload)); +} + +void RTPReceiverStrategy::SetLastMediaSpecificPayload( + const ModuleRTPUtility::PayloadUnion& payload) { + memcpy(&last_payload_, &payload, sizeof(last_payload_)); +} + +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h new file mode 100644 index 000000000..297cd0f05 --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_ + +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" +#include "webrtc/typedefs.h" + +namespace webrtc { + +// This strategy deals with media-specific RTP packet processing. +// This class is not thread-safe and must be protected by its caller. +class RTPReceiverStrategy { + public: + RTPReceiverStrategy(); + virtual ~RTPReceiverStrategy() {} + + // Parses the RTP packet. Implementations should keep a reference to the + // calling RTPReceiver and call CallbackOfReceivedPayloadData if parsing + // succeeds. + // TODO(phoglund): This interaction is really ugly: clean up by removing + // the need of a back reference to parent, perhaps by returning something + // instead of calling back. + virtual WebRtc_Word32 ParseRtpPacket( + WebRtcRTPHeader* rtp_header, + const ModuleRTPUtility::PayloadUnion& specific_payload, + const bool is_red, + const WebRtc_UWord8* packet, + const WebRtc_UWord16 packet_length, + const WebRtc_Word64 timestamp_ms) = 0; + + // Retrieves the last known applicable frequency. + virtual WebRtc_Word32 GetFrequencyHz() const = 0; + + // Computes the current dead-or-alive state. + virtual RTPAliveType ProcessDeadOrAlive( + WebRtc_UWord16 last_payload_length) const = 0; + + // Checks if the provided payload can be handled by this strategy and if + // it is compatible with the provided parameters. + virtual bool PayloadIsCompatible( + const ModuleRTPUtility::Payload& payload, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const = 0; + + // Updates the rate in the payload in a media-specific way. + virtual void UpdatePayloadRate( + ModuleRTPUtility::Payload* payload, + const WebRtc_UWord32 rate) const = 0; + + // Creates a media-specific payload instance from the provided parameters. + virtual ModuleRTPUtility::Payload* CreatePayloadType( + const char payload_name[RTP_PAYLOAD_NAME_SIZE], + const WebRtc_Word8 payload_type, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) = 0; + + // Invokes the OnInitializeDecoder callback in a media-specific way. + virtual WebRtc_Word32 InvokeOnInitializeDecoder( + RtpFeedback* callback, + const WebRtc_Word32 id, + const WebRtc_Word8 payload_type, + const char payload_name[RTP_PAYLOAD_NAME_SIZE], + const ModuleRTPUtility::PayloadUnion& specific_payload) const = 0; + + // Prunes the payload type map of the specific payload type, if it exists. + // TODO(phoglund): Move this responsibility into some payload management + // class along with rtp_receiver's payload management. + virtual void PossiblyRemoveExistingPayloadType( + ModuleRTPUtility::PayloadTypeMap* payload_type_map, + const char payload_name[RTP_PAYLOAD_NAME_SIZE], + const size_t payload_name_length, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const { + // Default: do nothing. + } + + // Checks if the payload type has changed, and returns whether we should + // reset statistics and/or discard this packet. + virtual void CheckPayloadChanged( + const WebRtc_Word8 payload_type, + ModuleRTPUtility::PayloadUnion* specific_payload, + bool* should_reset_statistics, + bool* should_discard_changes) { + // Default: Keep changes and don't reset statistics. + *should_discard_changes = false; + *should_reset_statistics = false; + } + + // Stores / retrieves the last media specific payload for later reference. + void GetLastMediaSpecificPayload( + ModuleRTPUtility::PayloadUnion* payload) const; + void SetLastMediaSpecificPayload( + const ModuleRTPUtility::PayloadUnion& payload); + + protected: + ModuleRTPUtility::PayloadUnion last_payload_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_STRATEGY_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc index e5a742535..124e9fcf5 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc @@ -43,10 +43,12 @@ RTPReceiverVideo::~RTPReceiverVideo() { delete _receiveFEC; } -ModuleRTPUtility::Payload* RTPReceiverVideo::RegisterReceiveVideoPayload( +ModuleRTPUtility::Payload* RTPReceiverVideo::CreatePayloadType( const char payloadName[RTP_PAYLOAD_NAME_SIZE], const WebRtc_Word8 payloadType, - const WebRtc_UWord32 maxRate) { + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) { RtpVideoCodecTypes videoType = kRtpNoVideo; if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) { videoType = kRtpVp8Video; @@ -67,11 +69,68 @@ ModuleRTPUtility::Payload* RTPReceiverVideo::RegisterReceiveVideoPayload( payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); payload->typeSpecific.Video.videoCodecType = videoType; - payload->typeSpecific.Video.maxRate = maxRate; + payload->typeSpecific.Video.maxRate = rate; payload->audio = false; return payload; } +WebRtc_Word32 RTPReceiverVideo::ParseRtpPacket( + WebRtcRTPHeader* rtpHeader, + const ModuleRTPUtility::PayloadUnion& specificPayload, + const bool isRed, + const WebRtc_UWord8* packet, + const WebRtc_UWord16 packetLength, + const WebRtc_Word64 timestampMs) { + const WebRtc_UWord8* payloadData = + ModuleRTPUtility::GetPayloadData(rtpHeader, packet); + const WebRtc_UWord16 payloadDataLength = + ModuleRTPUtility::GetPayloadDataLength(rtpHeader, packetLength); + return ParseVideoCodecSpecific( + rtpHeader, payloadData, payloadDataLength, + specificPayload.Video.videoCodecType, isRed, packet, packetLength, + timestampMs); +} + +WebRtc_Word32 RTPReceiverVideo::GetFrequencyHz() const { + return kDefaultVideoFrequency; +} + +RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive( + WebRtc_UWord16 lastPayloadLength) const { + return kRtpDead; +} + +bool RTPReceiverVideo::PayloadIsCompatible( + const ModuleRTPUtility::Payload& payload, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const { + return !payload.audio; +} + +void RTPReceiverVideo::UpdatePayloadRate( + ModuleRTPUtility::Payload* payload, + const WebRtc_UWord32 rate) const { + payload->typeSpecific.Video.maxRate = rate; +} + +WebRtc_Word32 RTPReceiverVideo::InvokeOnInitializeDecoder( + RtpFeedback* callback, + const WebRtc_Word32 id, + const WebRtc_Word8 payloadType, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const ModuleRTPUtility::PayloadUnion& specificPayload) const { + // For video we just go with default values. + if (-1 == callback->OnInitializeDecoder( + id, payloadType, payloadName, kDefaultVideoFrequency, 1, 0)) { + WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id, + "Failed to create video decoder for payload type:%d", + payloadType); + return -1; + } + return 0; +} + // we have no critext when calling this // we are not allowed to have any critsects when calling // CallbackOfReceivedPayloadData diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h index 3e65d87fc..0dc59ded8 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h @@ -11,21 +11,20 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_VIDEO_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_VIDEO_H_ +#include "Bitrate.h" +#include "rtp_receiver.h" +#include "rtp_receiver_strategy.h" #include "rtp_rtcp_defines.h" #include "rtp_utility.h" - -#include "typedefs.h" - -#include "Bitrate.h" #include "scoped_ptr.h" +#include "typedefs.h" namespace webrtc { class CriticalSectionWrapper; class ModuleRtpRtcpImpl; class ReceiverFEC; -class RTPReceiver; -class RTPReceiverVideo { +class RTPReceiverVideo : public RTPReceiverStrategy { public: RTPReceiverVideo(const WebRtc_Word32 id, RTPReceiver* parent, @@ -33,20 +32,41 @@ class RTPReceiverVideo { virtual ~RTPReceiverVideo(); - ModuleRTPUtility::Payload* RegisterReceiveVideoPayload( + WebRtc_Word32 ParseRtpPacket( + WebRtcRTPHeader* rtp_header, + const ModuleRTPUtility::PayloadUnion& specificPayload, + const bool is_red, + const WebRtc_UWord8* packet, + const WebRtc_UWord16 packet_length, + const WebRtc_Word64 timestamp); + + WebRtc_Word32 GetFrequencyHz() const; + + RTPAliveType ProcessDeadOrAlive(WebRtc_UWord16 lastPayloadLength) const; + + bool PayloadIsCompatible( + const ModuleRTPUtility::Payload& payload, + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate) const; + + void UpdatePayloadRate( + ModuleRTPUtility::Payload* payload, + const WebRtc_UWord32 rate) const; + + ModuleRTPUtility::Payload* CreatePayloadType( const char payloadName[RTP_PAYLOAD_NAME_SIZE], const WebRtc_Word8 payloadType, - const WebRtc_UWord32 maxRate); + const WebRtc_UWord32 frequency, + const WebRtc_UWord8 channels, + const WebRtc_UWord32 rate); - 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, - const WebRtc_Word64 nowMS); + WebRtc_Word32 InvokeOnInitializeDecoder( + RtpFeedback* callback, + const WebRtc_Word32 id, + const WebRtc_Word8 payloadType, + const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const ModuleRTPUtility::PayloadUnion& specificPayload) const; virtual WebRtc_Word32 ReceiveRecoveredPacketCallback( WebRtcRTPHeader* rtpHeader, @@ -77,6 +97,16 @@ class RTPReceiverVideo { WebRtc_UWord8* dataBuffer) const; private: + 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, + const WebRtc_Word64 nowMS); + WebRtc_Word32 _id; RTPReceiver* _parent; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi index e07e6e2f5..3f932077e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi @@ -73,6 +73,8 @@ 'producer_fec.h', 'rtp_packet_history.cc', 'rtp_packet_history.h', + 'rtp_receiver_strategy.cc', + 'rtp_receiver_stragegy.h', 'rtp_receiver_video.cc', 'rtp_receiver_video.h', 'rtp_sender_video.cc', diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 4eef91734..c8722043c 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -8,9 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "common_types.h" #include "rtp_rtcp_impl.h" -#include "trace.h" #ifdef MATLAB #include "../test/BWEStandAlone/MatlabPlot.h" @@ -20,6 +18,11 @@ extern MatlabEngine eng; // global variable defined elsewhere #include //memcpy #include //assert +#include "common_types.h" +#include "rtp_receiver_audio.h" +#include "rtp_receiver_video.h" +#include "trace.h" + // local for this file namespace { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc index 298d47996..efc985cd1 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc @@ -313,6 +313,18 @@ bool OldTimestamp(uint32_t newTimestamp, * Misc utility routines */ +const WebRtc_UWord8* GetPayloadData(const WebRtcRTPHeader* rtp_header, + const WebRtc_UWord8* packet) { + return packet + rtp_header->header.headerLength; +} + +WebRtc_UWord16 GetPayloadDataLength(const WebRtcRTPHeader* rtp_header, + const WebRtc_UWord16 packet_length) { + WebRtc_UWord16 length = packet_length - rtp_header->header.paddingLength - + rtp_header->header.headerLength; + return static_cast(length); +} + #if defined(_WIN32) bool StringCompare(const char* str1, const char* str2, const WebRtc_UWord32 length) { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.h b/webrtc/modules/rtp_rtcp/source/rtp_utility.h index 20e7af1fb..4f35adcdf 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.h @@ -59,6 +59,8 @@ namespace ModuleRTPUtility PayloadUnion typeSpecific; }; + typedef std::map PayloadTypeMap; + // Return a clock that reads the time as reported by the operating // system. The returned instances are guaranteed to read the same // times; in particular, they return relative times relative to @@ -85,6 +87,14 @@ namespace ModuleRTPUtility WebRtc_UWord32 pow2(WebRtc_UWord8 exp); + // Returns a pointer to the payload data given a packet. + const WebRtc_UWord8* GetPayloadData(const WebRtcRTPHeader* rtp_header, + const WebRtc_UWord8* packet); + + // Returns payload length given a packet. + WebRtc_UWord16 GetPayloadDataLength(const WebRtcRTPHeader* rtp_header, + const WebRtc_UWord16 packet_length); + // Returns true if |newTimestamp| is older than |existingTimestamp|. // |wrapped| will be set to true if there has been a wraparound between the // two timestamps. @@ -170,7 +180,7 @@ namespace ModuleRTPUtility int frameWidth; int frameHeight; - const WebRtc_UWord8* data; + const WebRtc_UWord8* data; WebRtc_UWord16 dataLength; };