* Copyright (c) 2017 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 "call/rtp_demuxer.h"
#include <memory>
#include <set>
#include <string>
#include "absl/strings/string_view.h"
#include "call/test/mock_rtp_packet_sink_interface.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::testing::_;
using ::testing::AtLeast;
using ::testing::InSequence;
using ::testing::NiceMock;
class RtpDemuxerTest : public ::testing::Test {
protected:
~RtpDemuxerTest() {
for (auto* sink : sinks_to_tear_down_) {
demuxer_.RemoveSink(sink);
}
}
bool AddSink(const RtpDemuxerCriteria& criteria,
RtpPacketSinkInterface* sink) {
bool added = demuxer_.AddSink(criteria, sink);
if (added) {
sinks_to_tear_down_.insert(sink);
}
return added;
}
bool AddSinkOnlySsrc(uint32_t ssrc, RtpPacketSinkInterface* sink) {
RtpDemuxerCriteria criteria;
criteria.ssrcs().insert(ssrc);
return AddSink(criteria, sink);
}
bool AddSinkOnlyRsid(absl::string_view rsid, RtpPacketSinkInterface* sink) {
RtpDemuxerCriteria criteria(absl::string_view(), rsid);
return AddSink(criteria, sink);
}
bool AddSinkOnlyMid(absl::string_view mid, RtpPacketSinkInterface* sink) {
RtpDemuxerCriteria criteria(mid);
return AddSink(criteria, sink);
}
bool AddSinkBothMidRsid(absl::string_view mid,
absl::string_view rsid,
RtpPacketSinkInterface* sink) {
RtpDemuxerCriteria criteria(mid, rsid);
return AddSink(criteria, sink);
}
bool RemoveSink(RtpPacketSinkInterface* sink) {
sinks_to_tear_down_.erase(sink);
return demuxer_.RemoveSink(sink);
}
std::unique_ptr<RtpPacketReceived> CreatePacket(
uint32_t ssrc,
RtpPacketReceived::ExtensionManager* extension_manager) {
auto packet = std::make_unique<RtpPacketReceived>(extension_manager);
packet->SetSsrc(ssrc);
packet->SetSequenceNumber(next_sequence_number_++);
return packet;
}
std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrc(uint32_t ssrc) {
return CreatePacket(ssrc, nullptr);
}
std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcMid(
uint32_t ssrc,
absl::string_view mid) {
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.Register<RtpMid>(11);
auto packet = CreatePacket(ssrc, &extension_manager);
packet->SetExtension<RtpMid>(mid);
return packet;
}
std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcRsid(
uint32_t ssrc,
absl::string_view rsid) {
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.Register<RtpStreamId>(6);
auto packet = CreatePacket(ssrc, &extension_manager);
packet->SetExtension<RtpStreamId>(rsid);
return packet;
}
std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcRrid(
uint32_t ssrc,
absl::string_view rrid) {
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.Register<RepairedRtpStreamId>(7);
auto packet = CreatePacket(ssrc, &extension_manager);
packet->SetExtension<RepairedRtpStreamId>(rrid);
return packet;
}
std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcMidRsid(
uint32_t ssrc,
absl::string_view mid,
absl::string_view rsid) {
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.Register<RtpMid>(11);
extension_manager.Register<RtpStreamId>(6);
auto packet = CreatePacket(ssrc, &extension_manager);
packet->SetExtension<RtpMid>(mid);
packet->SetExtension<RtpStreamId>(rsid);
return packet;
}
std::unique_ptr<RtpPacketReceived> CreatePacketWithSsrcRsidRrid(
uint32_t ssrc,
absl::string_view rsid,
absl::string_view rrid) {
RtpPacketReceived::ExtensionManager extension_manager;
extension_manager.Register<RtpStreamId>(6);
extension_manager.Register<RepairedRtpStreamId>(7);
auto packet = CreatePacket(ssrc, &extension_manager);
packet->SetExtension<RtpStreamId>(rsid);
packet->SetExtension<RepairedRtpStreamId>(rrid);
return packet;
}
RtpDemuxer demuxer_;
std::set<RtpPacketSinkInterface*> sinks_to_tear_down_;
uint16_t next_sequence_number_ = 1;
};
class RtpDemuxerDeathTest : public RtpDemuxerTest {};
MATCHER_P(SamePacketAs, other, "") {
return arg.Ssrc() == other.Ssrc() &&
arg.SequenceNumber() == other.SequenceNumber();
}
TEST_F(RtpDemuxerTest, CanAddSinkBySsrc) {
MockRtpPacketSink sink;
constexpr uint32_t ssrc = 1;
EXPECT_TRUE(AddSinkOnlySsrc(ssrc, &sink));
}
TEST_F(RtpDemuxerTest, AllowAddSinkWithOverlappingPayloadTypesIfDifferentMid) {
const std::string mid1 = "v";
const std::string mid2 = "a";
constexpr uint8_t pt1 = 30;
constexpr uint8_t pt2 = 31;
constexpr uint8_t pt3 = 32;
RtpDemuxerCriteria pt1_pt2(mid1);
pt1_pt2.payload_types() = {pt1, pt2};
MockRtpPacketSink sink1;
AddSink(pt1_pt2, &sink1);
RtpDemuxerCriteria pt1_pt3(mid2);
pt1_pt3.payload_types() = {pt1, pt3};
MockRtpPacketSink sink2;
EXPECT_TRUE(AddSink(pt1_pt3, &sink2));
}
TEST_F(RtpDemuxerTest, RejectAddSinkForSameMidOnly) {
const std::string mid = "mid";
MockRtpPacketSink sink;
AddSinkOnlyMid(mid, &sink);
EXPECT_FALSE(AddSinkOnlyMid(mid, &sink));
}
TEST_F(RtpDemuxerTest, RejectAddSinkForSameMidRsid) {
const std::string mid = "v";
const std::string rsid = "1";
MockRtpPacketSink sink1;
AddSinkBothMidRsid(mid, rsid, &sink1);
MockRtpPacketSink sink2;
EXPECT_FALSE(AddSinkBothMidRsid(mid, rsid, &sink2));
}
TEST_F(RtpDemuxerTest, RejectAddSinkForConflictingMidAndMidRsid) {
const std::string mid = "v";
const std::string rsid = "1";
MockRtpPacketSink mid_sink;
AddSinkOnlyMid(mid, &mid_sink);
MockRtpPacketSink mid_rsid_sink;
EXPECT_FALSE(AddSinkBothMidRsid(mid, rsid, &mid_rsid_sink));
}
TEST_F(RtpDemuxerTest, RejectAddSinkForConflictingMidRsidAndMid) {
const std::string mid = "v";
const std::string rsid = "";
MockRtpPacketSink mid_rsid_sink;
AddSinkBothMidRsid(mid, rsid, &mid_rsid_sink);
MockRtpPacketSink mid_sink;
EXPECT_FALSE(AddSinkOnlyMid(mid, &mid_sink));
}
TEST_F(RtpDemuxerTest, AddSinkFailsIfCalledForTwoSinksWithSameSsrc) {
MockRtpPacketSink sink_a;
MockRtpPacketSink sink_b;
constexpr uint32_t ssrc = 1;
ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sink_a));
EXPECT_FALSE(AddSinkOnlySsrc(ssrc, &sink_b));
}
TEST_F(RtpDemuxerTest, AddSinkFailsIfCalledTwiceEvenIfSameSinkWithSameSsrc) {
MockRtpPacketSink sink;
constexpr uint32_t ssrc = 1;
ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sink));
EXPECT_FALSE(AddSinkOnlySsrc(ssrc, &sink));
}
TEST_F(RtpDemuxerTest, DISABLED_RejectAddSinkForSamePayloadTypes) {
constexpr uint8_t pt1 = 30;
constexpr uint8_t pt2 = 31;
RtpDemuxerCriteria pt1_pt2;
pt1_pt2.payload_types() = {pt1, pt2};
MockRtpPacketSink sink1;
AddSink(pt1_pt2, &sink1);
RtpDemuxerCriteria pt2_pt1;
pt2_pt1.payload_types() = {pt2, pt1};
MockRtpPacketSink sink2;
EXPECT_FALSE(AddSink(pt2_pt1, &sink2));
}
TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkBySsrc) {
constexpr uint32_t ssrcs[] = {101, 202, 303};
MockRtpPacketSink sinks[arraysize(ssrcs)];
for (size_t i = 0; i < arraysize(ssrcs); i++) {
AddSinkOnlySsrc(ssrcs[i], &sinks[i]);
}
for (size_t i = 0; i < arraysize(ssrcs); i++) {
auto packet = CreatePacketWithSsrc(ssrcs[i]);
EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByRsid) {
const std::string rsids[] = {"a", "b", "c"};
MockRtpPacketSink sinks[arraysize(rsids)];
for (size_t i = 0; i < arraysize(rsids); i++) {
AddSinkOnlyRsid(rsids[i], &sinks[i]);
}
for (size_t i = 0; i < arraysize(rsids); i++) {
auto packet =
CreatePacketWithSsrcRsid(rtc::checked_cast<uint32_t>(i), rsids[i]);
EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByMid) {
const std::string mids[] = {"a", "v", "s"};
MockRtpPacketSink sinks[arraysize(mids)];
for (size_t i = 0; i < arraysize(mids); i++) {
AddSinkOnlyMid(mids[i], &sinks[i]);
}
for (size_t i = 0; i < arraysize(mids); i++) {
auto packet =
CreatePacketWithSsrcMid(rtc::checked_cast<uint32_t>(i), mids[i]);
EXPECT_CALL(sinks[i], OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByMidAndRsid) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
MockRtpPacketSink sink;
AddSinkBothMidRsid(mid, rsid, &sink);
auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByRepairedRsid) {
const std::string rrid = "1";
constexpr uint32_t ssrc = 10;
MockRtpPacketSink sink;
AddSinkOnlyRsid(rrid, &sink);
auto packet_with_rrid = CreatePacketWithSsrcRrid(ssrc, rrid);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_rrid))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_rrid));
}
TEST_F(RtpDemuxerTest, OnRtpPacketCalledOnCorrectSinkByPayloadType) {
constexpr uint32_t ssrc = 10;
constexpr uint8_t payload_type = 30;
MockRtpPacketSink sink;
RtpDemuxerCriteria criteria;
criteria.payload_types() = {payload_type};
AddSink(criteria, &sink);
auto packet = CreatePacketWithSsrc(ssrc);
packet->SetPayloadType(payload_type);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, PacketsDeliveredInRightOrder) {
constexpr uint32_t ssrc = 101;
MockRtpPacketSink sink;
AddSinkOnlySsrc(ssrc, &sink);
std::unique_ptr<RtpPacketReceived> packets[5];
for (size_t i = 0; i < arraysize(packets); i++) {
packets[i] = CreatePacketWithSsrc(ssrc);
packets[i]->SetSequenceNumber(rtc::checked_cast<uint16_t>(i));
}
InSequence sequence;
for (const auto& packet : packets) {
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
}
for (const auto& packet : packets) {
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, SinkMappedToMultipleSsrcs) {
constexpr uint32_t ssrcs[] = {404, 505, 606};
MockRtpPacketSink sink;
for (uint32_t ssrc : ssrcs) {
AddSinkOnlySsrc(ssrc, &sink);
}
for (uint32_t ssrc : ssrcs) {
auto packet = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedBeforeFirstPacket) {
constexpr uint32_t ssrc = 404;
MockRtpPacketSink sink;
AddSinkOnlySsrc(ssrc, &sink);
ASSERT_TRUE(RemoveSink(&sink));
auto packet = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, NoCallbackOnSsrcSinkRemovedAfterFirstPacket) {
constexpr uint32_t ssrc = 404;
NiceMock<MockRtpPacketSink> sink;
AddSinkOnlySsrc(ssrc, &sink);
InSequence sequence;
for (size_t i = 0; i < 10; i++) {
ASSERT_TRUE(demuxer_.OnRtpPacket(*CreatePacketWithSsrc(ssrc)));
}
ASSERT_TRUE(RemoveSink(&sink));
auto packet = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, OnlyOneSinkPerSsrcGetsOnRtpPacketTriggered) {
MockRtpPacketSink sinks[3];
constexpr uint32_t ssrc = 404;
ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sinks[0]));
ASSERT_FALSE(AddSinkOnlySsrc(ssrc, &sinks[1]));
ASSERT_FALSE(AddSinkOnlySsrc(ssrc, &sinks[2]));
auto packet = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sinks[0], OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_CALL(sinks[1], OnRtpPacket(_)).Times(0);
EXPECT_CALL(sinks[2], OnRtpPacket(_)).Times(0);
ASSERT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, NoRepeatedCallbackOnRepeatedAddSinkForSameSink) {
constexpr uint32_t ssrc = 111;
MockRtpPacketSink sink;
ASSERT_TRUE(AddSinkOnlySsrc(ssrc, &sink));
ASSERT_FALSE(AddSinkOnlySsrc(ssrc, &sink));
auto packet = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, RemoveSinkReturnsFalseForNeverAddedSink) {
MockRtpPacketSink sink;
EXPECT_FALSE(RemoveSink(&sink));
}
TEST_F(RtpDemuxerTest, RemoveSinkReturnsTrueForPreviouslyAddedSsrcSink) {
constexpr uint32_t ssrc = 101;
MockRtpPacketSink sink;
AddSinkOnlySsrc(ssrc, &sink);
EXPECT_TRUE(RemoveSink(&sink));
}
TEST_F(RtpDemuxerTest,
RemoveSinkReturnsTrueForUnresolvedPreviouslyAddedRsidSink) {
const std::string rsid = "a";
MockRtpPacketSink sink;
AddSinkOnlyRsid(rsid, &sink);
EXPECT_TRUE(RemoveSink(&sink));
}
TEST_F(RtpDemuxerTest,
RemoveSinkReturnsTrueForResolvedPreviouslyAddedRsidSink) {
const std::string rsid = "a";
constexpr uint32_t ssrc = 101;
NiceMock<MockRtpPacketSink> sink;
AddSinkOnlyRsid(rsid, &sink);
ASSERT_TRUE(demuxer_.OnRtpPacket(*CreatePacketWithSsrcRsid(ssrc, rsid)));
EXPECT_TRUE(RemoveSink(&sink));
}
TEST_F(RtpDemuxerTest, RsidLearnedAndLaterPacketsDeliveredWithOnlySsrc) {
MockRtpPacketSink sink;
const std::string rsid = "a";
AddSinkOnlyRsid(rsid, &sink);
std::unique_ptr<RtpPacketReceived> packets[5];
constexpr uint32_t rsid_ssrc = 111;
packets[0] = CreatePacketWithSsrcRsid(rsid_ssrc, rsid);
for (size_t i = 1; i < arraysize(packets); i++) {
packets[i] = CreatePacketWithSsrc(rsid_ssrc);
}
InSequence sequence;
for (const auto& packet : packets) {
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
}
for (const auto& packet : packets) {
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedBeforeFirstPacket) {
MockRtpPacketSink sink;
const std::string rsid = "a";
AddSinkOnlyRsid(rsid, &sink);
ASSERT_TRUE(RemoveSink(&sink));
constexpr uint32_t ssrc = 111;
auto packet = CreatePacketWithSsrcRsid(ssrc, rsid);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, NoCallbackOnRsidSinkRemovedAfterFirstPacket) {
NiceMock<MockRtpPacketSink> sink;
const std::string rsid = "a";
AddSinkOnlyRsid(rsid, &sink);
InSequence sequence;
constexpr uint32_t ssrc = 111;
for (size_t i = 0; i < 10; i++) {
auto packet = CreatePacketWithSsrcRsid(ssrc, rsid);
ASSERT_TRUE(demuxer_.OnRtpPacket(*packet));
}
ASSERT_TRUE(RemoveSink(&sink));
auto packet = CreatePacketWithSsrcRsid(ssrc, rsid);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, NoCallbackOnMidSinkRemovedBeforeFirstPacket) {
const std::string mid = "v";
constexpr uint32_t ssrc = 10;
MockRtpPacketSink sink;
AddSinkOnlyMid(mid, &sink);
RemoveSink(&sink);
auto packet = CreatePacketWithSsrcMid(ssrc, mid);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, NoCallbackOnMidSinkRemovedAfterFirstPacket) {
const std::string mid = "v";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink;
AddSinkOnlyMid(mid, &sink);
auto p1 = CreatePacketWithSsrcMid(ssrc, mid);
demuxer_.OnRtpPacket(*p1);
RemoveSink(&sink);
auto p2 = CreatePacketWithSsrcMid(ssrc, mid);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*p2));
}
TEST_F(RtpDemuxerTest, NoCallbackOnMidRsidSinkRemovedAfterFirstPacket) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink;
AddSinkBothMidRsid(mid, rsid, &sink);
auto p1 = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid);
demuxer_.OnRtpPacket(*p1);
RemoveSink(&sink);
auto p2 = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*p2));
}
TEST_F(RtpDemuxerTest, FirstSsrcAssociatedWithAnRsidIsNotForgotten) {
MockRtpPacketSink sink_a;
const std::string rsid_a = "a";
AddSinkOnlyRsid(rsid_a, &sink_a);
MockRtpPacketSink sink_b;
const std::string rsid_b = "b";
AddSinkOnlyRsid(rsid_b, &sink_b);
InSequence sequence;
constexpr uint32_t shared_ssrc = 100;
auto packet_a = CreatePacketWithSsrcRsid(shared_ssrc, rsid_a);
EXPECT_CALL(sink_a, OnRtpPacket(SamePacketAs(*packet_a))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_a));
auto packet_b = CreatePacketWithSsrcRsid(shared_ssrc, rsid_b);
EXPECT_CALL(sink_a, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink_b, OnRtpPacket(SamePacketAs(*packet_b))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_b));
MockRtpPacketSink sink_c;
const std::string rsid_c = "c";
constexpr uint32_t some_other_ssrc = shared_ssrc + 1;
AddSinkOnlySsrc(some_other_ssrc, &sink_c);
auto packet_c = CreatePacketWithSsrcMid(shared_ssrc, rsid_c);
EXPECT_CALL(sink_a, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink_b, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink_c, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet_c));
}
TEST_F(RtpDemuxerTest, MultipleRsidsOnSameSink) {
MockRtpPacketSink sink;
const std::string rsids[] = {"a", "b", "c"};
for (const std::string& rsid : rsids) {
AddSinkOnlyRsid(rsid, &sink);
}
InSequence sequence;
for (size_t i = 0; i < arraysize(rsids); i++) {
const uint32_t ssrc = 1000 + static_cast<uint32_t>(i);
const uint16_t sequence_number = 50 + static_cast<uint16_t>(i);
auto packet = CreatePacketWithSsrcRsid(ssrc, rsids[i]);
packet->SetSequenceNumber(sequence_number);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
}
TEST_F(RtpDemuxerTest, SinkWithBothRsidAndSsrcAssociations) {
MockRtpPacketSink sink;
constexpr uint32_t standalone_ssrc = 10101;
constexpr uint32_t rsid_ssrc = 20202;
const std::string rsid = "1";
AddSinkOnlySsrc(standalone_ssrc, &sink);
AddSinkOnlyRsid(rsid, &sink);
InSequence sequence;
auto ssrc_packet = CreatePacketWithSsrc(standalone_ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*ssrc_packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*ssrc_packet));
auto rsid_packet = CreatePacketWithSsrcRsid(rsid_ssrc, rsid);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*rsid_packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*rsid_packet));
}
TEST_F(RtpDemuxerTest, AssociatingByRsidAndBySsrcCannotTriggerDoubleCall) {
constexpr uint32_t ssrc = 10101;
const std::string rsid = "a";
MockRtpPacketSink sink;
AddSinkOnlySsrc(ssrc, &sink);
AddSinkOnlyRsid(rsid, &sink);
auto packet = CreatePacketWithSsrcRsid(ssrc, rsid);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest,
PacketFittingBothRsidSinkAndSsrcSinkGivenOnlyToRsidSink) {
constexpr uint32_t ssrc = 111;
MockRtpPacketSink ssrc_sink;
AddSinkOnlySsrc(ssrc, &ssrc_sink);
const std::string rsid = "a";
MockRtpPacketSink rsid_sink;
AddSinkOnlyRsid(rsid, &rsid_sink);
auto packet = CreatePacketWithSsrcRsid(ssrc, rsid);
EXPECT_CALL(ssrc_sink, OnRtpPacket(_)).Times(0);
EXPECT_CALL(rsid_sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest,
GracefullyHandleRsidBeingMappedToPrevouslyAssociatedSsrc) {
constexpr uint32_t ssrc = 111;
NiceMock<MockRtpPacketSink> ssrc_sink;
AddSinkOnlySsrc(ssrc, &ssrc_sink);
const std::string rsid = "a";
NiceMock<MockRtpPacketSink> rsid_sink;
AddSinkOnlyRsid(rsid, &rsid_sink);
auto packet = CreatePacketWithSsrcRsid(ssrc, rsid);
demuxer_.OnRtpPacket(*packet);
RemoveSink(&ssrc_sink);
EXPECT_CALL(rsid_sink, OnRtpPacket(SamePacketAs(*packet))).Times(AtLeast(0));
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, RoutedByMidWhenSsrcAdded) {
const std::string mid = "v";
NiceMock<MockRtpPacketSink> sink;
AddSinkOnlyMid(mid, &sink);
constexpr uint32_t ssrc1 = 10;
constexpr uint32_t ssrc2 = 11;
auto packet_ssrc1_mid = CreatePacketWithSsrcMid(ssrc1, mid);
demuxer_.OnRtpPacket(*packet_ssrc1_mid);
auto packet_ssrc2_mid = CreatePacketWithSsrcMid(ssrc2, mid);
demuxer_.OnRtpPacket(*packet_ssrc2_mid);
auto packet_ssrc1_only = CreatePacketWithSsrc(ssrc1);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc1_only))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc1_only));
auto packet_ssrc2_only = CreatePacketWithSsrc(ssrc2);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc2_only))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc2_only));
}
TEST_F(RtpDemuxerTest, DontLearnMidSsrcBindingBeforeSinkAdded) {
const std::string mid = "v";
constexpr uint32_t ssrc = 10;
auto packet_ssrc_mid = CreatePacketWithSsrcMid(ssrc, mid);
ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_ssrc_mid));
MockRtpPacketSink sink;
AddSinkOnlyMid(mid, &sink);
auto packet_ssrc_only = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet_ssrc_only));
}
TEST_F(RtpDemuxerTest, DontForgetMidSsrcBindingWhenSinkRemoved) {
const std::string mid = "v";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink1;
AddSinkOnlyMid(mid, &sink1);
auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid);
demuxer_.OnRtpPacket(*packet_with_mid);
RemoveSink(&sink1);
MockRtpPacketSink sink2;
AddSinkOnlyMid(mid, &sink2);
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink2, OnRtpPacket(SamePacketAs(*packet_with_ssrc)));
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, RoutedByMidWithAnyRsid) {
const std::string mid = "v";
const std::string rsid1 = "1";
const std::string rsid2 = "2";
constexpr uint32_t ssrc1 = 10;
constexpr uint32_t ssrc2 = 11;
MockRtpPacketSink sink;
AddSinkOnlyMid(mid, &sink);
InSequence sequence;
auto packet_ssrc1_rsid1 = CreatePacketWithSsrcMidRsid(ssrc1, mid, rsid1);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc1_rsid1))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc1_rsid1));
auto packet_ssrc2_rsid2 = CreatePacketWithSsrcMidRsid(ssrc2, mid, rsid2);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_ssrc2_rsid2))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc2_rsid2));
}
TEST_F(RtpDemuxerTest, LearnMidThenRsidSeparatelyAndRouteBySsrc) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink;
AddSinkBothMidRsid(mid, rsid, &sink);
auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid);
ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_with_mid));
auto packet_with_rsid = CreatePacketWithSsrcRsid(ssrc, rsid);
ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_with_rsid));
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, LearnRsidThenMidSeparatelyAndRouteBySsrc) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink;
AddSinkBothMidRsid(mid, rsid, &sink);
auto packet_with_rsid = CreatePacketWithSsrcRsid(ssrc, rsid);
ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_with_rsid));
auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid);
ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_with_mid));
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, DontLearnMidRsidBindingBeforeSinkAdded) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
auto packet_with_both = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid);
ASSERT_FALSE(demuxer_.OnRtpPacket(*packet_with_both));
MockRtpPacketSink sink;
AddSinkBothMidRsid(mid, rsid, &sink);
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, DontForgetMidRsidBindingWhenSinkRemoved) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink1;
AddSinkBothMidRsid(mid, rsid, &sink1);
auto packet_with_both = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid);
demuxer_.OnRtpPacket(*packet_with_both);
RemoveSink(&sink1);
MockRtpPacketSink sink2;
AddSinkBothMidRsid(mid, rsid, &sink2);
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink2, OnRtpPacket(SamePacketAs(*packet_with_ssrc)));
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, LearnMidRsidBindingAfterSinkAdded) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
NiceMock<MockRtpPacketSink> sink;
AddSinkBothMidRsid(mid, rsid, &sink);
auto packet_with_both = CreatePacketWithSsrcMidRsid(ssrc, mid, rsid);
demuxer_.OnRtpPacket(*packet_with_both);
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc)));
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, DropByPayloadTypeIfNoSink) {
constexpr uint8_t payload_type = 30;
constexpr uint32_t ssrc = 10;
auto packet = CreatePacketWithSsrc(ssrc);
packet->SetPayloadType(payload_type);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, DropByPayloadTypeIfAddedInMultipleSinks) {
const std::string mid1 = "v";
const std::string mid2 = "a";
constexpr uint8_t payload_type = 30;
constexpr uint32_t ssrc = 10;
RtpDemuxerCriteria mid1_pt(mid1);
mid1_pt.payload_types() = {payload_type};
MockRtpPacketSink sink1;
AddSink(mid1_pt, &sink1);
RtpDemuxerCriteria mid2_pt(mid2);
mid2_pt.payload_types() = {payload_type};
MockRtpPacketSink sink2;
AddSink(mid2_pt, &sink2);
auto packet = CreatePacketWithSsrc(ssrc);
packet->SetPayloadType(payload_type);
EXPECT_CALL(sink1, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink2, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, RoutedByPayloadTypeIfAmbiguousSinkRemoved) {
const std::string mid1 = "v";
const std::string mid2 = "a";
constexpr uint8_t payload_type = 30;
constexpr uint32_t ssrc = 10;
RtpDemuxerCriteria mid1_pt(mid1);
mid1_pt.payload_types().insert(payload_type);
MockRtpPacketSink sink1;
AddSink(mid1_pt, &sink1);
RtpDemuxerCriteria mid2_pt(mid2);
mid2_pt.payload_types().insert(payload_type);
MockRtpPacketSink sink2;
AddSink(mid2_pt, &sink2);
RemoveSink(&sink1);
auto packet = CreatePacketWithSsrc(ssrc);
packet->SetPayloadType(payload_type);
EXPECT_CALL(sink1, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink2, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, RoutedByPayloadTypeLatchesSsrc) {
constexpr uint8_t payload_type = 30;
constexpr uint32_t ssrc = 10;
RtpDemuxerCriteria pt;
pt.payload_types().insert(payload_type);
NiceMock<MockRtpPacketSink> sink;
AddSink(pt, &sink);
auto packet_with_pt = CreatePacketWithSsrc(ssrc);
packet_with_pt->SetPayloadType(payload_type);
ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_with_pt));
auto packet_with_ssrc = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_ssrc))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_ssrc));
}
TEST_F(RtpDemuxerTest, PacketWithSameRsidDifferentMidRoutedToProperSink) {
const std::string mid1 = "mid1";
const std::string mid2 = "mid2";
const std::string rsid = "rsid";
constexpr uint32_t ssrc1 = 10;
constexpr uint32_t ssrc2 = 11;
NiceMock<MockRtpPacketSink> mid1_sink;
AddSinkBothMidRsid(mid1, rsid, &mid1_sink);
MockRtpPacketSink mid2_sink;
AddSinkBothMidRsid(mid2, rsid, &mid2_sink);
auto packet_mid1 = CreatePacketWithSsrcMidRsid(ssrc1, mid1, rsid);
ASSERT_TRUE(demuxer_.OnRtpPacket(*packet_mid1));
auto packet_mid2 = CreatePacketWithSsrcMidRsid(ssrc2, mid2, rsid);
EXPECT_CALL(mid2_sink, OnRtpPacket(SamePacketAs(*packet_mid2))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_mid2));
}
TEST_F(RtpDemuxerTest, SignaledMidShouldOverwriteSignaledSsrc) {
constexpr uint32_t ssrc = 11;
const std::string mid = "mid";
MockRtpPacketSink ssrc_sink;
AddSinkOnlySsrc(ssrc, &ssrc_sink);
MockRtpPacketSink mid_sink;
AddSinkOnlyMid(mid, &mid_sink);
auto p = CreatePacketWithSsrcMid(ssrc, mid);
EXPECT_CALL(ssrc_sink, OnRtpPacket(_)).Times(0);
EXPECT_CALL(mid_sink, OnRtpPacket(SamePacketAs(*p))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*p));
}
TEST_F(RtpDemuxerTest, SignaledMidShouldOverwriteSignalledSsrcPersistent) {
constexpr uint32_t ssrc = 11;
const std::string mid = "mid";
MockRtpPacketSink ssrc_sink;
AddSinkOnlySsrc(ssrc, &ssrc_sink);
NiceMock<MockRtpPacketSink> mid_sink;
AddSinkOnlyMid(mid, &mid_sink);
EXPECT_CALL(ssrc_sink, OnRtpPacket(_)).Times(0);
auto packet_with_mid = CreatePacketWithSsrcMid(ssrc, mid);
demuxer_.OnRtpPacket(*packet_with_mid);
auto packet_without_mid = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(mid_sink, OnRtpPacket(SamePacketAs(*packet_without_mid)))
.Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_without_mid));
}
TEST_F(RtpDemuxerTest, RouteByPayloadTypeMultipleMatch) {
constexpr uint32_t ssrc = 10;
constexpr uint8_t pt1 = 30;
constexpr uint8_t pt2 = 31;
MockRtpPacketSink sink;
RtpDemuxerCriteria criteria;
criteria.payload_types() = {pt1, pt2};
AddSink(criteria, &sink);
auto packet_with_pt1 = CreatePacketWithSsrc(ssrc);
packet_with_pt1->SetPayloadType(pt1);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_pt1)));
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_pt1));
auto packet_with_pt2 = CreatePacketWithSsrc(ssrc);
packet_with_pt2->SetPayloadType(pt2);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet_with_pt2)));
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_with_pt2));
}
TEST_F(RtpDemuxerTest, DontDemuxOnMidAloneIfAddedWithRsid) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
MockRtpPacketSink sink;
AddSinkBothMidRsid(mid, rsid, &sink);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
auto packet = CreatePacketWithSsrcMid(ssrc, mid);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, DemuxBySsrcEvenWithMidAndRsid) {
const std::string mid = "v";
const std::string rsid = "1";
constexpr uint32_t ssrc = 10;
RtpDemuxerCriteria criteria(mid, rsid);
criteria.ssrcs().insert(ssrc);
MockRtpPacketSink sink;
AddSink(criteria, &sink);
auto packet = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, DoNotCheckPayloadTypeIfMatchedByOtherCriteria) {
constexpr uint32_t ssrc = 10;
constexpr uint8_t payload_type = 30;
constexpr uint8_t different_payload_type = payload_type + 1;
RtpDemuxerCriteria criteria;
criteria.ssrcs().insert(ssrc);
criteria.payload_types().insert(payload_type);
MockRtpPacketSink sink;
AddSink(criteria, &sink);
auto packet = CreatePacketWithSsrc(ssrc);
packet->SetPayloadType(different_payload_type);
EXPECT_CALL(sink, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, PacketWithRsidAndRridRoutedByRrid) {
const std::string rsid = "1";
const std::string rrid = "1r";
constexpr uint32_t ssrc = 10;
MockRtpPacketSink sink_rsid;
AddSinkOnlyRsid(rsid, &sink_rsid);
MockRtpPacketSink sink_rrid;
AddSinkOnlyRsid(rrid, &sink_rrid);
auto packet = CreatePacketWithSsrcRsidRrid(ssrc, rsid, rrid);
EXPECT_CALL(sink_rsid, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink_rrid, OnRtpPacket(SamePacketAs(*packet))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, PacketWithRsidAndRridLatchesSsrcToRrid) {
const std::string rsid = "1";
const std::string rrid = "1r";
constexpr uint32_t ssrc = 10;
MockRtpPacketSink sink_rsid;
AddSinkOnlyRsid(rsid, &sink_rsid);
NiceMock<MockRtpPacketSink> sink_rrid;
AddSinkOnlyRsid(rrid, &sink_rrid);
auto packet_rsid_rrid = CreatePacketWithSsrcRsidRrid(ssrc, rsid, rrid);
demuxer_.OnRtpPacket(*packet_rsid_rrid);
auto packet_ssrc_only = CreatePacketWithSsrc(ssrc);
EXPECT_CALL(sink_rsid, OnRtpPacket(_)).Times(0);
EXPECT_CALL(sink_rrid, OnRtpPacket(SamePacketAs(*packet_ssrc_only))).Times(1);
EXPECT_TRUE(demuxer_.OnRtpPacket(*packet_ssrc_only));
}
TEST_F(RtpDemuxerTest, PacketWithMidAndUnknownRsidIsNotRoutedBySsrc) {
constexpr uint32_t ssrc = 10;
const std::string mid = "v";
const std::string rsid = "1";
const std::string wrong_rsid = "2";
RtpDemuxerCriteria criteria(mid, rsid);
criteria.ssrcs().insert(ssrc);
MockRtpPacketSink sink;
AddSink(criteria, &sink);
auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, wrong_rsid);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, PacketWithMidAndUnknownRsidIsNotRoutedByPayloadType) {
constexpr uint32_t ssrc = 10;
const std::string mid = "v";
const std::string rsid = "1";
const std::string wrong_rsid = "2";
constexpr uint8_t payload_type = 30;
RtpDemuxerCriteria criteria(mid, rsid);
criteria.payload_types().insert(payload_type);
MockRtpPacketSink sink;
AddSink(criteria, &sink);
auto packet = CreatePacketWithSsrcMidRsid(ssrc, mid, wrong_rsid);
packet->SetPayloadType(payload_type);
EXPECT_CALL(sink, OnRtpPacket(_)).Times(0);
EXPECT_FALSE(demuxer_.OnRtpPacket(*packet));
}
TEST_F(RtpDemuxerTest, MidMustNotExceedMaximumLength) {
MockRtpPacketSink sink1;
std::string mid1(BaseRtpStringExtension::kMaxValueSizeBytes + 1, 'a');
EXPECT_TRUE(AddSinkOnlyMid(mid1, &sink1));
MockRtpPacketSink sink2;
std::string mid2(mid1.substr(0, BaseRtpStringExtension::kMaxValueSizeBytes));
EXPECT_FALSE(AddSinkOnlyMid(mid2, &sink2));
EXPECT_FALSE(RemoveSink(&sink2));
EXPECT_TRUE(RemoveSink(&sink1));
}
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST_F(RtpDemuxerDeathTest, CriteriaMustBeNonEmpty) {
MockRtpPacketSink sink;
RtpDemuxerCriteria criteria;
EXPECT_DEATH(AddSink(criteria, &sink), "");
}
TEST_F(RtpDemuxerDeathTest, RsidMustBeAlphaNumeric) {
MockRtpPacketSink sink;
EXPECT_DEATH(AddSinkOnlyRsid("a_3", &sink), "");
}
TEST_F(RtpDemuxerDeathTest, MidMustBeToken) {
MockRtpPacketSink sink;
EXPECT_DEATH(AddSinkOnlyMid("a(3)", &sink), "");
}
TEST_F(RtpDemuxerDeathTest, RsidMustNotExceedMaximumLength) {
MockRtpPacketSink sink;
std::string rsid(BaseRtpStringExtension::kMaxValueSizeBytes + 1, 'a');
EXPECT_DEATH(AddSinkOnlyRsid(rsid, &sink), "");
}
#endif
}
}