diff options
Diffstat (limited to 'chromium/third_party/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc')
-rw-r--r-- | chromium/third_party/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc | 458 |
1 files changed, 217 insertions, 241 deletions
diff --git a/chromium/third_party/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc b/chromium/third_party/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc index 3f55db40389..2aa4961cdc7 100644 --- a/chromium/third_party/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc +++ b/chromium/third_party/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc @@ -10,12 +10,12 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" -#include <assert.h> //assert -#include <string.h> //memcpy +#include <string.h> -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/base/trace_event.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" -#include "webrtc/system_wrappers/interface/trace_event.h" +#include "webrtc/system_wrappers/include/tick_util.h" namespace webrtc { @@ -47,8 +47,7 @@ RTPSenderAudio::RTPSenderAudio(Clock* clock, _lastPayloadType(-1), _audioLevel_dBov(0) {} -RTPSenderAudio::~RTPSenderAudio() { -} +RTPSenderAudio::~RTPSenderAudio() {} int RTPSenderAudio::AudioFrequency() const { return kDtmfFrequencyHz; @@ -56,22 +55,20 @@ 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( const char payloadName[RTP_PAYLOAD_NAME_SIZE], const int8_t payloadType, const uint32_t frequency, - const uint8_t channels, + const size_t channels, const uint32_t rate, - RtpUtility::Payload*& payload) { + RtpUtility::Payload** payload) { if (RtpUtility::StringCompare(payloadName, "cn", 2)) { CriticalSectionScoped cs(_sendAudioCritsect.get()); // we can have multiple CNG payload types @@ -99,72 +96,65 @@ int32_t RTPSenderAudio::RegisterAudioPayload( return 0; // The default timestamp rate is 8000 Hz, but other rates may be defined. } - payload = new RtpUtility::Payload; - payload->typeSpecific.Audio.frequency = frequency; - payload->typeSpecific.Audio.channels = channels; - payload->typeSpecific.Audio.rate = rate; - payload->audio = true; - payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0'; - strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); + *payload = new RtpUtility::Payload; + (*payload)->typeSpecific.Audio.frequency = frequency; + (*payload)->typeSpecific.Audio.channels = channels; + (*payload)->typeSpecific.Audio.rate = rate; + (*payload)->audio = true; + (*payload)->name[RTP_PAYLOAD_NAME_SIZE - 1] = '\0'; + strncpy((*payload)->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 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(); @@ -185,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 @@ -208,8 +198,8 @@ int32_t RTPSenderAudio::SendAudio( // A source MAY send events and coded audio packets for the same time // but we don't support it if (_dtmfEventIsOn) { - if (frameType == kFrameEmpty) { - // kFrameEmpty is used to drive the DTMF when in CN mode + if (frameType == kEmptyFrame) { + // kEmptyFrame is used to drive the DTMF when in CN mode // it can be triggered more frequently than we want to send the // DTMF packets. if (packet_size_samples > (captureTimeStamp - _dtmfTimestampLastSent)) { @@ -259,7 +249,7 @@ int32_t RTPSenderAudio::SendAudio( return 0; } if (payloadSize == 0 || payloadData == NULL) { - if (frameType == kFrameEmpty) { + if (frameType == kEmptyFrame) { // we don't send empty audio RTP packets // no error since we use it to drive DTMF when we use VAD return 0; @@ -294,128 +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, - -1, 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) { @@ -426,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, -1, - 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 |