Remove RTP data implementation
Bug: webrtc:6625 Change-Id: Ie68d7a938d8b7be95a01cca74a176104e4e44e1b Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/215321 Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33759}
This commit is contained in:
committed by
Commit Bot
parent
f981cb3d2e
commit
7af57c6e48
@ -142,8 +142,6 @@ rtc_library("rtc_media_base") {
|
||||
"base/media_engine.h",
|
||||
"base/rid_description.cc",
|
||||
"base/rid_description.h",
|
||||
"base/rtp_data_engine.cc",
|
||||
"base/rtp_data_engine.h",
|
||||
"base/rtp_utils.cc",
|
||||
"base/rtp_utils.h",
|
||||
"base/stream_params.cc",
|
||||
@ -628,7 +626,6 @@ if (rtc_include_tests) {
|
||||
sources = [
|
||||
"base/codec_unittest.cc",
|
||||
"base/media_engine_unittest.cc",
|
||||
"base/rtp_data_engine_unittest.cc",
|
||||
"base/rtp_utils_unittest.cc",
|
||||
"base/sdp_fmtp_utils_unittest.cc",
|
||||
"base/stream_params_unittest.cc",
|
||||
|
||||
@ -422,93 +422,6 @@ void FakeVideoMediaChannel::ClearRecordableEncodedFrameCallback(uint32_t ssrc) {
|
||||
|
||||
void FakeVideoMediaChannel::GenerateKeyFrame(uint32_t ssrc) {}
|
||||
|
||||
FakeDataMediaChannel::FakeDataMediaChannel(void* unused,
|
||||
const DataOptions& options)
|
||||
: send_blocked_(false), max_bps_(-1) {}
|
||||
FakeDataMediaChannel::~FakeDataMediaChannel() {}
|
||||
const std::vector<DataCodec>& FakeDataMediaChannel::recv_codecs() const {
|
||||
return recv_codecs_;
|
||||
}
|
||||
const std::vector<DataCodec>& FakeDataMediaChannel::send_codecs() const {
|
||||
return send_codecs_;
|
||||
}
|
||||
const std::vector<DataCodec>& FakeDataMediaChannel::codecs() const {
|
||||
return send_codecs();
|
||||
}
|
||||
int FakeDataMediaChannel::max_bps() const {
|
||||
return max_bps_;
|
||||
}
|
||||
bool FakeDataMediaChannel::SetSendParameters(const DataSendParameters& params) {
|
||||
set_send_rtcp_parameters(params.rtcp);
|
||||
return (SetSendCodecs(params.codecs) &&
|
||||
SetMaxSendBandwidth(params.max_bandwidth_bps));
|
||||
}
|
||||
bool FakeDataMediaChannel::SetRecvParameters(const DataRecvParameters& params) {
|
||||
set_recv_rtcp_parameters(params.rtcp);
|
||||
return SetRecvCodecs(params.codecs);
|
||||
}
|
||||
bool FakeDataMediaChannel::SetSend(bool send) {
|
||||
return set_sending(send);
|
||||
}
|
||||
bool FakeDataMediaChannel::SetReceive(bool receive) {
|
||||
set_playout(receive);
|
||||
return true;
|
||||
}
|
||||
bool FakeDataMediaChannel::AddRecvStream(const StreamParams& sp) {
|
||||
if (!RtpHelper<DataMediaChannel>::AddRecvStream(sp))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool FakeDataMediaChannel::RemoveRecvStream(uint32_t ssrc) {
|
||||
if (!RtpHelper<DataMediaChannel>::RemoveRecvStream(ssrc))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool FakeDataMediaChannel::SendData(const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& payload,
|
||||
SendDataResult* result) {
|
||||
if (send_blocked_) {
|
||||
*result = SDR_BLOCK;
|
||||
return false;
|
||||
} else {
|
||||
last_sent_data_params_ = params;
|
||||
last_sent_data_ = std::string(payload.data<char>(), payload.size());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SendDataParams FakeDataMediaChannel::last_sent_data_params() {
|
||||
return last_sent_data_params_;
|
||||
}
|
||||
std::string FakeDataMediaChannel::last_sent_data() {
|
||||
return last_sent_data_;
|
||||
}
|
||||
bool FakeDataMediaChannel::is_send_blocked() {
|
||||
return send_blocked_;
|
||||
}
|
||||
void FakeDataMediaChannel::set_send_blocked(bool blocked) {
|
||||
send_blocked_ = blocked;
|
||||
}
|
||||
bool FakeDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
|
||||
if (fail_set_recv_codecs()) {
|
||||
// Fake the failure in SetRecvCodecs.
|
||||
return false;
|
||||
}
|
||||
recv_codecs_ = codecs;
|
||||
return true;
|
||||
}
|
||||
bool FakeDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) {
|
||||
if (fail_set_send_codecs()) {
|
||||
// Fake the failure in SetSendCodecs.
|
||||
return false;
|
||||
}
|
||||
send_codecs_ = codecs;
|
||||
return true;
|
||||
}
|
||||
bool FakeDataMediaChannel::SetMaxSendBandwidth(int bps) {
|
||||
max_bps_ = bps;
|
||||
return true;
|
||||
}
|
||||
|
||||
FakeVoiceEngine::FakeVoiceEngine() : fail_create_channel_(false) {
|
||||
// Add a fake audio codec. Note that the name must not be "" as there are
|
||||
// sanity checks against that.
|
||||
@ -668,22 +581,4 @@ void FakeMediaEngine::set_fail_create_channel(bool fail) {
|
||||
video_->fail_create_channel_ = fail;
|
||||
}
|
||||
|
||||
DataMediaChannel* FakeDataEngine::CreateChannel(const MediaConfig& config) {
|
||||
FakeDataMediaChannel* ch = new FakeDataMediaChannel(this, DataOptions());
|
||||
channels_.push_back(ch);
|
||||
return ch;
|
||||
}
|
||||
FakeDataMediaChannel* FakeDataEngine::GetChannel(size_t index) {
|
||||
return (channels_.size() > index) ? channels_[index] : NULL;
|
||||
}
|
||||
void FakeDataEngine::UnregisterChannel(DataMediaChannel* channel) {
|
||||
channels_.erase(absl::c_find(channels_, channel));
|
||||
}
|
||||
void FakeDataEngine::SetDataCodecs(const std::vector<DataCodec>& data_codecs) {
|
||||
data_codecs_ = data_codecs;
|
||||
}
|
||||
const std::vector<DataCodec>& FakeDataEngine::data_codecs() {
|
||||
return data_codecs_;
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -472,48 +472,6 @@ class FakeVideoMediaChannel : public RtpHelper<VideoMediaChannel> {
|
||||
int max_bps_;
|
||||
};
|
||||
|
||||
// Dummy option class, needed for the DataTraits abstraction in
|
||||
// channel_unittest.c.
|
||||
class DataOptions {};
|
||||
|
||||
class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
|
||||
public:
|
||||
explicit FakeDataMediaChannel(void* unused, const DataOptions& options);
|
||||
~FakeDataMediaChannel();
|
||||
const std::vector<DataCodec>& recv_codecs() const;
|
||||
const std::vector<DataCodec>& send_codecs() const;
|
||||
const std::vector<DataCodec>& codecs() const;
|
||||
int max_bps() const;
|
||||
|
||||
bool SetSendParameters(const DataSendParameters& params) override;
|
||||
bool SetRecvParameters(const DataRecvParameters& params) override;
|
||||
bool SetSend(bool send) override;
|
||||
bool SetReceive(bool receive) override;
|
||||
bool AddRecvStream(const StreamParams& sp) override;
|
||||
bool RemoveRecvStream(uint32_t ssrc) override;
|
||||
|
||||
bool SendData(const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& payload,
|
||||
SendDataResult* result) override;
|
||||
|
||||
SendDataParams last_sent_data_params();
|
||||
std::string last_sent_data();
|
||||
bool is_send_blocked();
|
||||
void set_send_blocked(bool blocked);
|
||||
|
||||
private:
|
||||
bool SetRecvCodecs(const std::vector<DataCodec>& codecs);
|
||||
bool SetSendCodecs(const std::vector<DataCodec>& codecs);
|
||||
bool SetMaxSendBandwidth(int bps);
|
||||
|
||||
std::vector<DataCodec> recv_codecs_;
|
||||
std::vector<DataCodec> send_codecs_;
|
||||
SendDataParams last_sent_data_params_;
|
||||
std::string last_sent_data_;
|
||||
bool send_blocked_;
|
||||
int max_bps_;
|
||||
};
|
||||
|
||||
class FakeVoiceEngine : public VoiceEngineInterface {
|
||||
public:
|
||||
FakeVoiceEngine();
|
||||
@ -609,25 +567,6 @@ class FakeMediaEngine : public CompositeMediaEngine {
|
||||
FakeVideoEngine* const video_;
|
||||
};
|
||||
|
||||
// Have to come afterwards due to declaration order
|
||||
|
||||
class FakeDataEngine : public DataEngineInterface {
|
||||
public:
|
||||
DataMediaChannel* CreateChannel(const MediaConfig& config) override;
|
||||
|
||||
FakeDataMediaChannel* GetChannel(size_t index);
|
||||
|
||||
void UnregisterChannel(DataMediaChannel* channel);
|
||||
|
||||
void SetDataCodecs(const std::vector<DataCodec>& data_codecs);
|
||||
|
||||
const std::vector<DataCodec>& data_codecs() override;
|
||||
|
||||
private:
|
||||
std::vector<FakeDataMediaChannel*> channels_;
|
||||
std::vector<DataCodec> data_codecs_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // MEDIA_BASE_FAKE_MEDIA_ENGINE_H_
|
||||
|
||||
@ -955,11 +955,8 @@ enum DataMessageType {
|
||||
// signal fires, on up the chain.
|
||||
struct ReceiveDataParams {
|
||||
// The in-packet stream indentifier.
|
||||
// RTP data channels use SSRCs, SCTP data channels use SIDs.
|
||||
union {
|
||||
uint32_t ssrc;
|
||||
int sid = 0;
|
||||
};
|
||||
// SCTP data channels use SIDs.
|
||||
int sid = 0;
|
||||
// The type of message (binary, text, or control).
|
||||
DataMessageType type = DMT_TEXT;
|
||||
// A per-stream value incremented per packet in the stream.
|
||||
@ -970,11 +967,7 @@ struct ReceiveDataParams {
|
||||
|
||||
struct SendDataParams {
|
||||
// The in-packet stream indentifier.
|
||||
// RTP data channels use SSRCs, SCTP data channels use SIDs.
|
||||
union {
|
||||
uint32_t ssrc;
|
||||
int sid = 0;
|
||||
};
|
||||
int sid = 0;
|
||||
// The type of message (binary, text, or control).
|
||||
DataMessageType type = DMT_TEXT;
|
||||
|
||||
|
||||
@ -158,17 +158,9 @@ class CompositeMediaEngine : public MediaEngineInterface {
|
||||
|
||||
enum DataChannelType {
|
||||
DCT_NONE = 0,
|
||||
DCT_RTP = 1,
|
||||
DCT_SCTP = 2,
|
||||
};
|
||||
|
||||
class DataEngineInterface {
|
||||
public:
|
||||
virtual ~DataEngineInterface() {}
|
||||
virtual DataMediaChannel* CreateChannel(const MediaConfig& config) = 0;
|
||||
virtual const std::vector<DataCodec>& data_codecs() = 0;
|
||||
};
|
||||
|
||||
webrtc::RtpParameters CreateRtpParametersWithOneEncoding();
|
||||
webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp);
|
||||
|
||||
|
||||
@ -1,340 +0,0 @@
|
||||
/*
|
||||
* 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 "media/base/rtp_data_engine.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "absl/strings/match.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "media/base/rtp_utils.h"
|
||||
#include "media/base/stream_params.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/data_rate_limiter.h"
|
||||
#include "rtc_base/helpers.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/sanitizer.h"
|
||||
|
||||
namespace cricket {
|
||||
|
||||
// We want to avoid IP fragmentation.
|
||||
static const size_t kDataMaxRtpPacketLen = 1200U;
|
||||
// We reserve space after the RTP header for future wiggle room.
|
||||
static const unsigned char kReservedSpace[] = {0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// Amount of overhead SRTP may take. We need to leave room in the
|
||||
// buffer for it, otherwise SRTP will fail later. If SRTP ever uses
|
||||
// more than this, we need to increase this number.
|
||||
static const size_t kMaxSrtpHmacOverhead = 16;
|
||||
|
||||
RtpDataEngine::RtpDataEngine() {
|
||||
data_codecs_.push_back(
|
||||
DataCodec(kGoogleRtpDataCodecPlType, kGoogleRtpDataCodecName));
|
||||
}
|
||||
|
||||
DataMediaChannel* RtpDataEngine::CreateChannel(const MediaConfig& config) {
|
||||
return new RtpDataMediaChannel(config);
|
||||
}
|
||||
|
||||
static const DataCodec* FindCodecByName(const std::vector<DataCodec>& codecs,
|
||||
const std::string& name) {
|
||||
for (const DataCodec& codec : codecs) {
|
||||
if (absl::EqualsIgnoreCase(name, codec.name))
|
||||
return &codec;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RtpDataMediaChannel::RtpDataMediaChannel(const MediaConfig& config)
|
||||
: DataMediaChannel(config) {
|
||||
Construct();
|
||||
SetPreferredDscp(rtc::DSCP_AF41);
|
||||
}
|
||||
|
||||
void RtpDataMediaChannel::Construct() {
|
||||
sending_ = false;
|
||||
receiving_ = false;
|
||||
send_limiter_.reset(new rtc::DataRateLimiter(kRtpDataMaxBandwidth / 8, 1.0));
|
||||
}
|
||||
|
||||
RtpDataMediaChannel::~RtpDataMediaChannel() {
|
||||
std::map<uint32_t, RtpClock*>::const_iterator iter;
|
||||
for (iter = rtp_clock_by_send_ssrc_.begin();
|
||||
iter != rtp_clock_by_send_ssrc_.end(); ++iter) {
|
||||
delete iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
void RTC_NO_SANITIZE("float-cast-overflow") // bugs.webrtc.org/8204
|
||||
RtpClock::Tick(double now, int* seq_num, uint32_t* timestamp) {
|
||||
*seq_num = ++last_seq_num_;
|
||||
*timestamp = timestamp_offset_ + static_cast<uint32_t>(now * clockrate_);
|
||||
// UBSan: 5.92374e+10 is outside the range of representable values of type
|
||||
// 'unsigned int'
|
||||
}
|
||||
|
||||
const DataCodec* FindUnknownCodec(const std::vector<DataCodec>& codecs) {
|
||||
DataCodec data_codec(kGoogleRtpDataCodecPlType, kGoogleRtpDataCodecName);
|
||||
std::vector<DataCodec>::const_iterator iter;
|
||||
for (iter = codecs.begin(); iter != codecs.end(); ++iter) {
|
||||
if (!iter->Matches(data_codec)) {
|
||||
return &(*iter);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const DataCodec* FindKnownCodec(const std::vector<DataCodec>& codecs) {
|
||||
DataCodec data_codec(kGoogleRtpDataCodecPlType, kGoogleRtpDataCodecName);
|
||||
std::vector<DataCodec>::const_iterator iter;
|
||||
for (iter = codecs.begin(); iter != codecs.end(); ++iter) {
|
||||
if (iter->Matches(data_codec)) {
|
||||
return &(*iter);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
|
||||
const DataCodec* unknown_codec = FindUnknownCodec(codecs);
|
||||
if (unknown_codec) {
|
||||
RTC_LOG(LS_WARNING) << "Failed to SetRecvCodecs because of unknown codec: "
|
||||
<< unknown_codec->ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
recv_codecs_ = codecs;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) {
|
||||
const DataCodec* known_codec = FindKnownCodec(codecs);
|
||||
if (!known_codec) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Failed to SetSendCodecs because there is no known codec.";
|
||||
return false;
|
||||
}
|
||||
|
||||
send_codecs_ = codecs;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::SetSendParameters(const DataSendParameters& params) {
|
||||
return (SetSendCodecs(params.codecs) &&
|
||||
SetMaxSendBandwidth(params.max_bandwidth_bps));
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::SetRecvParameters(const DataRecvParameters& params) {
|
||||
return SetRecvCodecs(params.codecs);
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::AddSendStream(const StreamParams& stream) {
|
||||
if (!stream.has_ssrcs()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetStreamBySsrc(send_streams_, stream.first_ssrc())) {
|
||||
RTC_LOG(LS_WARNING) << "Not adding data send stream '" << stream.id
|
||||
<< "' with ssrc=" << stream.first_ssrc()
|
||||
<< " because stream already exists.";
|
||||
return false;
|
||||
}
|
||||
|
||||
send_streams_.push_back(stream);
|
||||
// TODO(pthatcher): This should be per-stream, not per-ssrc.
|
||||
// And we should probably allow more than one per stream.
|
||||
rtp_clock_by_send_ssrc_[stream.first_ssrc()] =
|
||||
new RtpClock(kDataCodecClockrate, rtc::CreateRandomNonZeroId(),
|
||||
rtc::CreateRandomNonZeroId());
|
||||
|
||||
RTC_LOG(LS_INFO) << "Added data send stream '" << stream.id
|
||||
<< "' with ssrc=" << stream.first_ssrc();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::RemoveSendStream(uint32_t ssrc) {
|
||||
if (!GetStreamBySsrc(send_streams_, ssrc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RemoveStreamBySsrc(&send_streams_, ssrc);
|
||||
delete rtp_clock_by_send_ssrc_[ssrc];
|
||||
rtp_clock_by_send_ssrc_.erase(ssrc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::AddRecvStream(const StreamParams& stream) {
|
||||
if (!stream.has_ssrcs()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetStreamBySsrc(recv_streams_, stream.first_ssrc())) {
|
||||
RTC_LOG(LS_WARNING) << "Not adding data recv stream '" << stream.id
|
||||
<< "' with ssrc=" << stream.first_ssrc()
|
||||
<< " because stream already exists.";
|
||||
return false;
|
||||
}
|
||||
|
||||
recv_streams_.push_back(stream);
|
||||
RTC_LOG(LS_INFO) << "Added data recv stream '" << stream.id
|
||||
<< "' with ssrc=" << stream.first_ssrc();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::RemoveRecvStream(uint32_t ssrc) {
|
||||
RemoveStreamBySsrc(&recv_streams_, ssrc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not implemented.
|
||||
void RtpDataMediaChannel::ResetUnsignaledRecvStream() {}
|
||||
void RtpDataMediaChannel::OnDemuxerCriteriaUpdatePending() {}
|
||||
void RtpDataMediaChannel::OnDemuxerCriteriaUpdateComplete() {}
|
||||
|
||||
void RtpDataMediaChannel::OnPacketReceived(rtc::CopyOnWriteBuffer packet,
|
||||
int64_t /* packet_time_us */) {
|
||||
RtpHeader header;
|
||||
if (!GetRtpHeader(packet.cdata(), packet.size(), &header)) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t header_length;
|
||||
if (!GetRtpHeaderLen(packet.cdata(), packet.size(), &header_length)) {
|
||||
return;
|
||||
}
|
||||
const char* data =
|
||||
packet.cdata<char>() + header_length + sizeof(kReservedSpace);
|
||||
size_t data_len = packet.size() - header_length - sizeof(kReservedSpace);
|
||||
|
||||
if (!receiving_) {
|
||||
RTC_LOG(LS_WARNING) << "Not receiving packet " << header.ssrc << ":"
|
||||
<< header.seq_num << " before SetReceive(true) called.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FindCodecById(recv_codecs_, header.payload_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetStreamBySsrc(recv_streams_, header.ssrc)) {
|
||||
RTC_LOG(LS_WARNING) << "Received packet for unknown ssrc: " << header.ssrc;
|
||||
return;
|
||||
}
|
||||
|
||||
// Uncomment this for easy debugging.
|
||||
// const auto* found_stream = GetStreamBySsrc(recv_streams_, header.ssrc);
|
||||
// RTC_LOG(LS_INFO) << "Received packet"
|
||||
// << " groupid=" << found_stream.groupid
|
||||
// << ", ssrc=" << header.ssrc
|
||||
// << ", seqnum=" << header.seq_num
|
||||
// << ", timestamp=" << header.timestamp
|
||||
// << ", len=" << data_len;
|
||||
|
||||
ReceiveDataParams params;
|
||||
params.ssrc = header.ssrc;
|
||||
params.seq_num = header.seq_num;
|
||||
params.timestamp = header.timestamp;
|
||||
SignalDataReceived(params, data, data_len);
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::SetMaxSendBandwidth(int bps) {
|
||||
if (bps <= 0) {
|
||||
bps = kRtpDataMaxBandwidth;
|
||||
}
|
||||
send_limiter_.reset(new rtc::DataRateLimiter(bps / 8, 1.0));
|
||||
RTC_LOG(LS_INFO) << "RtpDataMediaChannel::SetSendBandwidth to " << bps
|
||||
<< "bps.";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RtpDataMediaChannel::SendData(const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& payload,
|
||||
SendDataResult* result) {
|
||||
if (result) {
|
||||
// If we return true, we'll set this to SDR_SUCCESS.
|
||||
*result = SDR_ERROR;
|
||||
}
|
||||
if (!sending_) {
|
||||
RTC_LOG(LS_WARNING) << "Not sending packet with ssrc=" << params.ssrc
|
||||
<< " len=" << payload.size()
|
||||
<< " before SetSend(true).";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.type != cricket::DMT_TEXT) {
|
||||
RTC_LOG(LS_WARNING)
|
||||
<< "Not sending data because binary type is unsupported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
const StreamParams* found_stream =
|
||||
GetStreamBySsrc(send_streams_, params.ssrc);
|
||||
if (!found_stream) {
|
||||
RTC_LOG(LS_WARNING) << "Not sending data because ssrc is unknown: "
|
||||
<< params.ssrc;
|
||||
return false;
|
||||
}
|
||||
|
||||
const DataCodec* found_codec =
|
||||
FindCodecByName(send_codecs_, kGoogleRtpDataCodecName);
|
||||
if (!found_codec) {
|
||||
RTC_LOG(LS_WARNING) << "Not sending data because codec is unknown: "
|
||||
<< kGoogleRtpDataCodecName;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t packet_len = (kMinRtpPacketLen + sizeof(kReservedSpace) +
|
||||
payload.size() + kMaxSrtpHmacOverhead);
|
||||
if (packet_len > kDataMaxRtpPacketLen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double now =
|
||||
rtc::TimeMicros() / static_cast<double>(rtc::kNumMicrosecsPerSec);
|
||||
|
||||
if (!send_limiter_->CanUse(packet_len, now)) {
|
||||
RTC_LOG(LS_VERBOSE) << "Dropped data packet of len=" << packet_len
|
||||
<< "; already sent " << send_limiter_->used_in_period()
|
||||
<< "/" << send_limiter_->max_per_period();
|
||||
return false;
|
||||
}
|
||||
|
||||
RtpHeader header;
|
||||
header.payload_type = found_codec->id;
|
||||
header.ssrc = params.ssrc;
|
||||
rtp_clock_by_send_ssrc_[header.ssrc]->Tick(now, &header.seq_num,
|
||||
&header.timestamp);
|
||||
|
||||
rtc::CopyOnWriteBuffer packet(kMinRtpPacketLen, packet_len);
|
||||
if (!SetRtpHeader(packet.MutableData(), packet.size(), header)) {
|
||||
return false;
|
||||
}
|
||||
packet.AppendData(kReservedSpace);
|
||||
packet.AppendData(payload);
|
||||
|
||||
RTC_LOG(LS_VERBOSE) << "Sent RTP data packet: "
|
||||
" stream="
|
||||
<< found_stream->id << " ssrc=" << header.ssrc
|
||||
<< ", seqnum=" << header.seq_num
|
||||
<< ", timestamp=" << header.timestamp
|
||||
<< ", len=" << payload.size();
|
||||
|
||||
rtc::PacketOptions options;
|
||||
options.info_signaled_after_sent.packet_type = rtc::PacketType::kData;
|
||||
MediaChannel::SendPacket(&packet, options);
|
||||
send_limiter_->Use(packet_len, now);
|
||||
if (result) {
|
||||
*result = SDR_SUCCESS;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* 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 MEDIA_BASE_RTP_DATA_ENGINE_H_
|
||||
#define MEDIA_BASE_RTP_DATA_ENGINE_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/media_channel.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "media/base/media_engine.h"
|
||||
|
||||
namespace rtc {
|
||||
class DataRateLimiter;
|
||||
}
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class RtpDataEngine : public DataEngineInterface {
|
||||
public:
|
||||
RtpDataEngine();
|
||||
|
||||
virtual DataMediaChannel* CreateChannel(const MediaConfig& config);
|
||||
|
||||
virtual const std::vector<DataCodec>& data_codecs() { return data_codecs_; }
|
||||
|
||||
private:
|
||||
std::vector<DataCodec> data_codecs_;
|
||||
};
|
||||
|
||||
// Keep track of sequence number and timestamp of an RTP stream. The
|
||||
// sequence number starts with a "random" value and increments. The
|
||||
// timestamp starts with a "random" value and increases monotonically
|
||||
// according to the clockrate.
|
||||
class RtpClock {
|
||||
public:
|
||||
RtpClock(int clockrate, uint16_t first_seq_num, uint32_t timestamp_offset)
|
||||
: clockrate_(clockrate),
|
||||
last_seq_num_(first_seq_num),
|
||||
timestamp_offset_(timestamp_offset) {}
|
||||
|
||||
// Given the current time (in number of seconds which must be
|
||||
// monotonically increasing), Return the next sequence number and
|
||||
// timestamp.
|
||||
void Tick(double now, int* seq_num, uint32_t* timestamp);
|
||||
|
||||
private:
|
||||
int clockrate_;
|
||||
uint16_t last_seq_num_;
|
||||
uint32_t timestamp_offset_;
|
||||
};
|
||||
|
||||
class RtpDataMediaChannel : public DataMediaChannel {
|
||||
public:
|
||||
explicit RtpDataMediaChannel(const MediaConfig& config);
|
||||
virtual ~RtpDataMediaChannel();
|
||||
|
||||
virtual bool SetSendParameters(const DataSendParameters& params);
|
||||
virtual bool SetRecvParameters(const DataRecvParameters& params);
|
||||
virtual bool AddSendStream(const StreamParams& sp);
|
||||
virtual bool RemoveSendStream(uint32_t ssrc);
|
||||
virtual bool AddRecvStream(const StreamParams& sp);
|
||||
virtual bool RemoveRecvStream(uint32_t ssrc);
|
||||
virtual void ResetUnsignaledRecvStream();
|
||||
virtual void OnDemuxerCriteriaUpdatePending();
|
||||
virtual void OnDemuxerCriteriaUpdateComplete();
|
||||
virtual bool SetSend(bool send) {
|
||||
sending_ = send;
|
||||
return true;
|
||||
}
|
||||
virtual bool SetReceive(bool receive) {
|
||||
receiving_ = receive;
|
||||
return true;
|
||||
}
|
||||
virtual void OnPacketReceived(rtc::CopyOnWriteBuffer packet,
|
||||
int64_t packet_time_us);
|
||||
virtual void OnReadyToSend(bool ready) {}
|
||||
virtual bool SendData(const SendDataParams& params,
|
||||
const rtc::CopyOnWriteBuffer& payload,
|
||||
SendDataResult* result);
|
||||
|
||||
private:
|
||||
void Construct();
|
||||
bool SetMaxSendBandwidth(int bps);
|
||||
bool SetSendCodecs(const std::vector<DataCodec>& codecs);
|
||||
bool SetRecvCodecs(const std::vector<DataCodec>& codecs);
|
||||
|
||||
bool sending_;
|
||||
bool receiving_;
|
||||
std::vector<DataCodec> send_codecs_;
|
||||
std::vector<DataCodec> recv_codecs_;
|
||||
std::vector<StreamParams> send_streams_;
|
||||
std::vector<StreamParams> recv_streams_;
|
||||
std::map<uint32_t, RtpClock*> rtp_clock_by_send_ssrc_;
|
||||
std::unique_ptr<rtc::DataRateLimiter> send_limiter_;
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
#endif // MEDIA_BASE_RTP_DATA_ENGINE_H_
|
||||
@ -1,362 +0,0 @@
|
||||
/*
|
||||
* 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 "media/base/rtp_data_engine.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "media/base/fake_network_interface.h"
|
||||
#include "media/base/media_constants.h"
|
||||
#include "media/base/rtp_utils.h"
|
||||
#include "rtc_base/copy_on_write_buffer.h"
|
||||
#include "rtc_base/fake_clock.h"
|
||||
#include "rtc_base/third_party/sigslot/sigslot.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
class FakeDataReceiver : public sigslot::has_slots<> {
|
||||
public:
|
||||
FakeDataReceiver() : has_received_data_(false) {}
|
||||
|
||||
void OnDataReceived(const cricket::ReceiveDataParams& params,
|
||||
const char* data,
|
||||
size_t len) {
|
||||
has_received_data_ = true;
|
||||
last_received_data_ = std::string(data, len);
|
||||
last_received_data_len_ = len;
|
||||
last_received_data_params_ = params;
|
||||
}
|
||||
|
||||
bool has_received_data() const { return has_received_data_; }
|
||||
std::string last_received_data() const { return last_received_data_; }
|
||||
size_t last_received_data_len() const { return last_received_data_len_; }
|
||||
cricket::ReceiveDataParams last_received_data_params() const {
|
||||
return last_received_data_params_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool has_received_data_;
|
||||
std::string last_received_data_;
|
||||
size_t last_received_data_len_;
|
||||
cricket::ReceiveDataParams last_received_data_params_;
|
||||
};
|
||||
|
||||
class RtpDataMediaChannelTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
// Seed needed for each test to satisfy expectations.
|
||||
iface_.reset(new cricket::FakeNetworkInterface());
|
||||
dme_.reset(CreateEngine());
|
||||
receiver_.reset(new FakeDataReceiver());
|
||||
}
|
||||
|
||||
void SetNow(double now) { clock_.SetTime(webrtc::Timestamp::Seconds(now)); }
|
||||
|
||||
cricket::RtpDataEngine* CreateEngine() {
|
||||
cricket::RtpDataEngine* dme = new cricket::RtpDataEngine();
|
||||
return dme;
|
||||
}
|
||||
|
||||
cricket::RtpDataMediaChannel* CreateChannel() {
|
||||
return CreateChannel(dme_.get());
|
||||
}
|
||||
|
||||
cricket::RtpDataMediaChannel* CreateChannel(cricket::RtpDataEngine* dme) {
|
||||
cricket::MediaConfig config;
|
||||
cricket::RtpDataMediaChannel* channel =
|
||||
static_cast<cricket::RtpDataMediaChannel*>(dme->CreateChannel(config));
|
||||
channel->SetInterface(iface_.get());
|
||||
channel->SignalDataReceived.connect(receiver_.get(),
|
||||
&FakeDataReceiver::OnDataReceived);
|
||||
return channel;
|
||||
}
|
||||
|
||||
FakeDataReceiver* receiver() { return receiver_.get(); }
|
||||
|
||||
bool HasReceivedData() { return receiver_->has_received_data(); }
|
||||
|
||||
std::string GetReceivedData() { return receiver_->last_received_data(); }
|
||||
|
||||
size_t GetReceivedDataLen() { return receiver_->last_received_data_len(); }
|
||||
|
||||
cricket::ReceiveDataParams GetReceivedDataParams() {
|
||||
return receiver_->last_received_data_params();
|
||||
}
|
||||
|
||||
bool HasSentData(int count) { return (iface_->NumRtpPackets() > count); }
|
||||
|
||||
std::string GetSentData(int index) {
|
||||
// Assume RTP header of length 12
|
||||
std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
|
||||
iface_->GetRtpPacket(index));
|
||||
if (packet->size() > 12) {
|
||||
return std::string(packet->data<char>() + 12, packet->size() - 12);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
cricket::RtpHeader GetSentDataHeader(int index) {
|
||||
std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
|
||||
iface_->GetRtpPacket(index));
|
||||
cricket::RtpHeader header;
|
||||
GetRtpHeader(packet->data(), packet->size(), &header);
|
||||
return header;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<cricket::RtpDataEngine> dme_;
|
||||
rtc::ScopedFakeClock clock_;
|
||||
std::unique_ptr<cricket::FakeNetworkInterface> iface_;
|
||||
std::unique_ptr<FakeDataReceiver> receiver_;
|
||||
};
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, SetUnknownCodecs) {
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
cricket::DataCodec known_codec;
|
||||
known_codec.id = 103;
|
||||
known_codec.name = "google-data";
|
||||
cricket::DataCodec unknown_codec;
|
||||
unknown_codec.id = 104;
|
||||
unknown_codec.name = "unknown-data";
|
||||
|
||||
cricket::DataSendParameters send_parameters_known;
|
||||
send_parameters_known.codecs.push_back(known_codec);
|
||||
cricket::DataRecvParameters recv_parameters_known;
|
||||
recv_parameters_known.codecs.push_back(known_codec);
|
||||
|
||||
cricket::DataSendParameters send_parameters_unknown;
|
||||
send_parameters_unknown.codecs.push_back(unknown_codec);
|
||||
cricket::DataRecvParameters recv_parameters_unknown;
|
||||
recv_parameters_unknown.codecs.push_back(unknown_codec);
|
||||
|
||||
cricket::DataSendParameters send_parameters_mixed;
|
||||
send_parameters_mixed.codecs.push_back(known_codec);
|
||||
send_parameters_mixed.codecs.push_back(unknown_codec);
|
||||
cricket::DataRecvParameters recv_parameters_mixed;
|
||||
recv_parameters_mixed.codecs.push_back(known_codec);
|
||||
recv_parameters_mixed.codecs.push_back(unknown_codec);
|
||||
|
||||
EXPECT_TRUE(dmc->SetSendParameters(send_parameters_known));
|
||||
EXPECT_FALSE(dmc->SetSendParameters(send_parameters_unknown));
|
||||
EXPECT_TRUE(dmc->SetSendParameters(send_parameters_mixed));
|
||||
EXPECT_TRUE(dmc->SetRecvParameters(recv_parameters_known));
|
||||
EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_unknown));
|
||||
EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_mixed));
|
||||
}
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, AddRemoveSendStream) {
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
cricket::StreamParams stream1;
|
||||
stream1.add_ssrc(41);
|
||||
EXPECT_TRUE(dmc->AddSendStream(stream1));
|
||||
cricket::StreamParams stream2;
|
||||
stream2.add_ssrc(42);
|
||||
EXPECT_TRUE(dmc->AddSendStream(stream2));
|
||||
|
||||
EXPECT_TRUE(dmc->RemoveSendStream(41));
|
||||
EXPECT_TRUE(dmc->RemoveSendStream(42));
|
||||
EXPECT_FALSE(dmc->RemoveSendStream(43));
|
||||
}
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, AddRemoveRecvStream) {
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
cricket::StreamParams stream1;
|
||||
stream1.add_ssrc(41);
|
||||
EXPECT_TRUE(dmc->AddRecvStream(stream1));
|
||||
cricket::StreamParams stream2;
|
||||
stream2.add_ssrc(42);
|
||||
EXPECT_TRUE(dmc->AddRecvStream(stream2));
|
||||
EXPECT_FALSE(dmc->AddRecvStream(stream2));
|
||||
|
||||
EXPECT_TRUE(dmc->RemoveRecvStream(41));
|
||||
EXPECT_TRUE(dmc->RemoveRecvStream(42));
|
||||
}
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, SendData) {
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
cricket::SendDataParams params;
|
||||
params.ssrc = 42;
|
||||
unsigned char data[] = "food";
|
||||
rtc::CopyOnWriteBuffer payload(data, 4);
|
||||
unsigned char padded_data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 'f', 'o', 'o', 'd',
|
||||
};
|
||||
cricket::SendDataResult result;
|
||||
|
||||
// Not sending
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_EQ(cricket::SDR_ERROR, result);
|
||||
EXPECT_FALSE(HasSentData(0));
|
||||
ASSERT_TRUE(dmc->SetSend(true));
|
||||
|
||||
// Unknown stream name.
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_EQ(cricket::SDR_ERROR, result);
|
||||
EXPECT_FALSE(HasSentData(0));
|
||||
|
||||
cricket::StreamParams stream;
|
||||
stream.add_ssrc(42);
|
||||
ASSERT_TRUE(dmc->AddSendStream(stream));
|
||||
|
||||
// Unknown codec;
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_EQ(cricket::SDR_ERROR, result);
|
||||
EXPECT_FALSE(HasSentData(0));
|
||||
|
||||
cricket::DataCodec codec;
|
||||
codec.id = 103;
|
||||
codec.name = cricket::kGoogleRtpDataCodecName;
|
||||
cricket::DataSendParameters parameters;
|
||||
parameters.codecs.push_back(codec);
|
||||
ASSERT_TRUE(dmc->SetSendParameters(parameters));
|
||||
|
||||
// Length too large;
|
||||
std::string x10000(10000, 'x');
|
||||
EXPECT_FALSE(dmc->SendData(
|
||||
params, rtc::CopyOnWriteBuffer(x10000.data(), x10000.length()), &result));
|
||||
EXPECT_EQ(cricket::SDR_ERROR, result);
|
||||
EXPECT_FALSE(HasSentData(0));
|
||||
|
||||
// Finally works!
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_EQ(cricket::SDR_SUCCESS, result);
|
||||
ASSERT_TRUE(HasSentData(0));
|
||||
EXPECT_EQ(sizeof(padded_data), GetSentData(0).length());
|
||||
EXPECT_EQ(0, memcmp(padded_data, GetSentData(0).data(), sizeof(padded_data)));
|
||||
cricket::RtpHeader header0 = GetSentDataHeader(0);
|
||||
EXPECT_NE(0, header0.seq_num);
|
||||
EXPECT_NE(0U, header0.timestamp);
|
||||
EXPECT_EQ(header0.ssrc, 42U);
|
||||
EXPECT_EQ(header0.payload_type, 103);
|
||||
|
||||
// Should bump timestamp by 180000 because the clock rate is 90khz.
|
||||
SetNow(2);
|
||||
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
ASSERT_TRUE(HasSentData(1));
|
||||
EXPECT_EQ(sizeof(padded_data), GetSentData(1).length());
|
||||
EXPECT_EQ(0, memcmp(padded_data, GetSentData(1).data(), sizeof(padded_data)));
|
||||
cricket::RtpHeader header1 = GetSentDataHeader(1);
|
||||
EXPECT_EQ(header1.ssrc, 42U);
|
||||
EXPECT_EQ(header1.payload_type, 103);
|
||||
EXPECT_EQ(static_cast<uint16_t>(header0.seq_num + 1),
|
||||
static_cast<uint16_t>(header1.seq_num));
|
||||
EXPECT_EQ(header0.timestamp + 180000, header1.timestamp);
|
||||
}
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, SendDataRate) {
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
ASSERT_TRUE(dmc->SetSend(true));
|
||||
|
||||
cricket::DataCodec codec;
|
||||
codec.id = 103;
|
||||
codec.name = cricket::kGoogleRtpDataCodecName;
|
||||
cricket::DataSendParameters parameters;
|
||||
parameters.codecs.push_back(codec);
|
||||
ASSERT_TRUE(dmc->SetSendParameters(parameters));
|
||||
|
||||
cricket::StreamParams stream;
|
||||
stream.add_ssrc(42);
|
||||
ASSERT_TRUE(dmc->AddSendStream(stream));
|
||||
|
||||
cricket::SendDataParams params;
|
||||
params.ssrc = 42;
|
||||
unsigned char data[] = "food";
|
||||
rtc::CopyOnWriteBuffer payload(data, 4);
|
||||
cricket::SendDataResult result;
|
||||
|
||||
// With rtp overhead of 32 bytes, each one of our packets is 36
|
||||
// bytes, or 288 bits. So, a limit of 872bps will allow 3 packets,
|
||||
// but not four.
|
||||
parameters.max_bandwidth_bps = 872;
|
||||
ASSERT_TRUE(dmc->SetSendParameters(parameters));
|
||||
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
|
||||
SetNow(0.9);
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
|
||||
SetNow(1.1);
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
SetNow(1.9);
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
|
||||
SetNow(2.2);
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_TRUE(dmc->SendData(params, payload, &result));
|
||||
EXPECT_FALSE(dmc->SendData(params, payload, &result));
|
||||
}
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, ReceiveData) {
|
||||
// PT= 103, SN=2, TS=3, SSRC = 4, data = "abcde"
|
||||
unsigned char data[] = {0x80, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00,
|
||||
0x00, 0x00, 'a', 'b', 'c', 'd', 'e'};
|
||||
rtc::CopyOnWriteBuffer packet(data, sizeof(data));
|
||||
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
// SetReceived not called.
|
||||
dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
|
||||
EXPECT_FALSE(HasReceivedData());
|
||||
|
||||
dmc->SetReceive(true);
|
||||
|
||||
// Unknown payload id
|
||||
dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
|
||||
EXPECT_FALSE(HasReceivedData());
|
||||
|
||||
cricket::DataCodec codec;
|
||||
codec.id = 103;
|
||||
codec.name = cricket::kGoogleRtpDataCodecName;
|
||||
cricket::DataRecvParameters parameters;
|
||||
parameters.codecs.push_back(codec);
|
||||
ASSERT_TRUE(dmc->SetRecvParameters(parameters));
|
||||
|
||||
// Unknown stream
|
||||
dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
|
||||
EXPECT_FALSE(HasReceivedData());
|
||||
|
||||
cricket::StreamParams stream;
|
||||
stream.add_ssrc(42);
|
||||
ASSERT_TRUE(dmc->AddRecvStream(stream));
|
||||
|
||||
// Finally works!
|
||||
dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
|
||||
EXPECT_TRUE(HasReceivedData());
|
||||
EXPECT_EQ("abcde", GetReceivedData());
|
||||
EXPECT_EQ(5U, GetReceivedDataLen());
|
||||
}
|
||||
|
||||
TEST_F(RtpDataMediaChannelTest, InvalidRtpPackets) {
|
||||
unsigned char data[] = {0x80, 0x65, 0x00, 0x02};
|
||||
rtc::CopyOnWriteBuffer packet(data, sizeof(data));
|
||||
|
||||
std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
|
||||
|
||||
// Too short
|
||||
dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
|
||||
EXPECT_FALSE(HasReceivedData());
|
||||
}
|
||||
Reference in New Issue
Block a user