(Auto)update libjingle 66138442-> 66236292

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6057 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/session/media/bundlefilter.cc b/talk/session/media/bundlefilter.cc
new file mode 100755
index 0000000..0d7927c
--- /dev/null
+++ b/talk/session/media/bundlefilter.cc
@@ -0,0 +1,114 @@
+/*
+ * libjingle
+ * Copyright 2004 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/session/media/bundlefilter.h"
+
+#include "talk/base/logging.h"
+#include "talk/media/base/rtputils.h"
+
+namespace cricket {
+
+static const uint32 kSsrc01 = 0x01;
+
+BundleFilter::BundleFilter() {
+}
+
+BundleFilter::~BundleFilter() {
+}
+
+bool BundleFilter::DemuxPacket(const char* data, size_t len, bool rtcp) {
+  // For rtp packets, we check whether the payload type can be found.
+  // For rtcp packets, we check whether the ssrc can be found or is the special
+  // value 1 except for SDES packets which always pass through. Plus, if
+  // |streams_| is empty, we will allow all rtcp packets pass through provided
+  // that they are valid rtcp packets in case that they are for early media.
+  if (!rtcp) {
+    int payload_type = 0;
+    if (!GetRtpPayloadType(data, len, &payload_type)) {
+      return false;
+    }
+    return FindPayloadType(payload_type);
+  }
+
+  // Rtcp packets using ssrc filter.
+  int pl_type = 0;
+  uint32 ssrc = 0;
+  if (!GetRtcpType(data, len, &pl_type)) return false;
+  if (pl_type == kRtcpTypeSDES) {
+    // SDES packet parsing not supported.
+    LOG(LS_INFO) << "SDES packet received for demux.";
+    return true;
+  } else {
+    if (!GetRtcpSsrc(data, len, &ssrc)) return false;
+    if (ssrc == kSsrc01) {
+      // SSRC 1 has a special meaning and indicates generic feedback on
+      // some systems and should never be dropped.  If it is forwarded
+      // incorrectly it will be ignored by lower layers anyway.
+      return true;
+    }
+  }
+  // Pass through if |streams_| is empty to allow early rtcp packets in.
+  return !HasStreams() || FindStream(ssrc);
+}
+
+void BundleFilter::AddPayloadType(int payload_type) {
+  payload_types_.insert(payload_type);
+}
+
+bool BundleFilter::AddStream(const StreamParams& stream) {
+  if (GetStreamBySsrc(streams_, stream.first_ssrc(), NULL)) {
+      LOG(LS_WARNING) << "Stream already added to filter";
+      return false;
+  }
+  streams_.push_back(stream);
+  return true;
+}
+
+bool BundleFilter::RemoveStream(uint32 ssrc) {
+  return RemoveStreamBySsrc(&streams_, ssrc);
+}
+
+bool BundleFilter::HasStreams() const {
+  return !streams_.empty();
+}
+
+bool BundleFilter::FindStream(uint32 ssrc) const {
+  if (ssrc == 0) {
+    return false;
+  }
+  return (GetStreamBySsrc(streams_, ssrc, NULL));
+}
+
+bool BundleFilter::FindPayloadType(int pl_type) const {
+  return payload_types_.find(pl_type) != payload_types_.end();
+}
+
+void BundleFilter::ClearAllPayloadTypes() {
+  payload_types_.clear();
+}
+
+}  // namespace cricket
diff --git a/talk/session/media/ssrcmuxfilter.h b/talk/session/media/bundlefilter.h
old mode 100644
new mode 100755
similarity index 76%
rename from talk/session/media/ssrcmuxfilter.h
rename to talk/session/media/bundlefilter.h
index 9420f54..34bc330
--- a/talk/session/media/ssrcmuxfilter.h
+++ b/talk/session/media/bundlefilter.h
@@ -25,9 +25,10 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TALK_SESSION_MEDIA_SSRCMUXFILTER_H_
-#define TALK_SESSION_MEDIA_SSRCMUXFILTER_H_
+#ifndef TALK_SESSION_MEDIA_BUNDLEFILTER_H_
+#define TALK_SESSION_MEDIA_BUNDLEFILTER_H_
 
+#include <set>
 #include <vector>
 
 #include "talk/base/basictypes.h"
@@ -35,33 +36,45 @@
 
 namespace cricket {
 
-// This class maintains list of recv SSRC's destined for cricket::BaseChannel.
 // In case of single RTP session and single transport channel, all session
 // ( or media) channels share a common transport channel. Hence they all get
 // SignalReadPacket when packet received on transport channel. This requires
 // cricket::BaseChannel to know all the valid sources, else media channel
 // will decode invalid packets.
-class SsrcMuxFilter {
+//
+// This class determines whether a packet is destined for cricket::BaseChannel.
+// For rtp packets, this is decided based on the payload type. For rtcp packets,
+// this is decided based on the sender ssrc values.
+class BundleFilter {
  public:
-  SsrcMuxFilter();
-  ~SsrcMuxFilter();
+  BundleFilter();
+  ~BundleFilter();
 
-  // Whether the rtp mux is active for a sdp session.
-  // Returns true if the filter contains a stream.
-  bool IsActive() const;
   // Determines packet belongs to valid cricket::BaseChannel.
   bool DemuxPacket(const char* data, size_t len, bool rtcp);
+
+  // Adds the supported payload type.
+  void AddPayloadType(int payload_type);
+
   // Adding a valid source to the filter.
   bool AddStream(const StreamParams& stream);
+
   // Removes source from the filter.
   bool RemoveStream(uint32 ssrc);
-  // Utility method added for unitest.
+
+  // Utility methods added for unitest.
+  // True if |streams_| is not empty.
+  bool HasStreams() const;
   bool FindStream(uint32 ssrc) const;
+  bool FindPayloadType(int pl_type) const;
+  void ClearAllPayloadTypes();
+
 
  private:
+  std::set<int> payload_types_;
   std::vector<StreamParams> streams_;
 };
 
 }  // namespace cricket
 
-#endif  // TALK_SESSION_MEDIA_SSRCMUXFILTER_H_
+#endif  // TALK_SESSION_MEDIA_BUNDLEFILTER_H_
diff --git a/talk/session/media/bundlefilter_unittest.cc b/talk/session/media/bundlefilter_unittest.cc
new file mode 100755
index 0000000..0386666
--- /dev/null
+++ b/talk/session/media/bundlefilter_unittest.cc
@@ -0,0 +1,196 @@
+/*
+ * libjingle
+ * Copyright 2004 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/base/gunit.h"
+#include "talk/session/media/bundlefilter.h"
+
+using cricket::StreamParams;
+
+static const int kSsrc1 = 0x1111;
+static const int kSsrc2 = 0x2222;
+static const int kSsrc3 = 0x3333;
+static const int kPayloadType1 = 0x11;
+static const int kPayloadType2 = 0x22;
+static const int kPayloadType3 = 0x33;
+
+// SSRC = 0x1111, Payload type = 0x11
+static const unsigned char kRtpPacketPt1Ssrc1[] = {
+    0x80, kPayloadType1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+    0x11,
+};
+
+// SSRC = 0x2222, Payload type = 0x22
+static const unsigned char kRtpPacketPt2Ssrc2[] = {
+    0x80, 0x80 + kPayloadType2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x22, 0x22,
+};
+
+// SSRC = 0x2222, Payload type = 0x33
+static const unsigned char kRtpPacketPt3Ssrc2[] = {
+    0x80, kPayloadType3, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
+    0x22,
+};
+
+// PT = 200 = SR, len = 28, SSRC of sender = 0x0001
+// NTP TS = 0, RTP TS = 0, packet count = 0
+static const unsigned char kRtcpPacketSrSsrc01[] = {
+    0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+};
+
+// PT = 200 = SR, len = 28, SSRC of sender = 0x2222
+// NTP TS = 0, RTP TS = 0, packet count = 0
+static const unsigned char kRtcpPacketSrSsrc2[] = {
+    0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x22, 0x22,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+};
+
+// First packet - SR = PT = 200, len = 0, SSRC of sender = 0x1111
+// NTP TS = 0, RTP TS = 0, packet count = 0
+// second packet - SDES = PT =  202, count = 0, SSRC = 0x1111, cname len = 0
+static const unsigned char kRtcpPacketCompoundSrSdesSsrc1[] = {
+    0x80, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x11, 0x11,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00,
+    0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00,
+};
+
+// SDES = PT =  202, count = 0, SSRC = 0x2222, cname len = 0
+static const unsigned char kRtcpPacketSdesSsrc2[] = {
+    0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 0x00,
+};
+
+// Packet has only mandatory fixed RTCP header
+static const unsigned char kRtcpPacketFixedHeaderOnly[] = {
+    0x80, 0xC8, 0x00, 0x00,
+};
+
+// Small packet for SSRC demux.
+static const unsigned char kRtcpPacketTooSmall[] = {
+    0x80, 0xC8, 0x00, 0x00, 0x00, 0x00,
+};
+
+// PT = 206, FMT = 1, Sender SSRC  = 0x1111, Media SSRC = 0x1111
+// No FCI information is needed for PLI.
+static const unsigned char kRtcpPacketNonCompoundRtcpPliFeedback[] = {
+    0x81, 0xCE, 0x00, 0x0C, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11,
+};
+
+TEST(BundleFilterTest, AddRemoveStreamTest) {
+  cricket::BundleFilter bundle_filter;
+  EXPECT_FALSE(bundle_filter.HasStreams());
+  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
+  StreamParams stream2;
+  stream2.ssrcs.push_back(kSsrc2);
+  stream2.ssrcs.push_back(kSsrc3);
+  EXPECT_TRUE(bundle_filter.AddStream(stream2));
+
+  EXPECT_TRUE(bundle_filter.HasStreams());
+  EXPECT_TRUE(bundle_filter.FindStream(kSsrc1));
+  EXPECT_TRUE(bundle_filter.FindStream(kSsrc2));
+  EXPECT_TRUE(bundle_filter.FindStream(kSsrc3));
+  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc1));
+  EXPECT_FALSE(bundle_filter.FindStream(kSsrc1));
+  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc3));
+  EXPECT_FALSE(bundle_filter.RemoveStream(kSsrc2));  // Already removed.
+  EXPECT_FALSE(bundle_filter.HasStreams());
+}
+
+TEST(BundleFilterTest, RtpPacketTest) {
+  cricket::BundleFilter bundle_filter;
+  bundle_filter.AddPayloadType(kPayloadType1);
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1),
+      sizeof(kRtpPacketPt1Ssrc1), false));
+  bundle_filter.AddPayloadType(kPayloadType2);
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtpPacketPt2Ssrc2),
+      sizeof(kRtpPacketPt2Ssrc2), false));
+
+  // Payload type 0x33 is not added.
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtpPacketPt3Ssrc2),
+      sizeof(kRtpPacketPt3Ssrc2), false));
+  // Size is too small.
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1), 11, false));
+
+  bundle_filter.ClearAllPayloadTypes();
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1),
+      sizeof(kRtpPacketPt1Ssrc1), false));
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtpPacketPt2Ssrc2),
+      sizeof(kRtpPacketPt2Ssrc2), false));
+}
+
+TEST(BundleFilterTest, RtcpPacketTest) {
+  cricket::BundleFilter bundle_filter;
+  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketCompoundSrSdesSsrc1),
+      sizeof(kRtcpPacketCompoundSrSdesSsrc1), true));
+  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc2)));
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
+      sizeof(kRtcpPacketSrSsrc2), true));
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2),
+      sizeof(kRtcpPacketSdesSsrc2), true));
+  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc2));
+  // RTCP Packets other than SR and RR are demuxed regardless of SSRC.
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2),
+      sizeof(kRtcpPacketSdesSsrc2), true));
+  // RTCP Packets with 'special' SSRC 0x01 are demuxed also
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketSrSsrc01),
+      sizeof(kRtcpPacketSrSsrc01), true));
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
+      sizeof(kRtcpPacketSrSsrc2), true));
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketFixedHeaderOnly),
+      sizeof(kRtcpPacketFixedHeaderOnly), true));
+  EXPECT_FALSE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketTooSmall),
+      sizeof(kRtcpPacketTooSmall), true));
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketNonCompoundRtcpPliFeedback),
+      sizeof(kRtcpPacketNonCompoundRtcpPliFeedback), true));
+  // If the streams_ is empty, rtcp packet passes through
+  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc1));
+  EXPECT_FALSE(bundle_filter.HasStreams());
+  EXPECT_TRUE(bundle_filter.DemuxPacket(
+      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
+      sizeof(kRtcpPacketSrSsrc2), true));
+}
diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc
index 9440e17..b13d5e1 100644
--- a/talk/session/media/channel.cc
+++ b/talk/session/media/channel.cc
@@ -38,7 +38,6 @@
 #include "talk/p2p/base/transportchannel.h"
 #include "talk/session/media/channelmanager.h"
 #include "talk/session/media/mediamessages.h"
-#include "talk/session/media/rtcpmuxfilter.h"
 #include "talk/session/media/typingmonitor.h"
 
 
@@ -559,15 +558,9 @@
                   << packet->length();
     return false;
   }
-  // If this channel is suppose to handle RTP data, that is determined by
-  // checking against ssrc filter. This is necessary to do it here to avoid
-  // double decryption.
-  if (ssrc_filter_.IsActive() &&
-      !ssrc_filter_.DemuxPacket(packet->data(), packet->length(), rtcp)) {
-    return false;
-  }
 
-  return true;
+  // Bundle filter handles both rtp and rtcp packets.
+  return bundle_filter_.DemuxPacket(packet->data(), packet->length(), rtcp);
 }
 
 void BaseChannel::HandlePacket(bool rtcp, talk_base::Buffer* packet,
@@ -996,12 +989,12 @@
   if (!media_channel()->AddRecvStream(sp))
     return false;
 
-  return ssrc_filter_.AddStream(sp);
+  return bundle_filter_.AddStream(sp);
 }
 
 bool BaseChannel::RemoveRecvStream_w(uint32 ssrc) {
   ASSERT(worker_thread() == talk_base::Thread::Current());
-  ssrc_filter_.RemoveStream(ssrc);
+  bundle_filter_.RemoveStream(ssrc);
   return media_channel()->RemoveRecvStream(ssrc);
 }
 
@@ -1479,6 +1472,10 @@
 
   // If everything worked, see if we can start receiving.
   if (ret) {
+    std::vector<AudioCodec>::const_iterator it = audio->codecs().begin();
+    for (; it != audio->codecs().end(); ++it) {
+      bundle_filter()->AddPayloadType(it->id);
+    }
     ChangeState();
   } else {
     LOG(LS_WARNING) << "Failed to set local voice description";
@@ -1844,6 +1841,10 @@
 
   // If everything worked, see if we can start receiving.
   if (ret) {
+    std::vector<VideoCodec>::const_iterator it = video->codecs().begin();
+    for (; it != video->codecs().end(); ++it) {
+      bundle_filter()->AddPayloadType(it->id);
+    }
     ChangeState();
   } else {
     LOG(LS_WARNING) << "Failed to set local video description";
@@ -2249,7 +2250,6 @@
     }
   } else {
     ret = SetBaseLocalContent_w(content, action, error_desc);
-
     if (action != CA_UPDATE || data->has_codecs()) {
       if (!media_channel()->SetRecvCodecs(data->codecs())) {
         SafeSetError("Failed to set data receive codecs.", error_desc);
@@ -2260,6 +2260,10 @@
 
   // If everything worked, see if we can start receiving.
   if (ret) {
+    std::vector<DataCodec>::const_iterator it = data->codecs().begin();
+    for (; it != data->codecs().end(); ++it) {
+      bundle_filter()->AddPayloadType(it->id);
+    }
     ChangeState();
   } else {
     LOG(LS_WARNING) << "Failed to set local data description";
diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h
index 2896bce..2aec552 100644
--- a/talk/session/media/channel.h
+++ b/talk/session/media/channel.h
@@ -44,11 +44,11 @@
 #include "talk/p2p/base/session.h"
 #include "talk/p2p/client/socketmonitor.h"
 #include "talk/session/media/audiomonitor.h"
+#include "talk/session/media/bundlefilter.h"
 #include "talk/session/media/mediamonitor.h"
 #include "talk/session/media/mediasession.h"
 #include "talk/session/media/rtcpmuxfilter.h"
 #include "talk/session/media/srtpfilter.h"
-#include "talk/session/media/ssrcmuxfilter.h"
 
 namespace cricket {
 
@@ -213,7 +213,7 @@
     }
   }
 
-  SsrcMuxFilter* ssrc_filter() { return &ssrc_filter_; }
+  BundleFilter* bundle_filter() { return &bundle_filter_; }
 
   const std::vector<StreamParams>& local_streams() const {
     return local_streams_;
@@ -372,7 +372,7 @@
   TransportChannel* rtcp_transport_channel_;
   SrtpFilter srtp_filter_;
   RtcpMuxFilter rtcp_mux_filter_;
-  SsrcMuxFilter ssrc_filter_;
+  BundleFilter bundle_filter_;
   talk_base::scoped_ptr<SocketMonitor> socket_monitor_;
   bool enabled_;
   bool writable_;
diff --git a/talk/session/media/channel_unittest.cc b/talk/session/media/channel_unittest.cc
index cb2bd69..6e88fd2 100644
--- a/talk/session/media/channel_unittest.cc
+++ b/talk/session/media/channel_unittest.cc
@@ -71,6 +71,8 @@
 static const uint32 kSsrc1 = 0x1111;
 static const uint32 kSsrc2 = 0x2222;
 static const uint32 kSsrc3 = 0x3333;
+static const int kAudioPts[] = {0, 8};
+static const int kVideoPts[] = {97, 99};
 
 template<class ChannelT,
          class MediaChannelT,
@@ -408,13 +410,13 @@
                                      static_cast<int>(rtcp_packet_.size()));
   }
   // Methods to send custom data.
-  bool SendCustomRtp1(uint32 ssrc, int sequence_number) {
-    std::string data(CreateRtpData(ssrc, sequence_number));
+  bool SendCustomRtp1(uint32 ssrc, int sequence_number, int pl_type = -1) {
+    std::string data(CreateRtpData(ssrc, sequence_number, pl_type));
     return media_channel1_->SendRtp(data.c_str(),
                                     static_cast<int>(data.size()));
   }
-  bool SendCustomRtp2(uint32 ssrc, int sequence_number) {
-    std::string data(CreateRtpData(ssrc, sequence_number));
+  bool SendCustomRtp2(uint32 ssrc, int sequence_number, int pl_type = -1) {
+    std::string data(CreateRtpData(ssrc, sequence_number, pl_type));
     return media_channel2_->SendRtp(data.c_str(),
                                     static_cast<int>(data.size()));
   }
@@ -445,13 +447,13 @@
                                       static_cast<int>(rtcp_packet_.size()));
   }
   // Methods to check custom data.
-  bool CheckCustomRtp1(uint32 ssrc, int sequence_number) {
-    std::string data(CreateRtpData(ssrc, sequence_number));
+  bool CheckCustomRtp1(uint32 ssrc, int sequence_number, int pl_type = -1 ) {
+    std::string data(CreateRtpData(ssrc, sequence_number, pl_type));
     return media_channel1_->CheckRtp(data.c_str(),
                                      static_cast<int>(data.size()));
   }
-  bool CheckCustomRtp2(uint32 ssrc, int sequence_number) {
-    std::string data(CreateRtpData(ssrc, sequence_number));
+  bool CheckCustomRtp2(uint32 ssrc, int sequence_number, int pl_type = -1) {
+    std::string data(CreateRtpData(ssrc, sequence_number, pl_type));
     return media_channel2_->CheckRtp(data.c_str(),
                                      static_cast<int>(data.size()));
   }
@@ -465,11 +467,14 @@
     return media_channel2_->CheckRtcp(data.c_str(),
                                       static_cast<int>(data.size()));
   }
-  std::string CreateRtpData(uint32 ssrc, int sequence_number) {
+  std::string CreateRtpData(uint32 ssrc, int sequence_number, int pl_type) {
     std::string data(rtp_packet_);
     // Set SSRC in the rtp packet copy.
     talk_base::SetBE32(const_cast<char*>(data.c_str()) + 8, ssrc);
     talk_base::SetBE16(const_cast<char*>(data.c_str()) + 2, sequence_number);
+    if (pl_type >= 0) {
+      talk_base::Set8(const_cast<char*>(data.c_str()), 1, pl_type);
+    }
     return data;
   }
   std::string CreateRtcpData(uint32 ssrc) {
@@ -1438,60 +1443,63 @@
     EXPECT_TRUE(CheckNoRtp2());
   }
 
-  void SendSsrcMuxToSsrcMuxWithRtcpMux() {
+  void SendBundleToBundle(
+      const int* pl_types, int len, bool rtcp_mux, bool secure) {
+    ASSERT_EQ(2, len);
     int sequence_number1_1 = 0, sequence_number2_2 = 0;
-    CreateChannels(SSRC_MUX | RTCP | RTCP_MUX, SSRC_MUX | RTCP | RTCP_MUX);
+    // Only pl_type1 was added to the bundle filter for both |channel1_|
+    // and |channel2_|.
+    int pl_type1 = pl_types[0];
+    int pl_type2 = pl_types[1];
+    int flags = SSRC_MUX | RTCP;
+    if (secure) flags |= SECURE;
+    uint32 expected_channels = 2U;
+    if (rtcp_mux) {
+      flags |= RTCP_MUX;
+      expected_channels = 1U;
+    }
+    CreateChannels(flags, flags);
     EXPECT_TRUE(SendInitiate());
     EXPECT_EQ(2U, GetTransport1()->channels().size());
-    EXPECT_EQ(1U, GetTransport2()->channels().size());
+    EXPECT_EQ(expected_channels, GetTransport2()->channels().size());
     EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(1U, GetTransport1()->channels().size());
-    EXPECT_EQ(1U, GetTransport2()->channels().size());
-    EXPECT_TRUE(channel1_->ssrc_filter()->IsActive());
-    // channel1 - should have media_content2 as remote. i.e. kSsrc2
-    EXPECT_TRUE(channel1_->ssrc_filter()->FindStream(kSsrc2));
-    EXPECT_TRUE(channel2_->ssrc_filter()->IsActive());
-    // channel2 - should have media_content1 as remote. i.e. kSsrc1
-    EXPECT_TRUE(channel2_->ssrc_filter()->FindStream(kSsrc1));
-    EXPECT_TRUE(SendCustomRtp1(kSsrc1, ++sequence_number1_1));
-    EXPECT_TRUE(SendCustomRtp2(kSsrc2, ++sequence_number2_2));
+    EXPECT_EQ(expected_channels, GetTransport1()->channels().size());
+    EXPECT_EQ(expected_channels, GetTransport2()->channels().size());
+    EXPECT_TRUE(channel1_->bundle_filter()->FindPayloadType(pl_type1));
+    EXPECT_TRUE(channel2_->bundle_filter()->FindPayloadType(pl_type1));
+    EXPECT_FALSE(channel1_->bundle_filter()->FindPayloadType(pl_type2));
+    EXPECT_FALSE(channel2_->bundle_filter()->FindPayloadType(pl_type2));
+    // channel1 - should only have media_content2 as remote. i.e. kSsrc2
+    EXPECT_TRUE(channel1_->bundle_filter()->FindStream(kSsrc2));
+    EXPECT_FALSE(channel1_->bundle_filter()->FindStream(kSsrc1));
+    // channel2 - should only have media_content1 as remote. i.e. kSsrc1
+    EXPECT_TRUE(channel2_->bundle_filter()->FindStream(kSsrc1));
+    EXPECT_FALSE(channel2_->bundle_filter()->FindStream(kSsrc2));
+
+    // Both channels can receive pl_type1 only.
+    EXPECT_TRUE(SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type1));
+    EXPECT_TRUE(CheckCustomRtp2(kSsrc1, sequence_number1_1, pl_type1));
+    EXPECT_TRUE(SendCustomRtp2(kSsrc2, ++sequence_number2_2, pl_type1));
+    EXPECT_TRUE(CheckCustomRtp1(kSsrc2, sequence_number2_2, pl_type1));
+    EXPECT_TRUE(CheckNoRtp1());
+    EXPECT_TRUE(CheckNoRtp2());
+
+    // RTCP test
+    EXPECT_TRUE(SendCustomRtp1(kSsrc1, ++sequence_number1_1, pl_type2));
+    EXPECT_FALSE(CheckCustomRtp2(kSsrc1, sequence_number1_1, pl_type2));
+    EXPECT_TRUE(SendCustomRtp2(kSsrc2, ++sequence_number2_2, pl_type2));
+    EXPECT_FALSE(CheckCustomRtp1(kSsrc2, sequence_number2_2, pl_type2));
+
     EXPECT_TRUE(SendCustomRtcp1(kSsrc1));
     EXPECT_TRUE(SendCustomRtcp2(kSsrc2));
-    EXPECT_TRUE(CheckCustomRtp1(kSsrc2, sequence_number2_2));
-    EXPECT_TRUE(CheckNoRtp1());
-    EXPECT_TRUE(CheckCustomRtp2(kSsrc1, sequence_number1_1));
-    EXPECT_TRUE(CheckNoRtp2());
     EXPECT_TRUE(CheckCustomRtcp1(kSsrc2));
     EXPECT_TRUE(CheckNoRtcp1());
     EXPECT_TRUE(CheckCustomRtcp2(kSsrc1));
     EXPECT_TRUE(CheckNoRtcp2());
-  }
 
-  void SendSsrcMuxToSsrcMux() {
-    int sequence_number1_1 = 0, sequence_number2_2 = 0;
-    CreateChannels(SSRC_MUX | RTCP, SSRC_MUX | RTCP);
-    EXPECT_TRUE(SendInitiate());
-    EXPECT_EQ(2U, GetTransport1()->channels().size());
-    EXPECT_EQ(2U, GetTransport2()->channels().size());
-    EXPECT_TRUE(SendAccept());
-    EXPECT_EQ(2U, GetTransport1()->channels().size());
-    EXPECT_EQ(2U, GetTransport2()->channels().size());
-    EXPECT_TRUE(channel1_->ssrc_filter()->IsActive());
-    // channel1 - should have media_content2 as remote. i.e. kSsrc2
-    EXPECT_TRUE(channel1_->ssrc_filter()->FindStream(kSsrc2));
-    EXPECT_TRUE(channel2_->ssrc_filter()->IsActive());
-    // channel2 - should have media_content1 as remote. i.e. kSsrc1
-    EXPECT_TRUE(SendCustomRtp1(kSsrc1, ++sequence_number1_1));
-    EXPECT_TRUE(SendCustomRtp2(kSsrc2, ++sequence_number2_2));
-    EXPECT_TRUE(SendCustomRtcp1(kSsrc1));
-    EXPECT_TRUE(SendCustomRtcp2(kSsrc2));
-    EXPECT_TRUE(CheckCustomRtp1(kSsrc2, sequence_number2_2));
-    EXPECT_FALSE(CheckCustomRtp1(kSsrc1, sequence_number2_2));
-    EXPECT_TRUE(CheckCustomRtp2(kSsrc1, sequence_number1_1));
-    EXPECT_FALSE(CheckCustomRtp2(kSsrc2, sequence_number1_1));
-    EXPECT_TRUE(CheckCustomRtcp1(kSsrc2));
+    EXPECT_TRUE(SendCustomRtcp1(kSsrc2));
+    EXPECT_TRUE(SendCustomRtcp2(kSsrc1));
     EXPECT_FALSE(CheckCustomRtcp1(kSsrc1));
-    EXPECT_TRUE(CheckCustomRtcp2(kSsrc1));
     EXPECT_FALSE(CheckCustomRtcp2(kSsrc2));
   }
 
@@ -1753,9 +1761,14 @@
               error_);
   }
 
-  void TestSrtpError() {
-    static const unsigned char kBadPacket[] = {
-      0x84, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+  void TestSrtpError(int pl_type) {
+    // For Audio, only pl_type 0 is added to the bundle filter.
+    // For Video, only pl_type 97 is added to the bundle filter.
+    // So we need to pass in pl_type so that the packet can pass through
+    // the bundle filter before it can be processed by the srtp filter.
+    // The packet is not a valid srtp packet because it is too short.
+    unsigned const char kBadPacket[] = {
+      0x84, pl_type, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
     };
     CreateChannels(RTCP | SECURE, RTCP | SECURE);
     EXPECT_FALSE(channel1_->secure());
@@ -2277,7 +2290,7 @@
 }
 
 TEST_F(VoiceChannelTest, TestSrtpError) {
-  Base::TestSrtpError();
+  Base::TestSrtpError(kAudioPts[0]);
 }
 
 TEST_F(VoiceChannelTest, TestOnReadyToSend) {
@@ -2389,12 +2402,22 @@
   EXPECT_DOUBLE_EQ(0.0, right);
 }
 
-TEST_F(VoiceChannelTest, SendSsrcMuxToSsrcMux) {
-  Base::SendSsrcMuxToSsrcMux();
+TEST_F(VoiceChannelTest, SendBundleToBundle) {
+  Base::SendBundleToBundle(kAudioPts, ARRAY_SIZE(kAudioPts), false, false);
 }
 
-TEST_F(VoiceChannelTest, SendSsrcMuxToSsrcMuxWithRtcpMux) {
-  Base::SendSsrcMuxToSsrcMuxWithRtcpMux();
+TEST_F(VoiceChannelTest, SendBundleToBundleSecure) {
+  Base::SendBundleToBundle(kAudioPts, ARRAY_SIZE(kAudioPts), false, true);
+}
+
+TEST_F(VoiceChannelTest, SendBundleToBundleWithRtcpMux) {
+  Base::SendBundleToBundle(
+      kAudioPts, ARRAY_SIZE(kAudioPts), true, false);
+}
+
+TEST_F(VoiceChannelTest, SendBundleToBundleWithRtcpMuxSecure) {
+  Base::SendBundleToBundle(
+      kAudioPts, ARRAY_SIZE(kAudioPts), true, true);
 }
 
 TEST_F(VoiceChannelTest, TestSetChannelOptions) {
@@ -2604,18 +2627,28 @@
   Base::TestFlushRtcp();
 }
 
-TEST_F(VideoChannelTest, SendSsrcMuxToSsrcMux) {
-  Base::SendSsrcMuxToSsrcMux();
+TEST_F(VideoChannelTest, SendBundleToBundle) {
+  Base::SendBundleToBundle(kVideoPts, ARRAY_SIZE(kVideoPts), false, false);
 }
 
-TEST_F(VideoChannelTest, SendSsrcMuxToSsrcMuxWithRtcpMux) {
-  Base::SendSsrcMuxToSsrcMuxWithRtcpMux();
+TEST_F(VideoChannelTest, SendBundleToBundleSecure) {
+  Base::SendBundleToBundle(kVideoPts, ARRAY_SIZE(kVideoPts), false, true);
+}
+
+TEST_F(VideoChannelTest, SendBundleToBundleWithRtcpMux) {
+  Base::SendBundleToBundle(
+      kVideoPts, ARRAY_SIZE(kVideoPts), true, false);
+}
+
+TEST_F(VideoChannelTest, SendBundleToBundleWithRtcpMuxSecure) {
+  Base::SendBundleToBundle(
+      kVideoPts, ARRAY_SIZE(kVideoPts), true, true);
 }
 
 // TODO(gangji): Add VideoChannelTest.TestChangeStateError.
 
 TEST_F(VideoChannelTest, TestSrtpError) {
-  Base::TestSrtpError();
+  Base::TestSrtpError(kVideoPts[0]);
 }
 
 TEST_F(VideoChannelTest, TestOnReadyToSend) {
diff --git a/talk/session/media/ssrcmuxfilter.cc b/talk/session/media/ssrcmuxfilter.cc
deleted file mode 100644
index 638167d..0000000
--- a/talk/session/media/ssrcmuxfilter.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * libjingle
- * Copyright 2004 Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *  1. Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- *  3. The name of the author may not be used to endorse or promote products
- *     derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "talk/session/media/ssrcmuxfilter.h"
-
-#include <algorithm>
-
-#include "talk/base/logging.h"
-#include "talk/media/base/rtputils.h"
-
-namespace cricket {
-
-static const uint32 kSsrc01 = 0x01;
-
-SsrcMuxFilter::SsrcMuxFilter() {
-}
-
-SsrcMuxFilter::~SsrcMuxFilter() {
-}
-
-bool SsrcMuxFilter::IsActive() const {
-  return !streams_.empty();
-}
-
-bool SsrcMuxFilter::DemuxPacket(const char* data, size_t len, bool rtcp) {
-  uint32 ssrc = 0;
-  if (!rtcp) {
-    GetRtpSsrc(data, len, &ssrc);
-  } else {
-    int pl_type = 0;
-    if (!GetRtcpType(data, len, &pl_type)) return false;
-    if (pl_type == kRtcpTypeSDES) {
-      // SDES packet parsing not supported.
-      LOG(LS_INFO) << "SDES packet received for demux.";
-      return true;
-    } else {
-      if (!GetRtcpSsrc(data, len, &ssrc)) return false;
-      if (ssrc == kSsrc01) {
-        // SSRC 1 has a special meaning and indicates generic feedback on
-        // some systems and should never be dropped.  If it is forwarded
-        // incorrectly it will be ignored by lower layers anyway.
-        return true;
-      }
-    }
-  }
-  return FindStream(ssrc);
-}
-
-bool SsrcMuxFilter::AddStream(const StreamParams& stream) {
-  if (GetStreamBySsrc(streams_, stream.first_ssrc(), NULL)) {
-      LOG(LS_WARNING) << "Stream already added to filter";
-      return false;
-  }
-  streams_.push_back(stream);
-  return true;
-}
-
-bool SsrcMuxFilter::RemoveStream(uint32 ssrc) {
-  return RemoveStreamBySsrc(&streams_, ssrc);
-}
-
-bool SsrcMuxFilter::FindStream(uint32 ssrc) const {
-  if (ssrc == 0) {
-    return false;
-  }
-  return (GetStreamBySsrc(streams_, ssrc, NULL));
-}
-
-}  // namespace cricket
diff --git a/talk/session/media/ssrcmuxfilter_unittest.cc b/talk/session/media/ssrcmuxfilter_unittest.cc
deleted file mode 100644
index 85a4dbe..0000000
--- a/talk/session/media/ssrcmuxfilter_unittest.cc
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * libjingle
- * Copyright 2004 Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *  1. Redistributions of source code must retain the above copyright notice,
- *     this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright notice,
- *     this list of conditions and the following disclaimer in the documentation
- *     and/or other materials provided with the distribution.
- *  3. The name of the author may not be used to endorse or promote products
- *     derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "talk/base/gunit.h"
-#include "talk/session/media/ssrcmuxfilter.h"
-
-static const int kSsrc1 = 0x1111;
-static const int kSsrc2 = 0x2222;
-static const int kSsrc3 = 0x3333;
-
-using cricket::StreamParams;
-
-// SSRC = 0x1111
-static const unsigned char kRtpPacketSsrc1[] = {
-    0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,
-};
-
-// SSRC = 0x2222
-static const unsigned char kRtpPacketSsrc2[] = {
-    0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22,
-};
-
-// SSRC = 0
-static const unsigned char kRtpPacketInvalidSsrc[] = {
-    0x80, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-// invalid size
-static const unsigned char kRtpPacketTooSmall[] = {
-    0x80, 0x80, 0x00, 0x00,
-};
-
-// PT = 200 = SR, len = 28, SSRC of sender = 0x0001
-// NTP TS = 0, RTP TS = 0, packet count = 0
-static const unsigned char kRtcpPacketSrSsrc01[] = {
-    0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00,
-};
-
-// PT = 200 = SR, len = 28, SSRC of sender = 0x2222
-// NTP TS = 0, RTP TS = 0, packet count = 0
-static const unsigned char kRtcpPacketSrSsrc2[] = {
-    0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x22, 0x22,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00,
-};
-
-// First packet - SR = PT = 200, len = 0, SSRC of sender = 0x1111
-// NTP TS = 0, RTP TS = 0, packet count = 0
-// second packet - SDES = PT =  202, count = 0, SSRC = 0x1111, cname len = 0
-static const unsigned char kRtcpPacketCompoundSrSdesSsrc1[] = {
-    0x80, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x11, 0x11,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00,
-    0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00,
-};
-
-// SDES = PT =  202, count = 0, SSRC = 0x2222, cname len = 0
-static const unsigned char kRtcpPacketSdesSsrc2[] = {
-    0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 0x00,
-};
-
-// Packet has only mandatory fixed RTCP header
-static const unsigned char kRtcpPacketFixedHeaderOnly[] = {
-    0x80, 0xC8, 0x00, 0x00,
-};
-
-// Small packet for SSRC demux.
-static const unsigned char kRtcpPacketTooSmall[] = {
-    0x80, 0xC8, 0x00, 0x00, 0x00, 0x00,
-};
-
-// PT = 206, FMT = 1, Sender SSRC  = 0x1111, Media SSRC = 0x1111
-// No FCI information is needed for PLI.
-static const unsigned char kRtcpPacketNonCompoundRtcpPliFeedback[] = {
-    0x81, 0xCE, 0x00, 0x0C, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11,
-};
-
-TEST(SsrcMuxFilterTest, AddRemoveStreamTest) {
-  cricket::SsrcMuxFilter ssrc_filter;
-  EXPECT_FALSE(ssrc_filter.IsActive());
-  EXPECT_TRUE(ssrc_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
-  StreamParams stream2;
-  stream2.ssrcs.push_back(kSsrc2);
-  stream2.ssrcs.push_back(kSsrc3);
-  EXPECT_TRUE(ssrc_filter.AddStream(stream2));
-
-  EXPECT_TRUE(ssrc_filter.IsActive());
-  EXPECT_TRUE(ssrc_filter.FindStream(kSsrc1));
-  EXPECT_TRUE(ssrc_filter.FindStream(kSsrc2));
-  EXPECT_TRUE(ssrc_filter.FindStream(kSsrc3));
-  EXPECT_TRUE(ssrc_filter.RemoveStream(kSsrc1));
-  EXPECT_FALSE(ssrc_filter.FindStream(kSsrc1));
-  EXPECT_TRUE(ssrc_filter.RemoveStream(kSsrc3));
-  EXPECT_FALSE(ssrc_filter.RemoveStream(kSsrc2));  // Already removed.
-  EXPECT_FALSE(ssrc_filter.IsActive());
-}
-
-TEST(SsrcMuxFilterTest, RtpPacketTest) {
-  cricket::SsrcMuxFilter ssrc_filter;
-  EXPECT_TRUE(ssrc_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtpPacketSsrc1),
-      sizeof(kRtpPacketSsrc1), false));
-  EXPECT_TRUE(ssrc_filter.AddStream(StreamParams::CreateLegacy(kSsrc2)));
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtpPacketSsrc2),
-      sizeof(kRtpPacketSsrc2), false));
-  EXPECT_TRUE(ssrc_filter.RemoveStream(kSsrc2));
-  EXPECT_FALSE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtpPacketSsrc2),
-      sizeof(kRtpPacketSsrc2), false));
-  EXPECT_FALSE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtpPacketInvalidSsrc),
-      sizeof(kRtpPacketInvalidSsrc), false));
-  EXPECT_FALSE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtpPacketTooSmall),
-      sizeof(kRtpPacketTooSmall), false));
-}
-
-TEST(SsrcMuxFilterTest, RtcpPacketTest) {
-  cricket::SsrcMuxFilter ssrc_filter;
-  EXPECT_TRUE(ssrc_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketCompoundSrSdesSsrc1),
-      sizeof(kRtcpPacketCompoundSrSdesSsrc1), true));
-  EXPECT_TRUE(ssrc_filter.AddStream(StreamParams::CreateLegacy(kSsrc2)));
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
-      sizeof(kRtcpPacketSrSsrc2), true));
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2),
-      sizeof(kRtcpPacketSdesSsrc2), true));
-  EXPECT_TRUE(ssrc_filter.RemoveStream(kSsrc2));
-  // RTCP Packets other than SR and RR are demuxed regardless of SSRC.
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2),
-      sizeof(kRtcpPacketSdesSsrc2), true));
-  // RTCP Packets with 'special' SSRC 0x01 are demuxed also
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketSrSsrc01),
-      sizeof(kRtcpPacketSrSsrc01), true));
-  EXPECT_FALSE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
-      sizeof(kRtcpPacketSrSsrc2), true));
-  EXPECT_FALSE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketFixedHeaderOnly),
-      sizeof(kRtcpPacketFixedHeaderOnly), true));
-  EXPECT_FALSE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketTooSmall),
-      sizeof(kRtcpPacketTooSmall), true));
-  EXPECT_TRUE(ssrc_filter.DemuxPacket(
-      reinterpret_cast<const char*>(kRtcpPacketNonCompoundRtcpPliFeedback),
-      sizeof(kRtcpPacketNonCompoundRtcpPliFeedback), true));
-}