RTPPayloadRegistry: Use SdpAudioFormat to represent audio codecs

This is needed in the general case, now that we aim to support codecs
other than those built-in to WebRTC.

BUG=webrtc:8159

Change-Id: I40a41252bf69ad5d4d0208e3c1e8918da7394706
Reviewed-on: https://webrtc-review.googlesource.com/5380
Commit-Queue: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20136}
This commit is contained in:
Karl Wiberg
2017-10-04 12:38:53 +02:00
committed by Commit Bot
parent 83ccca1864
commit c62f6c7121
22 changed files with 205 additions and 259 deletions

View File

@ -85,6 +85,7 @@ rtc_source_set("rtp_rtcp_format") {
"../../api:array_view",
"../../api:libjingle_peerconnection_api",
"../../api:optional",
"../../api/audio_codecs:audio_codecs_api",
"../../common_video",
"../../rtc_base:rtc_base_approved",
"../../system_wrappers",
@ -380,6 +381,7 @@ if (rtc_include_tests) {
"../../test:rtp_test_utils",
"../../test:test_common",
"../../test:test_support",
"../audio_coding:audio_format_conversion",
"//testing/gmock",
]

View File

@ -21,7 +21,6 @@
namespace webrtc {
struct CodecInst;
class VideoCodec;
class RTPPayloadRegistry {
@ -35,13 +34,14 @@ class RTPPayloadRegistry {
// Replace all audio receive payload types with the given map.
void SetAudioReceivePayloads(std::map<int, SdpAudioFormat> codecs);
int32_t RegisterReceivePayload(const CodecInst& audio_codec,
int32_t RegisterReceivePayload(int payload_type,
const SdpAudioFormat& audio_format,
bool* created_new_payload_type);
int32_t RegisterReceivePayload(const VideoCodec& video_codec);
int32_t DeRegisterReceivePayload(int8_t payload_type);
int32_t ReceivePayloadType(const CodecInst& audio_codec,
int32_t ReceivePayloadType(const SdpAudioFormat& audio_format,
int8_t* payload_type) const;
int32_t ReceivePayloadType(const VideoCodec& video_codec,
int8_t* payload_type) const;
@ -96,7 +96,7 @@ class RTPPayloadRegistry {
private:
// Prunes the payload type map of the specific payload type, if it exists.
void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
const CodecInst& audio_codec);
const SdpAudioFormat& audio_format);
bool IsRtxInternal(const RTPHeader& header) const;
// Returns the payload type for the payload with name |payload_name|, or -1 if

View File

@ -19,7 +19,6 @@
namespace webrtc {
struct CodecInst;
class RTPPayloadRegistry;
class VideoCodec;
@ -61,7 +60,13 @@ class RtpReceiver {
// Registers a receive payload in the payload registry and notifies the media
// receiver strategy.
virtual int32_t RegisterReceivePayload(const CodecInst& audio_codec) = 0;
virtual int32_t RegisterReceivePayload(
int payload_type,
const SdpAudioFormat& audio_format) = 0;
// Deprecated version of the above.
int32_t RegisterReceivePayload(const CodecInst& audio_codec);
// Registers a receive payload in the payload registry.
virtual int32_t RegisterReceivePayload(const VideoCodec& video_codec) = 0;

View File

@ -15,6 +15,7 @@
#include <list>
#include <vector>
#include "api/audio_codecs/audio_format.h"
#include "common_types.h" // NOLINT(build/include)
#include "modules/include/module_common_types.h"
#include "rtc_base/deprecation.h"
@ -40,9 +41,8 @@ const int kBogusRtpRateForAudioRtcp = 8000;
const uint8_t kRtpHeaderSize = 12;
struct AudioPayload {
uint32_t frequency;
size_t channels;
uint32_t rate;
SdpAudioFormat format;
uint32_t rate;
};
struct VideoPayload {
@ -271,12 +271,9 @@ class RtpFeedback {
/*
* channels - number of channels in codec (1 = mono, 2 = stereo)
*/
virtual int32_t OnInitializeDecoder(
int8_t payload_type,
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
uint32_t rate) = 0;
virtual int32_t OnInitializeDecoder(int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) = 0;
virtual void OnIncomingSSRCChanged(uint32_t ssrc) = 0;
@ -452,10 +449,8 @@ class NullRtpFeedback : public RtpFeedback {
public:
~NullRtpFeedback() override {}
int32_t OnInitializeDecoder(int8_t payload_type,
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
int32_t OnInitializeDecoder(int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) override;
void OnIncomingSSRCChanged(uint32_t ssrc) override {}
@ -463,10 +458,8 @@ class NullRtpFeedback : public RtpFeedback {
};
inline int32_t NullRtpFeedback::OnInitializeDecoder(
int8_t payload_type,
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) {
return 0;
}

View File

@ -23,14 +23,9 @@ namespace webrtc {
namespace {
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
const CodecInst& audio_codec) {
if (!payload.typeSpecific.is_audio())
return false;
if (_stricmp(payload.name, audio_codec.plname) != 0)
return false;
const AudioPayload& audio_payload = payload.typeSpecific.audio_payload();
return audio_payload.frequency == static_cast<uint32_t>(audio_codec.plfreq) &&
audio_payload.channels == audio_codec.channels;
const SdpAudioFormat& audio_format) {
return payload.typeSpecific.is_audio() &&
audio_format.Matches(payload.typeSpecific.audio_payload().format);
}
bool PayloadIsCompatible(const RtpUtility::Payload& payload,
@ -46,12 +41,10 @@ bool PayloadIsCompatible(const RtpUtility::Payload& payload,
return true;
}
RtpUtility::Payload CreatePayloadType(const CodecInst& audio_codec) {
RTC_DCHECK_GE(audio_codec.plfreq, 1000);
return {audio_codec.plname,
PayloadUnion(
AudioPayload{rtc::dchecked_cast<uint32_t>(audio_codec.plfreq),
audio_codec.channels, 0})};
RtpUtility::Payload CreatePayloadType(const SdpAudioFormat& audio_format) {
RTC_DCHECK_GE(audio_format.clockrate_hz, 1000);
return {audio_format.name.c_str(),
PayloadUnion(AudioPayload{audio_format, 0})};
}
RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) {
@ -125,10 +118,9 @@ void RTPPayloadRegistry::SetAudioReceivePayloads(
for (const auto& kv : codecs) {
const int& rtp_payload_type = kv.first;
const SdpAudioFormat& audio_format = kv.second;
const CodecInst ci = SdpToCodecInst(rtp_payload_type, audio_format);
RTC_DCHECK(IsPayloadTypeValid(rtp_payload_type));
payload_type_map_.insert(
std::make_pair(rtp_payload_type, CreatePayloadType(ci)));
payload_type_map_.emplace(rtp_payload_type,
CreatePayloadType(audio_format));
}
// Clear the value of last received payload type since it might mean
@ -137,8 +129,10 @@ void RTPPayloadRegistry::SetAudioReceivePayloads(
last_received_media_payload_type_ = -1;
}
int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
bool* created_new_payload) {
int32_t RTPPayloadRegistry::RegisterReceivePayload(
int payload_type,
const SdpAudioFormat& audio_format,
bool* created_new_payload) {
rtc::CritScope cs(&crit_sect_);
#if RTC_DCHECK_IS_ON
@ -147,26 +141,26 @@ int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
#endif
*created_new_payload = false;
if (!IsPayloadTypeValid(audio_codec.pltype))
if (!IsPayloadTypeValid(payload_type))
return -1;
auto it = payload_type_map_.find(audio_codec.pltype);
const auto 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)) {
if (PayloadIsCompatible(it->second, audio_format)) {
it->second.typeSpecific.audio_payload().rate = 0;
return 0;
}
LOG(LS_ERROR) << "Payload type already registered: " << audio_codec.pltype;
LOG(LS_ERROR) << "Payload type already registered: " << payload_type;
return -1;
}
// Audio codecs must be unique.
DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec);
DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_format);
const auto insert_status = payload_type_map_.emplace(
audio_codec.pltype, CreatePayloadType(audio_codec));
const auto insert_status =
payload_type_map_.emplace(payload_type, CreatePayloadType(audio_format));
RTC_DCHECK(insert_status.second); // Insertion succeeded.
*created_new_payload = true;
@ -222,10 +216,10 @@ 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) {
const SdpAudioFormat& audio_format) {
for (auto iterator = payload_type_map_.begin();
iterator != payload_type_map_.end(); ++iterator) {
if (PayloadIsCompatible(iterator->second, audio_codec)) {
if (PayloadIsCompatible(iterator->second, audio_format)) {
// Remove old setting.
payload_type_map_.erase(iterator);
break;
@ -233,13 +227,14 @@ void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
}
}
int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec,
int8_t* payload_type) const {
int32_t RTPPayloadRegistry::ReceivePayloadType(
const SdpAudioFormat& audio_format,
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)) {
if (PayloadIsCompatible(it.second, audio_format)) {
*payload_type = it.first;
return 0;
}
@ -308,7 +303,7 @@ int RTPPayloadRegistry::GetPayloadTypeFrequency(
}
rtc::CritScope cs(&crit_sect_);
return payload->typeSpecific.is_audio()
? payload->typeSpecific.audio_payload().frequency
? payload->typeSpecific.audio_payload().format.clockrate_hz
: kVideoPayloadTypeFrequency;
}

View File

@ -24,13 +24,6 @@ using ::testing::Return;
using ::testing::StrEq;
using ::testing::_;
static const char* kTypicalPayloadName = "name";
static const size_t kTypicalChannels = 1;
static const uint32_t kTypicalFrequency = 44000;
static const CodecInst kTypicalAudioCodec = {-1 /* pltype */, "name",
kTypicalFrequency, 0 /* pacsize */,
kTypicalChannels};
TEST(RtpPayloadRegistryTest,
RegistersAndRemembersVideoPayloadsUntilDeregistered) {
RTPPayloadRegistry rtp_payload_registry;
@ -60,12 +53,11 @@ TEST(RtpPayloadRegistryTest,
TEST(RtpPayloadRegistryTest,
RegistersAndRemembersAudioPayloadsUntilDeregistered) {
RTPPayloadRegistry rtp_payload_registry;
uint8_t payload_type = 97;
constexpr int payload_type = 97;
const SdpAudioFormat audio_format("name", 44000, 1);
bool new_payload_created = false;
CodecInst audio_codec = kTypicalAudioCodec;
audio_codec.pltype = payload_type;
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
audio_codec, &new_payload_created));
payload_type, audio_format, &new_payload_created));
EXPECT_TRUE(new_payload_created) << "A new payload WAS created.";
@ -74,12 +66,10 @@ TEST(RtpPayloadRegistryTest,
EXPECT_TRUE(retrieved_payload);
// We should get back the corresponding payload that we registered.
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload->name);
EXPECT_STREQ("name", retrieved_payload->name);
EXPECT_TRUE(retrieved_payload->typeSpecific.is_audio());
EXPECT_EQ(kTypicalFrequency,
retrieved_payload->typeSpecific.audio_payload().frequency);
EXPECT_EQ(kTypicalChannels,
retrieved_payload->typeSpecific.audio_payload().channels);
EXPECT_EQ(audio_format,
retrieved_payload->typeSpecific.audio_payload().format);
// Now forget about it and verify it's gone.
EXPECT_EQ(0, rtp_payload_registry.DeRegisterReceivePayload(payload_type));
@ -87,103 +77,77 @@ TEST(RtpPayloadRegistryTest,
}
TEST(RtpPayloadRegistryTest, AudioRedWorkProperly) {
const uint8_t kRedPayloadType = 127;
const int kRedSampleRate = 8000;
const size_t kRedChannels = 1;
RTPPayloadRegistry rtp_payload_registry;
bool new_payload_created = false;
CodecInst red_audio_codec;
strncpy(red_audio_codec.plname, "red", RTP_PAYLOAD_NAME_SIZE);
red_audio_codec.pltype = kRedPayloadType;
red_audio_codec.plfreq = kRedSampleRate;
red_audio_codec.channels = kRedChannels;
const SdpAudioFormat red_format("red", 8000, 1);
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
red_audio_codec, &new_payload_created));
127, red_format, &new_payload_created));
EXPECT_TRUE(new_payload_created);
EXPECT_EQ(kRedPayloadType, rtp_payload_registry.red_payload_type());
EXPECT_EQ(127, rtp_payload_registry.red_payload_type());
const auto retrieved_payload =
rtp_payload_registry.PayloadTypeToPayload(kRedPayloadType);
const auto retrieved_payload = rtp_payload_registry.PayloadTypeToPayload(127);
EXPECT_TRUE(retrieved_payload);
EXPECT_TRUE(retrieved_payload->typeSpecific.is_audio());
EXPECT_STRCASEEQ("red", retrieved_payload->name);
// Sample rate is correctly registered.
EXPECT_EQ(kRedSampleRate,
rtp_payload_registry.GetPayloadTypeFrequency(kRedPayloadType));
EXPECT_EQ(red_format, retrieved_payload->typeSpecific.audio_payload().format);
}
TEST(RtpPayloadRegistryTest,
DoesNotAcceptSamePayloadTypeTwiceExceptIfPayloadIsCompatible) {
uint8_t payload_type = 97;
constexpr int payload_type = 97;
RTPPayloadRegistry rtp_payload_registry;
bool ignored = false;
CodecInst audio_codec = kTypicalAudioCodec;
audio_codec.pltype = payload_type;
EXPECT_EQ(0,
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
const SdpAudioFormat audio_format("name", 44000, 1);
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format, &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))
const SdpAudioFormat audio_format_2("name", 44001, 1); // Not compatible.
EXPECT_EQ(-1, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format_2, &ignored))
<< "Adding incompatible codec with same payload type = bad.";
// Change payload type.
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(
payload_type - 1, audio_format_2, &ignored))
<< "With a different payload type is fine though.";
// Ensure both payloads are preserved.
const auto retrieved_payload1 =
rtp_payload_registry.PayloadTypeToPayload(payload_type);
EXPECT_TRUE(retrieved_payload1);
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload1->name);
EXPECT_STREQ("name", retrieved_payload1->name);
EXPECT_TRUE(retrieved_payload1->typeSpecific.is_audio());
EXPECT_EQ(kTypicalFrequency,
retrieved_payload1->typeSpecific.audio_payload().frequency);
EXPECT_EQ(kTypicalChannels,
retrieved_payload1->typeSpecific.audio_payload().channels);
EXPECT_EQ(audio_format,
retrieved_payload1->typeSpecific.audio_payload().format);
const auto retrieved_payload2 =
rtp_payload_registry.PayloadTypeToPayload(payload_type - 1);
EXPECT_TRUE(retrieved_payload2);
EXPECT_STREQ(kTypicalPayloadName, retrieved_payload2->name);
EXPECT_STREQ("name", retrieved_payload2->name);
EXPECT_TRUE(retrieved_payload2->typeSpecific.is_audio());
EXPECT_EQ(kTypicalFrequency + 1,
retrieved_payload2->typeSpecific.audio_payload().frequency);
EXPECT_EQ(kTypicalChannels,
retrieved_payload2->typeSpecific.audio_payload().channels);
EXPECT_EQ(audio_format_2,
retrieved_payload2->typeSpecific.audio_payload().format);
// 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));
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format, &ignored));
}
TEST(RtpPayloadRegistryTest,
RemovesCompatibleCodecsOnRegistryIfCodecsMustBeUnique) {
uint8_t payload_type = 97;
constexpr int payload_type = 97;
RTPPayloadRegistry rtp_payload_registry;
bool ignored = false;
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 - 1;
EXPECT_EQ(
0, rtp_payload_registry.RegisterReceivePayload(audio_codec_2, &ignored));
const SdpAudioFormat audio_format("name", 44000, 1);
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format, &ignored));
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type - 1, audio_format, &ignored));
EXPECT_FALSE(rtp_payload_registry.PayloadTypeToPayload(payload_type))
<< "The first payload should be "
@ -191,13 +155,11 @@ TEST(RtpPayloadRegistryTest,
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|
// Now ensure non-compatible codecs aren't removed. Make |audio_format_2|
// incompatible by changing the frequency.
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));
const SdpAudioFormat audio_format_2("name", 44001, 1);
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type + 1, audio_format_2, &ignored));
EXPECT_TRUE(rtp_payload_registry.PayloadTypeToPayload(payload_type - 1))
<< "Not compatible; both payloads should be kept.";
@ -217,10 +179,10 @@ TEST(RtpPayloadRegistryTest,
EXPECT_TRUE(media_type_unchanged);
bool ignored;
CodecInst audio_codec = kTypicalAudioCodec;
audio_codec.pltype = 34;
EXPECT_EQ(0,
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
constexpr int payload_type = 34;
const SdpAudioFormat audio_format("name", 44000, 1);
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format, &ignored));
EXPECT_EQ(-1, rtp_payload_registry.last_received_payload_type());
media_type_unchanged = rtp_payload_registry.ReportMediaPayloadType(18);
@ -235,13 +197,10 @@ TEST_P(ParameterizedRtpPayloadRegistryTest,
RTPPayloadRegistry rtp_payload_registry;
bool ignored;
CodecInst audio_codec;
strncpy(audio_codec.plname, "whatever", RTP_PAYLOAD_NAME_SIZE);
audio_codec.pltype = GetParam();
audio_codec.plfreq = 1900;
audio_codec.channels = 1;
EXPECT_EQ(-1,
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
const int payload_type = GetParam();
const SdpAudioFormat audio_format("whatever", 1900, 1);
EXPECT_EQ(-1, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format, &ignored));
}
INSTANTIATE_TEST_CASE_P(TestKnownBadPayloadTypes,
@ -254,14 +213,10 @@ 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.channels = 1;
EXPECT_EQ(0,
rtp_payload_registry.RegisterReceivePayload(audio_codec, &ignored));
const int payload_type = GetParam();
const SdpAudioFormat audio_format("generic-codec", 1900, 1); // Dummy values.
EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
payload_type, audio_format, &ignored));
}
INSTANTIATE_TEST_CASE_P(TestDynamicRange,

View File

@ -35,7 +35,6 @@ RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback)
cng_fb_payload_type_(-1),
num_energy_(0),
current_remote_energy_() {
last_payload_.emplace(AudioPayload{0, 1, 0});
memset(current_remote_energy_, 0, sizeof(current_remote_energy_));
}
@ -104,22 +103,24 @@ bool RTPReceiverAudio::ShouldReportCsrcChanges(uint8_t payload_type) const {
// -
// - G7221 frame N/A
int32_t RTPReceiverAudio::OnNewPayloadTypeCreated(
const CodecInst& audio_codec) {
int payload_type,
const SdpAudioFormat& audio_format) {
rtc::CritScope lock(&crit_sect_);
if (RtpUtility::StringCompare(audio_codec.plname, "telephone-event", 15)) {
telephone_event_payload_type_ = audio_codec.pltype;
if (RtpUtility::StringCompare(audio_format.name.c_str(), "telephone-event",
15)) {
telephone_event_payload_type_ = payload_type;
}
if (RtpUtility::StringCompare(audio_codec.plname, "cn", 2)) {
if (RtpUtility::StringCompare(audio_format.name.c_str(), "cn", 2)) {
// We support comfort noise at four different frequencies.
if (audio_codec.plfreq == 8000) {
cng_nb_payload_type_ = audio_codec.pltype;
} else if (audio_codec.plfreq == 16000) {
cng_wb_payload_type_ = audio_codec.pltype;
} else if (audio_codec.plfreq == 32000) {
cng_swb_payload_type_ = audio_codec.pltype;
} else if (audio_codec.plfreq == 48000) {
cng_fb_payload_type_ = audio_codec.pltype;
if (audio_format.clockrate_hz == 8000) {
cng_nb_payload_type_ = payload_type;
} else if (audio_format.clockrate_hz == 16000) {
cng_wb_payload_type_ = payload_type;
} else if (audio_format.clockrate_hz == 32000) {
cng_swb_payload_type_ = payload_type;
} else if (audio_format.clockrate_hz == 48000) {
cng_fb_payload_type_ = payload_type;
} else {
assert(false);
return -1;
@ -191,8 +192,7 @@ int32_t RTPReceiverAudio::InvokeOnInitializeDecoder(
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
const PayloadUnion& specific_payload) const {
const auto& ap = specific_payload.audio_payload();
if (callback->OnInitializeDecoder(payload_type, payload_name, ap.frequency,
ap.channels, ap.rate) == -1) {
if (callback->OnInitializeDecoder(payload_type, ap.format, ap.rate) == -1) {
LOG(LS_ERROR) << "Failed to create decoder for payload type: "
<< payload_name << "/" << static_cast<int>(payload_type);
return -1;
@ -301,7 +301,7 @@ int32_t RTPReceiverAudio::ParseAudioCodecSpecific(
payload_data + 1, payload_data_length - 1, rtp_header);
}
rtp_header->type.Audio.channel = audio_specific.channels;
rtp_header->type.Audio.channel = audio_specific.format.num_channels;
return data_callback_->OnReceivedPayloadData(payload_data,
payload_data_length, rtp_header);
}

View File

@ -55,7 +55,8 @@ class RTPReceiverAudio : public RTPReceiverStrategy,
bool ShouldReportCsrcChanges(uint8_t payload_type) const override;
int32_t OnNewPayloadTypeCreated(const CodecInst& audio_codec) override;
int32_t OnNewPayloadTypeCreated(int payload_type,
const SdpAudioFormat& audio_format) override;
int32_t InvokeOnInitializeDecoder(
RtpFeedback* callback,

View File

@ -19,6 +19,7 @@
#include <vector>
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/codecs/audio_format_conversion.h"
#include "modules/rtp_rtcp/include/rtp_payload_registry.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
@ -57,6 +58,11 @@ RtpReceiver* RtpReceiver::CreateAudioReceiver(
RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback));
}
int32_t RtpReceiver::RegisterReceivePayload(const CodecInst& audio_codec) {
return RegisterReceivePayload(audio_codec.pltype,
CodecInstToSdp(audio_codec));
}
RtpReceiverImpl::RtpReceiverImpl(Clock* clock,
RtpFeedback* incoming_messages_callback,
RTPPayloadRegistry* rtp_payload_registry,
@ -81,7 +87,9 @@ RtpReceiverImpl::~RtpReceiverImpl() {
}
}
int32_t RtpReceiverImpl::RegisterReceivePayload(const CodecInst& audio_codec) {
int32_t RtpReceiverImpl::RegisterReceivePayload(
int payload_type,
const SdpAudioFormat& audio_format) {
rtc::CritScope lock(&critical_section_rtp_receiver_);
// TODO(phoglund): Try to streamline handling of the RED codec and some other
@ -89,11 +97,12 @@ int32_t RtpReceiverImpl::RegisterReceivePayload(const CodecInst& audio_codec) {
// payload or not.
bool created_new_payload = false;
int32_t result = rtp_payload_registry_->RegisterReceivePayload(
audio_codec, &created_new_payload);
payload_type, audio_format, &created_new_payload);
if (created_new_payload) {
if (rtp_media_receiver_->OnNewPayloadTypeCreated(audio_codec) != 0) {
LOG(LS_ERROR) << "Failed to register payload: " << audio_codec.plname
<< "/" << static_cast<int>(audio_codec.pltype);
if (rtp_media_receiver_->OnNewPayloadTypeCreated(payload_type,
audio_format) != 0) {
LOG(LS_ERROR) << "Failed to register payload: " << audio_format.name
<< "/" << payload_type;
return -1;
}
}
@ -240,10 +249,7 @@ bool RtpReceiverImpl::GetLatestTimestamps(uint32_t* timestamp,
// Implementation note: must not hold critsect when called.
void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) {
bool new_ssrc = false;
bool re_initialize_decoder = false;
char payload_name[RTP_PAYLOAD_NAME_SIZE];
size_t channels = 1;
uint32_t rate = 0;
rtc::Optional<AudioPayload> reinitialize_audio_payload;
{
rtc::CritScope lock(&critical_section_rtp_receiver_);
@ -262,18 +268,16 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) {
if (ssrc_ != 0) {
// Do we have the same codec? Then re-initialize coder.
if (rtp_header.payloadType == last_received_payload_type) {
re_initialize_decoder = true;
const auto payload = rtp_payload_registry_->PayloadTypeToPayload(
rtp_header.payloadType);
if (!payload) {
return;
}
payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
if (payload->typeSpecific.is_audio()) {
channels = payload->typeSpecific.audio_payload().channels;
rate = payload->typeSpecific.audio_payload().rate;
reinitialize_audio_payload.emplace(
payload->typeSpecific.audio_payload());
} else {
// OnInitializeDecoder() is only used for audio.
}
}
}
@ -287,11 +291,10 @@ void RtpReceiverImpl::CheckSSRCChanged(const RTPHeader& rtp_header) {
cb_rtp_feedback_->OnIncomingSSRCChanged(rtp_header.ssrc);
}
if (re_initialize_decoder) {
if (-1 ==
cb_rtp_feedback_->OnInitializeDecoder(
rtp_header.payloadType, payload_name,
rtp_header.payload_type_frequency, channels, rate)) {
if (reinitialize_audio_payload) {
if (-1 == cb_rtp_feedback_->OnInitializeDecoder(
rtp_header.payloadType, reinitialize_audio_payload->format,
reinitialize_audio_payload->rate)) {
// New stream, same codec.
LOG(LS_ERROR) << "Failed to create decoder for payload type: "
<< static_cast<int>(rtp_header.payloadType);

View File

@ -36,7 +36,8 @@ class RtpReceiverImpl : public RtpReceiver {
virtual ~RtpReceiverImpl();
int32_t RegisterReceivePayload(const CodecInst& audio_codec) override;
int32_t RegisterReceivePayload(int payload_type,
const SdpAudioFormat& audio_format) override;
int32_t RegisterReceivePayload(const VideoCodec& video_codec) override;
int32_t DeRegisterReceivePayload(const int8_t payload_type) override;

View File

@ -56,7 +56,9 @@ class RTPReceiverStrategy {
// Notifies the strategy that we have created a new non-RED audio payload type
// in the payload registry.
virtual int32_t OnNewPayloadTypeCreated(const CodecInst& audio_codec) = 0;
virtual int32_t OnNewPayloadTypeCreated(
int payload_type,
const SdpAudioFormat& audio_format) = 0;
// Invokes the OnInitializeDecoder callback in a media-specific way.
virtual int32_t InvokeOnInitializeDecoder(

View File

@ -51,12 +51,8 @@ class RtpReceiverTest : public ::testing::Test {
&mock_rtp_data_,
nullptr,
&rtp_payload_registry_)) {
CodecInst voice_codec = {};
voice_codec.pltype = kPcmuPayloadType;
voice_codec.plfreq = 8000;
voice_codec.rate = kTestRate;
memcpy(voice_codec.plname, "PCMU", 5);
rtp_receiver_->RegisterReceivePayload(voice_codec);
rtp_receiver_->RegisterReceivePayload(kPcmuPayloadType,
SdpAudioFormat("PCMU", 8000, 1));
}
~RtpReceiverTest() {}
@ -90,7 +86,8 @@ TEST_F(RtpReceiverTest, GetSources) {
header.numCSRCs = 2;
header.arrOfCSRCs[0] = kCsrc1;
header.arrOfCSRCs[1] = kCsrc2;
const PayloadUnion payload_specific{AudioPayload()};
const PayloadUnion payload_specific{
AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
@ -140,7 +137,8 @@ TEST_F(RtpReceiverTest, GetSourcesChangeSSRC) {
header.payloadType = kPcmuPayloadType;
header.ssrc = kSsrc1;
header.timestamp = rtp_timestamp(now_ms);
const PayloadUnion payload_specific{AudioPayload()};
const PayloadUnion payload_specific{
AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
@ -191,7 +189,8 @@ TEST_F(RtpReceiverTest, GetSourcesRemoveOutdatedSource) {
RTPHeader header;
header.payloadType = kPcmuPayloadType;
header.timestamp = rtp_timestamp(now_ms);
const PayloadUnion payload_specific{AudioPayload()};
const PayloadUnion payload_specific{
AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
header.numCSRCs = 1;
size_t kSourceListSize = 20;
@ -265,7 +264,8 @@ TEST_F(RtpReceiverTest, GetSourcesContainsAudioLevelExtension) {
header.timestamp = rtp_timestamp(time1_ms);
header.extension.hasAudioLevel = true;
header.extension.audioLevel = 10;
const PayloadUnion payload_specific{AudioPayload()};
const PayloadUnion payload_specific{
AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
@ -317,7 +317,8 @@ TEST_F(RtpReceiverTest,
header.timestamp = rtp_timestamp(time1_ms);
header.extension.hasAudioLevel = true;
header.extension.audioLevel = 10;
const PayloadUnion payload_specific{AudioPayload()};
const PayloadUnion payload_specific{
AudioPayload{SdpAudioFormat("foo", 8000, 1), 0}};
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));

View File

@ -44,7 +44,8 @@ bool RTPReceiverVideo::ShouldReportCsrcChanges(uint8_t payload_type) const {
}
int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
const CodecInst& audio_codec) {
int payload_type,
const SdpAudioFormat& audio_format) {
RTC_NOTREACHED();
return 0;
}

View File

@ -38,7 +38,8 @@ class RTPReceiverVideo : public RTPReceiverStrategy {
bool ShouldReportCsrcChanges(uint8_t payload_type) const override;
int32_t OnNewPayloadTypeCreated(const CodecInst& audio_codec) override;
int32_t OnNewPayloadTypeCreated(int payload_type,
const SdpAudioFormat& audio_format) override;
int32_t InvokeOnInitializeDecoder(
RtpFeedback* callback,

View File

@ -241,7 +241,7 @@ int32_t RTPSender::RegisterPayload(
payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1)) {
if (audio_configured_ && payload->typeSpecific.is_audio()) {
auto& p = payload->typeSpecific.audio_payload();
if (p.frequency == frequency &&
if (rtc::SafeEq(p.format.clockrate_hz, frequency) &&
(p.rate == rate || p.rate == 0 || rate == 0)) {
p.rate = rate;
// Ensure that we update the rate if new or old is zero.

View File

@ -66,7 +66,9 @@ int32_t RTPSenderAudio::RegisterAudioPayload(
return 0;
}
*payload = new RtpUtility::Payload(
payloadName, PayloadUnion(AudioPayload{frequency, channels, rate}));
payloadName,
PayloadUnion(AudioPayload{
SdpAudioFormat(payloadName, frequency, channels), rate}));
return 0;
}

View File

@ -13,6 +13,7 @@
#include <vector>
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/codecs/audio_format_conversion.h"
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_receiver_audio.h"
@ -70,10 +71,8 @@ class VerifyingAudioReceiver : public RtpData {
class RTPCallback : public NullRtpFeedback {
public:
int32_t OnInitializeDecoder(int8_t payloadType,
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
int32_t OnInitializeDecoder(int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) override {
EXPECT_EQ(0u, rate) << "The rate should be zero";
return 0;
@ -129,9 +128,11 @@ class RtpRtcpAudioTest : public ::testing::Test {
void RegisterPayload(const CodecInst& codec) {
EXPECT_EQ(0, module1->RegisterSendPayload(codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(codec.pltype,
CodecInstToSdp(codec)));
EXPECT_EQ(0, module2->RegisterSendPayload(codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(codec.pltype,
CodecInstToSdp(codec)));
}
VerifyingAudioReceiver data_receiver1;
@ -210,7 +211,8 @@ TEST_F(RtpRtcpAudioTest, DTMF) {
memcpy(voice_codec.plname, "telephone-event", 16);
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(voice_codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.pltype, CodecInstToSdp(voice_codec)));
// Start DTMF test.
int timeStamp = 160;

View File

@ -13,6 +13,7 @@
#include <vector>
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/codecs/audio_format_conversion.h"
#include "modules/rtp_rtcp/include/receive_statistics.h"
#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@ -133,9 +134,11 @@ class RtpRtcpRtcpTest : public ::testing::Test {
memcpy(voice_codec.plname, "PCMU", 5);
EXPECT_EQ(0, module1->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(voice_codec));
EXPECT_EQ(0, rtp_receiver1_->RegisterReceivePayload(
voice_codec.pltype, CodecInstToSdp(voice_codec)));
EXPECT_EQ(0, module2->RegisterSendPayload(voice_codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(voice_codec));
EXPECT_EQ(0, rtp_receiver2_->RegisterReceivePayload(
voice_codec.pltype, CodecInstToSdp(voice_codec)));
// We need to send one RTP packet to get the RTCP packet to be accepted by
// the receiving module.

View File

@ -287,10 +287,8 @@ void RtpVideoStreamReceiver::OnRecoveredPacket(const uint8_t* rtp_packet,
// TODO(pbos): Remove as soon as audio can handle a changing payload type
// without this callback.
int32_t RtpVideoStreamReceiver::OnInitializeDecoder(
const int8_t payload_type,
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
const int frequency,
const size_t channels,
const int payload_type,
const SdpAudioFormat& audio_format,
const uint32_t rate) {
RTC_NOTREACHED();
return 0;

View File

@ -112,10 +112,8 @@ class RtpVideoStreamReceiver : public RtpData,
void OnRecoveredPacket(const uint8_t* packet, size_t packet_length) override;
// Implements RtpFeedback.
int32_t OnInitializeDecoder(int8_t payload_type,
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
int32_t OnInitializeDecoder(int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) override;
void OnIncomingSSRCChanged(uint32_t ssrc) override {}
void OnIncomingCSRCChanged(uint32_t CSRC, bool added) override {}

View File

@ -542,30 +542,12 @@ void Channel::OnIncomingCSRCChanged(uint32_t CSRC, bool added) {
// TODO(saza): remove.
}
int32_t Channel::OnInitializeDecoder(
int8_t payloadType,
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
uint32_t rate) {
CodecInst receiveCodec = {0};
CodecInst dummyCodec = {0};
receiveCodec.pltype = payloadType;
receiveCodec.plfreq = frequency;
receiveCodec.channels = channels;
receiveCodec.rate = rate;
strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
receiveCodec.pacsize = dummyCodec.pacsize;
// Register the new codec to the ACM
if (!audio_coding_->RegisterReceiveCodec(receiveCodec.pltype,
CodecInstToSdp(receiveCodec))) {
int32_t Channel::OnInitializeDecoder(int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) {
if (!audio_coding_->RegisterReceiveCodec(payload_type, audio_format)) {
LOG(LS_WARNING) << "Channel::OnInitializeDecoder() invalid codec (pt="
<< payloadType << ", name=" << payloadName
<< ") received - 1";
<< payload_type << ", " << audio_format << ") received -1";
return -1;
}
@ -1742,17 +1724,20 @@ void Channel::UpdatePlayoutTimestamp(bool rtcp) {
}
void Channel::RegisterReceiveCodecsToRTPModule() {
CodecInst codec;
const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
// TODO(kwiberg): Iterate over the factory's supported codecs instead?
const int nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
for (int idx = 0; idx < nSupportedCodecs; idx++) {
// Open up the RTP/RTCP receiver for all supported codecs
if ((audio_coding_->Codec(idx, &codec) == -1) ||
(rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
LOG(LS_WARNING) << "Channel::RegisterReceiveCodecsToRTPModule() unable"
<< " to register " << codec.plname << " (" << codec.pltype
<< "/" << codec.plfreq << "/" << codec.channels << "/"
<< codec.rate << ") to RTP/RTCP receiver";
CodecInst codec;
if (audio_coding_->Codec(idx, &codec) == -1) {
LOG(LS_WARNING) << "Unable to register codec #" << idx
<< " for RTP/RTCP receiver.";
continue;
}
const SdpAudioFormat format = CodecInstToSdp(codec);
if (!decoder_factory_->IsSupportedDecoder(format) ||
rtp_receiver_->RegisterReceivePayload(codec.pltype, format) == -1) {
LOG(LS_WARNING) << "Unable to register " << format
<< " for RTP/RTCP receiver.";
}
}
}

View File

@ -257,10 +257,8 @@ class Channel
const WebRtcRTPHeader* rtpHeader) override;
// From RtpFeedback in the RTP/RTCP module
int32_t OnInitializeDecoder(int8_t payloadType,
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
int frequency,
size_t channels,
int32_t OnInitializeDecoder(int payload_type,
const SdpAudioFormat& audio_format,
uint32_t rate) override;
void OnIncomingSSRCChanged(uint32_t ssrc) override;
void OnIncomingCSRCChanged(uint32_t CSRC, bool added) override;