webrtc/video_engine/main/source/vie_sender.cc

400 lines
11 KiB
C++

/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* vie_sender.cc
*/
#include "vie_sender.h"
#include "critical_section_wrapper.h"
#include "rtp_rtcp.h"
#ifdef WEBRTC_SRTP
#include "SrtpModule.h"
#endif
#include "rtp_dump.h"
#include "trace.h"
namespace webrtc {
// ----------------------------------------------------------------------------
// Constructor
// ----------------------------------------------------------------------------
ViESender::ViESender(int engineId, int channelId,
RtpRtcp& rtpRtcpModule)
: _engineId(engineId), _channelId(channelId),
_sendCritsect(*CriticalSectionWrapper::CreateCriticalSection()),
_rtpRtcp(rtpRtcpModule),
#ifdef WEBRTC_SRTP
_ptrSrtp(NULL),
_ptrSrtcp(NULL),
#endif
_ptrExternalEncryption(NULL), _ptrSrtpBuffer(NULL),
_ptrSrtcpBuffer(NULL), _ptrEncryptionBuffer(NULL), _ptrTransport(NULL),
_rtpDump(NULL)
{
}
// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
ViESender::~ViESender()
{
delete &_sendCritsect;
if (_ptrSrtpBuffer)
{
delete[] _ptrSrtpBuffer;
_ptrSrtpBuffer = NULL;
}
if (_ptrSrtcpBuffer)
{
delete[] _ptrSrtcpBuffer;
_ptrSrtcpBuffer = NULL;
}
if (_ptrEncryptionBuffer)
{
delete[] _ptrEncryptionBuffer;
_ptrEncryptionBuffer = NULL;
}
if (_rtpDump)
{
_rtpDump->Stop();
RtpDump::DestroyRtpDump(_rtpDump);
_rtpDump = NULL;
}
}
// ----------------------------------------------------------------------------
// RegisterExternalEncryption
// ----------------------------------------------------------------------------
int ViESender::RegisterExternalEncryption(Encryption* encryption)
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrExternalEncryption)
{
return -1;
}
_ptrEncryptionBuffer = new WebRtc_UWord8[kViEMaxMtu];
if (_ptrEncryptionBuffer == NULL)
{
return -1;
}
_ptrExternalEncryption = encryption;
return 0;
}
// ----------------------------------------------------------------------------
// DeregisterExternalEncryption
// ----------------------------------------------------------------------------
int ViESender::DeregisterExternalEncryption()
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrExternalEncryption == NULL)
{
return -1;
}
if (_ptrEncryptionBuffer)
{
delete _ptrEncryptionBuffer;
_ptrEncryptionBuffer = NULL;
}
_ptrExternalEncryption = NULL;
return 0;
}
// ----------------------------------------------------------------------------
// RegisterSendTransport
// ----------------------------------------------------------------------------
int ViESender::RegisterSendTransport(Transport* transport)
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrTransport)
{
return -1;
}
_ptrTransport = transport;
return 0;
}
// ----------------------------------------------------------------------------
// DeregisterSendTransport
// ----------------------------------------------------------------------------
int ViESender::DeregisterSendTransport()
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrTransport == NULL)
{
return -1;
}
_ptrTransport = NULL;
return 0;
}
#ifdef WEBRTC_SRTP
// ----------------------------------------------------------------------------
// RegisterSRTPModule
// ----------------------------------------------------------------------------
int ViESender::RegisterSRTPModule(SrtpModule* srtpModule)
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrSrtp ||
srtpModule == NULL)
{
return -1;
}
_ptrSrtpBuffer = new WebRtc_UWord8[KMaxPacketSize];
if (_ptrSrtpBuffer == NULL)
{
return -1;
}
_ptrSrtp = srtpModule;
return 0;
}
// ----------------------------------------------------------------------------
// DeregisterSRTPModule
// ----------------------------------------------------------------------------
int ViESender::DeregisterSRTPModule()
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrSrtp == NULL)
{
return -1;
}
if (_ptrSrtpBuffer)
{
delete [] _ptrSrtpBuffer;
_ptrSrtpBuffer = NULL;
}
_ptrSrtp = NULL;
return 0;
}
// ----------------------------------------------------------------------------
// RegisterSRTCPModule
// ----------------------------------------------------------------------------
int ViESender::RegisterSRTCPModule(SrtpModule* srtcpModule)
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrSrtcp ||
srtcpModule == NULL)
{
return -1;
}
_ptrSrtcpBuffer = new WebRtc_UWord8[KMaxPacketSize];
if (_ptrSrtcpBuffer == NULL)
{
return -1;
}
_ptrSrtcp = srtcpModule;
return 0;
}
// ----------------------------------------------------------------------------
// DeregisterSRTCPModule
// ----------------------------------------------------------------------------
int ViESender::DeregisterSRTCPModule()
{
CriticalSectionScoped cs(_sendCritsect);
if (_ptrSrtcp == NULL)
{
return -1;
}
if (_ptrSrtcpBuffer)
{
delete [] _ptrSrtcpBuffer;
_ptrSrtcpBuffer = NULL;
}
_ptrSrtcp = NULL;
return 0;
}
#endif
// ----------------------------------------------------------------------------
// StartRTPDump
// ----------------------------------------------------------------------------
int ViESender::StartRTPDump(const char fileNameUTF8[1024])
{
CriticalSectionScoped cs(_sendCritsect);
if (_rtpDump)
{
// Restart it if it already exists and is started
_rtpDump->Stop();
} else
{
_rtpDump = RtpDump::CreateRtpDump();
if (_rtpDump == NULL)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId,
_channelId),
"%s: Failed to create RTP dump", __FUNCTION__);
return -1;
}
}
if (_rtpDump->Start(fileNameUTF8) != 0)
{
RtpDump::DestroyRtpDump(_rtpDump);
_rtpDump = NULL;
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
ViEId(_engineId, _channelId),
"%s: Failed to start RTP dump", __FUNCTION__);
return -1;
}
return 0;
}
// ----------------------------------------------------------------------------
// StopRTPDump
// ----------------------------------------------------------------------------
int ViESender::StopRTPDump()
{
CriticalSectionScoped cs(_sendCritsect);
if (_rtpDump)
{
if (_rtpDump->IsActive())
{
_rtpDump->Stop();
} else
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId,
_channelId),
"%s: Dump not active", __FUNCTION__);
}
RtpDump::DestroyRtpDump(_rtpDump);
_rtpDump = NULL;
} else
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
ViEId(_engineId, _channelId), "%s: RTP dump not started",
__FUNCTION__);
return -1;
}
return 0;
}
// ----------------------------------------------------------------------------
// SendPacket
// ----------------------------------------------------------------------------
int ViESender::SendPacket(int vieId, const void *data, int len)
{
CriticalSectionScoped cs(_sendCritsect);
if (!_ptrTransport)
{
// No transport
return -1;
}
int channelId = ChannelId(vieId);
assert(channelId == _channelId);
// Prepare for possible encryption and sending
WebRtc_UWord8* sendPacket = (WebRtc_UWord8*) data;
int sendPacketLength = len;
if (_rtpDump)
{
_rtpDump->DumpPacket(sendPacket, sendPacketLength);
}
#ifdef WEBRTC_SRTP
if (_ptrSrtp)
{
_ptrSrtp->encrypt(_channelId, sendPacket, _ptrSrtpBuffer, sendPacketLength, (int*) &sendPacketLength);
if (sendPacketLength <= 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "RTP encryption failed for channel");
return -1;
}
else if (sendPacketLength > KMaxPacketSize)
{
WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
" %d bytes is allocated as RTP output => memory is now corrupted", KMaxPacketSize);
return -1;
}
sendPacket = _ptrSrtpBuffer;
}
#endif
if (_ptrExternalEncryption)
{
_ptrExternalEncryption->encrypt(_channelId, sendPacket,
_ptrEncryptionBuffer, sendPacketLength,
(int*) &sendPacketLength);
sendPacket = _ptrEncryptionBuffer;
}
return _ptrTransport->SendPacket(_channelId, sendPacket, sendPacketLength);
}
// ----------------------------------------------------------------------------
// SendRTCPPacket
// ----------------------------------------------------------------------------
int ViESender::SendRTCPPacket(int vieId, const void *data, int len)
{
CriticalSectionScoped cs(_sendCritsect);
if (!_ptrTransport)
{
// No transport
return -1;
}
int channelId = ChannelId(vieId);
assert(channelId == _channelId);
// Prepare for possible encryption and sending
WebRtc_UWord8* sendPacket = (WebRtc_UWord8*) data;
int sendPacketLength = len;
if (_rtpDump)
{
_rtpDump->DumpPacket(sendPacket, sendPacketLength);
}
#ifdef WEBRTC_SRTP
if (_ptrSrtcp)
{
_ptrSrtcp->encrypt_rtcp(_channelId, sendPacket, _ptrSrtcpBuffer, sendPacketLength, (int*) &sendPacketLength);
if (sendPacketLength <= 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId, _channelId), "RTCP encryption failed for channel");
return -1;
}
else if (sendPacketLength > KMaxPacketSize)
{
WEBRTC_TRACE(webrtc::kTraceCritical, webrtc::kTraceVideo, ViEId(_engineId, _channelId), " %d bytes is allocated as RTCP output => memory is now corrupted", KMaxPacketSize);
return -1;
}
sendPacket = _ptrSrtcpBuffer;
}
#endif
if (_ptrExternalEncryption)
{
_ptrExternalEncryption->encrypt_rtcp(_channelId, sendPacket,
_ptrEncryptionBuffer,
sendPacketLength,
(int*) &sendPacketLength);
sendPacket = _ptrEncryptionBuffer;
}
return _ptrTransport->SendRTCPPacket(_channelId, sendPacket,
sendPacketLength);
}
} // namespace webrtc