Help to land 7969005 on behalf of solenberg. The review and try is done in 7969005.

- Add ability to VoE to send Absolute Sender Time header extension.
- Refactor handling of RTP header extensions in VoE to work the same as in ViE.
- Add API to enable receiving Absolute Sender Time in VoE.

This is part of the work to include audio packets in bandwidth estimation, for
better accuracy in estimates.

BUG=
TBR=solenberg@webrtc.org,henrikg@webrtc.org,stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5654 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
wu@webrtc.org 2014-03-06 23:49:08 +00:00
parent 79047f99c1
commit ebdb0e3ad0
18 changed files with 490 additions and 300 deletions

View File

@ -32,6 +32,11 @@ struct RTPHeaderExtension {
int32_t transmissionTimeOffset;
bool hasAbsoluteSendTime;
uint32_t absoluteSendTime;
// Audio Level includes both level in dBov and voiced/unvoiced bit. See:
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
bool hasAudioLevel;
uint8_t audioLevel;
};
struct RTPHeader {

View File

@ -670,25 +670,6 @@ class RtpRtcp : public Module {
virtual int32_t SendREDPayloadType(
int8_t& payloadType) const = 0;
/*
* Set status and ID for header-extension-for-audio-level-indication.
* See http://tools.ietf.org/html/rfc6464 for more details.
*
* return -1 on failure else 0
*/
virtual int32_t SetRTPAudioLevelIndicationStatus(
const bool enable,
const uint8_t ID) = 0;
/*
* Get status and ID for header-extension-for-audio-level-indication.
*
* return -1 on failure else 0
*/
virtual int32_t GetRTPAudioLevelIndicationStatus(
bool& enable,
uint8_t& ID) const = 0;
/*
* Store the audio level in dBov for header-extension-for-audio-level-
* indication.

View File

@ -22,7 +22,7 @@ const uint16_t kRtpOneByteHeaderExtensionId = 0xBEDE;
const size_t kRtpOneByteHeaderLength = 4;
const size_t kTransmissionTimeOffsetLength = 4;
const size_t kAudioLevelLength = 2;
const size_t kAudioLevelLength = 4;
const size_t kAbsoluteSendTimeLength = 4;
struct HeaderExtension {
@ -37,11 +37,7 @@ struct HeaderExtension {
length = kTransmissionTimeOffsetLength;
break;
case kRtpExtensionAudioLevel:
// TODO(solenberg): Because of how the audio level extension is handled
// in RTPSenderAudio::SendAudio(), we cannot set the actual length here
// but must leave it at zero. The consequence is that any other header
// extensions registered for an audio channel are effectively ignored.
// length = kAudioLevelLength;
length = kAudioLevelLength;
break;
case kRtpExtensionAbsoluteSendTime:
length = kAbsoluteSendTimeLength;

View File

@ -1209,29 +1209,6 @@ int32_t ModuleRtpRtcpImpl::SetAudioPacketSize(
return rtp_sender_.SetAudioPacketSize(packet_size_samples);
}
int32_t ModuleRtpRtcpImpl::SetRTPAudioLevelIndicationStatus(
const bool enable,
const uint8_t id) {
WEBRTC_TRACE(kTraceModuleCall,
kTraceRtpRtcp,
id_,
"SetRTPAudioLevelIndicationStatus(enable=%d, ID=%u)",
enable,
id);
return rtp_sender_.SetAudioLevelIndicationStatus(enable, id);
}
int32_t ModuleRtpRtcpImpl::GetRTPAudioLevelIndicationStatus(
bool& enable,
uint8_t& id) const {
WEBRTC_TRACE(kTraceModuleCall,
kTraceRtpRtcp,
id_,
"GetRTPAudioLevelIndicationStatus()");
return rtp_sender_.AudioLevelIndicationStatus(&enable, &id);
}
int32_t ModuleRtpRtcpImpl::SetAudioLevel(
const uint8_t level_d_bov) {
WEBRTC_TRACE(kTraceModuleCall,

View File

@ -295,14 +295,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
// Get payload type for Redundant Audio Data RFC 2198.
virtual int32_t SendREDPayloadType(int8_t& payload_type) const OVERRIDE;
// Set status and id for header-extension-for-audio-level-indication.
virtual int32_t SetRTPAudioLevelIndicationStatus(
const bool enable, const uint8_t id) OVERRIDE;
// Get status and id for header-extension-for-audio-level-indication.
virtual int32_t GetRTPAudioLevelIndicationStatus(
bool& enable, uint8_t& id) const OVERRIDE;
// Store the audio level in d_bov for header-extension-for-audio-level-
// indication.
virtual int32_t SetAudioLevel(const uint8_t level_d_bov) OVERRIDE;

View File

@ -1117,9 +1117,8 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer) const {
data_buffer + kHeaderLength + total_block_length);
break;
case kRtpExtensionAudioLevel:
// Because AudioLevel is handled specially by RTPSenderAudio, we pretend
// we don't have to care about it here, which is true until we wan't to
// use it together with any of the other extensions we support.
block_length = BuildAudioLevelExtension(
data_buffer + kHeaderLength + total_block_length);
break;
case kRtpExtensionAbsoluteSendTime:
block_length = BuildAbsoluteSendTimeExtension(
@ -1179,8 +1178,42 @@ uint8_t RTPSender::BuildTransmissionTimeOffsetExtension(
return kTransmissionTimeOffsetLength;
}
uint8_t RTPSender::BuildAbsoluteSendTimeExtension(
uint8_t* data_buffer) const {
uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const {
// An RTP Header Extension for Client-to-Mixer Audio Level Indication
//
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
//
// The form of the audio level extension block:
//
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ID | len=0 |V| level | 0x00 | 0x00 |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Note that we always include 2 pad bytes, which will result in legal and
// correctly parsed RTP, but may be a bit wasteful if more short extensions
// are implemented. Right now the pad bytes would anyway be required at end
// of the extension block, so it makes no difference.
// Get id defined by user.
uint8_t id;
if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) != 0) {
// Not registered.
return 0;
}
size_t pos = 0;
const uint8_t len = 0;
data_buffer[pos++] = (id << 4) + len;
data_buffer[pos++] = (1 << 7) + 0; // Voice, 0 dBov.
data_buffer[pos++] = 0; // Padding.
data_buffer[pos++] = 0; // Padding.
// kAudioLevelLength is including pad bytes.
assert(pos == kAudioLevelLength);
return kAudioLevelLength;
}
uint8_t RTPSender::BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const {
// Absolute send time in RTP streams.
//
// The absolute send time is signaled to the receiver in-band using the
@ -1265,6 +1298,55 @@ bool RTPSender::UpdateTransmissionTimeOffset(
return true;
}
bool RTPSender::UpdateAudioLevel(uint8_t *rtp_packet,
const uint16_t rtp_packet_length,
const RTPHeader &rtp_header,
const bool is_voiced,
const uint8_t dBov) const {
CriticalSectionScoped cs(send_critsect_);
// Get length until start of header extension block.
int extension_block_pos =
rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(
kRtpExtensionAudioLevel);
if (extension_block_pos < 0) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, id_,
"Failed to update audio level, not registered.");
return false;
}
int block_pos = 12 + rtp_header.numCSRCs + extension_block_pos;
if (rtp_packet_length < block_pos + kAudioLevelLength ||
rtp_header.headerLength < block_pos + kAudioLevelLength) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, id_,
"Failed to update audio level, invalid length.");
return false;
}
// Verify that header contains extension.
if (!((rtp_packet[12 + rtp_header.numCSRCs] == 0xBE) &&
(rtp_packet[12 + rtp_header.numCSRCs + 1] == 0xDE))) {
WEBRTC_TRACE(
kTraceStream, kTraceRtpRtcp, id_,
"Failed to update audio level, hdr extension not found.");
return false;
}
// Get id.
uint8_t id = 0;
if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) != 0) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, id_,
"Failed to update audio level, no id.");
return false;
}
// Verify first byte in block.
const uint8_t first_block_byte = (id << 4) + 0;
if (rtp_packet[block_pos] != first_block_byte) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, id_,
"Failed to update audio level.");
return false;
}
rtp_packet[block_pos + 1] = (is_voiced ? 0x80 : 0x00) + (dBov & 0x7f);
return true;
}
bool RTPSender::UpdateAbsoluteSendTime(
uint8_t *rtp_packet, const uint16_t rtp_packet_length,
const RTPHeader &rtp_header, const int64_t now_ms) const {
@ -1463,19 +1545,6 @@ int32_t RTPSender::SetAudioPacketSize(
return audio_->SetAudioPacketSize(packet_size_samples);
}
int32_t RTPSender::SetAudioLevelIndicationStatus(const bool enable,
const uint8_t ID) {
if (!audio_configured_) {
return -1;
}
return audio_->SetAudioLevelIndicationStatus(enable, ID);
}
int32_t RTPSender::AudioLevelIndicationStatus(bool *enable,
uint8_t* id) const {
return audio_->AudioLevelIndicationStatus(*enable, *id);
}
int32_t RTPSender::SetAudioLevel(const uint8_t level_d_bov) {
return audio_->SetAudioLevel(level_d_bov);
}

View File

@ -153,15 +153,19 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
uint16_t BuildRTPHeaderExtension(uint8_t* data_buffer) const;
uint8_t BuildTransmissionTimeOffsetExtension(
uint8_t *data_buffer) const;
uint8_t BuildAbsoluteSendTimeExtension(
uint8_t* data_buffer) const;
uint8_t BuildTransmissionTimeOffsetExtension(uint8_t *data_buffer) const;
uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const;
uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const;
bool UpdateTransmissionTimeOffset(uint8_t *rtp_packet,
const uint16_t rtp_packet_length,
const RTPHeader &rtp_header,
const int64_t time_diff_ms) const;
bool UpdateAudioLevel(uint8_t *rtp_packet,
const uint16_t rtp_packet_length,
const RTPHeader &rtp_header,
const bool is_voiced,
const uint8_t dBov) const;
bool UpdateAbsoluteSendTime(uint8_t *rtp_packet,
const uint16_t rtp_packet_length,
const RTPHeader &rtp_header,
@ -228,12 +232,6 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
// packet in silence (CNG).
int32_t SetAudioPacketSize(const uint16_t packet_size_samples);
// Set status and ID for header-extension-for-audio-level-indication.
int32_t SetAudioLevelIndicationStatus(const bool enable, const uint8_t ID);
// Get status and ID for header-extension-for-audio-level-indication.
int32_t AudioLevelIndicationStatus(bool *enable, uint8_t *id) const;
// Store the audio level in d_bov for
// header-extension-for-audio-level-indication.
int32_t SetAudioLevel(const uint8_t level_d_bov);

View File

@ -17,7 +17,7 @@
namespace webrtc {
RTPSenderAudio::RTPSenderAudio(const int32_t id, Clock* clock,
RTPSenderInterface* rtpSender) :
RTPSender* rtpSender) :
_id(id),
_clock(clock),
_rtpSender(rtpSender),
@ -42,8 +42,6 @@ RTPSenderAudio::RTPSenderAudio(const int32_t id, Clock* clock,
_cngSWBPayloadType(-1),
_cngFBPayloadType(-1),
_lastPayloadType(-1),
_includeAudioLevelIndication(false), // @TODO - reset at Init()?
_audioLevelIndicationID(0),
_audioLevel_dBov(0) {
};
@ -365,52 +363,12 @@ int32_t RTPSenderAudio::SendAudio(
if (rtpHeaderLength <= 0) {
return -1;
}
if (maxPayloadLength < (rtpHeaderLength + payloadSize)) {
// Too large payload buffer.
return -1;
}
{
CriticalSectionScoped cs(_sendAudioCritsect);
// https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
if (_includeAudioLevelIndication) {
dataBuffer[0] |= 0x10; // set eXtension bit
/*
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0xBE | 0xDE | length=1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | len=0 |V| level | 0x00 | 0x00 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
// add our ID (0xBEDE)
ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer+rtpHeaderLength,
RTP_AUDIO_LEVEL_UNIQUE_ID);
rtpHeaderLength += 2;
// add the length (length=1) in number of word32
const uint8_t length = 1;
ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer+rtpHeaderLength,
length);
rtpHeaderLength += 2;
// add ID (defined by the user) and len(=0) byte
const uint8_t id = _audioLevelIndicationID;
const uint8_t len = 0;
dataBuffer[rtpHeaderLength++] = (id << 4) + len;
// add voice-activity flag (V) bit and the audio level (in dBov)
const uint8_t V = (frameType == kAudioFrameSpeech);
uint8_t level = _audioLevel_dBov;
dataBuffer[rtpHeaderLength++] = (V << 7) + level;
// add two bytes zero padding
ModuleRTPUtility::AssignUWord16ToBuffer(dataBuffer+rtpHeaderLength, 0);
rtpHeaderLength += 2;
}
if(maxPayloadLength < rtpHeaderLength + payloadSize ) {
// too large payload buffer
return -1;
}
if (_REDPayloadType >= 0 && // Have we configured RED?
fragmentation &&
fragmentation->fragmentationVectorSize > 1 &&
@ -474,6 +432,17 @@ int32_t RTPSenderAudio::SendAudio(
}
}
_lastPayloadType = payloadType;
// Update audio level extension, if included.
{
uint16_t packetSize = payloadSize + rtpHeaderLength;
ModuleRTPUtility::RTPHeaderParser rtp_parser(dataBuffer, packetSize);
RTPHeader rtp_header;
rtp_parser.Parse(rtp_header);
_rtpSender->UpdateAudioLevel(dataBuffer, packetSize, rtp_header,
(frameType == kAudioFrameSpeech),
_audioLevel_dBov);
}
} // end critical section
TRACE_EVENT_ASYNC_END2("webrtc", "Audio", captureTimeStamp,
"timestamp", _rtpSender->Timestamp(),
@ -486,32 +455,6 @@ int32_t RTPSenderAudio::SendAudio(
PacedSender::kHighPriority);
}
int32_t
RTPSenderAudio::SetAudioLevelIndicationStatus(const bool enable,
const uint8_t ID)
{
if(enable && (ID < 1 || ID > 14))
{
return -1;
}
CriticalSectionScoped cs(_sendAudioCritsect);
_includeAudioLevelIndication = enable;
_audioLevelIndicationID = ID;
return 0;
}
int32_t
RTPSenderAudio::AudioLevelIndicationStatus(bool& enable,
uint8_t& ID) const
{
CriticalSectionScoped cs(_sendAudioCritsect);
enable = _includeAudioLevelIndication;
ID = _audioLevelIndicationID;
return 0;
}
// Audio level magnitude and voice activity flag are set for each RTP packet
int32_t
RTPSenderAudio::SetAudioLevel(const uint8_t level_dBov)

View File

@ -23,7 +23,7 @@ class RTPSenderAudio: public DTMFqueue
{
public:
RTPSenderAudio(const int32_t id, Clock* clock,
RTPSenderInterface* rtpSender);
RTPSender* rtpSender);
virtual ~RTPSenderAudio();
int32_t RegisterAudioPayload(
@ -44,13 +44,6 @@ public:
// set audio packet size, used to determine when it's time to send a DTMF packet in silence (CNG)
int32_t SetAudioPacketSize(const uint16_t packetSizeSamples);
// Set status and ID for header-extension-for-audio-level-indication.
// Valid ID range is [1,14].
int32_t SetAudioLevelIndicationStatus(const bool enable, const uint8_t ID);
// Get status and ID for header-extension-for-audio-level-indication.
int32_t AudioLevelIndicationStatus(bool& enable, uint8_t& ID) const;
// Store the audio level in dBov for header-extension-for-audio-level-indication.
// Valid range is [0,100]. Actual value is negative.
int32_t SetAudioLevel(const uint8_t level_dBov);
@ -86,7 +79,7 @@ protected:
private:
int32_t _id;
Clock* _clock;
RTPSenderInterface* _rtpSender;
RTPSender* _rtpSender;
CriticalSectionWrapper* _audioFeedbackCritsect;
RtpAudioFeedback* _audioFeedback;
@ -117,8 +110,6 @@ private:
int8_t _lastPayloadType;
// Audio level indication (https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/)
bool _includeAudioLevelIndication;
uint8_t _audioLevelIndicationID;
uint8_t _audioLevel_dBov;
};
} // namespace webrtc

View File

@ -160,11 +160,8 @@ TEST_F(RtpSenderTest, RegisterRtpAudioLevelHeaderExtension) {
EXPECT_EQ(0, rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
// Accounted size for audio level is zero because it is currently specially
// treated by RTPSenderAudio.
EXPECT_EQ(0, rtp_sender_->RtpHeaderExtensionTotalLength());
// EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength,
// rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength,
rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
kRtpExtensionAudioLevel));
EXPECT_EQ(0, rtp_sender_->RtpHeaderExtensionTotalLength());
@ -183,14 +180,16 @@ TEST_F(RtpSenderTest, RegisterRtpHeaderExtensions) {
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
EXPECT_EQ(kRtpOneByteHeaderLength + kTransmissionTimeOffsetLength +
kAbsoluteSendTimeLength, rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset));
EXPECT_EQ(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength,
kAbsoluteSendTimeLength + kAudioLevelLength,
rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset));
EXPECT_EQ(kRtpOneByteHeaderLength + kAbsoluteSendTimeLength +
kAudioLevelLength, rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime));
EXPECT_EQ(0, rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(kRtpOneByteHeaderLength + kAudioLevelLength,
rtp_sender_->RtpHeaderExtensionTotalLength());
EXPECT_EQ(0, rtp_sender_->DeregisterRtpHeaderExtension(
kRtpExtensionAudioLevel));
EXPECT_EQ(0, rtp_sender_->RtpHeaderExtensionTotalLength());
@ -202,23 +201,24 @@ TEST_F(RtpSenderTest, BuildRTPPacket) {
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(12, length);
EXPECT_EQ(kRtpHeaderSize, length);
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
webrtc::RTPHeader rtp_header;
RtpHeaderExtensionMap map;
map.Register(kRtpExtensionTransmissionTimeOffset,
kTransmissionTimeOffsetExtensionId);
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map);
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, NULL);
ASSERT_TRUE(valid_rtp_header);
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_FALSE(rtp_header.extension.hasTransmissionTimeOffset);
EXPECT_FALSE(rtp_header.extension.hasAbsoluteSendTime);
EXPECT_FALSE(rtp_header.extension.hasAudioLevel);
EXPECT_EQ(0, rtp_header.extension.transmissionTimeOffset);
EXPECT_EQ(0u, rtp_header.extension.absoluteSendTime);
EXPECT_EQ(0u, rtp_header.extension.audioLevel);
}
TEST_F(RtpSenderTest, BuildRTPPacketWithTransmissionOffsetExtension) {
@ -231,7 +231,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithTransmissionOffsetExtension) {
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
EXPECT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionTotalLength(),
length);
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
@ -246,6 +247,7 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithTransmissionOffsetExtension) {
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
EXPECT_EQ(kTimeOffset, rtp_header.extension.transmissionTimeOffset);
// Parse without map extension
@ -255,6 +257,7 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithTransmissionOffsetExtension) {
ASSERT_TRUE(valid_rtp_header2);
VerifyRTPHeaderCommon(rtp_header2);
EXPECT_EQ(length, rtp_header2.headerLength);
EXPECT_FALSE(rtp_header2.extension.hasTransmissionTimeOffset);
EXPECT_EQ(0, rtp_header2.extension.transmissionTimeOffset);
}
@ -269,7 +272,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithNegativeTransmissionOffsetExtension) {
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
EXPECT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionTotalLength(),
length);
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
@ -284,6 +288,7 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithNegativeTransmissionOffsetExtension) {
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
EXPECT_EQ(kNegTimeOffset, rtp_header.extension.transmissionTimeOffset);
}
@ -297,7 +302,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithAbsoluteSendTimeExtension) {
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
EXPECT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionTotalLength(),
length);
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
@ -311,6 +317,7 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithAbsoluteSendTimeExtension) {
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime);
EXPECT_EQ(kAbsoluteSendTime, rtp_header.extension.absoluteSendTime);
// Parse without map extension
@ -320,9 +327,54 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithAbsoluteSendTimeExtension) {
ASSERT_TRUE(valid_rtp_header2);
VerifyRTPHeaderCommon(rtp_header2);
EXPECT_EQ(length, rtp_header2.headerLength);
EXPECT_FALSE(rtp_header2.extension.hasAbsoluteSendTime);
EXPECT_EQ(0u, rtp_header2.extension.absoluteSendTime);
}
TEST_F(RtpSenderTest, BuildRTPPacketWithAudioLevelExtension) {
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionTotalLength(),
length);
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
webrtc::RTPHeader rtp_header;
// Updating audio level is done in RTPSenderAudio, so simulate it here.
rtp_parser.Parse(rtp_header);
rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true, kAudioLevel);
RtpHeaderExtensionMap map;
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map);
ASSERT_TRUE(valid_rtp_header);
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
// Expect kAudioLevel + 0x80 because we set "voiced" to true in the call to
// UpdateAudioLevel(), above.
EXPECT_EQ(kAudioLevel + 0x80u, rtp_header.extension.audioLevel);
// Parse without map extension
webrtc::RTPHeader rtp_header2;
const bool valid_rtp_header2 = rtp_parser.Parse(rtp_header2, NULL);
ASSERT_TRUE(valid_rtp_header2);
VerifyRTPHeaderCommon(rtp_header2);
EXPECT_EQ(length, rtp_header2.headerLength);
EXPECT_FALSE(rtp_header2.extension.hasAudioLevel);
EXPECT_EQ(0u, rtp_header2.extension.audioLevel);
}
TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
EXPECT_EQ(0, rtp_sender_->SetTransmissionTimeOffset(kTimeOffset));
EXPECT_EQ(0, rtp_sender_->SetAbsoluteSendTime(kAbsoluteSendTime));
@ -330,30 +382,42 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
EXPECT_EQ(kRtpHeaderSize + rtp_sender_->RtpHeaderExtensionTotalLength(),
length);
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
webrtc::RTPHeader rtp_header;
// Updating audio level is done in RTPSenderAudio, so simulate it here.
rtp_parser.Parse(rtp_header);
rtp_sender_->UpdateAudioLevel(packet_, length, rtp_header, true, kAudioLevel);
RtpHeaderExtensionMap map;
map.Register(kRtpExtensionTransmissionTimeOffset,
kTransmissionTimeOffsetExtensionId);
map.Register(kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId);
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map);
ASSERT_TRUE(valid_rtp_header);
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
EXPECT_TRUE(rtp_header.extension.hasTransmissionTimeOffset);
EXPECT_TRUE(rtp_header.extension.hasAbsoluteSendTime);
EXPECT_TRUE(rtp_header.extension.hasAudioLevel);
EXPECT_EQ(kTimeOffset, rtp_header.extension.transmissionTimeOffset);
EXPECT_EQ(kAbsoluteSendTime, rtp_header.extension.absoluteSendTime);
EXPECT_EQ(kAudioLevel + 0x80u, rtp_header.extension.audioLevel);
// Parse without map extension
webrtc::RTPHeader rtp_header2;
@ -362,8 +426,12 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
ASSERT_TRUE(valid_rtp_header2);
VerifyRTPHeaderCommon(rtp_header2);
EXPECT_EQ(length, rtp_header2.headerLength);
EXPECT_FALSE(rtp_header2.extension.hasTransmissionTimeOffset);
EXPECT_FALSE(rtp_header2.extension.hasAbsoluteSendTime);
EXPECT_FALSE(rtp_header2.extension.hasAudioLevel);
EXPECT_EQ(0, rtp_header2.extension.transmissionTimeOffset);
EXPECT_EQ(0u, rtp_header2.extension.absoluteSendTime);
EXPECT_EQ(0u, rtp_header2.extension.audioLevel);
}
TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
@ -493,7 +561,7 @@ TEST_F(RtpSenderTest, SendPadding) {
uint16_t seq_num = kSeqNum;
uint32_t timestamp = kTimestamp;
rtp_sender_->SetStorePacketsStatus(true, 10);
int rtp_header_len = 12;
int32_t rtp_header_len = kRtpHeaderSize;
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
rtp_header_len += 4; // 4 bytes extension.
@ -613,7 +681,7 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) {
uint16_t seq_num = kSeqNum;
rtp_sender_->SetStorePacketsStatus(true, 10);
int rtp_header_len = 12;
int32_t rtp_header_len = kRtpHeaderSize;
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
rtp_header_len += 4; // 4 bytes extension.
@ -939,48 +1007,6 @@ TEST_F(RtpSenderTest, StreamDataCountersCallbacks) {
rtp_sender_->RegisterRtpStatisticsCallback(NULL);
}
TEST_F(RtpSenderAudioTest, BuildRTPPacketWithAudioLevelExtension) {
EXPECT_EQ(0, rtp_sender_->SetAudioLevelIndicationStatus(true,
kAudioLevelExtensionId));
EXPECT_EQ(0, rtp_sender_->SetAudioLevel(kAudioLevel));
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kAudioPayload,
kMarkerBit,
kTimestamp,
0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
// Currently, no space is added by for header extension by BuildRTPHeader().
EXPECT_EQ(0, rtp_sender_->RtpHeaderExtensionTotalLength());
// Verify
webrtc::ModuleRTPUtility::RTPHeaderParser rtp_parser(packet_, length);
webrtc::RTPHeader rtp_header;
RtpHeaderExtensionMap map;
map.Register(kRtpExtensionAudioLevel, kAudioLevelExtensionId);
const bool valid_rtp_header = rtp_parser.Parse(rtp_header, &map);
ASSERT_TRUE(valid_rtp_header);
ASSERT_FALSE(rtp_parser.RTCP());
VerifyRTPHeaderCommon(rtp_header);
EXPECT_EQ(length, rtp_header.headerLength);
// TODO(solenberg): Should verify that we got audio level in header extension.
// Parse without map extension
webrtc::RTPHeader rtp_header2;
const bool valid_rtp_header2 = rtp_parser.Parse(rtp_header2, NULL);
ASSERT_TRUE(valid_rtp_header2);
VerifyRTPHeaderCommon(rtp_header2);
EXPECT_EQ(length, rtp_header2.headerLength);
// TODO(solenberg): Should verify that we didn't get audio level.
EXPECT_EQ(0, rtp_sender_->SetAudioLevelIndicationStatus(false, 0));
}
TEST_F(RtpSenderAudioTest, SendAudio) {
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "PAYLOAD_NAME";
const uint8_t payload_type = 127;
@ -1007,8 +1033,6 @@ TEST_F(RtpSenderAudioTest, SendAudio) {
}
TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) {
EXPECT_EQ(0, rtp_sender_->SetAudioLevelIndicationStatus(true,
kAudioLevelExtensionId));
EXPECT_EQ(0, rtp_sender_->SetAudioLevel(kAudioLevel));
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAudioLevel, kAudioLevelExtensionId));
@ -1044,7 +1068,6 @@ TEST_F(RtpSenderAudioTest, SendAudioWithAudioLevelExtension) {
EXPECT_EQ(0, memcmp(extension, payload_data - sizeof(extension),
sizeof(extension)));
EXPECT_EQ(0, rtp_sender_->SetAudioLevelIndicationStatus(false, 0));
}
} // namespace webrtc

View File

@ -398,6 +398,10 @@ bool RTPHeaderParser::Parse(RTPHeader& header,
header.extension.hasAbsoluteSendTime = false;
header.extension.absoluteSendTime = 0;
// May not be present in packet.
header.extension.hasAudioLevel = false;
header.extension.audioLevel = 0;
if (X) {
/* RTP header extension, RFC 3550.
0 1 2 3
@ -496,7 +500,11 @@ void RTPHeaderParser::ParseOneByteExtensionHeader(
break;
}
case kRtpExtensionAudioLevel: {
// --- Only used for debugging ---
if (len != 0) {
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
"Incorrect audio level len: %d", len);
return;
}
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@ -509,6 +517,9 @@ void RTPHeaderParser::ParseOneByteExtensionHeader(
// const uint8_t level = (*ptr & 0x7f);
// DEBUG_PRINT("RTP_AUDIO_LEVEL_UNIQUE_ID: ID=%u, len=%u, V=%u,
// level=%u", ID, len, V, level);
header.extension.audioLevel = *ptr++;
header.extension.hasAudioLevel = true;
break;
}
case kRtpExtensionAbsoluteSendTime: {

View File

@ -3503,9 +3503,7 @@ Channel::GetRemoteCSRCs(unsigned int arrCSRC[15])
return CSRCs;
}
int
Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
{
int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
if (rtp_audioproc_.get() == NULL) {
rtp_audioproc_.reset(AudioProcessing::Create(VoEModuleId(_instanceId,
_channelId)));
@ -3519,23 +3517,24 @@ Channel::SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID)
}
_includeAudioLevelIndication = enable;
if (enable) {
rtp_header_parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
ID);
} else {
rtp_header_parser_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
}
return _rtpRtcpModule->SetRTPAudioLevelIndicationStatus(enable, ID);
return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
}
int
Channel::GetRTPAudioLevelIndicationStatus(bool& enabled, unsigned char& ID)
{
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId,_channelId),
"GetRTPAudioLevelIndicationStatus() => enabled=%d, ID=%u",
enabled, ID);
return _rtpRtcpModule->GetRTPAudioLevelIndicationStatus(enabled, ID);
int Channel::SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id) {
return SetSendRtpHeaderExtension(enable, kRtpExtensionAbsoluteSendTime, id);
}
int Channel::SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id) {
rtp_header_parser_->DeregisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime);
if (enable) {
if (!rtp_header_parser_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, id)) {
return -1;
}
}
return 0;
}
int
@ -5059,5 +5058,14 @@ int Channel::SetRedPayloadType(int red_payload_type) {
return 0;
}
int Channel::SetSendRtpHeaderExtension(bool enable, RTPExtensionType type,
unsigned char id) {
int error = 0;
_rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
if (enable) {
error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
}
return error;
}
} // namespace voe
} // namespace webrtc

View File

@ -253,8 +253,9 @@ public:
int GetLocalSSRC(unsigned int& ssrc);
int GetRemoteSSRC(unsigned int& ssrc);
int GetRemoteCSRCs(unsigned int arrCSRC[15]);
int SetRTPAudioLevelIndicationStatus(bool enable, unsigned char ID);
int GetRTPAudioLevelIndicationStatus(bool& enable, unsigned char& ID);
int SetSendAudioLevelIndicationStatus(bool enable, unsigned char id);
int SetSendAbsoluteSenderTimeStatus(bool enable, unsigned char id);
int SetReceiveAbsoluteSenderTimeStatus(bool enable, unsigned char id);
int SetRTCPStatus(bool enable);
int GetRTCPStatus(bool& enabled);
int SetRTCP_CNAME(const char cName[256]);
@ -438,6 +439,8 @@ private:
void RegisterReceiveCodecsToRTPModule();
int SetRedPayloadType(int red_payload_type);
int SetSendRtpHeaderExtension(bool enable, RTPExtensionType type,
unsigned char id);
CriticalSectionWrapper& _fileCritSect;
CriticalSectionWrapper& _callbackCritSect;

View File

@ -152,12 +152,19 @@ public:
virtual int GetRemoteSSRC(int channel, unsigned int& ssrc) = 0;
// Sets the status of rtp-audio-level-indication on a specific |channel|.
virtual int SetRTPAudioLevelIndicationStatus(
int channel, bool enable, unsigned char ID = 1) = 0;
virtual int SetSendAudioLevelIndicationStatus(int channel,
bool enable,
unsigned char id = 1) = 0;
// Sets the status of rtp-audio-level-indication on a specific |channel|.
virtual int GetRTPAudioLevelIndicationStatus(
int channel, bool& enabled, unsigned char& ID) = 0;
// Sets the status of sending absolute sender time on a specific |channel|.
virtual int SetSendAbsoluteSenderTimeStatus(int channel,
bool enable,
unsigned char id) = 0;
// Sets status of receiving absolute sender time on a specific |channel|.
virtual int SetReceiveAbsoluteSenderTimeStatus(int channel,
bool enable,
unsigned char id) = 0;
// Gets the CSRCs of the incoming RTP packets.
virtual int GetRemoteCSRCs(int channel, unsigned int arrCSRC[15]) = 0;

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2014 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/interface/module_common_types.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
#include "webrtc/system_wrappers/interface/atomic32.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"
class ExtensionVerifyTransport : public webrtc::Transport {
public:
ExtensionVerifyTransport()
: received_packets_(0),
ok_packets_(0),
parser_(webrtc::RtpHeaderParser::Create()),
audio_level_id_(-1),
absolute_sender_time_id_(-1) {
}
virtual int SendPacket(int channel, const void* data, int len) {
++received_packets_;
webrtc::RTPHeader header = {0};
if (parser_->Parse(static_cast<const uint8_t*>(data), len, &header)) {
bool ok = true;
if (audio_level_id_ >= 0 && !header.extension.hasAudioLevel) {
ok = false;
}
if (absolute_sender_time_id_ >= 0 &&
!header.extension.hasAbsoluteSendTime) {
ok = false;
}
if (ok) {
++ok_packets_;
}
}
return len;
}
virtual int SendRTCPPacket(int channel, const void* data, int len) {
return len;
}
void SetAudioLevelId(int id) {
audio_level_id_ = id;
parser_->RegisterRtpHeaderExtension(webrtc::kRtpExtensionAudioLevel, id);
}
void SetAbsoluteSenderTimeId(int id) {
absolute_sender_time_id_ = id;
parser_->RegisterRtpHeaderExtension(webrtc::kRtpExtensionAbsoluteSendTime,
id);
}
bool WaitForNPackets(int count) {
while (received_packets_.Value() < count) {
webrtc::SleepMs(10);
}
return (ok_packets_.Value() == count);
}
private:
webrtc::Atomic32 received_packets_;
webrtc::Atomic32 ok_packets_;
webrtc::scoped_ptr<webrtc::RtpHeaderParser> parser_;
int audio_level_id_;
int absolute_sender_time_id_;
};
class SendRtpRtcpHeaderExtensionsTest : public AfterStreamingFixture {
protected:
virtual void SetUp() {
PausePlaying();
EXPECT_EQ(0, voe_network_->DeRegisterExternalTransport(channel_));
EXPECT_EQ(0, voe_network_->RegisterExternalTransport(channel_,
verifying_transport_));
}
virtual void TearDown() {
PausePlaying();
}
ExtensionVerifyTransport verifying_transport_;
};
TEST_F(SendRtpRtcpHeaderExtensionsTest, SentPacketsIncludeAudioLevel) {
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAudioLevelIndicationStatus(channel_, true,
9));
verifying_transport_.SetAudioLevelId(9);
ResumePlaying();
EXPECT_TRUE(verifying_transport_.WaitForNPackets(10));
}
TEST_F(SendRtpRtcpHeaderExtensionsTest, SentPacketsIncludeAbsoluteSenderTime) {
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAbsoluteSenderTimeStatus(channel_, true,
11));
verifying_transport_.SetAbsoluteSenderTimeId(11);
ResumePlaying();
EXPECT_TRUE(verifying_transport_.WaitForNPackets(10));
}
TEST_F(SendRtpRtcpHeaderExtensionsTest, SentPacketsIncludeAllExtensions1) {
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAudioLevelIndicationStatus(channel_, true,
9));
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAbsoluteSenderTimeStatus(channel_, true,
11));
verifying_transport_.SetAudioLevelId(9);
verifying_transport_.SetAbsoluteSenderTimeId(11);
ResumePlaying();
EXPECT_TRUE(verifying_transport_.WaitForNPackets(10));
}
TEST_F(SendRtpRtcpHeaderExtensionsTest, SentPacketsIncludeAllExtensions2) {
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAbsoluteSenderTimeStatus(channel_, true,
3));
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAudioLevelIndicationStatus(channel_, true,
9));
verifying_transport_.SetAbsoluteSenderTimeId(3);
verifying_transport_.SetAudioLevelId(9);
ResumePlaying();
EXPECT_TRUE(verifying_transport_.WaitForNPackets(10));
}
class ReceiveRtpRtcpHeaderExtensionsTest : public AfterStreamingFixture {
protected:
virtual void SetUp() {
PausePlaying();
}
};
TEST_F(ReceiveRtpRtcpHeaderExtensionsTest, ReceivedAbsoluteSenderTimeWorks) {
EXPECT_EQ(0, voe_rtp_rtcp_->SetSendAbsoluteSenderTimeStatus(channel_, true,
11));
EXPECT_EQ(0, voe_rtp_rtcp_->SetReceiveAbsoluteSenderTimeStatus(channel_, true,
11));
ResumePlaying();
// Ensure the RTP-RTCP process gets scheduled.
Sleep(1000);
// TODO(solenberg): Verify received packets are forwarded to RBE.
}

View File

@ -211,62 +211,96 @@ int VoERTP_RTCPImpl::GetRemoteCSRCs(int channel, unsigned int arrCSRC[15])
return channelPtr->GetRemoteCSRCs(arrCSRC);
}
int VoERTP_RTCPImpl::SetRTPAudioLevelIndicationStatus(int channel,
bool enable,
unsigned char ID)
int VoERTP_RTCPImpl::SetSendAudioLevelIndicationStatus(int channel,
bool enable,
unsigned char id)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetRTPAudioLevelIndicationStatus(channel=%d, enable=%d,"
" ID=%u)", channel, enable, ID);
"SetSendAudioLevelIndicationStatus(channel=%d, enable=%d,"
" ID=%u)", channel, enable, id);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (enable && (ID < kVoiceEngineMinRtpExtensionId ||
ID > kVoiceEngineMaxRtpExtensionId))
if (enable && (id < kVoiceEngineMinRtpExtensionId ||
id > kVoiceEngineMaxRtpExtensionId))
{
// [RFC5285] The 4-bit ID is the local identifier of this element in
// [RFC5285] The 4-bit id is the local identifier of this element in
// the range 1-14 inclusive.
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetRTPAudioLevelIndicationStatus() invalid ID parameter");
"SetSendAudioLevelIndicationStatus() invalid ID parameter");
return -1;
}
// Set state and ID for the specified channel.
// Set state and id for the specified channel.
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetRTPAudioLevelIndicationStatus() failed to locate channel");
"SetSendAudioLevelIndicationStatus() failed to locate channel");
return -1;
}
return channelPtr->SetRTPAudioLevelIndicationStatus(enable, ID);
return channelPtr->SetSendAudioLevelIndicationStatus(enable, id);
}
int VoERTP_RTCPImpl::GetRTPAudioLevelIndicationStatus(int channel,
bool& enabled,
unsigned char& ID)
{
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"GetRTPAudioLevelIndicationStatus(channel=%d, enable=?, ID=?)",
channel);
if (!_shared->statistics().Initialized())
{
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL)
{
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"GetRTPAudioLevelIndicationStatus() failed to locate channel");
return -1;
}
return channelPtr->GetRTPAudioLevelIndicationStatus(enabled, ID);
int VoERTP_RTCPImpl::SetSendAbsoluteSenderTimeStatus(int channel,
bool enable,
unsigned char id) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetSendAbsoluteSenderTimeStatus(channel=%d, enable=%d, id=%u)",
channel, enable, id);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (enable && (id < kVoiceEngineMinRtpExtensionId ||
id > kVoiceEngineMaxRtpExtensionId)) {
// [RFC5285] The 4-bit id is the local identifier of this element in
// the range 1-14 inclusive.
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetSendAbsoluteSenderTimeStatus() invalid id parameter");
return -1;
}
// Set state and id for the specified channel.
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetSendAbsoluteSenderTimeStatus() failed to locate channel");
return -1;
}
return channelPtr->SetSendAbsoluteSenderTimeStatus(enable, id);
}
int VoERTP_RTCPImpl::SetReceiveAbsoluteSenderTimeStatus(int channel,
bool enable,
unsigned char id) {
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
"SetReceiveAbsoluteSenderTimeStatus(channel=%d, enable=%d, id=%u)",
channel, enable, id);
if (!_shared->statistics().Initialized()) {
_shared->SetLastError(VE_NOT_INITED, kTraceError);
return -1;
}
if (enable && (id < kVoiceEngineMinRtpExtensionId ||
id > kVoiceEngineMaxRtpExtensionId)) {
// [RFC5285] The 4-bit id is the local identifier of this element in
// the range 1-14 inclusive.
_shared->SetLastError(VE_INVALID_ARGUMENT, kTraceError,
"SetReceiveAbsoluteSenderTimeStatus() invalid id parameter");
return -1;
}
// Set state and id for the specified channel.
voe::ChannelOwner ch = _shared->channel_manager().GetChannel(channel);
voe::Channel* channelPtr = ch.channel();
if (channelPtr == NULL) {
_shared->SetLastError(VE_CHANNEL_NOT_VALID, kTraceError,
"SetReceiveAbsoluteSenderTimeStatus() failed to locate channel");
return -1;
}
return channelPtr->SetReceiveAbsoluteSenderTimeStatus(enable, id);
}
int VoERTP_RTCPImpl::SetRTCPStatus(int channel, bool enable)

View File

@ -63,13 +63,17 @@ public:
virtual int GetRemoteSSRC(int channel, unsigned int& ssrc);
// RTP Header Extension for Client-to-Mixer Audio Level Indication
virtual int SetRTPAudioLevelIndicationStatus(int channel,
bool enable,
unsigned char ID);
virtual int SetSendAudioLevelIndicationStatus(int channel,
bool enable,
unsigned char id);
virtual int GetRTPAudioLevelIndicationStatus(int channel,
bool& enabled,
unsigned char& ID);
// RTP Header Extension for Absolute Sender Time
virtual int SetSendAbsoluteSenderTimeStatus(int channel,
bool enable,
unsigned char id);
virtual int SetReceiveAbsoluteSenderTimeStatus(int channel,
bool enable,
unsigned char id);
// CSRC
virtual int GetRemoteCSRCs(int channel, unsigned int arrCSRC[15]);

View File

@ -184,6 +184,7 @@
'test/auto_test/standard/neteq_test.cc',
'test/auto_test/standard/network_test.cc',
'test/auto_test/standard/rtp_rtcp_before_streaming_test.cc',
'test/auto_test/standard/rtp_rtcp_extensions.cc',
'test/auto_test/standard/rtp_rtcp_test.cc',
'test/auto_test/standard/voe_base_misc_test.cc',
'test/auto_test/standard/video_sync_test.cc',