| Index: webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
|
| diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
|
| index 7d4afc6e36199f77baa394779aa026be203bb9c1..a4354d393ea99cea9a6a0964a77c962fe8d6ab4b 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
|
| @@ -10,76 +10,55 @@
|
|
|
| #include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
|
|
| -#include <algorithm>
|
| -
|
| -#include "webrtc/base/checks.h"
|
| #include "webrtc/base/logging.h"
|
| -#include "webrtc/base/stringutils.h"
|
| #include "webrtc/common_types.h"
|
| #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
|
|
|
| namespace webrtc {
|
|
|
| -namespace {
|
| -
|
| -bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
| - const CodecInst& audio_codec) {
|
| - if (!payload.audio)
|
| - return false;
|
| - if (_stricmp(payload.name, audio_codec.plname) != 0)
|
| - return false;
|
| - const AudioPayload& audio_payload = payload.typeSpecific.Audio;
|
| - const uint32_t rate = std::max(0, audio_codec.rate);
|
| - return audio_payload.frequency == static_cast<uint32_t>(audio_codec.plfreq) &&
|
| - audio_payload.channels == audio_codec.channels &&
|
| - (audio_payload.rate == rate || audio_payload.rate == 0 || rate == 0);
|
| -}
|
| -
|
| -bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
| - const VideoCodec& video_codec) {
|
| - return !payload.audio && _stricmp(payload.name, video_codec.plName) == 0;
|
| -}
|
| -
|
| -RtpUtility::Payload CreatePayloadType(const CodecInst& audio_codec) {
|
| - RtpUtility::Payload payload;
|
| - payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
| - strncpy(payload.name, audio_codec.plname, RTP_PAYLOAD_NAME_SIZE - 1);
|
| - RTC_DCHECK_GE(audio_codec.plfreq, 1000);
|
| - payload.typeSpecific.Audio.frequency = audio_codec.plfreq;
|
| - payload.typeSpecific.Audio.channels = audio_codec.channels;
|
| - payload.typeSpecific.Audio.rate = std::max(0, audio_codec.rate);
|
| - payload.audio = true;
|
| - return payload;
|
| -}
|
| -
|
| -RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) {
|
| - switch (type) {
|
| - case kVideoCodecVP8:
|
| - return kRtpVideoVp8;
|
| - case kVideoCodecVP9:
|
| - return kRtpVideoVp9;
|
| - case kVideoCodecH264:
|
| - return kRtpVideoH264;
|
| - case kVideoCodecRED:
|
| - case kVideoCodecULPFEC:
|
| - return kRtpVideoNone;
|
| - default:
|
| - return kRtpVideoGeneric;
|
| - }
|
| -}
|
| -
|
| -RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) {
|
| - RtpUtility::Payload payload;
|
| - payload.name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
| - strncpy(payload.name, video_codec.plName, RTP_PAYLOAD_NAME_SIZE - 1);
|
| - payload.typeSpecific.Video.videoCodecType =
|
| - ConvertToRtpVideoCodecType(video_codec.codecType);
|
| - payload.audio = false;
|
| - return payload;
|
| -}
|
| -
|
| -bool IsPayloadTypeValid(int8_t payload_type) {
|
| +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) {}
|
| +
|
| +RTPPayloadRegistry::~RTPPayloadRegistry() {
|
| + while (!payload_type_map_.empty()) {
|
| + RtpUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
|
| + delete it->second;
|
| + payload_type_map_.erase(it);
|
| + }
|
| +}
|
| +
|
| +int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
|
| + bool* created_new_payload) {
|
| + return RegisterReceivePayload(
|
| + audio_codec.plname, audio_codec.pltype, audio_codec.plfreq,
|
| + audio_codec.channels, std::max(0, audio_codec.rate), created_new_payload);
|
| +}
|
| +
|
| +int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
| + const VideoCodec& video_codec) {
|
| + bool dummy_created_new_payload;
|
| + return RegisterReceivePayload(video_codec.plName, video_codec.plType,
|
| + kVideoPayloadTypeFrequency, 0 /* channels */,
|
| + 0 /* rate */, &dummy_created_new_payload);
|
| +}
|
| +
|
| +int32_t RTPPayloadRegistry::RegisterReceivePayload(
|
| + const char* const payload_name,
|
| + const int8_t payload_type,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate,
|
| + bool* created_new_payload) {
|
| assert(payload_type >= 0);
|
| + assert(payload_name);
|
| + *created_new_payload = false;
|
|
|
| // Sanity check.
|
| switch (payload_type) {
|
| @@ -95,48 +74,58 @@
|
| case 79: // 207 Extended report.
|
| LOG(LS_ERROR) << "Can't register invalid receiver payload type: "
|
| << payload_type;
|
| - return false;
|
| + return -1;
|
| default:
|
| - return true;
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -RTPPayloadRegistry::RTPPayloadRegistry()
|
| - : incoming_payload_type_(-1),
|
| - last_received_payload_type_(-1),
|
| - last_received_media_payload_type_(-1),
|
| - rtx_(false),
|
| - ssrc_rtx_(0) {}
|
| -
|
| -RTPPayloadRegistry::~RTPPayloadRegistry() = default;
|
| -
|
| -int32_t RTPPayloadRegistry::RegisterReceivePayload(const CodecInst& audio_codec,
|
| - bool* created_new_payload) {
|
| - *created_new_payload = false;
|
| - if (!IsPayloadTypeValid(audio_codec.pltype))
|
| + break;
|
| + }
|
| +
|
| + size_t payload_name_length = strlen(payload_name);
|
| +
|
| + rtc::CritScope cs(&crit_sect_);
|
| +
|
| + RtpUtility::PayloadTypeMap::iterator it =
|
| + payload_type_map_.find(payload_type);
|
| +
|
| + if (it != payload_type_map_.end()) {
|
| + // We already use this payload type.
|
| + RtpUtility::Payload* payload = it->second;
|
| +
|
| + assert(payload);
|
| +
|
| + size_t name_length = strlen(payload->name);
|
| +
|
| + // Check if it's the same as we already have.
|
| + // If same, ignore sending an error.
|
| + if (payload_name_length == name_length &&
|
| + RtpUtility::StringCompare(
|
| + payload->name, payload_name, payload_name_length)) {
|
| + if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
|
| + channels, rate)) {
|
| + rtp_payload_strategy_->UpdatePayloadRate(payload, rate);
|
| + return 0;
|
| + }
|
| + }
|
| + LOG(LS_ERROR) << "Payload type already registered: "
|
| + << static_cast<int>(payload_type);
|
| return -1;
|
| -
|
| - rtc::CritScope cs(&crit_sect_);
|
| -
|
| - auto it = payload_type_map_.find(audio_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, audio_codec)) {
|
| - it->second.typeSpecific.Audio.rate = std::max(0, audio_codec.rate);
|
| - return 0;
|
| - }
|
| - LOG(LS_ERROR) << "Payload type already registered: " << audio_codec.pltype;
|
| - return -1;
|
| - }
|
| -
|
| - // Audio codecs must be unique.
|
| - DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(audio_codec);
|
| -
|
| - payload_type_map_[audio_codec.pltype] = CreatePayloadType(audio_codec);
|
| + }
|
| +
|
| + if (rtp_payload_strategy_->CodecsMustBeUnique()) {
|
| + DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
| + payload_name, payload_name_length, frequency, channels, rate);
|
| + }
|
| +
|
| + RtpUtility::Payload* payload = rtp_payload_strategy_->CreatePayloadType(
|
| + payload_name, payload_type, frequency, channels, rate);
|
| +
|
| + payload_type_map_[payload_type] = payload;
|
| *created_new_payload = true;
|
| +
|
| + if (RtpUtility::StringCompare(payload_name, "red", 3)) {
|
| + red_payload_type_ = payload_type;
|
| + } else if (RtpUtility::StringCompare(payload_name, "ulpfec", 6)) {
|
| + ulpfec_payload_type_ = payload_type;
|
| + }
|
|
|
| // Successful set of payload type, clear the value of last received payload
|
| // type since it might mean something else.
|
| @@ -145,37 +134,14 @@
|
| 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
|
| - // type since it might mean something else.
|
| - last_received_payload_type_ = -1;
|
| - last_received_media_payload_type_ = -1;
|
| - return 0;
|
| -}
|
| -
|
| int32_t RTPPayloadRegistry::DeRegisterReceivePayload(
|
| const int8_t payload_type) {
|
| rtc::CritScope cs(&crit_sect_);
|
| - payload_type_map_.erase(payload_type);
|
| + RtpUtility::PayloadTypeMap::iterator it =
|
| + payload_type_map_.find(payload_type);
|
| + assert(it != payload_type_map_.end());
|
| + delete it->second;
|
| + payload_type_map_.erase(it);
|
| return 0;
|
| }
|
|
|
| @@ -183,40 +149,95 @@
|
| // for audio codecs, but there can for video.
|
| // Always called from within a critical section.
|
| void RTPPayloadRegistry::DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
| - const CodecInst& audio_codec) {
|
| - for (auto iterator = payload_type_map_.begin();
|
| - iterator != payload_type_map_.end(); ++iterator) {
|
| - if (PayloadIsCompatible(iterator->second, audio_codec)) {
|
| - // Remove old setting.
|
| - payload_type_map_.erase(iterator);
|
| - break;
|
| + const char* const payload_name,
|
| + const size_t payload_name_length,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate) {
|
| + RtpUtility::PayloadTypeMap::iterator iterator = payload_type_map_.begin();
|
| + for (; iterator != payload_type_map_.end(); ++iterator) {
|
| + RtpUtility::Payload* payload = iterator->second;
|
| + size_t name_length = strlen(payload->name);
|
| +
|
| + if (payload_name_length == name_length &&
|
| + RtpUtility::StringCompare(
|
| + payload->name, payload_name, payload_name_length)) {
|
| + // We found the payload name in the list.
|
| + // If audio, check frequency and rate.
|
| + if (payload->audio) {
|
| + if (rtp_payload_strategy_->PayloadIsCompatible(*payload, frequency,
|
| + channels, rate)) {
|
| + // Remove old setting.
|
| + delete payload;
|
| + payload_type_map_.erase(iterator);
|
| + break;
|
| + }
|
| + } else if (RtpUtility::StringCompare(payload_name, "red", 3)) {
|
| + delete payload;
|
| + payload_type_map_.erase(iterator);
|
| + break;
|
| + }
|
| }
|
| }
|
| }
|
|
|
| int32_t RTPPayloadRegistry::ReceivePayloadType(const CodecInst& audio_codec,
|
| int8_t* payload_type) const {
|
| - assert(payload_type);
|
| - rtc::CritScope cs(&crit_sect_);
|
| -
|
| - for (const auto& it : payload_type_map_) {
|
| - if (PayloadIsCompatible(it.second, audio_codec)) {
|
| - *payload_type = it.first;
|
| - return 0;
|
| - }
|
| - }
|
| - return -1;
|
| + return ReceivePayloadType(audio_codec.plname, audio_codec.plfreq,
|
| + audio_codec.channels, std::max(0, audio_codec.rate),
|
| + payload_type);
|
| }
|
|
|
| int32_t RTPPayloadRegistry::ReceivePayloadType(const VideoCodec& video_codec,
|
| int8_t* payload_type) const {
|
| + return ReceivePayloadType(video_codec.plName, kVideoPayloadTypeFrequency,
|
| + 0 /* channels */, 0 /* rate */, payload_type);
|
| +}
|
| +
|
| +int32_t RTPPayloadRegistry::ReceivePayloadType(const char* const payload_name,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate,
|
| + int8_t* payload_type) const {
|
| assert(payload_type);
|
| - rtc::CritScope cs(&crit_sect_);
|
| -
|
| - for (const auto& it : payload_type_map_) {
|
| - if (PayloadIsCompatible(it.second, video_codec)) {
|
| - *payload_type = it.first;
|
| - return 0;
|
| + size_t payload_name_length = strlen(payload_name);
|
| +
|
| + rtc::CritScope cs(&crit_sect_);
|
| +
|
| + RtpUtility::PayloadTypeMap::const_iterator it = payload_type_map_.begin();
|
| +
|
| + for (; it != payload_type_map_.end(); ++it) {
|
| + RtpUtility::Payload* payload = it->second;
|
| + assert(payload);
|
| +
|
| + size_t name_length = strlen(payload->name);
|
| + if (payload_name_length == name_length &&
|
| + RtpUtility::StringCompare(
|
| + payload->name, payload_name, payload_name_length)) {
|
| + // Name matches.
|
| + if (payload->audio) {
|
| + if (rate == 0) {
|
| + // [default] audio, check freq and channels.
|
| + if (payload->typeSpecific.Audio.frequency == frequency &&
|
| + payload->typeSpecific.Audio.channels == channels) {
|
| + *payload_type = it->first;
|
| + return 0;
|
| + }
|
| + } else {
|
| + // Non-default audio, check freq, channels and rate.
|
| + if (payload->typeSpecific.Audio.frequency == frequency &&
|
| + payload->typeSpecific.Audio.channels == channels &&
|
| + payload->typeSpecific.Audio.rate == rate) {
|
| + // extra rate condition added
|
| + *payload_type = it->first;
|
| + return 0;
|
| + }
|
| + }
|
| + } else {
|
| + // Video.
|
| + *payload_type = it->first;
|
| + return 0;
|
| + }
|
| }
|
| }
|
| return -1;
|
| @@ -312,8 +333,7 @@
|
|
|
| bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {
|
| rtc::CritScope cs(&crit_sect_);
|
| - auto it = payload_type_map_.find(header.payloadType);
|
| - return it != payload_type_map_.end() && _stricmp(it->second.name, "red") == 0;
|
| + return red_payload_type_ == header.payloadType;
|
| }
|
|
|
| bool RTPPayloadRegistry::IsEncapsulated(const RTPHeader& header) const {
|
| @@ -323,13 +343,14 @@
|
| bool RTPPayloadRegistry::GetPayloadSpecifics(uint8_t payload_type,
|
| PayloadUnion* payload) const {
|
| rtc::CritScope cs(&crit_sect_);
|
| - auto it = payload_type_map_.find(payload_type);
|
| + RtpUtility::PayloadTypeMap::const_iterator it =
|
| + payload_type_map_.find(payload_type);
|
|
|
| // Check that this is a registered payload type.
|
| if (it == payload_type_map_.end()) {
|
| return false;
|
| }
|
| - *payload = it->second.typeSpecific;
|
| + *payload = it->second->typeSpecific;
|
| return true;
|
| }
|
|
|
| @@ -340,22 +361,22 @@
|
| return -1;
|
| }
|
| rtc::CritScope cs(&crit_sect_);
|
| - return payload->audio ? payload->typeSpecific.Audio.frequency
|
| - : kVideoPayloadTypeFrequency;
|
| + return rtp_payload_strategy_->GetPayloadTypeFrequency(*payload);
|
| }
|
|
|
| const RtpUtility::Payload* RTPPayloadRegistry::PayloadTypeToPayload(
|
| uint8_t payload_type) const {
|
| rtc::CritScope cs(&crit_sect_);
|
|
|
| - auto it = payload_type_map_.find(payload_type);
|
| + RtpUtility::PayloadTypeMap::const_iterator it =
|
| + payload_type_map_.find(payload_type);
|
|
|
| // Check that this is a registered payload type.
|
| if (it == payload_type_map_.end()) {
|
| return nullptr;
|
| }
|
|
|
| - return &it->second;
|
| + return it->second;
|
| }
|
|
|
| void RTPPayloadRegistry::SetIncomingPayloadType(const RTPHeader& header) {
|
| @@ -374,15 +395,106 @@
|
| return false;
|
| }
|
|
|
| -// Returns -1 if a payload with name |payload_name| is not registered.
|
| -int8_t RTPPayloadRegistry::GetPayloadTypeWithName(
|
| - const char* payload_name) const {
|
| - rtc::CritScope cs(&crit_sect_);
|
| - for (const auto& it : payload_type_map_) {
|
| - if (_stricmp(it.second.name, payload_name) == 0)
|
| - return it.first;
|
| - }
|
| - return -1;
|
| +class RTPPayloadAudioStrategy : public RTPPayloadStrategy {
|
| + public:
|
| + bool CodecsMustBeUnique() const override { return true; }
|
| +
|
| + bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate) const override {
|
| + return
|
| + payload.audio &&
|
| + payload.typeSpecific.Audio.frequency == frequency &&
|
| + payload.typeSpecific.Audio.channels == channels &&
|
| + (payload.typeSpecific.Audio.rate == rate ||
|
| + payload.typeSpecific.Audio.rate == 0 || rate == 0);
|
| + }
|
| +
|
| + void UpdatePayloadRate(RtpUtility::Payload* payload,
|
| + const uint32_t rate) const override {
|
| + payload->typeSpecific.Audio.rate = rate;
|
| + }
|
| +
|
| + RtpUtility::Payload* CreatePayloadType(const char* const payloadName,
|
| + const int8_t payloadType,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate) const override {
|
| + RtpUtility::Payload* payload = new RtpUtility::Payload;
|
| + payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
| + strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
|
| + assert(frequency >= 1000);
|
| + payload->typeSpecific.Audio.frequency = frequency;
|
| + payload->typeSpecific.Audio.channels = channels;
|
| + payload->typeSpecific.Audio.rate = rate;
|
| + payload->audio = true;
|
| + return payload;
|
| + }
|
| +
|
| + int GetPayloadTypeFrequency(
|
| + const RtpUtility::Payload& payload) const override {
|
| + return payload.typeSpecific.Audio.frequency;
|
| + }
|
| +};
|
| +
|
| +class RTPPayloadVideoStrategy : public RTPPayloadStrategy {
|
| + public:
|
| + bool CodecsMustBeUnique() const override { return false; }
|
| +
|
| + bool PayloadIsCompatible(const RtpUtility::Payload& payload,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate) const override {
|
| + return !payload.audio;
|
| + }
|
| +
|
| + void UpdatePayloadRate(RtpUtility::Payload* payload,
|
| + const uint32_t rate) const override {}
|
| +
|
| + RtpUtility::Payload* CreatePayloadType(const char* const payloadName,
|
| + const int8_t payloadType,
|
| + const uint32_t frequency,
|
| + const size_t channels,
|
| + const uint32_t rate) const override {
|
| + RtpVideoCodecTypes videoType = kRtpVideoGeneric;
|
| +
|
| + if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
|
| + videoType = kRtpVideoVp8;
|
| + } else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) {
|
| + videoType = kRtpVideoVp9;
|
| + } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
|
| + videoType = kRtpVideoH264;
|
| + } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
|
| + videoType = kRtpVideoGeneric;
|
| + } else if (RtpUtility::StringCompare(payloadName, "ULPFEC", 6) ||
|
| + RtpUtility::StringCompare(payloadName, "RED", 3)) {
|
| + videoType = kRtpVideoNone;
|
| + } else {
|
| + videoType = kRtpVideoGeneric;
|
| + }
|
| + RtpUtility::Payload* payload = new RtpUtility::Payload;
|
| +
|
| + payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
| + strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
|
| + payload->typeSpecific.Video.videoCodecType = videoType;
|
| + payload->audio = false;
|
| + return payload;
|
| + }
|
| +
|
| + int GetPayloadTypeFrequency(
|
| + const RtpUtility::Payload& payload) const override {
|
| + return kVideoPayloadTypeFrequency;
|
| + }
|
| +};
|
| +
|
| +RTPPayloadStrategy* RTPPayloadStrategy::CreateStrategy(
|
| + const bool handling_audio) {
|
| + if (handling_audio) {
|
| + return new RTPPayloadAudioStrategy();
|
| + } else {
|
| + return new RTPPayloadVideoStrategy();
|
| + }
|
| }
|
|
|
| } // namespace webrtc
|
|
|