Decoupled RTP audio processor from RTP receiver.

BUG=
TEST=Ran vie_auto_test, rtp_rtcp_unittests, voe_auto_test

Review URL: https://webrtc-codereview.appspot.com/979004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3279 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
phoglund@webrtc.org 2012-12-13 10:48:24 +00:00
parent 5b689efe8e
commit 92bb417cb1
5 changed files with 229 additions and 187 deletions

View File

@ -32,8 +32,8 @@ using ModuleRTPUtility::VideoPayload;
RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
const bool audio,
RtpRtcpClock* clock,
ModuleRtpRtcpImpl* owner) :
RTPReceiverAudio(id),
ModuleRtpRtcpImpl* owner,
RtpAudioFeedback* incomingMessagesCallback) :
RTPReceiverVideo(id, owner),
Bitrate(clock),
_id(id),
@ -96,6 +96,8 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
_nackMethod(kNackOff),
_RTX(false),
_ssrcRTX(0) {
_rtpReceiverAudio = new RTPReceiverAudio(id, this, incomingMessagesCallback);
memset(_currentRemoteCSRC, 0, sizeof(_currentRemoteCSRC));
memset(_currentRemoteEnergy, 0, sizeof(_currentRemoteEnergy));
memset(&_lastReceivedAudioSpecific, 0, sizeof(_lastReceivedAudioSpecific));
@ -121,6 +123,7 @@ RTPReceiver::~RTPReceiver() {
delete it->second;
_payloadTypeMap.erase(it);
}
delete _rtpReceiverAudio;
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, _id, "%s deleted", __FUNCTION__);
}
@ -392,8 +395,8 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
} else {
if (_audio) {
payload = RegisterReceiveAudioPayload(payloadName, payloadType,
frequency, channels, rate);
payload = _rtpReceiverAudio->RegisterReceiveAudioPayload(
payloadName, payloadType, frequency, channels, rate);
} else {
payload = RegisterReceiveVideoPayload(payloadName, payloadType, rate);
}
@ -752,7 +755,7 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket(
WebRtc_Word32 retVal = 0;
if(_audio) {
retVal = ParseAudioCodecSpecific(rtp_header,
retVal = _rtpReceiverAudio->ParseAudioCodecSpecific(rtp_header,
payload_data,
payload_data_length,
audio_specific,
@ -821,7 +824,7 @@ RTPReceiver::UpdateStatistics(const WebRtcRTPHeader* rtpHeader,
WebRtc_UWord32 freq = 90000;
if(_audio)
{
freq = AudioFrequency();
freq = _rtpReceiverAudio->AudioFrequency();
}
Bitrate::Update(bytes);
@ -922,7 +925,7 @@ bool RTPReceiver::RetransmitOfOldPacket(
}
WebRtc_UWord32 frequencyKHz = 90; // Video frequency.
if (_audio) {
frequencyKHz = AudioFrequency() / 1000;
frequencyKHz = _rtpReceiverAudio->AudioFrequency() / 1000;
}
WebRtc_Word64 timeDiffMS = _clock.GetTimeInMS() - _lastReceiveTime;
// Diff in time stamp since last received in order.
@ -1030,7 +1033,7 @@ RTPReceiver::EstimatedRemoteTimeStamp(WebRtc_UWord32& timestamp) const
WebRtc_UWord32 freq = 90000;
if(_audio)
{
freq = AudioFrequency();
freq = _rtpReceiverAudio->AudioFrequency();
}
if(_localTimeLastReceivedTimestamp == 0)
{
@ -1192,13 +1195,22 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
}
}
if (_audio) {
if (TelephoneEventPayloadType(payloadType)) {
if (_rtpReceiverAudio->TelephoneEventPayloadType(payloadType)) {
// don't do callbacks for DTMF packets
isRED = false;
return 0;
}
// frequency is updated for CNG
if (CNGPayloadType(payloadType, audioSpecificPayload.frequency)) {
bool cngPayloadTypeHasChanged = false;
bool isCngPayloadType = _rtpReceiverAudio->CNGPayloadType(
payloadType, &audioSpecificPayload.frequency,
&cngPayloadTypeHasChanged);
if (cngPayloadTypeHasChanged) {
ResetStatistics();
}
if (isCngPayloadType) {
// don't do callbacks for DTMF packets
isRED = false;
return 0;
@ -1295,7 +1307,8 @@ void RTPReceiver::CheckCSRC(const WebRtcRTPHeader* rtpHeader) {
{
CriticalSectionScoped lock(_criticalSectionRTPReceiver);
if (TelephoneEventPayloadType(rtpHeader->header.payloadType)) {
if (_rtpReceiverAudio->TelephoneEventPayloadType(
rtpHeader->header.payloadType)) {
// Don't do this for DTMF packets
return;
}
@ -1625,4 +1638,5 @@ RTPReceiver::ProcessBitrate()
Bitrate::Process();
}
} // namespace webrtc

View File

@ -29,13 +29,14 @@ class RtpRtcpFeedback;
class ModuleRtpRtcpImpl;
class Trace;
class RTPReceiver : public RTPReceiverAudio, public RTPReceiverVideo, public Bitrate
class RTPReceiver : public RTPReceiverVideo, public Bitrate
{
public:
RTPReceiver(const WebRtc_Word32 id,
const bool audio,
RtpRtcpClock* clock,
ModuleRtpRtcpImpl* owner);
ModuleRtpRtcpImpl* owner,
RtpAudioFeedback* incomingMessagesCallback);
virtual ~RTPReceiver();
@ -154,10 +155,13 @@ public:
void RTXStatus(bool* enable, WebRtc_UWord32* SSRC) const;
protected:
virtual WebRtc_Word32 CallbackOfReceivedPayloadData(const WebRtc_UWord8* payloadData,
RTPReceiverAudio* GetAudioReceiver() const { return _rtpReceiverAudio; }
virtual WebRtc_Word32 CallbackOfReceivedPayloadData(
const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
const WebRtcRTPHeader* rtpHeader);
protected:
virtual bool RetransmitOfOldPacket(const WebRtc_UWord16 sequenceNumber,
const WebRtc_UWord32 rtpTimeStamp) const;
@ -189,6 +193,8 @@ private:
bool ProcessNACKBitRate(WebRtc_UWord32 now);
private:
RTPReceiverAudio* _rtpReceiverAudio;
WebRtc_Word32 _id;
const bool _audio;
ModuleRtpRtcpImpl& _rtpRtcp;

View File

@ -15,10 +15,16 @@
#include <math.h> // pow()
#include "critical_section_wrapper.h"
#include "rtp_receiver.h"
namespace webrtc {
RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id):
_id(id),
RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id,
RTPReceiver* parent,
RtpAudioFeedback* incomingMessagesCallback)
: _id(id),
_parent(parent),
_criticalSectionRtpReceiverAudio(
CriticalSectionWrapper::CreateCriticalSection()),
_lastReceivedFrequency(8000),
_telephoneEvent(false),
_telephoneEventForwardToDecoder(false),
@ -31,27 +37,14 @@ RTPReceiverAudio::RTPReceiverAudio(const WebRtc_Word32 id):
_cngPayloadType(-1),
_G722PayloadType(-1),
_lastReceivedG722(false),
_criticalSectionFeedback(CriticalSectionWrapper::CreateCriticalSection()),
_cbAudioFeedback(NULL)
_cbAudioFeedback(incomingMessagesCallback)
{
}
RTPReceiverAudio::~RTPReceiverAudio()
{
delete _criticalSectionFeedback;
}
WebRtc_Word32
RTPReceiverAudio::RegisterIncomingAudioCallback(RtpAudioFeedback* incomingMessagesCallback)
{
CriticalSectionScoped lock(_criticalSectionFeedback);
_cbAudioFeedback = incomingMessagesCallback;
return 0;
}
WebRtc_UWord32
RTPReceiverAudio::AudioFrequency() const
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
if(_lastReceivedG722)
{
return 8000;
@ -65,6 +58,7 @@ RTPReceiverAudio::SetTelephoneEventStatus(const bool enable,
const bool forwardToDecoder,
const bool detectEndOfTone)
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
_telephoneEvent= enable;
_telephoneEventDetectEndOfTone = detectEndOfTone;
_telephoneEventForwardToDecoder = forwardToDecoder;
@ -75,6 +69,7 @@ RTPReceiverAudio::SetTelephoneEventStatus(const bool enable,
bool
RTPReceiverAudio::TelephoneEvent() const
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
return _telephoneEvent;
}
@ -82,27 +77,32 @@ RTPReceiverAudio::TelephoneEvent() const
bool
RTPReceiverAudio::TelephoneEventForwardToDecoder() const
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
return _telephoneEventForwardToDecoder;
}
bool
RTPReceiverAudio::TelephoneEventPayloadType(const WebRtc_Word8 payloadType) const
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
return (_telephoneEventPayloadType == payloadType)?true:false;
}
bool
RTPReceiverAudio::CNGPayloadType(const WebRtc_Word8 payloadType,
WebRtc_UWord32& frequency)
WebRtc_UWord32* frequency,
bool* cngPayloadTypeHasChanged)
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
*cngPayloadTypeHasChanged = false;
// We can have four CNG on 8000Hz, 16000Hz, 32000Hz and 48000Hz.
if(_cngNBPayloadType == payloadType)
{
frequency = 8000;
*frequency = 8000;
if ((_cngPayloadType != -1) &&(_cngPayloadType !=_cngNBPayloadType))
{
ResetStatistics();
}
*cngPayloadTypeHasChanged = true;
_cngPayloadType = _cngNBPayloadType;
return true;
} else if(_cngWBPayloadType == payloadType)
@ -110,33 +110,27 @@ RTPReceiverAudio::CNGPayloadType(const WebRtc_Word8 payloadType,
// if last received codec is G.722 we must use frequency 8000
if(_lastReceivedG722)
{
frequency = 8000;
*frequency = 8000;
} else
{
frequency = 16000;
*frequency = 16000;
}
if ((_cngPayloadType != -1) &&(_cngPayloadType !=_cngWBPayloadType))
{
ResetStatistics();
}
*cngPayloadTypeHasChanged = true;
_cngPayloadType = _cngWBPayloadType;
return true;
}else if(_cngSWBPayloadType == payloadType)
{
frequency = 32000;
*frequency = 32000;
if ((_cngPayloadType != -1) &&(_cngPayloadType !=_cngSWBPayloadType))
{
ResetStatistics();
}
*cngPayloadTypeHasChanged = true;
_cngPayloadType = _cngSWBPayloadType;
return true;
}else if(_cngFBPayloadType == payloadType)
{
frequency = 48000;
*frequency = 48000;
if ((_cngPayloadType != -1) &&(_cngPayloadType !=_cngFBPayloadType))
{
ResetStatistics();
}
*cngPayloadTypeHasChanged = true;
_cngPayloadType = _cngFBPayloadType;
return true;
}else
@ -194,6 +188,8 @@ ModuleRTPUtility::Payload* RTPReceiverAudio::RegisterReceiveAudioPayload(
const WebRtc_UWord32 frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate) {
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
if (ModuleRTPUtility::StringCompare(payloadName, "telephone-event", 15)) {
_telephoneEventPayloadType = payloadType;
}
@ -223,6 +219,35 @@ ModuleRTPUtility::Payload* RTPReceiverAudio::RegisterReceiveAudioPayload(
return payload;
}
void RTPReceiverAudio::SendTelephoneEvents(
WebRtc_UWord8 numberOfNewEvents,
WebRtc_UWord8 newEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS],
WebRtc_UWord8 numberOfRemovedEvents,
WebRtc_UWord8 removedEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS]) {
// Copy these variables since we can't hold the critsect when we call the
// callback. _cbAudioFeedback and _id are immutable though.
bool telephoneEvent;
bool telephoneEventDetectEndOfTone;
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
telephoneEvent = _telephoneEvent;
telephoneEventDetectEndOfTone = _telephoneEventDetectEndOfTone;
}
if (telephoneEvent) {
for (int n = 0; n < numberOfNewEvents; ++n) {
_cbAudioFeedback->OnReceivedTelephoneEvent(
_id, newEvents[n], false);
}
if (telephoneEventDetectEndOfTone) {
for (int n = 0; n < numberOfRemovedEvents; ++n) {
_cbAudioFeedback->OnReceivedTelephoneEvent(
_id, removedEvents[n], true);
}
}
}
}
// we are not allowed to have any critsects when calling CallbackOfReceivedPayloadData
WebRtc_Word32
RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader,
@ -235,18 +260,17 @@ RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader,
WebRtc_UWord8 removedEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS];
WebRtc_UWord8 numberOfNewEvents = 0;
WebRtc_UWord8 numberOfRemovedEvents = 0;
bool telephoneEventPacket = TelephoneEventPayloadType(rtpHeader->header.payloadType);
if(payloadLength == 0)
{
return 0;
}
{
CriticalSectionScoped lock(_criticalSectionFeedback);
bool telephoneEventPacket = TelephoneEventPayloadType(rtpHeader->header.payloadType);
if(telephoneEventPacket)
{
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
// RFC 4733 2.3
/*
0 1 2 3
@ -302,29 +326,22 @@ RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader,
// RFC 4733 See 2.5.1.5. & 2.5.2.4. Multiple Events in a Packet
}
if(_telephoneEvent && _cbAudioFeedback)
// This needs to be called without locks held.
SendTelephoneEvents(numberOfNewEvents, newEvents, numberOfRemovedEvents,
removedEvents);
{
for (int n = 0; n < numberOfNewEvents; n++)
{
_cbAudioFeedback->OnReceivedTelephoneEvent(_id, newEvents[n], false);
}
if(_telephoneEventDetectEndOfTone)
{
for (int n = 0; n < numberOfRemovedEvents; n++)
{
_cbAudioFeedback->OnReceivedTelephoneEvent(_id, removedEvents[n], true);
}
}
}
}
CriticalSectionScoped lock(_criticalSectionRtpReceiverAudio.get());
if(! telephoneEventPacket )
{
_lastReceivedFrequency = audioSpecific.frequency;
}
// Check if this is a CNG packet, receiver might want to know
WebRtc_UWord32 dummy;
if(CNGPayloadType(rtpHeader->header.payloadType, dummy))
WebRtc_UWord32 ignored;
bool alsoIgnored;
if(CNGPayloadType(rtpHeader->header.payloadType, &ignored, &alsoIgnored))
{
rtpHeader->type.Audio.isCNG=true;
rtpHeader->frameType = kAudioFrameCN;
@ -350,18 +367,20 @@ RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader,
return 0;
}
}
}
if(isRED && !(payloadData[0] & 0x80))
{
// we recive only one frame packed in a RED packet remove the RED wrapper
rtpHeader->header.payloadType = payloadData[0];
// only one frame in the RED strip the one byte to help NetEq
return CallbackOfReceivedPayloadData(payloadData+1,
return _parent->CallbackOfReceivedPayloadData(payloadData+1,
payloadLength-1,
rtpHeader);
}
rtpHeader->type.Audio.channel = audioSpecific.channels;
return CallbackOfReceivedPayloadData(payloadData, payloadLength, rtpHeader);
return _parent->CallbackOfReceivedPayloadData(
payloadData, payloadLength, rtpHeader);
}
} // namespace webrtc

View File

@ -15,19 +15,21 @@
#include "rtp_rtcp_defines.h"
#include "rtp_utility.h"
#include "scoped_ptr.h"
#include "typedefs.h"
namespace webrtc {
class CriticalSectionWrapper;
class RTPReceiver;
// Handles audio RTP packets. This class is thread-safe.
class RTPReceiverAudio
{
public:
RTPReceiverAudio(const WebRtc_Word32 id);
virtual ~RTPReceiverAudio();
WebRtc_Word32 RegisterIncomingAudioCallback(RtpAudioFeedback* incomingMessagesCallback);
RTPReceiverAudio(const WebRtc_Word32 id,
RTPReceiver* parent,
RtpAudioFeedback* incomingMessagesCallback);
ModuleRTPUtility::Payload* RegisterReceiveAudioPayload(
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
@ -52,23 +54,27 @@ public:
// Is TelephoneEvent configured with payload type payloadType
bool TelephoneEventPayloadType(const WebRtc_Word8 payloadType) const;
// Is CNG configured with payload type payloadType
bool CNGPayloadType(const WebRtc_Word8 payloadType, WebRtc_UWord32& frequency);
// Returns true if CNG is configured with payload type payloadType. If so,
// the frequency and cngPayloadTypeHasChanged are filled in.
bool CNGPayloadType(const WebRtc_Word8 payloadType,
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);
virtual WebRtc_Word32 ResetStatistics() = 0;
protected:
virtual WebRtc_Word32 CallbackOfReceivedPayloadData(const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadSize,
const WebRtcRTPHeader* rtpHeader) = 0;
private:
void SendTelephoneEvents(
WebRtc_UWord8 numberOfNewEvents,
WebRtc_UWord8 newEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS],
WebRtc_UWord8 numberOfRemovedEvents,
WebRtc_UWord8 removedEvents[MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS]);
WebRtc_Word32 _id;
RTPReceiver* _parent;
scoped_ptr<CriticalSectionWrapper> _criticalSectionRtpReceiverAudio;
WebRtc_UWord32 _lastReceivedFrequency;
@ -88,7 +94,6 @@ private:
WebRtc_Word8 _G722PayloadType;
bool _lastReceivedG722;
CriticalSectionWrapper* _criticalSectionFeedback;
RtpAudioFeedback* _cbAudioFeedback;
};
} // namespace webrtc

View File

@ -59,7 +59,7 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
configuration.audio_messages,
configuration.paced_sender),
_rtpReceiver(configuration.id, configuration.audio, configuration.clock,
this),
this, configuration.audio_messages),
_rtcpSender(configuration.id, configuration.audio, configuration.clock,
this),
_rtcpReceiver(configuration.id, configuration.clock, this),
@ -103,8 +103,6 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
_rtcpReceiver.RegisterRtcpObservers(configuration.intra_frame_callback,
configuration.bandwidth_callback,
configuration.rtcp_feedback);
_rtpReceiver.RegisterIncomingAudioCallback(configuration.audio_messages);
_rtcpSender.RegisterSendTransport(configuration.outgoing_transport);
// make sure that RTCP objects are aware of our SSRC
@ -1549,15 +1547,15 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SetTelephoneEventStatus(
" detectEndOfTone:%d)", enable, forwardToDecoder,
detectEndOfTone);
return _rtpReceiver.SetTelephoneEventStatus(enable, forwardToDecoder,
detectEndOfTone);
return _rtpReceiver.GetAudioReceiver()->SetTelephoneEventStatus(
enable, forwardToDecoder, detectEndOfTone);
}
// Is outband TelephoneEvent turned on/off?
bool ModuleRtpRtcpImpl::TelephoneEvent() const {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id, "TelephoneEvent()");
return _rtpReceiver.TelephoneEvent();
return _rtpReceiver.GetAudioReceiver()->TelephoneEvent();
}
// Is forwarding of outband telephone events turned on/off?
@ -1565,7 +1563,7 @@ bool ModuleRtpRtcpImpl::TelephoneEventForwardToDecoder() const {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, _id,
"TelephoneEventForwardToDecoder()");
return _rtpReceiver.TelephoneEventForwardToDecoder();
return _rtpReceiver.GetAudioReceiver()->TelephoneEventForwardToDecoder();
}
// Send a TelephoneEvent tone using RFC 2833 (4733)