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:
@ -426,6 +426,7 @@ if (rtc_include_tests) {
|
|||||||
"rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc",
|
"rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc",
|
||||||
"rtp_rtcp/source/flexfec_receiver_unittest.cc",
|
"rtp_rtcp/source/flexfec_receiver_unittest.cc",
|
||||||
"rtp_rtcp/source/flexfec_sender_unittest.cc",
|
"rtp_rtcp/source/flexfec_sender_unittest.cc",
|
||||||
|
"rtp_rtcp/source/mock/mock_rtp_payload_strategy.h",
|
||||||
"rtp_rtcp/source/nack_rtx_unittest.cc",
|
"rtp_rtcp/source/nack_rtx_unittest.cc",
|
||||||
"rtp_rtcp/source/packet_loss_stats_unittest.cc",
|
"rtp_rtcp/source/packet_loss_stats_unittest.cc",
|
||||||
"rtp_rtcp/source/playout_delay_oracle_unittest.cc",
|
"rtp_rtcp/source/playout_delay_oracle_unittest.cc",
|
||||||
|
|||||||
@ -34,6 +34,7 @@ rtc_static_library("rtp_rtcp") {
|
|||||||
"source/forward_error_correction.h",
|
"source/forward_error_correction.h",
|
||||||
"source/forward_error_correction_internal.cc",
|
"source/forward_error_correction_internal.cc",
|
||||||
"source/forward_error_correction_internal.h",
|
"source/forward_error_correction_internal.h",
|
||||||
|
"source/mock/mock_rtp_payload_strategy.h",
|
||||||
"source/packet_loss_stats.cc",
|
"source/packet_loss_stats.cc",
|
||||||
"source/packet_loss_stats.h",
|
"source/packet_loss_stats.h",
|
||||||
"source/playout_delay_oracle.cc",
|
"source/playout_delay_oracle.cc",
|
||||||
|
|||||||
@ -25,24 +25,46 @@ namespace webrtc {
|
|||||||
struct CodecInst;
|
struct CodecInst;
|
||||||
class VideoCodec;
|
class VideoCodec;
|
||||||
|
|
||||||
// TODO(magjed): Remove once external code is updated.
|
// This strategy deals with the audio/video-specific aspects
|
||||||
|
// of payload handling.
|
||||||
class RTPPayloadStrategy {
|
class RTPPayloadStrategy {
|
||||||
public:
|
public:
|
||||||
static RTPPayloadStrategy* CreateStrategy(bool handling_audio) {
|
virtual ~RTPPayloadStrategy() {}
|
||||||
return nullptr;
|
|
||||||
}
|
virtual bool CodecsMustBeUnique() const = 0;
|
||||||
|
|
||||||
|
virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
||||||
|
uint32_t frequency,
|
||||||
|
size_t channels,
|
||||||
|
uint32_t rate) const = 0;
|
||||||
|
|
||||||
|
virtual void UpdatePayloadRate(RtpUtility::Payload* payload,
|
||||||
|
uint32_t rate) const = 0;
|
||||||
|
|
||||||
|
virtual RtpUtility::Payload* CreatePayloadType(const char* payload_name,
|
||||||
|
int8_t payload_type,
|
||||||
|
uint32_t frequency,
|
||||||
|
size_t channels,
|
||||||
|
uint32_t rate) const = 0;
|
||||||
|
|
||||||
|
virtual int GetPayloadTypeFrequency(
|
||||||
|
const RtpUtility::Payload& payload) const = 0;
|
||||||
|
|
||||||
|
static RTPPayloadStrategy* CreateStrategy(bool handling_audio);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RTPPayloadStrategy() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RTPPayloadRegistry {
|
class RTPPayloadRegistry {
|
||||||
public:
|
public:
|
||||||
RTPPayloadRegistry();
|
// The registry takes ownership of the strategy.
|
||||||
|
explicit RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy);
|
||||||
~RTPPayloadRegistry();
|
~RTPPayloadRegistry();
|
||||||
// TODO(magjed): Remove once external code is updated.
|
|
||||||
explicit RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy)
|
|
||||||
: RTPPayloadRegistry() {}
|
|
||||||
|
|
||||||
// TODO(magjed): Split RTPPayloadRegistry into separate Audio and Video class
|
// TODO(magjed): Split RTPPayloadRegistry into separate Audio and Video class
|
||||||
// and simplify the code. http://crbug/webrtc/6743.
|
// and remove RTPPayloadStrategy, RTPPayloadVideoStrategy,
|
||||||
|
// RTPPayloadAudioStrategy, and simplify the code. http://crbug/webrtc/6743.
|
||||||
int32_t RegisterReceivePayload(const CodecInst& audio_codec,
|
int32_t RegisterReceivePayload(const CodecInst& audio_codec,
|
||||||
bool* created_new_payload_type);
|
bool* created_new_payload_type);
|
||||||
int32_t RegisterReceivePayload(const VideoCodec& video_codec);
|
int32_t RegisterReceivePayload(const VideoCodec& video_codec);
|
||||||
@ -96,9 +118,13 @@ class RTPPayloadRegistry {
|
|||||||
// Returns true if the new media payload type has not changed.
|
// Returns true if the new media payload type has not changed.
|
||||||
bool ReportMediaPayloadType(uint8_t media_payload_type);
|
bool ReportMediaPayloadType(uint8_t media_payload_type);
|
||||||
|
|
||||||
int8_t red_payload_type() const { return GetPayloadTypeWithName("red"); }
|
int8_t red_payload_type() const {
|
||||||
|
rtc::CritScope cs(&crit_sect_);
|
||||||
|
return red_payload_type_;
|
||||||
|
}
|
||||||
int8_t ulpfec_payload_type() const {
|
int8_t ulpfec_payload_type() const {
|
||||||
return GetPayloadTypeWithName("ulpfec");
|
rtc::CritScope cs(&crit_sect_);
|
||||||
|
return ulpfec_payload_type_;
|
||||||
}
|
}
|
||||||
int8_t last_received_payload_type() const {
|
int8_t last_received_payload_type() const {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
@ -117,17 +143,34 @@ class RTPPayloadRegistry {
|
|||||||
RTC_DEPRECATED void set_use_rtx_payload_mapping_on_restore(bool val) {}
|
RTC_DEPRECATED void set_use_rtx_payload_mapping_on_restore(bool val) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int32_t RegisterReceivePayload(const char* payload_name,
|
||||||
|
int8_t payload_type,
|
||||||
|
uint32_t frequency,
|
||||||
|
size_t channels,
|
||||||
|
uint32_t rate,
|
||||||
|
bool* created_new_payload_type);
|
||||||
|
|
||||||
|
int32_t ReceivePayloadType(const char* payload_name,
|
||||||
|
uint32_t frequency,
|
||||||
|
size_t channels,
|
||||||
|
uint32_t rate,
|
||||||
|
int8_t* payload_type) const;
|
||||||
|
|
||||||
// Prunes the payload type map of the specific payload type, if it exists.
|
// Prunes the payload type map of the specific payload type, if it exists.
|
||||||
void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
||||||
const CodecInst& audio_codec);
|
const char* payload_name,
|
||||||
|
size_t payload_name_length,
|
||||||
|
uint32_t frequency,
|
||||||
|
size_t channels,
|
||||||
|
uint32_t rate);
|
||||||
|
|
||||||
bool IsRtxInternal(const RTPHeader& header) const;
|
bool IsRtxInternal(const RTPHeader& header) const;
|
||||||
// Returns the payload type for the payload with name |payload_name|, or -1 if
|
|
||||||
// no such payload is registered.
|
|
||||||
int8_t GetPayloadTypeWithName(const char* payload_name) const;
|
|
||||||
|
|
||||||
rtc::CriticalSection crit_sect_;
|
rtc::CriticalSection crit_sect_;
|
||||||
std::map<int, RtpUtility::Payload> payload_type_map_;
|
RtpUtility::PayloadTypeMap payload_type_map_;
|
||||||
|
std::unique_ptr<RTPPayloadStrategy> rtp_payload_strategy_;
|
||||||
|
int8_t red_payload_type_;
|
||||||
|
int8_t ulpfec_payload_type_;
|
||||||
int8_t incoming_payload_type_;
|
int8_t incoming_payload_type_;
|
||||||
int8_t last_received_payload_type_;
|
int8_t last_received_payload_type_;
|
||||||
int8_t last_received_media_payload_type_;
|
int8_t last_received_media_payload_type_;
|
||||||
|
|||||||
@ -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 {
|
class RtpRtcpRtxNackTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
RtpRtcpRtxNackTest()
|
RtpRtcpRtxNackTest()
|
||||||
: rtp_rtcp_module_(nullptr),
|
: rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
|
||||||
|
rtp_rtcp_module_(nullptr),
|
||||||
transport_(kTestSsrc + 1),
|
transport_(kTestSsrc + 1),
|
||||||
receiver_(),
|
receiver_(),
|
||||||
payload_data_length(sizeof(payload_data)),
|
payload_data_length(sizeof(payload_data)),
|
||||||
|
|||||||
@ -10,76 +10,55 @@
|
|||||||
|
|
||||||
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
#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/logging.h"
|
||||||
#include "webrtc/base/stringutils.h"
|
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
||||||
|
|
||||||
namespace webrtc {
|
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,
|
RTPPayloadRegistry::~RTPPayloadRegistry() {
|
||||||
const CodecInst& audio_codec) {
|
while (!payload_type_map_.empty()) {
|
||||||
if (!payload.audio)
|
RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
|
||||||
return false;
|
delete it->second;
|
||||||
if (_stricmp(payload.name, audio_codec.plname) != 0)
|
payload_type_map_.erase(it);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) {
|
int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
|
||||||
RtpUtility::Payload payload;
|
bool* created_new_payload) {
|
||||||
payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
return RegisterReceivePayload(
|
||||||
strncpy(payload.name, video_codec.plName, RTP_PAYLOAD_NAME_SIZE - 1);
|
audio_codec.plname, audio_codec.pltype, audio_codec.plfreq,
|
||||||
payload.typeSpecific.Video.videoCodecType =
|
audio_codec.channels, std::max(0, audio_codec.rate), created_new_payload);
|
||||||
ConvertToRtpVideoCodecType(video_codec.codecType);
|
|
||||||
payload.audio = false;
|
|
||||||
return 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_type >= 0);
|
||||||
|
assert(payload_name);
|
||||||
|
*created_new_payload = false;
|
||||||
|
|
||||||
// Sanity check.
|
// Sanity check.
|
||||||
switch (payload_type) {
|
switch (payload_type) {
|
||||||
@ -95,76 +74,59 @@ bool IsPayloadTypeValid(int8_t payload_type) {
|
|||||||
case 79: // 207 Extended report.
|
case 79: // 207 Extended report.
|
||||||
LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
|
LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
|
||||||
<< payload_type;
|
<< payload_type;
|
||||||
return false;
|
return -1;
|
||||||
default:
|
default:
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
size_t payload_name_length = strlen(payload_name);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
rtc::CritScope cs(&crit_sect_);
|
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()) {
|
if (it != payload_type_map_.end()) {
|
||||||
// We already use this payload type. Check if it's the same as we already
|
// We already use this payload type.
|
||||||
// have. If same, ignore sending an error.
|
RtpUtility::Payload* payload = it->second;
|
||||||
if (PayloadIsCompatible(it->second, audio_codec)) {
|
|
||||||
it->second.typeSpecific.Audio.rate = std::max(0, audio_codec.rate);
|
assert(payload);
|
||||||
return 0;
|
|
||||||
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio codecs must be unique.
|
if (rtp_payload_strategy_->CodecsMustBeUnique()) {
|
||||||
DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec);
|
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;
|
*created_new_payload = true;
|
||||||
|
|
||||||
// Successful set of payload type, clear the value of last received payload
|
if (RtpUtility::StringCompare(payload_name, "red", 3)) {
|
||||||
// type since it might mean something else.
|
red_payload_type_ = payload_type;
|
||||||
last_received_payload_type_ = -1;
|
} else if (RtpUtility::StringCompare(payload_name, "ulpfec", 6)) {
|
||||||
last_received_media_payload_type_ = -1;
|
ulpfec_payload_type_ = payload_type;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payload_type_map_[video_codec.plType] = CreatePayloadType(video_codec);
|
|
||||||
|
|
||||||
// Successful set of payload type, clear the value of last received payload
|
// Successful set of payload type, clear the value of last received payload
|
||||||
// type since it might mean something else.
|
// type since it might mean something else.
|
||||||
last_received_payload_type_ = -1;
|
last_received_payload_type_ = -1;
|
||||||
@ -175,7 +137,11 @@ int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
|||||||
int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
|
int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
|
||||||
const int8_t payload_type) {
|
const int8_t payload_type) {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,40 +149,95 @@ int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
|
|||||||
// for audio codecs, but there can for video.
|
// for audio codecs, but there can for video.
|
||||||
// Always called from within a critical section.
|
// Always called from within a critical section.
|
||||||
void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
||||||
const CodecInst& audio_codec) {
|
const char* const payload_name,
|
||||||
for (auto iterator = payload_type_map_.begin();
|
const size_t payload_name_length,
|
||||||
iterator != payload_type_map_.end(); ++iterator) {
|
const uint32_t frequency,
|
||||||
if (PayloadIsCompatible(iterator->second, audio_codec)) {
|
const size_t channels,
|
||||||
// Remove old setting.
|
const uint32_t rate) {
|
||||||
payload_type_map_.erase(iterator);
|
RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin();
|
||||||
break;
|
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,
|
int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec,
|
||||||
int8_t* payload_type) const {
|
int8_t* payload_type) const {
|
||||||
assert(payload_type);
|
return ReceivePayloadType(audio_codec.plname, audio_codec.plfreq,
|
||||||
rtc::CritScope cs(&crit_sect_);
|
audio_codec.channels, std::max(0, audio_codec.rate),
|
||||||
|
payload_type);
|
||||||
for (const auto& it : payload_type_map_) {
|
|
||||||
if (PayloadIsCompatible(it.second, audio_codec)) {
|
|
||||||
*payload_type = it.first;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec,
|
int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec,
|
||||||
int8_t* payload_type) const {
|
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);
|
assert(payload_type);
|
||||||
|
size_t payload_name_length = strlen(payload_name);
|
||||||
|
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
|
|
||||||
for (const auto& it : payload_type_map_) {
|
RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin();
|
||||||
if (PayloadIsCompatible(it.second, video_codec)) {
|
|
||||||
*payload_type = it.first;
|
for (; it != payload_type_map_.end(); ++it) {
|
||||||
return 0;
|
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;
|
return -1;
|
||||||
@ -312,8 +333,7 @@ void RTPPayloadRegistry::SetRtxPayloadType(int payload_type,
|
|||||||
|
|
||||||
bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
|
bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
auto it = payload_type_map_.find(header.payloadType);
|
return red_payload_type_ == header.payloadType;
|
||||||
return it != payload_type_map_.end() && _stricmp(it->second.name, "red") == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
|
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,
|
bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
|
||||||
PayloadUnion* payload) const {
|
PayloadUnion* payload) const {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
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.
|
// Check that this is a registered payload type.
|
||||||
if (it == payload_type_map_.end()) {
|
if (it == payload_type_map_.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*payload = it->second.typeSpecific;
|
*payload = it->second->typeSpecific;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,22 +361,22 @@ int RTPPayloadRegistry::GetPayloadTypeFrequency(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rtc::CritScope cs(&crit_sect_);
|
rtc::CritScope cs(&crit_sect_);
|
||||||
return payload->audio ? payload->typeSpecific.Audio.frequency
|
return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
|
||||||
: kVideoPayloadTypeFrequency;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload(
|
const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload(
|
||||||
uint8_t payload_type) const {
|
uint8_t payload_type) const {
|
||||||
rtc::CritScope cs(&crit_sect_);
|
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.
|
// Check that this is a registered payload type.
|
||||||
if (it == payload_type_map_.end()) {
|
if (it == payload_type_map_.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
|
void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
|
||||||
@ -374,15 +395,106 @@ bool RTPPayloadRegistry::ReportMediaPayloadType(uint8_t media_payload_type) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns -1 if a payload with name |payload_name| is not registered.
|
class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
|
||||||
int8_t RTPPayloadRegistry::GetPayloadTypeWithName(
|
public:
|
||||||
const char* payload_name) const {
|
bool CodecsMustBeUnique() const override { return true; }
|
||||||
rtc::CritScope cs(&crit_sect_);
|
|
||||||
for (const auto& it : payload_type_map_) {
|
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
||||||
if (_stricmp(it.second.name, payload_name) == 0)
|
const uint32_t frequency,
|
||||||
return it.first;
|
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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
#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/include/rtp_payload_registry.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/source/byte_io.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/modules/rtp_rtcp/source/rtp_utility.h"
|
||||||
#include "webrtc/test/gmock.h"
|
#include "webrtc/test/gmock.h"
|
||||||
#include "webrtc/test/gtest.h"
|
#include "webrtc/test/gtest.h"
|
||||||
@ -27,72 +28,116 @@ using ::testing::_;
|
|||||||
|
|
||||||
static const char* kTypicalPayloadName = "name";
|
static const char* kTypicalPayloadName = "name";
|
||||||
static const size_t kTypicalChannels = 1;
|
static const size_t kTypicalChannels = 1;
|
||||||
static const uint32_t kTypicalFrequency = 44000;
|
static const int kTypicalFrequency = 44000;
|
||||||
static const uint32_t kTypicalRate = 32 * 1024;
|
static const int kTypicalRate = 32 * 1024;
|
||||||
static const CodecInst kTypicalAudioCodec = {-1 /* pltype */, "name",
|
static const CodecInst kTypicalAudioCodec = {-1 /* pltype */, "name",
|
||||||
kTypicalFrequency, 0 /* pacsize */,
|
kTypicalFrequency, 0 /* pacsize */,
|
||||||
kTypicalChannels, kTypicalRate};
|
kTypicalChannels, kTypicalRate};
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest,
|
class RtpPayloadRegistryTest : public ::testing::Test {
|
||||||
RegistersAndRemembersVideoPayloadsUntilDeregistered) {
|
public:
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
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;
|
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;
|
VideoCodec video_codec;
|
||||||
video_codec.codecType = kVideoCodecVP8;
|
video_codec.codecType = kVideoCodecVP8;
|
||||||
strncpy(video_codec.plName, "VP8", RTP_PAYLOAD_NAME_SIZE);
|
strncpy(video_codec.plName, "VP8", RTP_PAYLOAD_NAME_SIZE);
|
||||||
video_codec.plType = payload_type;
|
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 =
|
const RtpUtility::Payload* retrieved_payload =
|
||||||
rtp_payload_registry.PayloadTypeToPayload(payload_type);
|
rtp_payload_registry_->PayloadTypeToPayload(payload_type);
|
||||||
EXPECT_TRUE(retrieved_payload);
|
EXPECT_TRUE(retrieved_payload);
|
||||||
|
|
||||||
// We should get back the corresponding payload that we registered.
|
// We should get back the exact pointer to the payload returned by the
|
||||||
EXPECT_STREQ("VP8", retrieved_payload->name);
|
// payload strategy.
|
||||||
EXPECT_FALSE(retrieved_payload->audio);
|
EXPECT_EQ(returned_video_payload_on_heap, retrieved_payload);
|
||||||
EXPECT_EQ(kRtpVideoVp8, retrieved_payload->typeSpecific.Video.videoCodecType);
|
|
||||||
|
|
||||||
// Now forget about it and verify it's gone.
|
// Now forget about it and verify it's gone.
|
||||||
EXPECT_EQ(0, rtp_payload_registry.DeRegisterReceivePayload(payload_type));
|
EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type));
|
||||||
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type));
|
EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest,
|
TEST_F(RtpPayloadRegistryTest,
|
||||||
RegistersAndRemembersAudioPayloadsUntilDeregistered) {
|
RegistersAndRemembersAudioPayloadsUntilDeregistered) {
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
|
||||||
uint8_t payload_type = 97;
|
uint8_t payload_type = 97;
|
||||||
|
RtpUtility::Payload* returned_payload_on_heap =
|
||||||
|
ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
|
||||||
|
|
||||||
bool new_payload_created = false;
|
bool new_payload_created = false;
|
||||||
CodecInst audio_codec = kTypicalAudioCodec;
|
CodecInst audio_codec = kTypicalAudioCodec;
|
||||||
audio_codec.pltype = payload_type;
|
audio_codec.pltype = payload_type;
|
||||||
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
|
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(
|
||||||
audio_codec, &new_payload_created));
|
audio_codec, &new_payload_created));
|
||||||
|
|
||||||
EXPECT_TRUE(new_payload_created) << "A new payload WAS created.";
|
EXPECT_TRUE(new_payload_created) << "A new payload WAS created.";
|
||||||
|
|
||||||
const RtpUtility::Payload* retrieved_payload =
|
const RtpUtility::Payload* retrieved_payload =
|
||||||
rtp_payload_registry.PayloadTypeToPayload(payload_type);
|
rtp_payload_registry_->PayloadTypeToPayload(payload_type);
|
||||||
EXPECT_TRUE(retrieved_payload);
|
EXPECT_TRUE(retrieved_payload);
|
||||||
|
|
||||||
// We should get back the corresponding payload that we registered.
|
// We should get back the exact pointer to the payload returned by the
|
||||||
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
|
// payload strategy.
|
||||||
EXPECT_TRUE(retrieved_payload->audio);
|
EXPECT_EQ(returned_payload_on_heap, retrieved_payload);
|
||||||
EXPECT_EQ(kTypicalFrequency, retrieved_payload->typeSpecific.Audio.frequency);
|
|
||||||
EXPECT_EQ(kTypicalChannels, retrieved_payload->typeSpecific.Audio.channels);
|
|
||||||
EXPECT_EQ(kTypicalRate, retrieved_payload->typeSpecific.Audio.rate);
|
|
||||||
|
|
||||||
// Now forget about it and verify it's gone.
|
// Now forget about it and verify it's gone.
|
||||||
EXPECT_EQ(0, rtp_payload_registry.DeRegisterReceivePayload(payload_type));
|
EXPECT_EQ(0, rtp_payload_registry_->DeRegisterReceivePayload(payload_type));
|
||||||
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type));
|
EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest, AudioRedWorkProperly) {
|
TEST_F(RtpPayloadRegistryTest, AudioRedWorkProperly) {
|
||||||
const uint8_t kRedPayloadType = 127;
|
const uint8_t kRedPayloadType = 127;
|
||||||
const int kRedSampleRate = 8000;
|
const int kRedSampleRate = 8000;
|
||||||
const size_t kRedChannels = 1;
|
const size_t kRedChannels = 1;
|
||||||
const int kRedBitRate = 0;
|
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;
|
bool new_payload_created = false;
|
||||||
CodecInst red_audio_codec;
|
CodecInst red_audio_codec;
|
||||||
@ -101,170 +146,170 @@ TEST(RtpPayloadRegistryTest, AudioRedWorkProperly) {
|
|||||||
red_audio_codec.plfreq = kRedSampleRate;
|
red_audio_codec.plfreq = kRedSampleRate;
|
||||||
red_audio_codec.channels = kRedChannels;
|
red_audio_codec.channels = kRedChannels;
|
||||||
red_audio_codec.rate = kRedBitRate;
|
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));
|
red_audio_codec, &new_payload_created));
|
||||||
EXPECT_TRUE(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 =
|
const RtpUtility::Payload* retrieved_payload =
|
||||||
rtp_payload_registry.PayloadTypeToPayload(kRedPayloadType);
|
rtp_payload_registry_->PayloadTypeToPayload(kRedPayloadType);
|
||||||
EXPECT_TRUE(retrieved_payload);
|
EXPECT_TRUE(retrieved_payload);
|
||||||
EXPECT_TRUE(retrieved_payload->audio);
|
EXPECT_TRUE(retrieved_payload->audio);
|
||||||
EXPECT_STRCASEEQ("red", retrieved_payload->name);
|
EXPECT_STRCASEEQ("red", retrieved_payload->name);
|
||||||
|
|
||||||
// Sample rate is correctly registered.
|
// Sample rate is correctly registered.
|
||||||
EXPECT_EQ(kRedSampleRate,
|
EXPECT_EQ(kRedSampleRate,
|
||||||
rtp_payload_registry.GetPayloadTypeFrequency(kRedPayloadType));
|
rtp_payload_registry_->GetPayloadTypeFrequency(kRedPayloadType));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest,
|
TEST_F(RtpPayloadRegistryTest,
|
||||||
DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
|
DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
|
||||||
uint8_t payload_type = 97;
|
uint8_t payload_type = 97;
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
|
||||||
|
|
||||||
bool ignored = false;
|
bool ignored = false;
|
||||||
|
RtpUtility::Payload* first_payload_on_heap =
|
||||||
|
ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
|
||||||
CodecInst audio_codec = kTypicalAudioCodec;
|
CodecInst audio_codec = kTypicalAudioCodec;
|
||||||
audio_codec.pltype = payload_type;
|
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(
|
EXPECT_EQ(
|
||||||
-1, rtp_payload_registry.RegisterReceivePayload(audio_codec_2, &ignored))
|
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||||
<< "Adding incompatible codec with same payload type = bad.";
|
|
||||||
|
|
||||||
// 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;
|
audio_codec_2.pltype = payload_type - 1;
|
||||||
EXPECT_EQ(
|
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.";
|
<< "With a different payload type is fine though.";
|
||||||
|
|
||||||
// Ensure both payloads are preserved.
|
// Ensure both payloads are preserved.
|
||||||
const RtpUtility::Payload* retrieved_payload =
|
const RtpUtility::Payload* retrieved_payload =
|
||||||
rtp_payload_registry.PayloadTypeToPayload(payload_type);
|
rtp_payload_registry_->PayloadTypeToPayload(payload_type);
|
||||||
EXPECT_TRUE(retrieved_payload);
|
EXPECT_TRUE(retrieved_payload);
|
||||||
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
|
EXPECT_EQ(first_payload_on_heap, retrieved_payload);
|
||||||
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);
|
|
||||||
|
|
||||||
retrieved_payload =
|
retrieved_payload =
|
||||||
rtp_payload_registry.PayloadTypeToPayload(payload_type - 1);
|
rtp_payload_registry_->PayloadTypeToPayload(payload_type - 1);
|
||||||
EXPECT_TRUE(retrieved_payload);
|
EXPECT_TRUE(retrieved_payload);
|
||||||
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
|
EXPECT_EQ(second_payload_on_heap, retrieved_payload);
|
||||||
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);
|
|
||||||
|
|
||||||
// Ok, update the rate for one of the codecs. If either the incoming rate or
|
// 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
|
// 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.
|
// codec twice, and in that case roughly the following happens.
|
||||||
EXPECT_EQ(0,
|
ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
|
||||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
.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,
|
TEST_F(RtpPayloadRegistryTest,
|
||||||
RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
|
RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
|
||||||
|
ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
|
||||||
|
.WillByDefault(Return(true));
|
||||||
|
ON_CALL(*mock_payload_strategy_, CodecsMustBeUnique())
|
||||||
|
.WillByDefault(Return(true));
|
||||||
|
|
||||||
uint8_t payload_type = 97;
|
uint8_t payload_type = 97;
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
|
||||||
|
|
||||||
bool ignored = false;
|
bool ignored = false;
|
||||||
|
ExpectReturnOfTypicalAudioPayload(payload_type, kTypicalRate);
|
||||||
CodecInst audio_codec = kTypicalAudioCodec;
|
CodecInst audio_codec = kTypicalAudioCodec;
|
||||||
audio_codec.pltype = payload_type;
|
audio_codec.pltype = payload_type;
|
||||||
EXPECT_EQ(0,
|
EXPECT_EQ(
|
||||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||||
|
ExpectReturnOfTypicalAudioPayload(payload_type - 1, kTypicalRate);
|
||||||
CodecInst audio_codec_2 = kTypicalAudioCodec;
|
CodecInst audio_codec_2 = kTypicalAudioCodec;
|
||||||
audio_codec_2.pltype = payload_type - 1;
|
audio_codec_2.pltype = payload_type - 1;
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(audio_codec_2,
|
||||||
0, rtp_payload_registry.RegisterReceivePayload(audio_codec_2, &ignored));
|
&ignored));
|
||||||
|
|
||||||
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type))
|
EXPECT_FALSE(rtp_payload_registry_->PayloadTypeToPayload(payload_type))
|
||||||
<< "The first payload should be "
|
<< "The first payload should be "
|
||||||
"deregistered because the only thing that differs is payload type.";
|
"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.";
|
<< "The second payload should still be registered though.";
|
||||||
|
|
||||||
// Now ensure non-compatible codecs aren't removed. Make |audio_codec_3|
|
// Now ensure non-compatible codecs aren't removed.
|
||||||
// incompatible by changing the frequency.
|
ON_CALL(*mock_payload_strategy_, PayloadIsCompatible(_, _, _, _))
|
||||||
|
.WillByDefault(Return(false));
|
||||||
|
ExpectReturnOfTypicalAudioPayload(payload_type + 1, kTypicalRate);
|
||||||
CodecInst audio_codec_3 = kTypicalAudioCodec;
|
CodecInst audio_codec_3 = kTypicalAudioCodec;
|
||||||
audio_codec_3.pltype = payload_type + 1;
|
audio_codec_3.pltype = payload_type + 1;
|
||||||
audio_codec_3.plfreq = kTypicalFrequency + 1;
|
EXPECT_EQ(0, rtp_payload_registry_->RegisterReceivePayload(audio_codec_3,
|
||||||
EXPECT_EQ(
|
&ignored));
|
||||||
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.";
|
<< "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.";
|
<< "Not compatible; both payloads should be kept.";
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest,
|
TEST_F(RtpPayloadRegistryTest,
|
||||||
LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
|
LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
rtp_payload_registry_->set_last_received_payload_type(17);
|
||||||
rtp_payload_registry.set_last_received_payload_type(17);
|
EXPECT_EQ(17, rtp_payload_registry_->last_received_payload_type());
|
||||||
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);
|
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);
|
EXPECT_TRUE(media_type_unchanged);
|
||||||
|
|
||||||
bool ignored;
|
bool ignored;
|
||||||
|
ExpectReturnOfTypicalAudioPayload(34, kTypicalRate);
|
||||||
CodecInst audio_codec = kTypicalAudioCodec;
|
CodecInst audio_codec = kTypicalAudioCodec;
|
||||||
audio_codec.pltype = 34;
|
audio_codec.pltype = 34;
|
||||||
EXPECT_EQ(0,
|
EXPECT_EQ(
|
||||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||||
|
|
||||||
EXPECT_EQ(-1, rtp_payload_registry.last_received_payload_type());
|
EXPECT_EQ(-1, rtp_payload_registry_->last_received_payload_type());
|
||||||
media_type_unchanged = rtp_payload_registry.ReportMediaPayloadType(18);
|
media_type_unchanged = rtp_payload_registry_->ReportMediaPayloadType(18);
|
||||||
EXPECT_FALSE(media_type_unchanged);
|
EXPECT_FALSE(media_type_unchanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParameterizedRtpPayloadRegistryTest
|
class ParameterizedRtpPayloadRegistryTest
|
||||||
: public ::testing::TestWithParam<int> {};
|
: public RtpPayloadRegistryTest,
|
||||||
|
public ::testing::WithParamInterface<int> {};
|
||||||
|
|
||||||
TEST_P(ParameterizedRtpPayloadRegistryTest,
|
TEST_P(ParameterizedRtpPayloadRegistryTest,
|
||||||
FailsToRegisterKnownPayloadsWeAreNotInterestedIn) {
|
FailsToRegisterKnownPayloadsWeAreNotInterestedIn) {
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
int payload_type = GetParam();
|
||||||
|
|
||||||
bool ignored;
|
bool ignored;
|
||||||
CodecInst audio_codec;
|
CodecInst audio_codec;
|
||||||
strncpy(audio_codec.plname, "whatever", RTP_PAYLOAD_NAME_SIZE);
|
strncpy(audio_codec.plname, "whatever", RTP_PAYLOAD_NAME_SIZE);
|
||||||
audio_codec.pltype = GetParam();
|
audio_codec.pltype = static_cast<uint8_t>(payload_type);
|
||||||
audio_codec.plfreq = 1900;
|
audio_codec.plfreq = 19;
|
||||||
audio_codec.channels = 1;
|
audio_codec.channels = 1;
|
||||||
audio_codec.rate = 17;
|
audio_codec.rate = 17;
|
||||||
EXPECT_EQ(-1,
|
EXPECT_EQ(
|
||||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
-1, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes,
|
INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes,
|
||||||
ParameterizedRtpPayloadRegistryTest,
|
ParameterizedRtpPayloadRegistryTest,
|
||||||
testing::Values(64, 72, 73, 74, 75, 76, 77, 78, 79));
|
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) {
|
TEST_P(RtpPayloadRegistryGenericTest, RegisterGenericReceivePayloadType) {
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
|
||||||
|
|
||||||
bool ignored;
|
bool ignored;
|
||||||
CodecInst audio_codec;
|
CodecInst audio_codec;
|
||||||
// Dummy values, except for payload_type.
|
// Dummy values, except for payload_type.
|
||||||
strncpy(audio_codec.plname, "generic-codec", RTP_PAYLOAD_NAME_SIZE);
|
strncpy(audio_codec.plname, "generic-codec", RTP_PAYLOAD_NAME_SIZE);
|
||||||
audio_codec.pltype = GetParam();
|
audio_codec.pltype = GetParam();
|
||||||
audio_codec.plfreq = 1900;
|
audio_codec.plfreq = 19;
|
||||||
audio_codec.channels = 1;
|
audio_codec.channels = 1;
|
||||||
audio_codec.rate = 17;
|
audio_codec.rate = 17;
|
||||||
EXPECT_EQ(0,
|
EXPECT_EQ(
|
||||||
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
|
0, rtp_payload_registry_->RegisterReceivePayload(audio_codec, &ignored));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates an RTX packet for the given length and original sequence number.
|
// 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.";
|
<< "The restored packet should have the correct ssrc.";
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest, MultipleRtxPayloadTypes) {
|
TEST_F(RtpPayloadRegistryTest, MultipleRtxPayloadTypes) {
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
|
||||||
// Set the incoming payload type to 90.
|
// Set the incoming payload type to 90.
|
||||||
RTPHeader header;
|
RTPHeader header;
|
||||||
header.payloadType = 90;
|
header.payloadType = 90;
|
||||||
header.ssrc = 1;
|
header.ssrc = 1;
|
||||||
rtp_payload_registry.SetIncomingPayloadType(header);
|
rtp_payload_registry_->SetIncomingPayloadType(header);
|
||||||
rtp_payload_registry.SetRtxSsrc(100);
|
rtp_payload_registry_->SetRtxSsrc(100);
|
||||||
// Map two RTX payload types.
|
// Map two RTX payload types.
|
||||||
rtp_payload_registry.SetRtxPayloadType(105, 95);
|
rtp_payload_registry_->SetRtxPayloadType(105, 95);
|
||||||
rtp_payload_registry.SetRtxPayloadType(106, 96);
|
rtp_payload_registry_->SetRtxPayloadType(106, 96);
|
||||||
|
|
||||||
TestRtxPacket(&rtp_payload_registry, 105, 95, true);
|
TestRtxPacket(rtp_payload_registry_.get(), 105, 95, true);
|
||||||
TestRtxPacket(&rtp_payload_registry, 106, 96, true);
|
TestRtxPacket(rtp_payload_registry_.get(), 106, 96, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RtpPayloadRegistryTest, InvalidRtxConfiguration) {
|
TEST_F(RtpPayloadRegistryTest, InvalidRtxConfiguration) {
|
||||||
RTPPayloadRegistry rtp_payload_registry;
|
rtp_payload_registry_->SetRtxSsrc(100);
|
||||||
rtp_payload_registry.SetRtxSsrc(100);
|
|
||||||
// Fails because no mappings exist and the incoming payload type isn't known.
|
// 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.
|
// Succeeds when the mapping is used, but fails for the implicit fallback.
|
||||||
rtp_payload_registry.SetRtxPayloadType(105, 95);
|
rtp_payload_registry_->SetRtxPayloadType(105, 95);
|
||||||
TestRtxPacket(&rtp_payload_registry, 105, 95, true);
|
TestRtxPacket(rtp_payload_registry_.get(), 105, 95, true);
|
||||||
TestRtxPacket(&rtp_payload_registry, 106, 0, false);
|
TestRtxPacket(rtp_payload_registry_.get(), 106, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(TestDynamicRange,
|
INSTANTIATE_TEST_CASE_P(TestDynamicRange,
|
||||||
|
|||||||
@ -64,6 +64,16 @@ class RTPReceiverAudio : public RTPReceiverStrategy,
|
|||||||
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
||||||
const PayloadUnion& specific_payload) const override;
|
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
|
// We need to look out for special payload types here and sometimes reset
|
||||||
// statistics. In addition we sometimes need to tweak the frequency.
|
// statistics. In addition we sometimes need to tweak the frequency.
|
||||||
void CheckPayloadChanged(int8_t payload_type,
|
void CheckPayloadChanged(int8_t payload_type,
|
||||||
@ -79,6 +89,8 @@ class RTPReceiverAudio : public RTPReceiverStrategy,
|
|||||||
const AudioPayload& audio_specific,
|
const AudioPayload& audio_specific,
|
||||||
bool is_red);
|
bool is_red);
|
||||||
|
|
||||||
|
uint32_t last_received_frequency_;
|
||||||
|
|
||||||
bool telephone_event_forward_to_decoder_;
|
bool telephone_event_forward_to_decoder_;
|
||||||
int8_t telephone_event_payload_type_;
|
int8_t telephone_event_payload_type_;
|
||||||
std::set<uint8_t> telephone_event_reported_;
|
std::set<uint8_t> telephone_event_reported_;
|
||||||
|
|||||||
@ -36,6 +36,8 @@ struct Payload {
|
|||||||
PayloadUnion typeSpecific;
|
PayloadUnion typeSpecific;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<int8_t, Payload*> PayloadTypeMap;
|
||||||
|
|
||||||
bool StringCompare(const char* str1, const char* str2, const uint32_t length);
|
bool StringCompare(const char* str1, const char* str2, const uint32_t length);
|
||||||
|
|
||||||
// Round up to the nearest size that is a multiple of 4.
|
// Round up to the nearest size that is a multiple of 4.
|
||||||
|
|||||||
@ -101,7 +101,8 @@ class RtpRtcpAPITest : public ::testing::Test {
|
|||||||
configuration.outgoing_transport = &null_transport_;
|
configuration.outgoing_transport = &null_transport_;
|
||||||
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
module_.reset(RtpRtcp::CreateRtpRtcp(configuration));
|
module_.reset(RtpRtcp::CreateRtpRtcp(configuration));
|
||||||
rtp_payload_registry_.reset(new RTPPayloadRegistry());
|
rtp_payload_registry_.reset(new RTPPayloadRegistry(
|
||||||
|
RTPPayloadStrategy::CreateStrategy(true)));
|
||||||
rtp_receiver_.reset(RtpReceiver::CreateAudioReceiver(
|
rtp_receiver_.reset(RtpReceiver::CreateAudioReceiver(
|
||||||
&fake_clock_, NULL, NULL, rtp_payload_registry_.get()));
|
&fake_clock_, NULL, NULL, rtp_payload_registry_.get()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -101,8 +101,10 @@ class RtpRtcpAudioTest : public ::testing::Test {
|
|||||||
receive_statistics1_.reset(ReceiveStatistics::Create(&fake_clock));
|
receive_statistics1_.reset(ReceiveStatistics::Create(&fake_clock));
|
||||||
receive_statistics2_.reset(ReceiveStatistics::Create(&fake_clock));
|
receive_statistics2_.reset(ReceiveStatistics::Create(&fake_clock));
|
||||||
|
|
||||||
rtp_payload_registry1_.reset(new RTPPayloadRegistry());
|
rtp_payload_registry1_.reset(new RTPPayloadRegistry(
|
||||||
rtp_payload_registry2_.reset(new RTPPayloadRegistry());
|
RTPPayloadStrategy::CreateStrategy(true)));
|
||||||
|
rtp_payload_registry2_.reset(new RTPPayloadRegistry(
|
||||||
|
RTPPayloadStrategy::CreateStrategy(true)));
|
||||||
|
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
configuration.audio = true;
|
configuration.audio = true;
|
||||||
|
|||||||
@ -94,8 +94,10 @@ class RtpRtcpRtcpTest : public ::testing::Test {
|
|||||||
configuration.intra_frame_callback = myRTCPFeedback1;
|
configuration.intra_frame_callback = myRTCPFeedback1;
|
||||||
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
configuration.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
|
|
||||||
rtp_payload_registry1_.reset(new RTPPayloadRegistry());
|
rtp_payload_registry1_.reset(new RTPPayloadRegistry(
|
||||||
rtp_payload_registry2_.reset(new RTPPayloadRegistry());
|
RTPPayloadStrategy::CreateStrategy(true)));
|
||||||
|
rtp_payload_registry2_.reset(new RTPPayloadRegistry(
|
||||||
|
RTPPayloadStrategy::CreateStrategy(true)));
|
||||||
|
|
||||||
module1 = RtpRtcp::CreateRtpRtcp(configuration);
|
module1 = RtpRtcp::CreateRtpRtcp(configuration);
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,8 @@ namespace webrtc {
|
|||||||
class RtpRtcpVideoTest : public ::testing::Test {
|
class RtpRtcpVideoTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
RtpRtcpVideoTest()
|
RtpRtcpVideoTest()
|
||||||
: test_ssrc_(3456),
|
: rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
|
||||||
|
test_ssrc_(3456),
|
||||||
test_timestamp_(4567),
|
test_timestamp_(4567),
|
||||||
test_sequence_number_(2345),
|
test_sequence_number_(2345),
|
||||||
fake_clock(123456),
|
fake_clock(123456),
|
||||||
|
|||||||
@ -271,7 +271,8 @@ class SsrcHandlers {
|
|||||||
const PayloadTypes& payload_types,
|
const PayloadTypes& payload_types,
|
||||||
LostPackets* lost_packets)
|
LostPackets* lost_packets)
|
||||||
: rtp_header_parser_(RtpHeaderParser::Create()),
|
: rtp_header_parser_(RtpHeaderParser::Create()),
|
||||||
rtp_payload_registry_(new RTPPayloadRegistry()),
|
rtp_payload_registry_(new RTPPayloadRegistry(
|
||||||
|
RTPPayloadStrategy::CreateStrategy(false))),
|
||||||
rtp_module_(),
|
rtp_module_(),
|
||||||
payload_sink_(),
|
payload_sink_(),
|
||||||
ssrc_(ssrc),
|
ssrc_(ssrc),
|
||||||
|
|||||||
@ -106,6 +106,7 @@ RtpStreamReceiver::RtpStreamReceiver(
|
|||||||
remb_(remb),
|
remb_(remb),
|
||||||
process_thread_(process_thread),
|
process_thread_(process_thread),
|
||||||
ntp_estimator_(clock_),
|
ntp_estimator_(clock_),
|
||||||
|
rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
|
||||||
rtp_header_parser_(RtpHeaderParser::Create()),
|
rtp_header_parser_(RtpHeaderParser::Create()),
|
||||||
rtp_receiver_(RtpReceiver::CreateVideoReceiver(clock_,
|
rtp_receiver_(RtpReceiver::CreateVideoReceiver(clock_,
|
||||||
this,
|
this,
|
||||||
|
|||||||
@ -834,7 +834,8 @@ Channel::Channel(int32_t channelId,
|
|||||||
_channelId(channelId),
|
_channelId(channelId),
|
||||||
event_log_proxy_(new RtcEventLogProxy()),
|
event_log_proxy_(new RtcEventLogProxy()),
|
||||||
rtp_header_parser_(RtpHeaderParser::Create()),
|
rtp_header_parser_(RtpHeaderParser::Create()),
|
||||||
rtp_payload_registry_(new RTPPayloadRegistry()),
|
rtp_payload_registry_(
|
||||||
|
new RTPPayloadRegistry(RTPPayloadStrategy::CreateStrategy(true))),
|
||||||
rtp_receive_statistics_(
|
rtp_receive_statistics_(
|
||||||
ReceiveStatistics::Create(Clock::GetRealTimeClock())),
|
ReceiveStatistics::Create(Clock::GetRealTimeClock())),
|
||||||
rtp_receiver_(
|
rtp_receiver_(
|
||||||
|
|||||||
Reference in New Issue
Block a user