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
This commit is contained in:
phoglund@webrtc.org 2012-12-18 15:40:53 +00:00
parent 59ad541e57
commit 07bf43c673
13 changed files with 581 additions and 242 deletions

View File

@ -24,6 +24,7 @@
#define TIMEOUT_SEI_MESSAGES_MS 30000 // in milliseconds #define TIMEOUT_SEI_MESSAGES_MS 30000 // in milliseconds
namespace webrtc{ namespace webrtc{
enum RTCPMethod enum RTCPMethod
{ {
kRtcpOff = 0, kRtcpOff = 0,

View File

@ -8,17 +8,20 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "trace.h"
#include "rtp_receiver.h" #include "rtp_receiver.h"
#include "rtp_rtcp_defines.h"
#include "rtp_rtcp_impl.h"
#include "critical_section_wrapper.h"
#include <cassert> #include <cassert>
#include <string.h> //memcpy
#include <math.h> // floor #include <math.h> // floor
#include <stdlib.h> // abs #include <stdlib.h> // abs
#include <string.h> //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 { namespace webrtc {
@ -36,7 +39,6 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
RtpAudioFeedback* incomingMessagesCallback) : RtpAudioFeedback* incomingMessagesCallback) :
Bitrate(clock), Bitrate(clock),
_id(id), _id(id),
_audio(audio),
_rtpRtcp(*owner), _rtpRtcp(*owner),
_criticalSectionCbs(CriticalSectionWrapper::CreateCriticalSection()), _criticalSectionCbs(CriticalSectionWrapper::CreateCriticalSection()),
_cbRtpFeedback(NULL), _cbRtpFeedback(NULL),
@ -48,8 +50,6 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
_lastReceivedPayloadLength(0), _lastReceivedPayloadLength(0),
_lastReceivedPayloadType(-1), _lastReceivedPayloadType(-1),
_lastReceivedMediaPayloadType(-1), _lastReceivedMediaPayloadType(-1),
_lastReceivedAudioSpecific(),
_lastReceivedVideoSpecific(),
_packetTimeOutMS(0), _packetTimeOutMS(0),
@ -95,16 +95,21 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
_nackMethod(kNackOff), _nackMethod(kNackOff),
_RTX(false), _RTX(false),
_ssrcRTX(0) { _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); _rtpReceiverAudio = new RTPReceiverAudio(id, this, incomingMessagesCallback);
_rtpReceiverVideo = new RTPReceiverVideo(id, this, owner); _rtpReceiverVideo = new RTPReceiverVideo(id, this, owner);
if (audio) {
_rtpMediaReceiver = _rtpReceiverAudio;
} else {
_rtpMediaReceiver = _rtpReceiverVideo;
}
memset(_currentRemoteCSRC, 0, sizeof(_currentRemoteCSRC)); memset(_currentRemoteCSRC, 0, sizeof(_currentRemoteCSRC));
memset(_currentRemoteEnergy, 0, sizeof(_currentRemoteEnergy)); 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__); WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id, "%s created", __FUNCTION__);
} }
@ -131,13 +136,17 @@ RTPReceiver::~RTPReceiver() {
RtpVideoCodecTypes RtpVideoCodecTypes
RTPReceiver::VideoCodecType() const RTPReceiver::VideoCodecType() const
{ {
return _lastReceivedVideoSpecific.videoCodecType; ModuleRTPUtility::PayloadUnion mediaSpecific;
_rtpMediaReceiver->GetLastMediaSpecificPayload(&mediaSpecific);
return mediaSpecific.Video.videoCodecType;
} }
WebRtc_UWord32 WebRtc_UWord32
RTPReceiver::MaxConfiguredBitrate() const RTPReceiver::MaxConfiguredBitrate() const
{ {
return _lastReceivedVideoSpecific.maxRate; ModuleRTPUtility::PayloadUnion mediaSpecific;
_rtpMediaReceiver->GetLastMediaSpecificPayload(&mediaSpecific);
return mediaSpecific.Video.maxRate;
} }
bool bool
@ -201,7 +210,7 @@ void RTPReceiver::PacketTimeout()
} }
void void
RTPReceiver::ProcessDeadOrAlive(const bool RTCPalive, const WebRtc_Word64 now) RTPReceiver::ProcessDeadOrAlive(const bool rtcpAlive, const WebRtc_Word64 now)
{ {
if(_cbRtpFeedback == NULL) if(_cbRtpFeedback == NULL)
{ {
@ -217,25 +226,10 @@ RTPReceiver::ProcessDeadOrAlive(const bool RTCPalive, const WebRtc_Word64 now)
} else } else
{ {
if(RTCPalive) if(rtcpAlive)
{ {
if(_audio) alive = _rtpMediaReceiver->ProcessDeadOrAlive(
{ _lastReceivedPayloadLength);
// 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
}
}else }else
{ {
// no RTP packet for 1 sec and no RTCP // no RTP packet for 1 sec and no RTCP
@ -331,19 +325,9 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
// if same ignore sending an error // if same ignore sending an error
if (payloadNameLength == nameLength && if (payloadNameLength == nameLength &&
StringCompare(payload->name, payloadName, payloadNameLength)) { StringCompare(payload->name, payloadName, payloadNameLength)) {
if (_audio && if (_rtpMediaReceiver->PayloadIsCompatible(*payload, frequency,
payload->audio && channels, rate)) {
payload->typeSpecific.Audio.frequency == frequency && _rtpMediaReceiver->UpdatePayloadRate(payload, rate);
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;
return 0; return 0;
} }
} }
@ -352,38 +336,11 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
__FUNCTION__, payloadType); __FUNCTION__, payloadType);
return -1; 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<WebRtc_Word8, Payload*>::iterator audio_it =
_payloadTypeMap.begin();
while (audio_it != _payloadTypeMap.end()) {
Payload* payload = audio_it->second;
size_t nameLength = strlen(payload->name);
if (payloadNameLength == nameLength && _rtpMediaReceiver->PossiblyRemoveExistingPayloadType(
StringCompare(payload->name, payloadName, payloadNameLength)) { &_payloadTypeMap, payloadName, payloadNameLength, frequency, channels,
// we found the payload name in the list rate);
// 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++;
}
}
Payload* payload = NULL; Payload* payload = NULL;
// save the RED payload type // save the RED payload type
@ -395,13 +352,8 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
} else { } else {
if (_audio) { payload = _rtpMediaReceiver->CreatePayloadType(
payload = _rtpReceiverAudio->RegisterReceiveAudioPayload( payloadName, payloadType, frequency, channels, rate);
payloadName, payloadType, frequency, channels, rate);
} else {
payload = _rtpReceiverVideo->RegisterReceiveVideoPayload(
payloadName, payloadType, rate);
}
} }
if (payload == NULL) { if (payload == NULL) {
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id, WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
@ -512,7 +464,7 @@ WebRtc_Word32 RTPReceiver::ReceivePayload(
if(payload->audio) { if(payload->audio) {
*frequency = payload->typeSpecific.Audio.frequency; *frequency = payload->typeSpecific.Audio.frequency;
} else { } else {
*frequency = 90000; *frequency = kDefaultVideoFrequency;
} }
} }
if (channels) { if (channels) {
@ -565,7 +517,7 @@ WebRtc_Word32 RTPReceiver::RemotePayload(
if (payload->audio) { if (payload->audio) {
*frequency = payload->typeSpecific.Audio.frequency; *frequency = payload->typeSpecific.Audio.frequency;
} else { } else {
*frequency = 90000; *frequency = kDefaultVideoFrequency;
} }
} }
if (channels) { if (channels) {
@ -721,19 +673,12 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket(
CheckSSRCChanged(rtp_header); CheckSSRCChanged(rtp_header);
bool is_red = false; bool is_red = false;
VideoPayload video_specific; ModuleRTPUtility::PayloadUnion specificPayload;
video_specific.maxRate = 0;
video_specific.videoCodecType = kRtpNoVideo;
AudioPayload audio_specific;
audio_specific.channels = 0;
audio_specific.frequency = 0;
if (CheckPayloadChanged(rtp_header, if (CheckPayloadChanged(rtp_header,
first_payload_byte, first_payload_byte,
is_red, is_red,
audio_specific, &specificPayload) == -1) {
video_specific) == -1) {
if (length - rtp_header->header.headerLength == 0) if (length - rtp_header->header.headerLength == 0)
{ {
// ok keepalive packet // ok keepalive packet
@ -749,22 +694,13 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket(
} }
CheckCSRC(rtp_header); CheckCSRC(rtp_header);
const WebRtc_UWord8* payload_data =
packet + rtp_header->header.headerLength;
WebRtc_UWord16 payload_data_length = WebRtc_UWord16 payload_data_length =
static_cast<WebRtc_UWord16>(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) { if(retVal < 0) {
return retVal; return retVal;
} }
@ -816,11 +752,7 @@ RTPReceiver::UpdateStatistics(const WebRtcRTPHeader* rtpHeader,
const WebRtc_UWord16 bytes, const WebRtc_UWord16 bytes,
const bool oldPacket) const bool oldPacket)
{ {
WebRtc_UWord32 freq = 90000; WebRtc_UWord32 freq = _rtpMediaReceiver->GetFrequencyHz();
if(_audio)
{
freq = _rtpReceiverAudio->AudioFrequency();
}
Bitrate::Update(bytes); Bitrate::Update(bytes);
@ -918,10 +850,8 @@ bool RTPReceiver::RetransmitOfOldPacket(
if (InOrderPacket(sequenceNumber)) { if (InOrderPacket(sequenceNumber)) {
return false; return false;
} }
WebRtc_UWord32 frequencyKHz = 90; // Video frequency.
if (_audio) { WebRtc_UWord32 frequencyKHz = _rtpMediaReceiver->GetFrequencyHz() / 1000;
frequencyKHz = _rtpReceiverAudio->AudioFrequency() / 1000;
}
WebRtc_Word64 timeDiffMS = _clock.GetTimeInMS() - _lastReceiveTime; WebRtc_Word64 timeDiffMS = _clock.GetTimeInMS() - _lastReceiveTime;
// Diff in time stamp since last received in order. // Diff in time stamp since last received in order.
WebRtc_Word32 rtpTimeStampDiffMS = static_cast<WebRtc_Word32>( WebRtc_Word32 rtpTimeStampDiffMS = static_cast<WebRtc_Word32>(
@ -1025,11 +955,8 @@ WebRtc_Word32
RTPReceiver::EstimatedRemoteTimeStamp(WebRtc_UWord32& timestamp) const RTPReceiver::EstimatedRemoteTimeStamp(WebRtc_UWord32& timestamp) const
{ {
CriticalSectionScoped lock(_criticalSectionRTPReceiver); CriticalSectionScoped lock(_criticalSectionRTPReceiver);
WebRtc_UWord32 freq = 90000; WebRtc_UWord32 freq = _rtpMediaReceiver->GetFrequencyHz();
if(_audio)
{
freq = _rtpReceiverAudio->AudioFrequency();
}
if(_localTimeLastReceivedTimestamp == 0) if(_localTimeLastReceivedTimestamp == 0)
{ {
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__); WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id, "%s invalid state", __FUNCTION__);
@ -1079,7 +1006,7 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
bool newSSRC = false; bool newSSRC = false;
bool reInitializeDecoder = false; bool reInitializeDecoder = false;
char payloadName[RTP_PAYLOAD_NAME_SIZE]; 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_UWord8 channels = 1;
WebRtc_UWord32 rate = 0; WebRtc_UWord32 rate = 0;
@ -1119,7 +1046,7 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
channels = payload->typeSpecific.Audio.channels; channels = payload->typeSpecific.Audio.channels;
rate = payload->typeSpecific.Audio.rate; rate = payload->typeSpecific.Audio.rate;
} else { } else {
frequency = 90000; frequency = kDefaultVideoFrequency;
} }
} }
} }
@ -1149,12 +1076,17 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtpHeader) {
} }
// no criticalsection when called // 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( WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
const WebRtcRTPHeader* rtpHeader, const WebRtcRTPHeader* rtpHeader,
const WebRtc_Word8 firstPayloadByte, const WebRtc_Word8 firstPayloadByte,
bool& isRED, bool& isRED,
AudioPayload& audioSpecificPayload, ModuleRTPUtility::PayloadUnion* specificPayload) {
VideoPayload& videoSpecificPayload) {
bool reInitializeDecoder = false; bool reInitializeDecoder = false;
char payloadName[RTP_PAYLOAD_NAME_SIZE]; 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 //when we receive RED we need to check the real payload type
if (payloadType == _lastReceivedPayloadType) { if (payloadType == _lastReceivedPayloadType) {
if(_audio) _rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload);
{
memcpy(&audioSpecificPayload, &_lastReceivedAudioSpecific,
sizeof(_lastReceivedAudioSpecific));
} else {
memcpy(&videoSpecificPayload, &_lastReceivedVideoSpecific,
sizeof(_lastReceivedVideoSpecific));
}
return 0; return 0;
} }
} }
if (_audio) { bool shouldResetStatistics = false;
if (_rtpReceiverAudio->TelephoneEventPayloadType(payloadType)) { bool shouldDiscardChanges = false;
// 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);
if (cngPayloadTypeHasChanged) { _rtpMediaReceiver->CheckPayloadChanged(
ResetStatistics(); payloadType, specificPayload, &shouldResetStatistics,
} &shouldDiscardChanges);
if (isCngPayloadType) { if (shouldResetStatistics) {
// don't do callbacks for DTMF packets ResetStatistics();
isRED = false;
return 0;
}
} }
if (shouldDiscardChanges) {
isRED = false;
return 0;
}
std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it = std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
_payloadTypeMap.find(payloadType); _payloadTypeMap.find(payloadType);
@ -1222,22 +1140,16 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
assert(payload); assert(payload);
payloadName[RTP_PAYLOAD_NAME_SIZE - 1] = 0; payloadName[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payloadName, payload->name, RTP_PAYLOAD_NAME_SIZE - 1); strncpy(payloadName, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
_lastReceivedPayloadType = payloadType; _lastReceivedPayloadType = payloadType;
reInitializeDecoder = true; reInitializeDecoder = true;
if(payload->audio) { _rtpMediaReceiver->SetLastMediaSpecificPayload(payload->typeSpecific);
memcpy(&_lastReceivedAudioSpecific, &(payload->typeSpecific.Audio), _rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload);
sizeof(_lastReceivedAudioSpecific));
memcpy(&audioSpecificPayload, &(payload->typeSpecific.Audio),
sizeof(_lastReceivedAudioSpecific));
} else {
memcpy(&_lastReceivedVideoSpecific, &(payload->typeSpecific.Video),
sizeof(_lastReceivedVideoSpecific));
memcpy(&videoSpecificPayload, &(payload->typeSpecific.Video),
sizeof(_lastReceivedVideoSpecific));
if (_lastReceivedVideoSpecific.videoCodecType == kRtpFecVideo) if(!payload->audio) {
if (VideoCodecType() == kRtpFecVideo)
{ {
// Only reset the decoder on media packets. // Only reset the decoder on media packets.
reInitializeDecoder = false; reInitializeDecoder = false;
@ -1254,39 +1166,16 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
ResetStatistics(); ResetStatistics();
} }
} else { } else {
if(_audio) _rtpMediaReceiver->GetLastMediaSpecificPayload(specificPayload);
{
memcpy(&audioSpecificPayload, &_lastReceivedAudioSpecific,
sizeof(_lastReceivedAudioSpecific));
} else
{
memcpy(&videoSpecificPayload, &_lastReceivedVideoSpecific,
sizeof(_lastReceivedVideoSpecific));
}
isRED = false; isRED = false;
} }
} // end critsect } // end critsect
if (reInitializeDecoder) { if (reInitializeDecoder) {
CriticalSectionScoped lock(_criticalSectionCbs); CriticalSectionScoped lock(_criticalSectionCbs);
if (_cbRtpFeedback) { if (_cbRtpFeedback) {
// create new decoder instance if (-1 == _rtpMediaReceiver->InvokeOnInitializeDecoder(
if(_audio) { _cbRtpFeedback, _id, payloadType, payloadName, *specificPayload)) {
if (-1 == _cbRtpFeedback->OnInitializeDecoder(_id, payloadType, return -1; // Wrong payload type.
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
}
} }
} }
} }

View File

@ -19,8 +19,6 @@
#include "rtp_header_extension.h" #include "rtp_header_extension.h"
#include "rtp_rtcp.h" #include "rtp_rtcp.h"
#include "rtp_rtcp_defines.h" #include "rtp_rtcp_defines.h"
#include "rtp_receiver_audio.h"
#include "rtp_receiver_video.h"
#include "rtcp_receiver_help.h" #include "rtcp_receiver_help.h"
#include "Bitrate.h" #include "Bitrate.h"
@ -28,6 +26,11 @@ namespace webrtc {
class RtpRtcpFeedback; class RtpRtcpFeedback;
class ModuleRtpRtcpImpl; class ModuleRtpRtcpImpl;
class Trace; class Trace;
class RTPReceiverAudio;
class RTPReceiverVideo;
class RTPReceiverStrategy;
const WebRtc_Word32 kDefaultVideoFrequency = 90000;
class RTPReceiver : public Bitrate class RTPReceiver : public Bitrate
{ {
@ -186,8 +189,7 @@ private:
WebRtc_Word32 CheckPayloadChanged(const WebRtcRTPHeader* rtpHeader, WebRtc_Word32 CheckPayloadChanged(const WebRtcRTPHeader* rtpHeader,
const WebRtc_Word8 firstPayloadByte, const WebRtc_Word8 firstPayloadByte,
bool& isRED, bool& isRED,
ModuleRTPUtility::AudioPayload& audioSpecific, ModuleRTPUtility::PayloadUnion* payload);
ModuleRTPUtility::VideoPayload& videoSpecific);
void UpdateNACKBitRate(WebRtc_Word32 bytes, WebRtc_UWord32 now); void UpdateNACKBitRate(WebRtc_Word32 bytes, WebRtc_UWord32 now);
bool ProcessNACKBitRate(WebRtc_UWord32 now); bool ProcessNACKBitRate(WebRtc_UWord32 now);
@ -195,9 +197,9 @@ private:
private: private:
RTPReceiverAudio* _rtpReceiverAudio; RTPReceiverAudio* _rtpReceiverAudio;
RTPReceiverVideo* _rtpReceiverVideo; RTPReceiverVideo* _rtpReceiverVideo;
RTPReceiverStrategy* _rtpMediaReceiver;
WebRtc_Word32 _id; WebRtc_Word32 _id;
const bool _audio;
ModuleRtpRtcpImpl& _rtpRtcp; ModuleRtpRtcpImpl& _rtpRtcp;
CriticalSectionWrapper* _criticalSectionCbs; CriticalSectionWrapper* _criticalSectionCbs;
@ -210,14 +212,11 @@ private:
WebRtc_Word8 _lastReceivedPayloadType; WebRtc_Word8 _lastReceivedPayloadType;
WebRtc_Word8 _lastReceivedMediaPayloadType; WebRtc_Word8 _lastReceivedMediaPayloadType;
ModuleRTPUtility::AudioPayload _lastReceivedAudioSpecific;
ModuleRTPUtility::VideoPayload _lastReceivedVideoSpecific;
WebRtc_UWord32 _packetTimeOutMS; WebRtc_UWord32 _packetTimeOutMS;
WebRtc_Word8 _redPayloadType; WebRtc_Word8 _redPayloadType;
std::map<WebRtc_Word8, ModuleRTPUtility::Payload*> _payloadTypeMap; ModuleRTPUtility::PayloadTypeMap _payloadTypeMap;
RtpHeaderExtensionMap _rtpHeaderExtensionMap; RtpHeaderExtensionMap _rtpHeaderExtensionMap;
// SSRCs // SSRCs
WebRtc_UWord32 _SSRC; WebRtc_UWord32 _SSRC;
@ -265,6 +264,7 @@ private:
bool _RTX; bool _RTX;
WebRtc_UWord32 _ssrcRTX; WebRtc_UWord32 _ssrcRTX;
}; };
} // namespace webrtc } // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_H_ #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_H_

View File

@ -16,6 +16,7 @@
#include "critical_section_wrapper.h" #include "critical_section_wrapper.h"
#include "rtp_receiver.h" #include "rtp_receiver.h"
#include "trace.h"
namespace webrtc { namespace webrtc {
RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id, RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id,
@ -39,6 +40,7 @@ RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id,
_lastReceivedG722(false), _lastReceivedG722(false),
_cbAudioFeedback(incomingMessagesCallback) _cbAudioFeedback(incomingMessagesCallback)
{ {
last_payload_.Audio.channels = 1;
} }
WebRtc_UWord32 WebRtc_UWord32
@ -182,7 +184,7 @@ RTPReceiverAudio::CNGPayloadType(const WebRtc_Word8 payloadType,
G7221 frame N/A G7221 frame N/A
*/ */
ModuleRTPUtility::Payload* RTPReceiverAudio::RegisterReceiveAudioPayload( ModuleRTPUtility::Payload* RTPReceiverAudio::CreatePayloadType(
const char payloadName[RTP_PAYLOAD_NAME_SIZE], const char payloadName[RTP_PAYLOAD_NAME_SIZE],
const WebRtc_Word8 payloadType, const WebRtc_Word8 payloadType,
const WebRtc_UWord32 frequency, 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 // we are not allowed to have any critsects when calling CallbackOfReceivedPayloadData
WebRtc_Word32 WebRtc_Word32
RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader, RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader,

View File

@ -13,10 +13,11 @@
#include <set> #include <set>
#include "rtp_receiver.h"
#include "rtp_receiver_strategy.h"
#include "rtp_rtcp_defines.h" #include "rtp_rtcp_defines.h"
#include "rtp_utility.h" #include "rtp_utility.h"
#include "scoped_ptr.h" #include "scoped_ptr.h"
#include "typedefs.h" #include "typedefs.h"
namespace webrtc { namespace webrtc {
@ -24,20 +25,13 @@ class CriticalSectionWrapper;
class RTPReceiver; class RTPReceiver;
// Handles audio RTP packets. This class is thread-safe. // Handles audio RTP packets. This class is thread-safe.
class RTPReceiverAudio class RTPReceiverAudio : public RTPReceiverStrategy
{ {
public: public:
RTPReceiverAudio(const WebRtc_Word32 id, RTPReceiverAudio(const WebRtc_Word32 id,
RTPReceiver* parent, RTPReceiver* parent,
RtpAudioFeedback* incomingMessagesCallback); 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; WebRtc_UWord32 AudioFrequency() const;
// Outband TelephoneEvent (DTMF) detection // Outband TelephoneEvent (DTMF) detection
@ -60,11 +54,59 @@ public:
WebRtc_UWord32* frequency, WebRtc_UWord32* frequency,
bool* cngPayloadTypeHasChanged); bool* cngPayloadTypeHasChanged);
WebRtc_Word32 ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader, WebRtc_Word32 ParseRtpPacket(
const WebRtc_UWord8* payloadData, WebRtcRTPHeader* rtpHeader,
const WebRtc_UWord16 payloadLength, const ModuleRTPUtility::PayloadUnion& specificPayload,
const ModuleRTPUtility::AudioPayload& audioSpecific, const bool isRed,
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: private:
void SendTelephoneEvents( void SendTelephoneEvents(
WebRtc_UWord8 numberOfNewEvents, WebRtc_UWord8 numberOfNewEvents,
@ -72,6 +114,13 @@ private:
WebRtc_UWord8 numberOfRemovedEvents, WebRtc_UWord8 numberOfRemovedEvents,
WebRtc_UWord8 removedEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS]); 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; WebRtc_Word32 _id;
RTPReceiver* _parent; RTPReceiver* _parent;
scoped_ptr<CriticalSectionWrapper> _criticalSectionRtpReceiverAudio; scoped_ptr<CriticalSectionWrapper> _criticalSectionRtpReceiverAudio;

View File

@ -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 <cstdlib>
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

View File

@ -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_

View File

@ -43,10 +43,12 @@ RTPReceiverVideo::~RTPReceiverVideo() {
delete _receiveFEC; delete _receiveFEC;
} }
ModuleRTPUtility::Payload* RTPReceiverVideo::RegisterReceiveVideoPayload( ModuleRTPUtility::Payload* RTPReceiverVideo::CreatePayloadType(
const char payloadName[RTP_PAYLOAD_NAME_SIZE], const char payloadName[RTP_PAYLOAD_NAME_SIZE],
const WebRtc_Word8 payloadType, const WebRtc_Word8 payloadType,
const WebRtc_UWord32 maxRate) { const WebRtc_UWord32 frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate) {
RtpVideoCodecTypes videoType = kRtpNoVideo; RtpVideoCodecTypes videoType = kRtpNoVideo;
if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) { if (ModuleRTPUtility::StringCompare(payloadName, "VP8", 3)) {
videoType = kRtpVp8Video; videoType = kRtpVp8Video;
@ -67,11 +69,68 @@ ModuleRTPUtility::Payload* RTPReceiverVideo::RegisterReceiveVideoPayload(
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
payload->typeSpecific.Video.videoCodecType = videoType; payload->typeSpecific.Video.videoCodecType = videoType;
payload->typeSpecific.Video.maxRate = maxRate; payload->typeSpecific.Video.maxRate = rate;
payload->audio = false; payload->audio = false;
return payload; 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 have no critext when calling this
// we are not allowed to have any critsects when calling // we are not allowed to have any critsects when calling
// CallbackOfReceivedPayloadData // CallbackOfReceivedPayloadData

View File

@ -11,21 +11,20 @@
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_VIDEO_H_ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_VIDEO_H_
#define 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_rtcp_defines.h"
#include "rtp_utility.h" #include "rtp_utility.h"
#include "typedefs.h"
#include "Bitrate.h"
#include "scoped_ptr.h" #include "scoped_ptr.h"
#include "typedefs.h"
namespace webrtc { namespace webrtc {
class CriticalSectionWrapper; class CriticalSectionWrapper;
class ModuleRtpRtcpImpl; class ModuleRtpRtcpImpl;
class ReceiverFEC; class ReceiverFEC;
class RTPReceiver;
class RTPReceiverVideo { class RTPReceiverVideo : public RTPReceiverStrategy {
public: public:
RTPReceiverVideo(const WebRtc_Word32 id, RTPReceiverVideo(const WebRtc_Word32 id,
RTPReceiver* parent, RTPReceiver* parent,
@ -33,20 +32,41 @@ class RTPReceiverVideo {
virtual ~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 char payloadName[RTP_PAYLOAD_NAME_SIZE],
const WebRtc_Word8 payloadType, const WebRtc_Word8 payloadType,
const WebRtc_UWord32 maxRate); const WebRtc_UWord32 frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate);
WebRtc_Word32 ParseVideoCodecSpecific( WebRtc_Word32 InvokeOnInitializeDecoder(
WebRtcRTPHeader* rtpHeader, RtpFeedback* callback,
const WebRtc_UWord8* payloadData, const WebRtc_Word32 id,
const WebRtc_UWord16 payloadDataLength, const WebRtc_Word8 payloadType,
const RtpVideoCodecTypes videoType, const char payloadName[RTP_PAYLOAD_NAME_SIZE],
const bool isRED, const ModuleRTPUtility::PayloadUnion& specificPayload) const;
const WebRtc_UWord8* incomingRtpPacket,
const WebRtc_UWord16 incomingRtpPacketSize,
const WebRtc_Word64 nowMS);
virtual WebRtc_Word32 ReceiveRecoveredPacketCallback( virtual WebRtc_Word32 ReceiveRecoveredPacketCallback(
WebRtcRTPHeader* rtpHeader, WebRtcRTPHeader* rtpHeader,
@ -77,6 +97,16 @@ class RTPReceiverVideo {
WebRtc_UWord8* dataBuffer) const; WebRtc_UWord8* dataBuffer) const;
private: 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; WebRtc_Word32 _id;
RTPReceiver* _parent; RTPReceiver* _parent;

View File

@ -73,6 +73,8 @@
'producer_fec.h', 'producer_fec.h',
'rtp_packet_history.cc', 'rtp_packet_history.cc',
'rtp_packet_history.h', 'rtp_packet_history.h',
'rtp_receiver_strategy.cc',
'rtp_receiver_stragegy.h',
'rtp_receiver_video.cc', 'rtp_receiver_video.cc',
'rtp_receiver_video.h', 'rtp_receiver_video.h',
'rtp_sender_video.cc', 'rtp_sender_video.cc',

View File

@ -8,9 +8,7 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "common_types.h"
#include "rtp_rtcp_impl.h" #include "rtp_rtcp_impl.h"
#include "trace.h"
#ifdef MATLAB #ifdef MATLAB
#include "../test/BWEStandAlone/MatlabPlot.h" #include "../test/BWEStandAlone/MatlabPlot.h"
@ -20,6 +18,11 @@ extern MatlabEngine eng; // global variable defined elsewhere
#include <string.h> //memcpy #include <string.h> //memcpy
#include <cassert> //assert #include <cassert> //assert
#include "common_types.h"
#include "rtp_receiver_audio.h"
#include "rtp_receiver_video.h"
#include "trace.h"
// local for this file // local for this file
namespace { namespace {

View File

@ -313,6 +313,18 @@ bool OldTimestamp(uint32_t newTimestamp,
* Misc utility routines * 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<WebRtc_UWord16>(length);
}
#if defined(_WIN32) #if defined(_WIN32)
bool StringCompare(const char* str1, const char* str2, bool StringCompare(const char* str1, const char* str2,
const WebRtc_UWord32 length) { const WebRtc_UWord32 length) {

View File

@ -59,6 +59,8 @@ namespace ModuleRTPUtility
PayloadUnion typeSpecific; PayloadUnion typeSpecific;
}; };
typedef std::map<WebRtc_Word8, Payload*> PayloadTypeMap;
// Return a clock that reads the time as reported by the operating // Return a clock that reads the time as reported by the operating
// system. The returned instances are guaranteed to read the same // system. The returned instances are guaranteed to read the same
// times; in particular, they return relative times relative to // times; in particular, they return relative times relative to
@ -85,6 +87,14 @@ namespace ModuleRTPUtility
WebRtc_UWord32 pow2(WebRtc_UWord8 exp); 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|. // Returns true if |newTimestamp| is older than |existingTimestamp|.
// |wrapped| will be set to true if there has been a wraparound between the // |wrapped| will be set to true if there has been a wraparound between the
// two timestamps. // two timestamps.
@ -170,7 +180,7 @@ namespace ModuleRTPUtility
int frameWidth; int frameWidth;
int frameHeight; int frameHeight;
const WebRtc_UWord8* data; const WebRtc_UWord8* data;
WebRtc_UWord16 dataLength; WebRtc_UWord16 dataLength;
}; };