Eliminated need for video receiver to talk to its parent. Also we will now determine if the packet is the first one already in the rtp general receiver. The possible downside would be that recovered video packets no longer can be flagged as the first packet, but I don't think that can happen. Even if it can happen, maybe the bit was set anyway at an earlier stage. The tests run fine. BUG= TEST=rtp_rtcp_unittests, vie_auto_test, voe_auto_test Review URL: https://webrtc-codereview.appspot.com/1022011 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3382 4adac7df-926f-26a2-2b94-8c16560cd09d
266 lines
8.1 KiB
C++
266 lines
8.1 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#include "webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h"
|
|
|
|
#include "webrtc/system_wrappers/interface/trace.h"
|
|
|
|
namespace webrtc {
|
|
|
|
RTPPayloadRegistry::RTPPayloadRegistry(
|
|
const WebRtc_Word32 id)
|
|
: id_(id),
|
|
rtp_media_receiver_(NULL),
|
|
red_payload_type_(-1),
|
|
last_received_payload_type_(-1),
|
|
last_received_media_payload_type_(-1) {
|
|
}
|
|
|
|
RTPPayloadRegistry::~RTPPayloadRegistry() {
|
|
while (!payload_type_map_.empty()) {
|
|
ModuleRTPUtility::PayloadTypeMap::iterator it = payload_type_map_.begin();
|
|
delete it->second;
|
|
payload_type_map_.erase(it);
|
|
}
|
|
}
|
|
|
|
WebRtc_Word32 RTPPayloadRegistry::RegisterReceivePayload(
|
|
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
|
const WebRtc_Word8 payload_type,
|
|
const WebRtc_UWord32 frequency,
|
|
const WebRtc_UWord8 channels,
|
|
const WebRtc_UWord32 rate) {
|
|
assert(rtp_media_receiver_);
|
|
assert(payload_name);
|
|
|
|
// Sanity check.
|
|
switch (payload_type) {
|
|
// Reserved payload types to avoid RTCP conflicts when marker bit is set.
|
|
case 64: // 192 Full INTRA-frame request.
|
|
case 72: // 200 Sender report.
|
|
case 73: // 201 Receiver report.
|
|
case 74: // 202 Source description.
|
|
case 75: // 203 Goodbye.
|
|
case 76: // 204 Application-defined.
|
|
case 77: // 205 Transport layer FB message.
|
|
case 78: // 206 Payload-specific FB message.
|
|
case 79: // 207 Extended report.
|
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
|
|
"%s invalid payloadtype:%d",
|
|
__FUNCTION__, payload_type);
|
|
return -1;
|
|
default:
|
|
break;
|
|
}
|
|
size_t payload_name_length = strlen(payload_name);
|
|
|
|
ModuleRTPUtility::PayloadTypeMap::iterator it =
|
|
payload_type_map_.find(payload_type);
|
|
|
|
if (it != payload_type_map_.end()) {
|
|
// We already use this payload type.
|
|
ModuleRTPUtility::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 &&
|
|
ModuleRTPUtility::StringCompare(
|
|
payload->name, payload_name, payload_name_length)) {
|
|
if (rtp_media_receiver_->PayloadIsCompatible(*payload, frequency,
|
|
channels, rate)) {
|
|
rtp_media_receiver_->UpdatePayloadRate(payload, rate);
|
|
return 0;
|
|
}
|
|
}
|
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
|
|
"%s invalid argument payload_type:%d already registered",
|
|
__FUNCTION__, payload_type);
|
|
return -1;
|
|
}
|
|
|
|
rtp_media_receiver_->PossiblyRemoveExistingPayloadType(
|
|
&payload_type_map_, payload_name, payload_name_length, frequency, channels,
|
|
rate);
|
|
|
|
ModuleRTPUtility::Payload* payload = NULL;
|
|
|
|
// Save the RED payload type. Used in both audio and video.
|
|
if (ModuleRTPUtility::StringCompare(payload_name, "red", 3)) {
|
|
red_payload_type_ = payload_type;
|
|
payload = new ModuleRTPUtility::Payload;
|
|
payload->audio = false;
|
|
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
|
strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
|
|
} else {
|
|
payload = rtp_media_receiver_->CreatePayloadType(
|
|
payload_name, payload_type, frequency, channels, rate);
|
|
}
|
|
if (payload == NULL) {
|
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
|
|
"%s failed to register payload",
|
|
__FUNCTION__);
|
|
return -1;
|
|
}
|
|
payload_type_map_[payload_type] = payload;
|
|
|
|
// 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;
|
|
}
|
|
|
|
WebRtc_Word32 RTPPayloadRegistry::DeRegisterReceivePayload(
|
|
const WebRtc_Word8 payload_type) {
|
|
assert(rtp_media_receiver_);
|
|
ModuleRTPUtility::PayloadTypeMap::iterator it =
|
|
payload_type_map_.find(payload_type);
|
|
|
|
if (it == payload_type_map_.end()) {
|
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
|
|
"%s failed to find payload_type:%d",
|
|
__FUNCTION__, payload_type);
|
|
return -1;
|
|
}
|
|
delete it->second;
|
|
payload_type_map_.erase(it);
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_Word32 RTPPayloadRegistry::ReceivePayloadType(
|
|
const char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
|
const WebRtc_UWord32 frequency,
|
|
const WebRtc_UWord8 channels,
|
|
const WebRtc_UWord32 rate,
|
|
WebRtc_Word8* payload_type) const {
|
|
if (payload_type == NULL) {
|
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, id_,
|
|
"%s invalid argument", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
size_t payload_name_length = strlen(payload_name);
|
|
|
|
ModuleRTPUtility::PayloadTypeMap::const_iterator it =
|
|
payload_type_map_.begin();
|
|
|
|
while (it != payload_type_map_.end()) {
|
|
ModuleRTPUtility::Payload* payload = it->second;
|
|
assert(payload);
|
|
|
|
size_t name_length = strlen(payload->name);
|
|
if (payload_name_length == name_length &&
|
|
ModuleRTPUtility::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;
|
|
}
|
|
}
|
|
it++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32 RTPPayloadRegistry::ReceivePayload(
|
|
const WebRtc_Word8 payload_type,
|
|
char payload_name[RTP_PAYLOAD_NAME_SIZE],
|
|
WebRtc_UWord32* frequency,
|
|
WebRtc_UWord8* channels,
|
|
WebRtc_UWord32* rate) const {
|
|
assert(rtp_media_receiver_);
|
|
ModuleRTPUtility::PayloadTypeMap::const_iterator it =
|
|
payload_type_map_.find(payload_type);
|
|
|
|
if (it == payload_type_map_.end()) {
|
|
return -1;
|
|
}
|
|
ModuleRTPUtility::Payload* payload = it->second;
|
|
assert(payload);
|
|
|
|
if (frequency) {
|
|
if (payload->audio) {
|
|
*frequency = payload->typeSpecific.Audio.frequency;
|
|
} else {
|
|
*frequency = kDefaultVideoFrequency;
|
|
}
|
|
}
|
|
if (channels) {
|
|
if (payload->audio) {
|
|
*channels = payload->typeSpecific.Audio.channels;
|
|
} else {
|
|
*channels = 1;
|
|
}
|
|
}
|
|
if (rate) {
|
|
if (payload->audio) {
|
|
*rate = payload->typeSpecific.Audio.rate;
|
|
} else {
|
|
assert(false);
|
|
*rate = 0;
|
|
}
|
|
}
|
|
if (payload_name) {
|
|
payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
|
|
strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_UWord32 RTPPayloadRegistry::PayloadTypeToPayload(
|
|
const WebRtc_UWord8 payload_type,
|
|
ModuleRTPUtility::Payload*& payload) const {
|
|
assert(rtp_media_receiver_);
|
|
|
|
ModuleRTPUtility::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 -1;
|
|
}
|
|
payload = it->second;
|
|
return 0;
|
|
}
|
|
|
|
bool RTPPayloadRegistry::ReportMediaPayloadType(
|
|
WebRtc_UWord8 media_payload_type) {
|
|
if (last_received_media_payload_type_ == media_payload_type) {
|
|
// Media type unchanged.
|
|
return true;
|
|
}
|
|
last_received_media_payload_type_ = media_payload_type;
|
|
return false;
|
|
}
|
|
|
|
} // namespace webrtc
|