| Index: webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
|
| diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
|
| index 3ae64117d2b337bb3ac5742be32362e989e5b668..3bc861ccdabf5ae8406321e3691a1c8984beb86b 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
|
| @@ -10,8 +10,7 @@
|
|
|
| #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h"
|
|
|
| -#include <assert.h> //assert
|
| -#include <string.h> //memcpy
|
| +#include <string.h>
|
|
|
| #include "webrtc/base/trace_event.h"
|
| #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
| @@ -48,8 +47,7 @@ RTPSenderAudio::RTPSenderAudio(Clock* clock,
|
| _lastPayloadType(-1),
|
| _audioLevel_dBov(0) {}
|
|
|
| -RTPSenderAudio::~RTPSenderAudio() {
|
| -}
|
| +RTPSenderAudio::~RTPSenderAudio() {}
|
|
|
| int RTPSenderAudio::AudioFrequency() const {
|
| return kDtmfFrequencyHz;
|
| @@ -57,13 +55,11 @@ int RTPSenderAudio::AudioFrequency() const {
|
|
|
| // set audio packet size, used to determine when it's time to send a DTMF packet
|
| // in silence (CNG)
|
| -int32_t
|
| -RTPSenderAudio::SetAudioPacketSize(const uint16_t packetSizeSamples)
|
| -{
|
| - CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| +int32_t RTPSenderAudio::SetAudioPacketSize(uint16_t packetSizeSamples) {
|
| + CriticalSectionScoped cs(_sendAudioCritsect.get());
|
|
|
| - _packetSizeSamples = packetSizeSamples;
|
| - return 0;
|
| + _packetSizeSamples = packetSizeSamples;
|
| + return 0;
|
| }
|
|
|
| int32_t RTPSenderAudio::RegisterAudioPayload(
|
| @@ -110,62 +106,55 @@ int32_t RTPSenderAudio::RegisterAudioPayload(
|
| return 0;
|
| }
|
|
|
| -bool
|
| -RTPSenderAudio::MarkerBit(const FrameType frameType,
|
| - const int8_t payload_type)
|
| -{
|
| - CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| - // for audio true for first packet in a speech burst
|
| - bool markerBit = false;
|
| - if (_lastPayloadType != payload_type) {
|
| - if (payload_type != -1 && (_cngNBPayloadType == payload_type ||
|
| - _cngWBPayloadType == payload_type ||
|
| - _cngSWBPayloadType == payload_type ||
|
| - _cngFBPayloadType == payload_type)) {
|
| - // Only set a marker bit when we change payload type to a non CNG
|
| - return false;
|
| - }
|
| +bool RTPSenderAudio::MarkerBit(FrameType frameType, int8_t payload_type) {
|
| + CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| + // for audio true for first packet in a speech burst
|
| + bool markerBit = false;
|
| + if (_lastPayloadType != payload_type) {
|
| + if (payload_type != -1 && (_cngNBPayloadType == payload_type ||
|
| + _cngWBPayloadType == payload_type ||
|
| + _cngSWBPayloadType == payload_type ||
|
| + _cngFBPayloadType == payload_type)) {
|
| + // Only set a marker bit when we change payload type to a non CNG
|
| + return false;
|
| + }
|
|
|
| - // payload_type differ
|
| - if (_lastPayloadType == -1) {
|
| - if (frameType != kAudioFrameCN) {
|
| - // first packet and NOT CNG
|
| - return true;
|
| - } else {
|
| - // first packet and CNG
|
| - _inbandVADactive = true;
|
| - return false;
|
| - }
|
| + // payload_type differ
|
| + if (_lastPayloadType == -1) {
|
| + if (frameType != kAudioFrameCN) {
|
| + // first packet and NOT CNG
|
| + return true;
|
| + } else {
|
| + // first packet and CNG
|
| + _inbandVADactive = true;
|
| + return false;
|
| }
|
| -
|
| - // not first packet AND
|
| - // not CNG AND
|
| - // payload_type changed
|
| -
|
| - // set a marker bit when we change payload type
|
| - markerBit = true;
|
| }
|
|
|
| - // For G.723 G.729, AMR etc we can have inband VAD
|
| - if(frameType == kAudioFrameCN)
|
| - {
|
| - _inbandVADactive = true;
|
| + // not first packet AND
|
| + // not CNG AND
|
| + // payload_type changed
|
|
|
| - } else if(_inbandVADactive)
|
| - {
|
| - _inbandVADactive = false;
|
| - markerBit = true;
|
| - }
|
| - return markerBit;
|
| + // set a marker bit when we change payload type
|
| + markerBit = true;
|
| + }
|
| +
|
| + // For G.723 G.729, AMR etc we can have inband VAD
|
| + if (frameType == kAudioFrameCN) {
|
| + _inbandVADactive = true;
|
| + } else if (_inbandVADactive) {
|
| + _inbandVADactive = false;
|
| + markerBit = true;
|
| + }
|
| + return markerBit;
|
| }
|
|
|
| -int32_t RTPSenderAudio::SendAudio(
|
| - const FrameType frameType,
|
| - const int8_t payloadType,
|
| - const uint32_t captureTimeStamp,
|
| - const uint8_t* payloadData,
|
| - const size_t dataSize,
|
| - const RTPFragmentationHeader* fragmentation) {
|
| +int32_t RTPSenderAudio::SendAudio(FrameType frameType,
|
| + int8_t payloadType,
|
| + uint32_t captureTimeStamp,
|
| + const uint8_t* payloadData,
|
| + size_t dataSize,
|
| + const RTPFragmentationHeader* fragmentation) {
|
| // TODO(pwestin) Breakup function in smaller functions.
|
| size_t payloadSize = dataSize;
|
| size_t maxPayloadLength = _rtpSender->MaxPayloadLength();
|
| @@ -186,8 +175,8 @@ int32_t RTPSenderAudio::SendAudio(
|
|
|
| // Check if we have pending DTMFs to send
|
| if (!_dtmfEventIsOn && PendingDTMF()) {
|
| - int64_t delaySinceLastDTMF = _clock->TimeInMilliseconds() -
|
| - _dtmfTimeLastSent;
|
| + int64_t delaySinceLastDTMF =
|
| + _clock->TimeInMilliseconds() - _dtmfTimeLastSent;
|
|
|
| if (delaySinceLastDTMF > 100) {
|
| // New tone to play
|
| @@ -295,129 +284,120 @@ int32_t RTPSenderAudio::SendAudio(
|
| // Too large payload buffer.
|
| return -1;
|
| }
|
| - if (red_payload_type >= 0 && // Have we configured RED?
|
| - fragmentation && fragmentation->fragmentationVectorSize > 1 &&
|
| - !markerBit) {
|
| - if (timestampOffset <= 0x3fff) {
|
| - if (fragmentation->fragmentationVectorSize != 2) {
|
| - // we only support 2 codecs when using RED
|
| - return -1;
|
| - }
|
| - // only 0x80 if we have multiple blocks
|
| - dataBuffer[rtpHeaderLength++] =
|
| - 0x80 + fragmentation->fragmentationPlType[1];
|
| - size_t blockLength = fragmentation->fragmentationLength[1];
|
| -
|
| - // sanity blockLength
|
| - if (blockLength > 0x3ff) { // block length 10 bits 1023 bytes
|
| - return -1;
|
| - }
|
| - uint32_t REDheader = (timestampOffset << 10) + blockLength;
|
| - ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + rtpHeaderLength,
|
| - REDheader);
|
| - rtpHeaderLength += 3;
|
| -
|
| - dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
|
| - // copy the RED data
|
| - memcpy(dataBuffer + rtpHeaderLength,
|
| - payloadData + fragmentation->fragmentationOffset[1],
|
| - fragmentation->fragmentationLength[1]);
|
| -
|
| - // copy the normal data
|
| - memcpy(dataBuffer + rtpHeaderLength +
|
| - fragmentation->fragmentationLength[1],
|
| - payloadData + fragmentation->fragmentationOffset[0],
|
| - fragmentation->fragmentationLength[0]);
|
| -
|
| - payloadSize = fragmentation->fragmentationLength[0] +
|
| - fragmentation->fragmentationLength[1];
|
| - } else {
|
| - // silence for too long send only new data
|
| - dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
|
| - memcpy(dataBuffer + rtpHeaderLength,
|
| - payloadData + fragmentation->fragmentationOffset[0],
|
| - fragmentation->fragmentationLength[0]);
|
| + if (red_payload_type >= 0 && // Have we configured RED?
|
| + fragmentation && fragmentation->fragmentationVectorSize > 1 &&
|
| + !markerBit) {
|
| + if (timestampOffset <= 0x3fff) {
|
| + if (fragmentation->fragmentationVectorSize != 2) {
|
| + // we only support 2 codecs when using RED
|
| + return -1;
|
| + }
|
| + // only 0x80 if we have multiple blocks
|
| + dataBuffer[rtpHeaderLength++] =
|
| + 0x80 + fragmentation->fragmentationPlType[1];
|
| + size_t blockLength = fragmentation->fragmentationLength[1];
|
|
|
| - payloadSize = fragmentation->fragmentationLength[0];
|
| + // sanity blockLength
|
| + if (blockLength > 0x3ff) { // block length 10 bits 1023 bytes
|
| + return -1;
|
| }
|
| + uint32_t REDheader = (timestampOffset << 10) + blockLength;
|
| + ByteWriter<uint32_t>::WriteBigEndian(dataBuffer + rtpHeaderLength,
|
| + REDheader);
|
| + rtpHeaderLength += 3;
|
| +
|
| + dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
|
| + // copy the RED data
|
| + memcpy(dataBuffer + rtpHeaderLength,
|
| + payloadData + fragmentation->fragmentationOffset[1],
|
| + fragmentation->fragmentationLength[1]);
|
| +
|
| + // copy the normal data
|
| + memcpy(
|
| + dataBuffer + rtpHeaderLength + fragmentation->fragmentationLength[1],
|
| + payloadData + fragmentation->fragmentationOffset[0],
|
| + fragmentation->fragmentationLength[0]);
|
| +
|
| + payloadSize = fragmentation->fragmentationLength[0] +
|
| + fragmentation->fragmentationLength[1];
|
| } else {
|
| - if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
|
| - // use the fragment info if we have one
|
| - dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
|
| - memcpy(dataBuffer + rtpHeaderLength,
|
| - payloadData + fragmentation->fragmentationOffset[0],
|
| - fragmentation->fragmentationLength[0]);
|
| -
|
| - payloadSize = fragmentation->fragmentationLength[0];
|
| - } else {
|
| - memcpy(dataBuffer + rtpHeaderLength, payloadData, payloadSize);
|
| - }
|
| + // silence for too long send only new data
|
| + dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
|
| + memcpy(dataBuffer + rtpHeaderLength,
|
| + payloadData + fragmentation->fragmentationOffset[0],
|
| + fragmentation->fragmentationLength[0]);
|
| +
|
| + payloadSize = fragmentation->fragmentationLength[0];
|
| }
|
| - {
|
| - CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| - _lastPayloadType = payloadType;
|
| + } else {
|
| + if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
|
| + // use the fragment info if we have one
|
| + dataBuffer[rtpHeaderLength++] = fragmentation->fragmentationPlType[0];
|
| + memcpy(dataBuffer + rtpHeaderLength,
|
| + payloadData + fragmentation->fragmentationOffset[0],
|
| + fragmentation->fragmentationLength[0]);
|
| +
|
| + payloadSize = fragmentation->fragmentationLength[0];
|
| + } else {
|
| + memcpy(dataBuffer + rtpHeaderLength, payloadData, payloadSize);
|
| }
|
| - // Update audio level extension, if included.
|
| - size_t packetSize = payloadSize + rtpHeaderLength;
|
| - RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize);
|
| - RTPHeader rtp_header;
|
| - rtp_parser.Parse(rtp_header);
|
| - _rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header,
|
| - (frameType == kAudioFrameSpeech),
|
| - audio_level_dbov);
|
| - TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp, "timestamp",
|
| - _rtpSender->Timestamp(), "seqnum",
|
| - _rtpSender->SequenceNumber());
|
| - return _rtpSender->SendToNetwork(dataBuffer, payloadSize, rtpHeaderLength,
|
| - TickTime::MillisecondTimestamp(),
|
| - kAllowRetransmission,
|
| - RtpPacketSender::kHighPriority);
|
| }
|
| -
|
| - // Audio level magnitude and voice activity flag are set for each RTP packet
|
| -int32_t
|
| -RTPSenderAudio::SetAudioLevel(const uint8_t level_dBov)
|
| -{
|
| - if (level_dBov > 127)
|
| - {
|
| - return -1;
|
| - }
|
| + {
|
| CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| - _audioLevel_dBov = level_dBov;
|
| - return 0;
|
| + _lastPayloadType = payloadType;
|
| + }
|
| + // Update audio level extension, if included.
|
| + size_t packetSize = payloadSize + rtpHeaderLength;
|
| + RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize);
|
| + RTPHeader rtp_header;
|
| + rtp_parser.Parse(rtp_header);
|
| + _rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header,
|
| + (frameType == kAudioFrameSpeech),
|
| + audio_level_dbov);
|
| + TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp, "timestamp",
|
| + _rtpSender->Timestamp(), "seqnum",
|
| + _rtpSender->SequenceNumber());
|
| + return _rtpSender->SendToNetwork(dataBuffer, payloadSize, rtpHeaderLength,
|
| + TickTime::MillisecondTimestamp(),
|
| + kAllowRetransmission,
|
| + RtpPacketSender::kHighPriority);
|
| }
|
|
|
| - // Set payload type for Redundant Audio Data RFC 2198
|
| -int32_t
|
| -RTPSenderAudio::SetRED(const int8_t payloadType)
|
| -{
|
| - if(payloadType < -1 )
|
| - {
|
| - return -1;
|
| - }
|
| - CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| - _REDPayloadType = payloadType;
|
| - return 0;
|
| +// Audio level magnitude and voice activity flag are set for each RTP packet
|
| +int32_t RTPSenderAudio::SetAudioLevel(uint8_t level_dBov) {
|
| + if (level_dBov > 127) {
|
| + return -1;
|
| + }
|
| + CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| + _audioLevel_dBov = level_dBov;
|
| + return 0;
|
| }
|
|
|
| - // Get payload type for Redundant Audio Data RFC 2198
|
| -int32_t
|
| -RTPSenderAudio::RED(int8_t& payloadType) const
|
| -{
|
| - CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| - if(_REDPayloadType == -1)
|
| - {
|
| - // not configured
|
| - return -1;
|
| - }
|
| - payloadType = _REDPayloadType;
|
| - return 0;
|
| +// Set payload type for Redundant Audio Data RFC 2198
|
| +int32_t RTPSenderAudio::SetRED(int8_t payloadType) {
|
| + if (payloadType < -1) {
|
| + return -1;
|
| + }
|
| + CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| + _REDPayloadType = payloadType;
|
| + return 0;
|
| +}
|
| +
|
| +// Get payload type for Redundant Audio Data RFC 2198
|
| +int32_t RTPSenderAudio::RED(int8_t& payloadType) const {
|
| + CriticalSectionScoped cs(_sendAudioCritsect.get());
|
| + if (_REDPayloadType == -1) {
|
| + // not configured
|
| + return -1;
|
| + }
|
| + payloadType = _REDPayloadType;
|
| + return 0;
|
| }
|
|
|
| // Send a TelephoneEvent tone using RFC 2833 (4733)
|
| -int32_t RTPSenderAudio::SendTelephoneEvent(const uint8_t key,
|
| - const uint16_t time_ms,
|
| - const uint8_t level) {
|
| +int32_t RTPSenderAudio::SendTelephoneEvent(uint8_t key,
|
| + uint16_t time_ms,
|
| + uint8_t level) {
|
| {
|
| CriticalSectionScoped lock(_sendAudioCritsect.get());
|
| if (_dtmfPayloadType < 0) {
|
| @@ -428,63 +408,57 @@ int32_t RTPSenderAudio::SendTelephoneEvent(const uint8_t key,
|
| return AddDTMF(key, time_ms, level);
|
| }
|
|
|
| -int32_t
|
| -RTPSenderAudio::SendTelephoneEventPacket(bool ended,
|
| - int8_t dtmf_payload_type,
|
| - uint32_t dtmfTimeStamp,
|
| - uint16_t duration,
|
| - bool markerBit)
|
| -{
|
| - uint8_t dtmfbuffer[IP_PACKET_SIZE];
|
| - uint8_t sendCount = 1;
|
| - int32_t retVal = 0;
|
| -
|
| - if(ended)
|
| - {
|
| - // resend last packet in an event 3 times
|
| - sendCount = 3;
|
| - }
|
| - do
|
| - {
|
| - //Send DTMF data
|
| - _rtpSender->BuildRTPheader(dtmfbuffer, dtmf_payload_type, markerBit,
|
| - dtmfTimeStamp, _clock->TimeInMilliseconds());
|
| -
|
| - // reset CSRC and X bit
|
| - dtmfbuffer[0] &= 0xe0;
|
| -
|
| - //Create DTMF data
|
| - /* From RFC 2833:
|
| -
|
| - 0 1 2 3
|
| - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| - | event |E|R| volume | duration |
|
| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| - */
|
| - // R bit always cleared
|
| - uint8_t R = 0x00;
|
| - uint8_t volume = _dtmfLevel;
|
| -
|
| - // First packet un-ended
|
| - uint8_t E = ended ? 0x80 : 0x00;
|
| -
|
| - // First byte is Event number, equals key number
|
| - dtmfbuffer[12] = _dtmfKey;
|
| - dtmfbuffer[13] = E|R|volume;
|
| - ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 14, duration);
|
| -
|
| - TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
|
| - "Audio::SendTelephoneEvent", "timestamp",
|
| - dtmfTimeStamp, "seqnum",
|
| - _rtpSender->SequenceNumber());
|
| - retVal = _rtpSender->SendToNetwork(
|
| - dtmfbuffer, 4, 12, TickTime::MillisecondTimestamp(),
|
| - kAllowRetransmission, RtpPacketSender::kHighPriority);
|
| - sendCount--;
|
| -
|
| - }while (sendCount > 0 && retVal == 0);
|
| -
|
| - return retVal;
|
| +int32_t RTPSenderAudio::SendTelephoneEventPacket(bool ended,
|
| + int8_t dtmf_payload_type,
|
| + uint32_t dtmfTimeStamp,
|
| + uint16_t duration,
|
| + bool markerBit) {
|
| + uint8_t dtmfbuffer[IP_PACKET_SIZE];
|
| + uint8_t sendCount = 1;
|
| + int32_t retVal = 0;
|
| +
|
| + if (ended) {
|
| + // resend last packet in an event 3 times
|
| + sendCount = 3;
|
| + }
|
| + do {
|
| + // Send DTMF data
|
| + _rtpSender->BuildRTPheader(dtmfbuffer, dtmf_payload_type, markerBit,
|
| + dtmfTimeStamp, _clock->TimeInMilliseconds());
|
| +
|
| + // reset CSRC and X bit
|
| + dtmfbuffer[0] &= 0xe0;
|
| +
|
| + // Create DTMF data
|
| + /* From RFC 2833:
|
| +
|
| + 0 1 2 3
|
| + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| + | event |E|R| volume | duration |
|
| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| + */
|
| + // R bit always cleared
|
| + uint8_t R = 0x00;
|
| + uint8_t volume = _dtmfLevel;
|
| +
|
| + // First packet un-ended
|
| + uint8_t E = ended ? 0x80 : 0x00;
|
| +
|
| + // First byte is Event number, equals key number
|
| + dtmfbuffer[12] = _dtmfKey;
|
| + dtmfbuffer[13] = E | R | volume;
|
| + ByteWriter<uint16_t>::WriteBigEndian(dtmfbuffer + 14, duration);
|
| +
|
| + TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
|
| + "Audio::SendTelephoneEvent", "timestamp",
|
| + dtmfTimeStamp, "seqnum", _rtpSender->SequenceNumber());
|
| + retVal = _rtpSender->SendToNetwork(
|
| + dtmfbuffer, 4, 12, TickTime::MillisecondTimestamp(),
|
| + kAllowRetransmission, RtpPacketSender::kHighPriority);
|
| + sendCount--;
|
| + } while (sendCount > 0 && retVal == 0);
|
| +
|
| + return retVal;
|
| }
|
| } // namespace webrtc
|
|
|