Revert of Remove RTPPayloadStrategy and simplify RTPPayloadRegistry (patchset #7 id:240001 of https://codereview.webrtc.org/2524923002/ )
Reason for revert: Breaks downstream projects. Original issue's description: > Remove RTPPayloadStrategy and simplify RTPPayloadRegistry > > This CL removes RTPPayloadStrategy that is currently used to handle > audio/video specific aspects of payload handling. Instead, the audio and > video specific aspects will now have different functions, with linear > code flow. > > This CL does not contain any functional changes, and is just a > preparation for future CL:s. > > The main purpose with this CL is to add this function: > bool PayloadIsCompatible(const RtpUtility::Payload& payload, > const webrtc::VideoCodec& video_codec); > that can easily be extended in a future CL to look at video codec > specific information. > > BUG=webrtc:6743 > > Committed: https://crrev.com/b881254dc86d2cc80a52e08155433458be002166 > Cr-Commit-Position: refs/heads/master@{#15232} TBR=danilchap@webrtc.org,solenberg@webrtc.org,mflodman@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=webrtc:6743 Review-Url: https://codereview.webrtc.org/2528993002 Cr-Commit-Position: refs/heads/master@{#15234}
This commit is contained in:
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class MockRTPPayloadStrategy : public RTPPayloadStrategy {
|
||||
public:
|
||||
MOCK_CONST_METHOD0(CodecsMustBeUnique,
|
||||
bool());
|
||||
MOCK_CONST_METHOD4(PayloadIsCompatible,
|
||||
bool(const RtpUtility::Payload& payload,
|
||||
uint32_t frequency,
|
||||
size_t channels,
|
||||
uint32_t rate));
|
||||
MOCK_CONST_METHOD2(UpdatePayloadRate,
|
||||
void(RtpUtility::Payload* payload, uint32_t rate));
|
||||
MOCK_CONST_METHOD1(GetPayloadTypeFrequency,
|
||||
int(const RtpUtility::Payload& payload));
|
||||
MOCK_CONST_METHOD5(
|
||||
CreatePayloadType,
|
||||
RtpUtility::Payload*(const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
||||
int8_t payload_type,
|
||||
uint32_t frequency,
|
||||
size_t channels,
|
||||
uint32_t rate));
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_
|
||||
@ -169,7 +169,8 @@ class RtxLoopBackTransport : public webrtc::Transport {
|
||||
class RtpRtcpRtxNackTest : public ::testing::Test {
|
||||
protected:
|
||||
RtpRtcpRtxNackTest()
|
||||
: rtp_rtcp_module_(nullptr),
|
||||
: rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
|
||||
rtp_rtcp_module_(nullptr),
|
||||
transport_(kTestSsrc + 1),
|
||||
receiver_(),
|
||||
payload_data_length(sizeof(payload_data)),
|
||||
|
||||
@ -10,76 +10,55 @@
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/stringutils.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
RTPPayloadRegistry::RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy)
|
||||
: rtp_payload_strategy_(rtp_payload_strategy),
|
||||
red_payload_type_(-1),
|
||||
ulpfec_payload_type_(-1),
|
||||
incoming_payload_type_(-1),
|
||||
last_received_payload_type_(-1),
|
||||
last_received_media_payload_type_(-1),
|
||||
rtx_(false),
|
||||
ssrc_rtx_(0) {}
|
||||
|
||||
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
||||
const CodecInst& audio_codec) {
|
||||
if (!payload.audio)
|
||||
return false;
|
||||
if (_stricmp(payload.name, audio_codec.plname) != 0)
|
||||
return false;
|
||||
const AudioPayload& audio_payload = payload.typeSpecific.Audio;
|
||||
const uint32_t rate = std::max(0, audio_codec.rate);
|
||||
return audio_payload.frequency == static_cast<uint32_t>(audio_codec.plfreq) &&
|
||||
audio_payload.channels == audio_codec.channels &&
|
||||
(audio_payload.rate == rate || audio_payload.rate == 0 || rate == 0);
|
||||
}
|
||||
|
||||
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
||||
const VideoCodec& video_codec) {
|
||||
return !payload.audio && _stricmp(payload.name, video_codec.plName) == 0;
|
||||
}
|
||||
|
||||
RtpUtility::Payload CreatePayloadType(const CodecInst& audio_codec) {
|
||||
RtpUtility::Payload payload;
|
||||
payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
||||
strncpy(payload.name, audio_codec.plname, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
RTC_DCHECK_GE(audio_codec.plfreq, 1000);
|
||||
payload.typeSpecific.Audio.frequency = audio_codec.plfreq;
|
||||
payload.typeSpecific.Audio.channels = audio_codec.channels;
|
||||
payload.typeSpecific.Audio.rate = std::max(0, audio_codec.rate);
|
||||
payload.audio = true;
|
||||
return payload;
|
||||
}
|
||||
|
||||
RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) {
|
||||
switch (type) {
|
||||
case kVideoCodecVP8:
|
||||
return kRtpVideoVp8;
|
||||
case kVideoCodecVP9:
|
||||
return kRtpVideoVp9;
|
||||
case kVideoCodecH264:
|
||||
return kRtpVideoH264;
|
||||
case kVideoCodecRED:
|
||||
case kVideoCodecULPFEC:
|
||||
return kRtpVideoNone;
|
||||
default:
|
||||
return kRtpVideoGeneric;
|
||||
RTPPayloadRegistry::~RTPPayloadRegistry() {
|
||||
while (!payload_type_map_.empty()) {
|
||||
RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
|
||||
delete it->second;
|
||||
payload_type_map_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) {
|
||||
RtpUtility::Payload payload;
|
||||
payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
||||
strncpy(payload.name, video_codec.plName, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
payload.typeSpecific.Video.videoCodecType =
|
||||
ConvertToRtpVideoCodecType(video_codec.codecType);
|
||||
payload.audio = false;
|
||||
return payload;
|
||||
int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
|
||||
bool* created_new_payload) {
|
||||
return RegisterReceivePayload(
|
||||
audio_codec.plname, audio_codec.pltype, audio_codec.plfreq,
|
||||
audio_codec.channels, std::max(0, audio_codec.rate), created_new_payload);
|
||||
}
|
||||
|
||||
bool IsPayloadTypeValid(int8_t payload_type) {
|
||||
int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
||||
const VideoCodec& video_codec) {
|
||||
bool dummy_created_new_payload;
|
||||
return RegisterReceivePayload(video_codec.plName, video_codec.plType,
|
||||
kVideoPayloadTypeFrequency, 0 /* channels */,
|
||||
0 /* rate */, &dummy_created_new_payload);
|
||||
}
|
||||
|
||||
int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
||||
const char* const payload_name,
|
||||
const int8_t payload_type,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate,
|
||||
bool* created_new_payload) {
|
||||
assert(payload_type >= 0);
|
||||
assert(payload_name);
|
||||
*created_new_payload = false;
|
||||
|
||||
// Sanity check.
|
||||
switch (payload_type) {
|
||||
@ -95,76 +74,59 @@ bool IsPayloadTypeValid(int8_t payload_type) {
|
||||
case 79: // 207 Extended report.
|
||||
LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
|
||||
<< payload_type;
|
||||
return false;
|
||||
return -1;
|
||||
default:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
RTPPayloadRegistry::RTPPayloadRegistry()
|
||||
: incoming_payload_type_(-1),
|
||||
last_received_payload_type_(-1),
|
||||
last_received_media_payload_type_(-1),
|
||||
rtx_(false),
|
||||
ssrc_rtx_(0) {}
|
||||
|
||||
RTPPayloadRegistry::~RTPPayloadRegistry() = default;
|
||||
|
||||
int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
|
||||
bool* created_new_payload) {
|
||||
*created_new_payload = false;
|
||||
if (!IsPayloadTypeValid(audio_codec.pltype))
|
||||
return -1;
|
||||
size_t payload_name_length = strlen(payload_name);
|
||||
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
|
||||
auto it = payload_type_map_.find(audio_codec.pltype);
|
||||
RtpUtility::PayloadTypeMap::iterator it =
|
||||
payload_type_map_.find(payload_type);
|
||||
|
||||
if (it != payload_type_map_.end()) {
|
||||
// We already use this payload type. Check if it's the same as we already
|
||||
// have. If same, ignore sending an error.
|
||||
if (PayloadIsCompatible(it->second, audio_codec)) {
|
||||
it->second.typeSpecific.Audio.rate = std::max(0, audio_codec.rate);
|
||||
return 0;
|
||||
// We already use this payload type.
|
||||
RtpUtility::Payload* payload = it->second;
|
||||
|
||||
assert(payload);
|
||||
|
||||
size_t name_length = strlen(payload->name);
|
||||
|
||||
// Check if it's the same as we already have.
|
||||
// If same, ignore sending an error.
|
||||
if (payload_name_length == name_length &&
|
||||
RtpUtility::StringCompare(
|
||||
payload->name, payload_name, payload_name_length)) {
|
||||
if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
|
||||
channels, rate)) {
|
||||
rtp_payload_strategy_->UpdatePayloadRate(payload, rate);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
LOG(LS_ERROR) << "Payload type already registered: " << audio_codec.pltype;
|
||||
LOG(LS_ERROR) << "Payload type already registered: "
|
||||
<< static_cast<int>(payload_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Audio codecs must be unique.
|
||||
DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec);
|
||||
if (rtp_payload_strategy_->CodecsMustBeUnique()) {
|
||||
DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
||||
payload_name, payload_name_length, frequency, channels, rate);
|
||||
}
|
||||
|
||||
payload_type_map_[audio_codec.pltype] = CreatePayloadType(audio_codec);
|
||||
RtpUtility::Payload* payload = rtp_payload_strategy_->CreatePayloadType(
|
||||
payload_name, payload_type, frequency, channels, rate);
|
||||
|
||||
payload_type_map_[payload_type] = payload;
|
||||
*created_new_payload = true;
|
||||
|
||||
// Successful set of payload type, clear the value of last received payload
|
||||
// type since it might mean something else.
|
||||
last_received_payload_type_ = -1;
|
||||
last_received_media_payload_type_ = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
||||
const VideoCodec& video_codec) {
|
||||
if (!IsPayloadTypeValid(video_codec.plType))
|
||||
return -1;
|
||||
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
|
||||
auto it = payload_type_map_.find(video_codec.plType);
|
||||
if (it != payload_type_map_.end()) {
|
||||
// We already use this payload type. Check if it's the same as we already
|
||||
// have. If same, ignore sending an error.
|
||||
if (PayloadIsCompatible(it->second, video_codec))
|
||||
return 0;
|
||||
LOG(LS_ERROR) << "Payload type already registered: "
|
||||
<< static_cast<int>(video_codec.plType);
|
||||
return -1;
|
||||
if (RtpUtility::StringCompare(payload_name, "red", 3)) {
|
||||
red_payload_type_ = payload_type;
|
||||
} else if (RtpUtility::StringCompare(payload_name, "ulpfec", 6)) {
|
||||
ulpfec_payload_type_ = payload_type;
|
||||
}
|
||||
|
||||
payload_type_map_[video_codec.plType] = CreatePayloadType(video_codec);
|
||||
|
||||
// Successful set of payload type, clear the value of last received payload
|
||||
// type since it might mean something else.
|
||||
last_received_payload_type_ = -1;
|
||||
@ -175,7 +137,11 @@ int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
||||
int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
|
||||
const int8_t payload_type) {
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
payload_type_map_.erase(payload_type);
|
||||
RtpUtility::PayloadTypeMap::iterator it =
|
||||
payload_type_map_.find(payload_type);
|
||||
assert(it != payload_type_map_.end());
|
||||
delete it->second;
|
||||
payload_type_map_.erase(it);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -183,40 +149,95 @@ int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
|
||||
// for audio codecs, but there can for video.
|
||||
// Always called from within a critical section.
|
||||
void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
||||
const CodecInst& audio_codec) {
|
||||
for (auto iterator = payload_type_map_.begin();
|
||||
iterator != payload_type_map_.end(); ++iterator) {
|
||||
if (PayloadIsCompatible(iterator->second, audio_codec)) {
|
||||
// Remove old setting.
|
||||
payload_type_map_.erase(iterator);
|
||||
break;
|
||||
const char* const payload_name,
|
||||
const size_t payload_name_length,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate) {
|
||||
RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin();
|
||||
for (; iterator != payload_type_map_.end(); ++iterator) {
|
||||
RtpUtility::Payload* payload = iterator->second;
|
||||
size_t name_length = strlen(payload->name);
|
||||
|
||||
if (payload_name_length == name_length &&
|
||||
RtpUtility::StringCompare(
|
||||
payload->name, payload_name, payload_name_length)) {
|
||||
// We found the payload name in the list.
|
||||
// If audio, check frequency and rate.
|
||||
if (payload->audio) {
|
||||
if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
|
||||
channels, rate)) {
|
||||
// Remove old setting.
|
||||
delete payload;
|
||||
payload_type_map_.erase(iterator);
|
||||
break;
|
||||
}
|
||||
} else if (RtpUtility::StringCompare(payload_name, "red", 3)) {
|
||||
delete payload;
|
||||
payload_type_map_.erase(iterator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec,
|
||||
int8_t* payload_type) const {
|
||||
assert(payload_type);
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
|
||||
for (const auto& it : payload_type_map_) {
|
||||
if (PayloadIsCompatible(it.second, audio_codec)) {
|
||||
*payload_type = it.first;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return ReceivePayloadType(audio_codec.plname, audio_codec.plfreq,
|
||||
audio_codec.channels, std::max(0, audio_codec.rate),
|
||||
payload_type);
|
||||
}
|
||||
|
||||
int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec,
|
||||
int8_t* payload_type) const {
|
||||
return ReceivePayloadType(video_codec.plName, kVideoPayloadTypeFrequency,
|
||||
0 /* channels */, 0 /* rate */, payload_type);
|
||||
}
|
||||
|
||||
int32_t RTPPayloadRegistry::ReceivePayloadType(const char* const payload_name,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate,
|
||||
int8_t* payload_type) const {
|
||||
assert(payload_type);
|
||||
size_t payload_name_length = strlen(payload_name);
|
||||
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
|
||||
for (const auto& it : payload_type_map_) {
|
||||
if (PayloadIsCompatible(it.second, video_codec)) {
|
||||
*payload_type = it.first;
|
||||
return 0;
|
||||
RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin();
|
||||
|
||||
for (; it != payload_type_map_.end(); ++it) {
|
||||
RtpUtility::Payload* payload = it->second;
|
||||
assert(payload);
|
||||
|
||||
size_t name_length = strlen(payload->name);
|
||||
if (payload_name_length == name_length &&
|
||||
RtpUtility::StringCompare(
|
||||
payload->name, payload_name, payload_name_length)) {
|
||||
// Name matches.
|
||||
if (payload->audio) {
|
||||
if (rate == 0) {
|
||||
// [default] audio, check freq and channels.
|
||||
if (payload->typeSpecific.Audio.frequency == frequency &&
|
||||
payload->typeSpecific.Audio.channels == channels) {
|
||||
*payload_type = it->first;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Non-default audio, check freq, channels and rate.
|
||||
if (payload->typeSpecific.Audio.frequency == frequency &&
|
||||
payload->typeSpecific.Audio.channels == channels &&
|
||||
payload->typeSpecific.Audio.rate == rate) {
|
||||
// extra rate condition added
|
||||
*payload_type = it->first;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Video.
|
||||
*payload_type = it->first;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@ -312,8 +333,7 @@ void RTPPayloadRegistry::SetRtxPayloadType(int payload_type,
|
||||
|
||||
bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
auto it = payload_type_map_.find(header.payloadType);
|
||||
return it != payload_type_map_.end() && _stricmp(it->second.name, "red") == 0;
|
||||
return red_payload_type_ == header.payloadType;
|
||||
}
|
||||
|
||||
bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
|
||||
@ -323,13 +343,14 @@ bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
|
||||
bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
|
||||
PayloadUnion* payload) const {
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
auto it = payload_type_map_.find(payload_type);
|
||||
RtpUtility::PayloadTypeMap::const_iterator it =
|
||||
payload_type_map_.find(payload_type);
|
||||
|
||||
// Check that this is a registered payload type.
|
||||
if (it == payload_type_map_.end()) {
|
||||
return false;
|
||||
}
|
||||
*payload = it->second.typeSpecific;
|
||||
*payload = it->second->typeSpecific;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -340,22 +361,22 @@ int RTPPayloadRegistry::GetPayloadTypeFrequency(
|
||||
return -1;
|
||||
}
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
return payload->audio ? payload->typeSpecific.Audio.frequency
|
||||
: kVideoPayloadTypeFrequency;
|
||||
return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
|
||||
}
|
||||
|
||||
const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload(
|
||||
uint8_t payload_type) const {
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
|
||||
auto it = payload_type_map_.find(payload_type);
|
||||
RtpUtility::PayloadTypeMap::const_iterator it =
|
||||
payload_type_map_.find(payload_type);
|
||||
|
||||
// Check that this is a registered payload type.
|
||||
if (it == payload_type_map_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &it->second;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
|
||||
@ -374,15 +395,106 @@ bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns -1 if a payload with name |payload_name| is not registered.
|
||||
int8_t RTPPayloadRegistry::GetPayloadTypeWithName(
|
||||
const char* payload_name) const {
|
||||
rtc::CritScope cs(&crit_sect_);
|
||||
for (const auto& it : payload_type_map_) {
|
||||
if (_stricmp(it.second.name, payload_name) == 0)
|
||||
return it.first;
|
||||
class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
|
||||
public:
|
||||
bool CodecsMustBeUnique() const override { return true; }
|
||||
|
||||
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate) const override {
|
||||
return
|
||||
payload.audio &&
|
||||
payload.typeSpecific.Audio.frequency == frequency &&
|
||||
payload.typeSpecific.Audio.channels == channels &&
|
||||
(payload.typeSpecific.Audio.rate == rate ||
|
||||
payload.typeSpecific.Audio.rate == 0 || rate == 0);
|
||||
}
|
||||
|
||||
void UpdatePayloadRate(RtpUtility::Payload* payload,
|
||||
const uint32_t rate) const override {
|
||||
payload->typeSpecific.Audio.rate = rate;
|
||||
}
|
||||
|
||||
RtpUtility::Payload* CreatePayloadType(const char* const payloadName,
|
||||
const int8_t payloadType,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate) const override {
|
||||
RtpUtility::Payload* payload = new RtpUtility::Payload;
|
||||
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
||||
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
assert(frequency >= 1000);
|
||||
payload->typeSpecific.Audio.frequency = frequency;
|
||||
payload->typeSpecific.Audio.channels = channels;
|
||||
payload->typeSpecific.Audio.rate = rate;
|
||||
payload->audio = true;
|
||||
return payload;
|
||||
}
|
||||
|
||||
int GetPayloadTypeFrequency(
|
||||
const RtpUtility::Payload& payload) const override {
|
||||
return payload.typeSpecific.Audio.frequency;
|
||||
}
|
||||
};
|
||||
|
||||
class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
|
||||
public:
|
||||
bool CodecsMustBeUnique() const override { return false; }
|
||||
|
||||
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate) const override {
|
||||
return !payload.audio;
|
||||
}
|
||||
|
||||
void UpdatePayloadRate(RtpUtility::Payload* payload,
|
||||
const uint32_t rate) const override {}
|
||||
|
||||
RtpUtility::Payload* CreatePayloadType(const char* const payloadName,
|
||||
const int8_t payloadType,
|
||||
const uint32_t frequency,
|
||||
const size_t channels,
|
||||
const uint32_t rate) const override {
|
||||
RtpVideoCodecTypes videoType = kRtpVideoGeneric;
|
||||
|
||||
if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
|
||||
videoType = kRtpVideoVp8;
|
||||
} else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) {
|
||||
videoType = kRtpVideoVp9;
|
||||
} else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
|
||||
videoType = kRtpVideoH264;
|
||||
} else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
|
||||
videoType = kRtpVideoGeneric;
|
||||
} else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6) ||
|
||||
RtpUtility::StringCompare(payloadName, "RED", 3)) {
|
||||
videoType = kRtpVideoNone;
|
||||
} else {
|
||||
videoType = kRtpVideoGeneric;
|
||||
}
|
||||
RtpUtility::Payload* payload = new RtpUtility::Payload;
|
||||
|
||||
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
||||
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
payload->typeSpecific.Video.videoCodecType = videoType;
|
||||
payload->audio = false;
|
||||
return payload;
|
||||
}
|
||||
|
||||
int GetPayloadTypeFrequency(
|
||||
const RtpUtility::Payload& payload) const override {
|
||||
return kVideoPayloadTypeFrequency;
|
||||
}
|
||||
};
|
||||
|
||||
RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
|
||||
const bool handling_audio) {
|
||||
if (handling_audio) {
|
||||
return new RTPPayloadAudioStrategy();
|
||||
} else {
|
||||
return new RTPPayloadVideoStrategy();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
@ -27,72 +28,116 @@ using ::testing::_;
|
||||
|
||||
static const char* kTypicalPayloadName = "name";
|
||||
static const size_t kTypicalChannels = 1;
|
||||
static const uint32_t kTypicalFrequency = 44000;
|
||||
static const uint32_t kTypicalRate = 32 * 1024;
|
||||
static const int kTypicalFrequency = 44000;
|
||||
static const int kTypicalRate = 32 * 1024;
|
||||
static const CodecInst kTypicalAudioCodec = {-1 /* pltype */, "name",
|
||||
kTypicalFrequency, 0 /* pacsize */,
|
||||
kTypicalChannels, kTypicalRate};
|
||||
|
||||
TEST(RtpPayloadRegistryTest,
|
||||
RegistersAndRemembersVideoPayloadsUntilDeregistered) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
class RtpPayloadRegistryTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() {
|
||||
// Note: the payload registry takes ownership of the strategy.
|
||||
mock_payload_strategy_ = new testing::NiceMock<MockRTPPayloadStrategy>();
|
||||
rtp_payload_registry_.reset(new RTPPayloadRegistry(mock_payload_strategy_));
|
||||
}
|
||||
|
||||
protected:
|
||||
RtpUtility::Payload* ExpectReturnOfTypicalAudioPayload(uint8_t payload_type,
|
||||
uint32_t rate) {
|
||||
bool audio = true;
|
||||
RtpUtility::Payload returned_payload = {
|
||||
"name",
|
||||
audio,
|
||||
{// Initialize the audio struct in this case.
|
||||
{kTypicalFrequency, kTypicalChannels, rate}}};
|
||||
|
||||
// Note: we return a new payload since the payload registry takes ownership
|
||||
// of the created object.
|
||||
RtpUtility::Payload* returned_payload_on_heap =
|
||||
new RtpUtility::Payload(returned_payload);
|
||||
EXPECT_CALL(*mock_payload_strategy_,
|
||||
CreatePayloadType(StrEq(kTypicalPayloadName), payload_type,
|
||||
kTypicalFrequency, kTypicalChannels, rate))
|
||||
.WillOnce(Return(returned_payload_on_heap));
|
||||
return returned_payload_on_heap;
|
||||
}
|
||||
|
||||
std::unique_ptr<RTPPayloadRegistry> rtp_payload_registry_;
|
||||
testing::NiceMock<MockRTPPayloadStrategy>* mock_payload_strategy_;
|
||||
};
|
||||
|
||||
TEST_F(RtpPayloadRegistryTest,
|
||||
RegistersAndRemembersVideoPayloadsUntilDeregistered) {
|
||||
const uint8_t payload_type = 97;
|
||||
RtpUtility::Payload returned_video_payload = {
|
||||
"VP8", false /* audio */, {{kRtpVideoVp8}}};
|
||||
// Note: The payload registry takes ownership of this object in
|
||||
// RegisterReceivePayload.
|
||||
RtpUtility::Payload* returned_video_payload_on_heap =
|
||||
new RtpUtility::Payload(returned_video_payload);
|
||||
EXPECT_CALL(
|
||||
*mock_payload_strategy_,
|
||||
CreatePayloadType(StrEq("VP8"), payload_type, kVideoPayloadTypeFrequency,
|
||||
0 /* channels */, 0 /* rate */))
|
||||
.WillOnce(Return(returned_video_payload_on_heap));
|
||||
|
||||
VideoCodec video_codec;
|
||||
video_codec.codecType = kVideoCodecVP8;
|
||||
strncpy(video_codec.plName, "VP8", RTP_PAYLOAD_NAME_SIZE);
|
||||
video_codec.plType = payload_type;
|
||||
|
||||
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(video_codec));
|
||||
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(video_codec));
|
||||
|
||||
const RtpUtility::Payload* retrieved_payload =
|
||||
rtp_payload_registry.PayloadTypeToPayload(payload_type);
|
||||
rtp_payload_registry_->PayloadTypeToPayload(payload_type);
|
||||
EXPECT_TRUE(retrieved_payload);
|
||||
|
||||
// We should get back the corresponding payload that we registered.
|
||||
EXPECT_STREQ("VP8", retrieved_payload->name);
|
||||
EXPECT_FALSE(retrieved_payload->audio);
|
||||
EXPECT_EQ(kRtpVideoVp8, retrieved_payload->typeSpecific.Video.videoCodecType);
|
||||
// We should get back the exact pointer to the payload returned by the
|
||||
// payload strategy.
|
||||
EXPECT_EQ(returned_video_payload_on_heap, retrieved_payload);
|
||||
|
||||
// Now forget about it and verify it's gone.
|
||||
EXPECT_EQ(0, rtp_payload_registry.DeRegisterReceivePayload(payload_type));
|
||||
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type));
|
||||
EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type));
|
||||
EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type));
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest,
|
||||
RegistersAndRemembersAudioPayloadsUntilDeregistered) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
TEST_F(RtpPayloadRegistryTest,
|
||||
RegistersAndRemembersAudioPayloadsUntilDeregistered) {
|
||||
uint8_t payload_type = 97;
|
||||
RtpUtility::Payload* returned_payload_on_heap =
|
||||
ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
|
||||
|
||||
bool new_payload_created = false;
|
||||
CodecInst audio_codec = kTypicalAudioCodec;
|
||||
audio_codec.pltype = payload_type;
|
||||
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
|
||||
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
|
||||
audio_codec, &new_payload_created));
|
||||
|
||||
EXPECT_TRUE(new_payload_created) << "A new payload WAS created.";
|
||||
|
||||
const RtpUtility::Payload* retrieved_payload =
|
||||
rtp_payload_registry.PayloadTypeToPayload(payload_type);
|
||||
rtp_payload_registry_->PayloadTypeToPayload(payload_type);
|
||||
EXPECT_TRUE(retrieved_payload);
|
||||
|
||||
// We should get back the corresponding payload that we registered.
|
||||
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
|
||||
EXPECT_TRUE(retrieved_payload->audio);
|
||||
EXPECT_EQ(kTypicalFrequency, retrieved_payload->typeSpecific.Audio.frequency);
|
||||
EXPECT_EQ(kTypicalChannels, retrieved_payload->typeSpecific.Audio.channels);
|
||||
EXPECT_EQ(kTypicalRate, retrieved_payload->typeSpecific.Audio.rate);
|
||||
// We should get back the exact pointer to the payload returned by the
|
||||
// payload strategy.
|
||||
EXPECT_EQ(returned_payload_on_heap, retrieved_payload);
|
||||
|
||||
// Now forget about it and verify it's gone.
|
||||
EXPECT_EQ(0, rtp_payload_registry.DeRegisterReceivePayload(payload_type));
|
||||
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type));
|
||||
EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type));
|
||||
EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type));
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest, AudioRedWorkProperly) {
|
||||
TEST_F(RtpPayloadRegistryTest, AudioRedWorkProperly) {
|
||||
const uint8_t kRedPayloadType = 127;
|
||||
const int kRedSampleRate = 8000;
|
||||
const size_t kRedChannels = 1;
|
||||
const int kRedBitRate = 0;
|
||||
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
// This creates an audio RTP payload strategy.
|
||||
rtp_payload_registry_.reset(
|
||||
new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true)));
|
||||
|
||||
bool new_payload_created = false;
|
||||
CodecInst red_audio_codec;
|
||||
@ -101,170 +146,170 @@ TEST(RtpPayloadRegistryTest, AudioRedWorkProperly) {
|
||||
red_audio_codec.plfreq = kRedSampleRate;
|
||||
red_audio_codec.channels = kRedChannels;
|
||||
red_audio_codec.rate = kRedBitRate;
|
||||
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
|
||||
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
|
||||
red_audio_codec, &new_payload_created));
|
||||
EXPECT_TRUE(new_payload_created);
|
||||
|
||||
EXPECT_EQ(kRedPayloadType, rtp_payload_registry.red_payload_type());
|
||||
EXPECT_EQ(kRedPayloadType, rtp_payload_registry_->red_payload_type());
|
||||
|
||||
const RtpUtility::Payload* retrieved_payload =
|
||||
rtp_payload_registry.PayloadTypeToPayload(kRedPayloadType);
|
||||
rtp_payload_registry_->PayloadTypeToPayload(kRedPayloadType);
|
||||
EXPECT_TRUE(retrieved_payload);
|
||||
EXPECT_TRUE(retrieved_payload->audio);
|
||||
EXPECT_STRCASEEQ("red", retrieved_payload->name);
|
||||
|
||||
// Sample rate is correctly registered.
|
||||
EXPECT_EQ(kRedSampleRate,
|
||||
rtp_payload_registry.GetPayloadTypeFrequency(kRedPayloadType));
|
||||
rtp_payload_registry_->GetPayloadTypeFrequency(kRedPayloadType));
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest,
|
||||
DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
|
||||
TEST_F(RtpPayloadRegistryTest,
|
||||
DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
|
||||
uint8_t payload_type = 97;
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
|
||||
bool ignored = false;
|
||||
RtpUtility::Payload* first_payload_on_heap =
|
||||
ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
|
||||
CodecInst audio_codec = kTypicalAudioCodec;
|
||||
audio_codec.pltype = payload_type;
|
||||
EXPECT_EQ(0,
|
||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
||||
|
||||
CodecInst audio_codec_2 = kTypicalAudioCodec;
|
||||
audio_codec_2.pltype = payload_type;
|
||||
// Make |audio_codec_2| incompatible with |audio_codec| by changing
|
||||
// the frequency.
|
||||
audio_codec_2.plfreq = kTypicalFrequency + 1;
|
||||
EXPECT_EQ(
|
||||
-1, rtp_payload_registry.RegisterReceivePayload(audio_codec_2, &ignored))
|
||||
<< "Adding incompatible codec with same payload type = bad.";
|
||||
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||
|
||||
// Change payload type.
|
||||
EXPECT_EQ(
|
||||
-1, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored))
|
||||
<< "Adding same codec twice = bad.";
|
||||
|
||||
RtpUtility::Payload* second_payload_on_heap =
|
||||
ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
|
||||
CodecInst audio_codec_2 = kTypicalAudioCodec;
|
||||
audio_codec_2.pltype = payload_type - 1;
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry.RegisterReceivePayload(audio_codec_2, &ignored))
|
||||
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec_2, &ignored))
|
||||
<< "With a different payload type is fine though.";
|
||||
|
||||
// Ensure both payloads are preserved.
|
||||
const RtpUtility::Payload* retrieved_payload =
|
||||
rtp_payload_registry.PayloadTypeToPayload(payload_type);
|
||||
rtp_payload_registry_->PayloadTypeToPayload(payload_type);
|
||||
EXPECT_TRUE(retrieved_payload);
|
||||
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
|
||||
EXPECT_TRUE(retrieved_payload->audio);
|
||||
EXPECT_EQ(kTypicalFrequency, retrieved_payload->typeSpecific.Audio.frequency);
|
||||
EXPECT_EQ(kTypicalChannels, retrieved_payload->typeSpecific.Audio.channels);
|
||||
EXPECT_EQ(kTypicalRate, retrieved_payload->typeSpecific.Audio.rate);
|
||||
|
||||
EXPECT_EQ(first_payload_on_heap, retrieved_payload);
|
||||
retrieved_payload =
|
||||
rtp_payload_registry.PayloadTypeToPayload(payload_type - 1);
|
||||
rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1);
|
||||
EXPECT_TRUE(retrieved_payload);
|
||||
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
|
||||
EXPECT_TRUE(retrieved_payload->audio);
|
||||
EXPECT_EQ(kTypicalFrequency + 1,
|
||||
retrieved_payload->typeSpecific.Audio.frequency);
|
||||
EXPECT_EQ(kTypicalChannels, retrieved_payload->typeSpecific.Audio.channels);
|
||||
EXPECT_EQ(kTypicalRate, retrieved_payload->typeSpecific.Audio.rate);
|
||||
EXPECT_EQ(second_payload_on_heap, retrieved_payload);
|
||||
|
||||
// Ok, update the rate for one of the codecs. If either the incoming rate or
|
||||
// the stored rate is zero it's not really an error to register the same
|
||||
// codec twice, and in that case roughly the following happens.
|
||||
EXPECT_EQ(0,
|
||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
||||
ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
|
||||
.WillByDefault(Return(true));
|
||||
EXPECT_CALL(*mock_payload_strategy_,
|
||||
UpdatePayloadRate(first_payload_on_heap, kTypicalRate));
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest,
|
||||
RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
|
||||
TEST_F(RtpPayloadRegistryTest,
|
||||
RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
|
||||
ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
|
||||
.WillByDefault(Return(true));
|
||||
ON_CALL(*mock_payload_strategy_, CodecsMustBeUnique())
|
||||
.WillByDefault(Return(true));
|
||||
|
||||
uint8_t payload_type = 97;
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
|
||||
bool ignored = false;
|
||||
ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
|
||||
CodecInst audio_codec = kTypicalAudioCodec;
|
||||
audio_codec.pltype = payload_type;
|
||||
EXPECT_EQ(0,
|
||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||
ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
|
||||
CodecInst audio_codec_2 = kTypicalAudioCodec;
|
||||
audio_codec_2.pltype = payload_type - 1;
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry.RegisterReceivePayload(audio_codec_2, &ignored));
|
||||
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(audio_codec_2,
|
||||
&ignored));
|
||||
|
||||
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type))
|
||||
EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type))
|
||||
<< "The first payload should be "
|
||||
"deregistered because the only thing that differs is payload type.";
|
||||
EXPECT_TRUE(rtp_payload_registry.PayloadTypeToPayload(payload_type - 1))
|
||||
EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1))
|
||||
<< "The second payload should still be registered though.";
|
||||
|
||||
// Now ensure non-compatible codecs aren't removed. Make |audio_codec_3|
|
||||
// incompatible by changing the frequency.
|
||||
// Now ensure non-compatible codecs aren't removed.
|
||||
ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
|
||||
.WillByDefault(Return(false));
|
||||
ExpectReturnOfTypicalAudioPayload(payload_type + 1, kTypicalRate);
|
||||
CodecInst audio_codec_3 = kTypicalAudioCodec;
|
||||
audio_codec_3.pltype = payload_type + 1;
|
||||
audio_codec_3.plfreq = kTypicalFrequency + 1;
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry.RegisterReceivePayload(audio_codec_3, &ignored));
|
||||
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(audio_codec_3,
|
||||
&ignored));
|
||||
|
||||
EXPECT_TRUE(rtp_payload_registry.PayloadTypeToPayload(payload_type - 1))
|
||||
EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1))
|
||||
<< "Not compatible; both payloads should be kept.";
|
||||
EXPECT_TRUE(rtp_payload_registry.PayloadTypeToPayload(payload_type + 1))
|
||||
EXPECT_TRUE(rtp_payload_registry_->PayloadTypeToPayload(payload_type + 1))
|
||||
<< "Not compatible; both payloads should be kept.";
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest,
|
||||
LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
rtp_payload_registry.set_last_received_payload_type(17);
|
||||
EXPECT_EQ(17, rtp_payload_registry.last_received_payload_type());
|
||||
TEST_F(RtpPayloadRegistryTest,
|
||||
LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
|
||||
rtp_payload_registry_->set_last_received_payload_type(17);
|
||||
EXPECT_EQ(17, rtp_payload_registry_->last_received_payload_type());
|
||||
|
||||
bool media_type_unchanged = rtp_payload_registry.ReportMediaPayloadType(18);
|
||||
bool media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
|
||||
EXPECT_FALSE(media_type_unchanged);
|
||||
media_type_unchanged = rtp_payload_registry.ReportMediaPayloadType(18);
|
||||
media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
|
||||
EXPECT_TRUE(media_type_unchanged);
|
||||
|
||||
bool ignored;
|
||||
ExpectReturnOfTypicalAudioPayload(34, kTypicalRate);
|
||||
CodecInst audio_codec = kTypicalAudioCodec;
|
||||
audio_codec.pltype = 34;
|
||||
EXPECT_EQ(0,
|
||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||
|
||||
EXPECT_EQ(-1, rtp_payload_registry.last_received_payload_type());
|
||||
media_type_unchanged = rtp_payload_registry.ReportMediaPayloadType(18);
|
||||
EXPECT_EQ(-1, rtp_payload_registry_->last_received_payload_type());
|
||||
media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
|
||||
EXPECT_FALSE(media_type_unchanged);
|
||||
}
|
||||
|
||||
class ParameterizedRtpPayloadRegistryTest
|
||||
: public ::testing::TestWithParam<int> {};
|
||||
: public RtpPayloadRegistryTest,
|
||||
public ::testing::WithParamInterface<int> {};
|
||||
|
||||
TEST_P(ParameterizedRtpPayloadRegistryTest,
|
||||
FailsToRegisterKnownPayloadsWeAreNotInterestedIn) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
int payload_type = GetParam();
|
||||
|
||||
bool ignored;
|
||||
CodecInst audio_codec;
|
||||
strncpy(audio_codec.plname, "whatever", RTP_PAYLOAD_NAME_SIZE);
|
||||
audio_codec.pltype = GetParam();
|
||||
audio_codec.plfreq = 1900;
|
||||
audio_codec.pltype = static_cast<uint8_t>(payload_type);
|
||||
audio_codec.plfreq = 19;
|
||||
audio_codec.channels = 1;
|
||||
audio_codec.rate = 17;
|
||||
EXPECT_EQ(-1,
|
||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
||||
EXPECT_EQ(
|
||||
-1, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes,
|
||||
ParameterizedRtpPayloadRegistryTest,
|
||||
testing::Values(64, 72, 73, 74, 75, 76, 77, 78, 79));
|
||||
|
||||
class RtpPayloadRegistryGenericTest : public ::testing::TestWithParam<int> {};
|
||||
class RtpPayloadRegistryGenericTest
|
||||
: public RtpPayloadRegistryTest,
|
||||
public ::testing::WithParamInterface<int> {};
|
||||
|
||||
TEST_P(RtpPayloadRegistryGenericTest, RegisterGenericReceivePayloadType) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
|
||||
bool ignored;
|
||||
CodecInst audio_codec;
|
||||
// Dummy values, except for payload_type.
|
||||
strncpy(audio_codec.plname, "generic-codec", RTP_PAYLOAD_NAME_SIZE);
|
||||
audio_codec.pltype = GetParam();
|
||||
audio_codec.plfreq = 1900;
|
||||
audio_codec.plfreq = 19;
|
||||
audio_codec.channels = 1;
|
||||
audio_codec.rate = 17;
|
||||
EXPECT_EQ(0,
|
||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
||||
EXPECT_EQ(
|
||||
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||
}
|
||||
|
||||
// Generates an RTX packet for the given length and original sequence number.
|
||||
@ -339,31 +384,29 @@ void TestRtxPacket(RTPPayloadRegistry* rtp_payload_registry,
|
||||
<< "The restored packet should have the correct ssrc.";
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest, MultipleRtxPayloadTypes) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
TEST_F(RtpPayloadRegistryTest, MultipleRtxPayloadTypes) {
|
||||
// Set the incoming payload type to 90.
|
||||
RTPHeader header;
|
||||
header.payloadType = 90;
|
||||
header.ssrc = 1;
|
||||
rtp_payload_registry.SetIncomingPayloadType(header);
|
||||
rtp_payload_registry.SetRtxSsrc(100);
|
||||
rtp_payload_registry_->SetIncomingPayloadType(header);
|
||||
rtp_payload_registry_->SetRtxSsrc(100);
|
||||
// Map two RTX payload types.
|
||||
rtp_payload_registry.SetRtxPayloadType(105, 95);
|
||||
rtp_payload_registry.SetRtxPayloadType(106, 96);
|
||||
rtp_payload_registry_->SetRtxPayloadType(105, 95);
|
||||
rtp_payload_registry_->SetRtxPayloadType(106, 96);
|
||||
|
||||
TestRtxPacket(&rtp_payload_registry, 105, 95, true);
|
||||
TestRtxPacket(&rtp_payload_registry, 106, 96, true);
|
||||
TestRtxPacket(rtp_payload_registry_.get(), 105, 95, true);
|
||||
TestRtxPacket(rtp_payload_registry_.get(), 106, 96, true);
|
||||
}
|
||||
|
||||
TEST(RtpPayloadRegistryTest, InvalidRtxConfiguration) {
|
||||
RTPPayloadRegistry rtp_payload_registry;
|
||||
rtp_payload_registry.SetRtxSsrc(100);
|
||||
TEST_F(RtpPayloadRegistryTest, InvalidRtxConfiguration) {
|
||||
rtp_payload_registry_->SetRtxSsrc(100);
|
||||
// Fails because no mappings exist and the incoming payload type isn't known.
|
||||
TestRtxPacket(&rtp_payload_registry, 105, 0, false);
|
||||
TestRtxPacket(rtp_payload_registry_.get(), 105, 0, false);
|
||||
// Succeeds when the mapping is used, but fails for the implicit fallback.
|
||||
rtp_payload_registry.SetRtxPayloadType(105, 95);
|
||||
TestRtxPacket(&rtp_payload_registry, 105, 95, true);
|
||||
TestRtxPacket(&rtp_payload_registry, 106, 0, false);
|
||||
rtp_payload_registry_->SetRtxPayloadType(105, 95);
|
||||
TestRtxPacket(rtp_payload_registry_.get(), 105, 95, true);
|
||||
TestRtxPacket(rtp_payload_registry_.get(), 106, 0, false);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(TestDynamicRange,
|
||||
|
||||
@ -64,6 +64,16 @@ class RTPReceiverAudio : public RTPReceiverStrategy,
|
||||
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
||||
const PayloadUnion& specific_payload) const override;
|
||||
|
||||
// We do not allow codecs to have multiple payload types for audio, so we
|
||||
// need to override the default behavior (which is to do nothing).
|
||||
void PossiblyRemoveExistingPayloadType(
|
||||
RtpUtility::PayloadTypeMap* payload_type_map,
|
||||
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
||||
size_t payload_name_length,
|
||||
uint32_t frequency,
|
||||
uint8_t channels,
|
||||
uint32_t rate) const;
|
||||
|
||||
// We need to look out for special payload types here and sometimes reset
|
||||
// statistics. In addition we sometimes need to tweak the frequency.
|
||||
void CheckPayloadChanged(int8_t payload_type,
|
||||
@ -79,6 +89,8 @@ class RTPReceiverAudio : public RTPReceiverStrategy,
|
||||
const AudioPayload& audio_specific,
|
||||
bool is_red);
|
||||
|
||||
uint32_t last_received_frequency_;
|
||||
|
||||
bool telephone_event_forward_to_decoder_;
|
||||
int8_t telephone_event_payload_type_;
|
||||
std::set<uint8_t> telephone_event_reported_;
|
||||
|
||||
@ -36,6 +36,8 @@ struct Payload {
|
||||
PayloadUnion typeSpecific;
|
||||
};
|
||||
|
||||
typedef std::map<int8_t, Payload*> PayloadTypeMap;
|
||||
|
||||
bool StringCompare(const char* str1, const char* str2, const uint32_t length);
|
||||
|
||||
// Round up to the nearest size that is a multiple of 4.
|
||||
|
||||
Reference in New Issue
Block a user