Extracted rtp receiver payload management to its own class, made video receiver depend on that instead.

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
This commit is contained in:
phoglund@webrtc.org 2013-01-17 16:10:45 +00:00
parent 20ed36dada
commit efae5d5901
10 changed files with 454 additions and 313 deletions

View File

@ -0,0 +1,265 @@
/*
* 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

View File

@ -0,0 +1,88 @@
/*
* 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_RTP_PAYLOAD_REGISTRY_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PAYLOAD_REGISTRY_H_
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
namespace webrtc {
class RTPPayloadRegistry {
public:
explicit RTPPayloadRegistry(const WebRtc_Word32 id);
~RTPPayloadRegistry();
// Must be called before any other methods are used!
// TODO(phoglund): We shouldn't really have to talk to a media receiver here.
// It would make more sense to talk to some media-specific payload handling
// strategy. Can't do that right now because audio payload type handling is
// too tightly coupled with packet parsing.
void set_rtp_media_receiver(RTPReceiverStrategy* rtp_media_receiver) {
rtp_media_receiver_ = rtp_media_receiver;
}
WebRtc_Word32 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);
WebRtc_Word32 DeRegisterReceivePayload(
const WebRtc_Word8 payload_type);
WebRtc_Word32 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;
WebRtc_Word32 ReceivePayload(
const WebRtc_Word8 payload_type,
char payload_name[RTP_PAYLOAD_NAME_SIZE],
WebRtc_UWord32* frequency,
WebRtc_UWord8* channels,
WebRtc_UWord32* rate) const;
WebRtc_UWord32 PayloadTypeToPayload(
const WebRtc_UWord8 payload_type,
ModuleRTPUtility::Payload*& payload) const;
void ResetLastReceivedPayloadTypes() {
last_received_payload_type_ = -1;
last_received_media_payload_type_ = -1;
}
// Returns true if the new media payload type has not changed.
bool ReportMediaPayloadType(WebRtc_UWord8 media_payload_type);
WebRtc_Word8 red_payload_type() const { return red_payload_type_; }
WebRtc_Word8 last_received_payload_type() const {
return last_received_payload_type_;
}
void set_last_received_payload_type(WebRtc_Word8 last_received_payload_type) {
last_received_payload_type_ = last_received_payload_type;
}
private:
ModuleRTPUtility::PayloadTypeMap payload_type_map_;
WebRtc_Word32 id_;
RTPReceiverStrategy* rtp_media_receiver_;
WebRtc_Word8 red_payload_type_;
WebRtc_Word8 last_received_payload_type_;
WebRtc_Word8 last_received_media_payload_type_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PAYLOAD_REGISTRY_H_

View File

@ -39,6 +39,7 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
RtpData* incoming_payload_callback,
RtpFeedback* incoming_messages_callback)
: Bitrate(clock),
rtp_payload_registry_(id),
// TODO(phoglund): Remove hacks requiring direct access to the
// audio receiver and only instantiate one of these directly into the
// rtp_media_receiver_ field. Right now an audio receiver carries around a
@ -46,7 +47,7 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
rtp_receiver_audio_(new RTPReceiverAudio(
id, incoming_payload_callback, incoming_audio_messages_callback)),
rtp_receiver_video_(new RTPReceiverVideo(
id, this, incoming_payload_callback, owner)),
id, &rtp_payload_registry_, incoming_payload_callback, owner)),
id_(id),
rtp_rtcp_(*owner),
cb_rtp_feedback_(incoming_messages_callback),
@ -55,13 +56,9 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
CriticalSectionWrapper::CreateCriticalSection()),
last_receive_time_(0),
last_received_payload_length_(0),
last_received_payload_type_(-1),
last_received_media_payload_type_(-1),
packet_timeout_ms_(0),
red_payload_type_(-1),
payload_type_map_(),
rtp_header_extension_map_(),
ssrc_(0),
num_csrcs_(0),
@ -105,11 +102,15 @@ RTPReceiver::RTPReceiver(const WebRtc_Word32 id,
assert(incoming_audio_messages_callback &&
incoming_messages_callback &&
incoming_payload_callback);
if (audio) {
rtp_media_receiver_ = rtp_receiver_audio_;
rtp_media_receiver_ = rtp_receiver_audio_.get();
} else {
rtp_media_receiver_ = rtp_receiver_video_;
rtp_media_receiver_ = rtp_receiver_video_.get();
}
// TODO(phoglund): Get rid of this silly circular dependency between the
// payload manager and the video RTP receiver.
rtp_payload_registry_.set_rtp_media_receiver(rtp_media_receiver_);
memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_));
memset(current_remote_energy_, 0, sizeof(current_remote_energy_));
@ -123,14 +124,6 @@ RTPReceiver::~RTPReceiver() {
false);
}
delete critical_section_rtp_receiver_;
while (!payload_type_map_.empty()) {
std::map<WebRtc_Word8, Payload*>::iterator it = payload_type_map_.begin();
delete it->second;
payload_type_map_.erase(it);
}
delete rtp_receiver_video_;
delete rtp_receiver_audio_;
WEBRTC_TRACE(kTraceMemory, kTraceRtpRtcp, id_, "%s deleted", __FUNCTION__);
}
@ -147,11 +140,11 @@ WebRtc_UWord32 RTPReceiver::MaxConfiguredBitrate() const {
}
bool RTPReceiver::REDPayloadType(const WebRtc_Word8 payload_type) const {
return (red_payload_type_ == payload_type) ? true : false;
return rtp_payload_registry_.red_payload_type() == payload_type;
}
WebRtc_Word8 RTPReceiver::REDPayloadType() const {
return red_payload_type_;
return rtp_payload_registry_.red_payload_type();
}
WebRtc_Word32 RTPReceiver::SetPacketTimeout(const WebRtc_UWord32 timeout_ms) {
@ -183,8 +176,7 @@ void RTPReceiver::PacketTimeout() {
if (now - last_receive_time_ > packet_timeout_ms_) {
packet_time_out = true;
last_receive_time_ = 0; // Only one callback.
last_received_payload_type_ = -1; // Makes RemotePayload return -1.
last_received_media_payload_type_ = -1;
rtp_payload_registry_.ResetLastReceivedPayloadTypes();
}
}
if (packet_time_out) {
@ -233,104 +225,15 @@ WebRtc_Word32 RTPReceiver::RegisterReceivePayload(
const WebRtc_UWord32 frequency,
const WebRtc_UWord8 channels,
const WebRtc_UWord32 rate) {
assert(payload_name);
CriticalSectionScoped lock(critical_section_rtp_receiver_);
// 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);
std::map<WebRtc_Word8, Payload*>::iterator it =
payload_type_map_.find(payload_type);
if (it != payload_type_map_.end()) {
// We already use this payload type.
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 &&
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);
Payload* payload = NULL;
// Save the RED payload type. Used in both audio and video.
if (StringCompare(payload_name, "red", 3)) {
red_payload_type_ = payload_type;
payload = new 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;
return rtp_payload_registry_.RegisterReceivePayload(
payload_name, payload_type, frequency, channels, rate);
}
WebRtc_Word32 RTPReceiver::DeRegisterReceivePayload(
const WebRtc_Word8 payload_type) {
CriticalSectionScoped lock(critical_section_rtp_receiver_);
std::map<WebRtc_Word8, Payload*>::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;
return rtp_payload_registry_.DeRegisterReceivePayload(payload_type);
}
WebRtc_Word32 RTPReceiver::ReceivePayloadType(
@ -339,53 +242,9 @@ WebRtc_Word32 RTPReceiver::ReceivePayloadType(
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);
CriticalSectionScoped lock(critical_section_rtp_receiver_);
std::map<WebRtc_Word8, Payload*>::const_iterator it =
payload_type_map_.begin();
while (it != payload_type_map_.end()) {
Payload* payload = it->second;
assert(payload);
size_t name_length = strlen(payload->name);
if (payload_name_length == name_length &&
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;
return rtp_payload_registry_.ReceivePayloadType(
payload_name, frequency, channels, rate, payload_type);
}
WebRtc_Word32 RTPReceiver::ReceivePayload(
@ -395,84 +254,8 @@ WebRtc_Word32 RTPReceiver::ReceivePayload(
WebRtc_UWord8* channels,
WebRtc_UWord32* rate) const {
CriticalSectionScoped lock(critical_section_rtp_receiver_);
std::map<WebRtc_Word8, Payload*>::const_iterator it =
payload_type_map_.find(payload_type);
if (it == payload_type_map_.end()) {
return -1;
}
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_Word32 RTPReceiver::RemotePayload(
char payload_name[RTP_PAYLOAD_NAME_SIZE],
WebRtc_Word8* payload_type,
WebRtc_UWord32* frequency,
WebRtc_UWord8* channels) const {
if (last_received_payload_type_ == -1) {
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, id_,
"%s invalid state", __FUNCTION__);
return -1;
}
std::map<WebRtc_Word8, Payload*>::const_iterator it =
payload_type_map_.find(last_received_payload_type_);
if (it == payload_type_map_.end()) {
return -1;
}
Payload* payload = it->second;
assert(payload);
payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
if (payload_type) {
*payload_type = last_received_payload_type_;
}
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;
}
}
return 0;
return rtp_payload_registry_.ReceivePayload(
payload_type, payload_name, frequency, channels, rate);
}
WebRtc_Word32 RTPReceiver::RegisterRtpHeaderExtension(
@ -626,9 +409,14 @@ WebRtc_Word32 RTPReceiver::IncomingRTPPacket(
WebRtc_UWord16 payload_data_length =
ModuleRTPUtility::GetPayloadDataLength(rtp_header, packet_length);
bool is_first_packet_in_frame =
SequenceNumber() + 1 == rtp_header->header.sequenceNumber &&
TimeStamp() != rtp_header->header.timestamp;
bool is_first_packet = is_first_packet_in_frame || HaveNotReceivedPackets();
WebRtc_Word32 ret_val = rtp_media_receiver_->ParseRtpPacket(
rtp_header, specific_payload, is_red, packet,
packet_length, clock_.TimeInMilliseconds());
rtp_header, specific_payload, is_red, packet, packet_length,
clock_.TimeInMilliseconds(), is_first_packet);
if (ret_val < 0) {
return ret_val;
@ -835,18 +623,10 @@ int32_t RTPReceiver::LastReceivedTimeMs() const {
}
WebRtc_UWord32 RTPReceiver::PayloadTypeToPayload(
const WebRtc_UWord8 payload_type,
Payload*& payload) const {
std::map<WebRtc_Word8, Payload*>::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;
const WebRtc_UWord8 payload_type,
Payload*& payload) const {
CriticalSectionScoped lock(critical_section_rtp_receiver_);
return rtp_payload_registry_.PayloadTypeToPayload(payload_type, payload);
}
// Compute time stamp of the last incoming packet that is the first packet of
@ -907,8 +687,10 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtp_header) {
{
CriticalSectionScoped lock(critical_section_rtp_receiver_);
WebRtc_Word8 last_received_payload_type =
rtp_payload_registry_.last_received_payload_type();
if (ssrc_ != rtp_header->header.ssrc ||
(last_received_payload_type_ == -1 && ssrc_ == 0)) {
(last_received_payload_type == -1 && ssrc_ == 0)) {
// We need the payload_type_ to make the call if the remote SSRC is 0.
new_ssrc = true;
@ -922,16 +704,14 @@ void RTPReceiver::CheckSSRCChanged(const WebRtcRTPHeader* rtp_header) {
// Do we have a SSRC? Then the stream is restarted.
if (ssrc_) {
// Do we have the same codec? Then re-initialize coder.
if (rtp_header->header.payloadType == last_received_payload_type_) {
if (rtp_header->header.payloadType == last_received_payload_type) {
re_initialize_decoder = true;
std::map<WebRtc_Word8, Payload*>::iterator it =
payload_type_map_.find(rtp_header->header.payloadType);
if (it == payload_type_map_.end()) {
Payload* payload;
if (rtp_payload_registry_.PayloadTypeToPayload(
rtp_header->header.payloadType, payload) != 0) {
return;
}
Payload* payload = it->second;
assert(payload);
payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
@ -985,7 +765,9 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
{
CriticalSectionScoped lock(critical_section_rtp_receiver_);
if (payload_type != last_received_payload_type_) {
WebRtc_Word8 last_received_payload_type =
rtp_payload_registry_.last_received_payload_type();
if (payload_type != last_received_payload_type) {
if (REDPayloadType(payload_type)) {
// Get the real codec payload type.
payload_type = first_payload_byte & 0x7f;
@ -999,7 +781,7 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
}
// When we receive RED we need to check the real payload type.
if (payload_type == last_received_payload_type_) {
if (payload_type == last_received_payload_type) {
rtp_media_receiver_->GetLastMediaSpecificPayload(specific_payload);
return 0;
}
@ -1019,19 +801,17 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
return 0;
}
std::map<WebRtc_Word8, ModuleRTPUtility::Payload*>::iterator it =
payload_type_map_.find(payload_type);
// Check that this is a registered payload type.
if (it == payload_type_map_.end()) {
Payload* payload;
if (rtp_payload_registry_.PayloadTypeToPayload(payload_type,
payload) != 0) {
// Not a registered payload type.
return -1;
}
Payload* payload = it->second;
assert(payload);
payload_name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
strncpy(payload_name, payload->name, RTP_PAYLOAD_NAME_SIZE - 1);
last_received_payload_type_ = payload_type;
rtp_payload_registry_.set_last_received_payload_type(payload_type);
re_initialize_decoder = true;
@ -1043,12 +823,12 @@ WebRtc_Word32 RTPReceiver::CheckPayloadChanged(
// Only reset the decoder on media packets.
re_initialize_decoder = false;
} else {
if (last_received_media_payload_type_ ==
last_received_payload_type_) {
bool media_type_unchanged =
rtp_payload_registry_.ReportMediaPayloadType(payload_type);
if (media_type_unchanged) {
// Only reset the decoder if the media codec type has changed.
re_initialize_decoder = false;
}
last_received_media_payload_type_ = last_received_payload_type_;
}
}
if (re_initialize_decoder) {

View File

@ -18,7 +18,9 @@
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/typedefs.h"
namespace webrtc {
@ -76,11 +78,6 @@ class RTPReceiver : public Bitrate {
WebRtc_UWord8* channels,
WebRtc_UWord32* rate) const;
WebRtc_Word32 RemotePayload(char payload_name[RTP_PAYLOAD_NAME_SIZE],
WebRtc_Word8* payload_type,
WebRtc_UWord32* frequency,
WebRtc_UWord8* channels) const;
WebRtc_Word32 IncomingRTPPacket(
WebRtcRTPHeader* rtpheader,
const WebRtc_UWord8* incoming_rtp_packet,
@ -158,7 +155,7 @@ class RTPReceiver : public Bitrate {
void RTXStatus(bool* enable, WebRtc_UWord32* ssrc) const;
RTPReceiverAudio* GetAudioReceiver() const {
return rtp_receiver_audio_;
return rtp_receiver_audio_.get();
}
virtual WebRtc_Word8 REDPayloadType() const;
@ -190,9 +187,10 @@ class RTPReceiver : public Bitrate {
bool ProcessNACKBitRate(WebRtc_UWord32 now);
private:
RTPReceiverAudio* rtp_receiver_audio_;
RTPReceiverVideo* rtp_receiver_video_;
RTPReceiverStrategy* rtp_media_receiver_;
RTPPayloadRegistry rtp_payload_registry_;
scoped_ptr<RTPReceiverAudio> rtp_receiver_audio_;
scoped_ptr<RTPReceiverVideo> rtp_receiver_video_;
RTPReceiverStrategy* rtp_media_receiver_;
WebRtc_Word32 id_;
ModuleRtpRtcpImpl& rtp_rtcp_;
@ -202,14 +200,10 @@ class RTPReceiver : public Bitrate {
CriticalSectionWrapper* critical_section_rtp_receiver_;
mutable WebRtc_Word64 last_receive_time_;
WebRtc_UWord16 last_received_payload_length_;
WebRtc_Word8 last_received_payload_type_;
WebRtc_Word8 last_received_media_payload_type_;
WebRtc_UWord32 packet_timeout_ms_;
WebRtc_Word8 red_payload_type_;
ModuleRTPUtility::PayloadTypeMap payload_type_map_;
RtpHeaderExtensionMap rtp_header_extension_map_;
RtpHeaderExtensionMap rtp_header_extension_map_;
// SSRCs.
WebRtc_UWord32 ssrc_;

View File

@ -255,7 +255,8 @@ WebRtc_Word32 RTPReceiverAudio::ParseRtpPacket(
const bool isRed,
const WebRtc_UWord8* packet,
const WebRtc_UWord16 packetLength,
const WebRtc_Word64 timestampMs) {
const WebRtc_Word64 timestampMs,
const bool isFirstPacket) {
const WebRtc_UWord8* payloadData =
ModuleRTPUtility::GetPayloadData(rtpHeader, packet);

View File

@ -59,7 +59,8 @@ public:
const bool isRed,
const WebRtc_UWord8* packet,
const WebRtc_UWord16 packetLength,
const WebRtc_Word64 timestampMs);
const WebRtc_Word64 timestampMs,
const bool isFirstPacket);
WebRtc_Word32 GetFrequencyHz() const;

View File

@ -37,14 +37,16 @@ class RTPReceiverStrategy {
// Implementations are encouraged to use the provided packet buffer and RTP
// header as arguments to the callback; implementations are also allowed to
// make changes in the data as necessary. The specific_payload argument
// provides audio or video-specific data.
// provides audio or video-specific data. The is_first_packet argument is true
// if this packet is either the first packet ever or the first in its frame.
virtual WebRtc_Word32 ParseRtpPacket(
WebRtcRTPHeader* rtp_header,
const ModuleRTPUtility::PayloadUnion& specific_payload,
const bool is_red,
const WebRtc_UWord8* packet,
const WebRtc_UWord16 packet_length,
const WebRtc_Word64 timestamp_ms) = 0;
const WebRtc_Word64 timestamp_ms,
const bool is_first_packet) = 0;
// Retrieves the last known applicable frequency.
virtual WebRtc_Word32 GetFrequencyHz() const = 0;

View File

@ -16,7 +16,7 @@
#include "critical_section_wrapper.h"
#include "receiver_fec.h"
#include "rtp_receiver.h"
#include "rtp_payload_registry.h"
#include "rtp_rtcp_impl.h"
#include "rtp_utility.h"
#include "trace.h"
@ -27,13 +27,14 @@ WebRtc_UWord32 BitRateBPS(WebRtc_UWord16 x )
return (x & 0x3fff) * WebRtc_UWord32(pow(10.0f,(2 + (x >> 14))));
}
RTPReceiverVideo::RTPReceiverVideo(const WebRtc_Word32 id,
RTPReceiver* parent,
RtpData* data_callback,
ModuleRtpRtcpImpl* owner)
RTPReceiverVideo::RTPReceiverVideo(
const WebRtc_Word32 id,
const RTPPayloadRegistry* rtpRtpPayloadRegistry,
RtpData* data_callback,
ModuleRtpRtcpImpl* owner)
: RTPReceiverStrategy(data_callback),
_id(id),
_parent(parent),
_rtpRtpPayloadRegistry(rtpRtpPayloadRegistry),
_criticalSectionReceiverVideo(
CriticalSectionWrapper::CreateCriticalSection()),
_currentFecFrameDecoded(false),
@ -82,7 +83,8 @@ WebRtc_Word32 RTPReceiverVideo::ParseRtpPacket(
const bool isRed,
const WebRtc_UWord8* packet,
const WebRtc_UWord16 packetLength,
const WebRtc_Word64 timestampMs) {
const WebRtc_Word64 timestampMs,
const bool isFirstPacket) {
const WebRtc_UWord8* payloadData =
ModuleRTPUtility::GetPayloadData(rtpHeader, packet);
const WebRtc_UWord16 payloadDataLength =
@ -90,7 +92,7 @@ WebRtc_Word32 RTPReceiverVideo::ParseRtpPacket(
return ParseVideoCodecSpecific(
rtpHeader, payloadData, payloadDataLength,
specificPayload.Video.videoCodecType, isRed, packet, packetLength,
timestampMs);
timestampMs, isFirstPacket);
}
WebRtc_Word32 RTPReceiverVideo::GetFrequencyHz() const {
@ -144,7 +146,8 @@ WebRtc_Word32 RTPReceiverVideo::ParseVideoCodecSpecific(
const bool isRED,
const WebRtc_UWord8* incomingRtpPacket,
const WebRtc_UWord16 incomingRtpPacketSize,
const WebRtc_Word64 nowMS) {
const WebRtc_Word64 nowMS,
const bool isFirstPacket) {
WebRtc_Word32 retVal = 0;
_criticalSectionReceiverVideo->Enter();
@ -186,7 +189,8 @@ WebRtc_Word32 RTPReceiverVideo::ParseVideoCodecSpecific(
retVal = ParseVideoCodecSpecificSwitch(rtpHeader,
payloadData,
payloadDataLength,
videoType);
videoType,
isFirstPacket);
}
return retVal;
}
@ -237,7 +241,7 @@ WebRtc_Word32 RTPReceiverVideo::ReceiveRecoveredPacketCallback(
_currentFecFrameDecoded = true;
ModuleRTPUtility::Payload* payload = NULL;
if (_parent->PayloadTypeToPayload(
if (_rtpRtpPayloadRegistry->PayloadTypeToPayload(
rtpHeader->header.payloadType, payload) != 0) {
_criticalSectionReceiverVideo->Leave();
return -1;
@ -252,7 +256,7 @@ WebRtc_Word32 RTPReceiverVideo::ReceiveRecoveredPacketCallback(
// replace pltype
recoveredPacket[1] &= 0x80; // Reset.
recoveredPacket[1] += _parent->REDPayloadType();
recoveredPacket[1] += _rtpRtpPayloadRegistry->red_payload_type();
// add RED header
recoveredPacket[rtpHeaderLength] = rtpHeader->header.payloadType;
@ -261,11 +265,17 @@ WebRtc_Word32 RTPReceiverVideo::ReceiveRecoveredPacketCallback(
memcpy(recoveredPacket + rtpHeaderLength + REDForFECHeaderLength, payloadData,
payloadDataLength);
// A recovered packet can be the first packet, but we lack the ability to
// detect it at the moment since we do not store the history of recently
// received packets. Most codecs like VP8 deal with this in other ways.
bool isFirstPacket = false;
return ParseVideoCodecSpecificSwitch(
rtpHeader,
payloadData,
payloadDataLength,
payload->typeSpecific.Video.videoCodecType);
payload->typeSpecific.Video.videoCodecType,
isFirstPacket);
}
WebRtc_Word32 RTPReceiverVideo::SetCodecType(const RtpVideoCodecTypes videoType,
@ -288,7 +298,8 @@ WebRtc_Word32 RTPReceiverVideo::ParseVideoCodecSpecificSwitch(
WebRtcRTPHeader* rtpHeader,
const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadDataLength,
const RtpVideoCodecTypes videoType) {
const RtpVideoCodecTypes videoType,
const bool isFirstPacket) {
WebRtc_Word32 retVal = SetCodecType(videoType, rtpHeader);
if (retVal != 0) {
_criticalSectionReceiverVideo->Leave();
@ -301,6 +312,7 @@ WebRtc_Word32 RTPReceiverVideo::ParseVideoCodecSpecificSwitch(
// returning.
switch (videoType) {
case kRtpNoVideo:
rtpHeader->type.Video.isFirstPacket = isFirstPacket;
return ReceiveGenericCodec(rtpHeader, payloadData, payloadDataLength);
case kRtpVp8Video:
return ReceiveVp8Codec(rtpHeader, payloadData, payloadDataLength);
@ -386,13 +398,6 @@ WebRtc_Word32 RTPReceiverVideo::ReceiveGenericCodec(
const WebRtc_UWord16 payloadDataLength) {
rtpHeader->frameType = kVideoFrameKey;
bool isFirstPacketInFrame =
(_parent->SequenceNumber() + 1) == rtpHeader->header.sequenceNumber &&
(_parent->TimeStamp() != rtpHeader->header.timestamp);
if (isFirstPacketInFrame || _parent->HaveNotReceivedPackets()) {
rtpHeader->type.Video.isFirstPacket = true;
}
_criticalSectionReceiverVideo->Leave();
if (data_callback_->OnReceivedPayloadData(payloadData, payloadDataLength,

View File

@ -23,12 +23,12 @@ class CriticalSectionWrapper;
class ModuleRtpRtcpImpl;
class ReceiverFEC;
class RTPReceiver;
class RTPPayloadRegistry;
class RTPReceiverVideo : public RTPReceiverStrategy {
public:
// TODO(phoglund): Get rid of dependency on "parent".
RTPReceiverVideo(const WebRtc_Word32 id,
RTPReceiver* parent,
const RTPPayloadRegistry* rtp_payload_registry,
RtpData* data_callback,
ModuleRtpRtcpImpl* owner);
@ -40,7 +40,8 @@ class RTPReceiverVideo : public RTPReceiverStrategy {
const bool is_red,
const WebRtc_UWord8* packet,
const WebRtc_UWord16 packet_length,
const WebRtc_Word64 timestamp);
const WebRtc_Word64 timestamp,
const bool is_first_packet);
WebRtc_Word32 GetFrequencyHz() const;
@ -85,7 +86,8 @@ class RTPReceiverVideo : public RTPReceiverStrategy {
WebRtcRTPHeader* rtpHeader,
const WebRtc_UWord8* payloadData,
const WebRtc_UWord16 payloadDataLength,
const RtpVideoCodecTypes videoType);
const RtpVideoCodecTypes videoType,
const bool isFirstPacket);
WebRtc_Word32 ReceiveGenericCodec(WebRtcRTPHeader *rtpHeader,
const WebRtc_UWord8* payloadData,
@ -107,10 +109,11 @@ class RTPReceiverVideo : public RTPReceiverStrategy {
const bool isRED,
const WebRtc_UWord8* incomingRtpPacket,
const WebRtc_UWord16 incomingRtpPacketSize,
const WebRtc_Word64 nowMS);
const WebRtc_Word64 nowMS,
const bool isFirstPacket);
WebRtc_Word32 _id;
RTPReceiver* _parent;
const RTPPayloadRegistry* _rtpRtpPayloadRegistry;
CriticalSectionWrapper* _criticalSectionReceiverVideo;

View File

@ -73,6 +73,8 @@
'producer_fec.h',
'rtp_packet_history.cc',
'rtp_packet_history.h',
'rtp_payload_registry.h',
'rtp_payload_registry.cc',
'rtp_receiver_strategy.cc',
'rtp_receiver_strategy.h',
'rtp_receiver_video.cc',