Move RtpExtension to api/ directory and config.h/.cc to call/.

BUG=webrtc:5876
R=deadbeef@webrtc.org, solenberg@webrtc.org

Review-Url: https://codereview.webrtc.org/3004723002 .
Cr-Commit-Position: refs/heads/master@{#19639}
diff --git a/webrtc/api/BUILD.gn b/webrtc/api/BUILD.gn
index 3d19f03..e58f393 100644
--- a/webrtc/api/BUILD.gn
+++ b/webrtc/api/BUILD.gn
@@ -62,6 +62,7 @@
     "proxy.h",
     "rtcerror.cc",
     "rtcerror.h",
+    "rtpparameters.cc",
     "rtpparameters.h",
     "rtpreceiverinterface.h",
     "rtpsender.h",
@@ -258,6 +259,7 @@
       "ortc/mediadescription_unittest.cc",
       "ortc/sessiondescription_unittest.cc",
       "rtcerror_unittest.cc",
+      "rtpparameters_unittest.cc",
     ]
 
     if (!build_with_chromium && is_clang) {
diff --git a/webrtc/api/rtpparameters.cc b/webrtc/api/rtpparameters.cc
new file mode 100644
index 0000000..29b14fb
--- /dev/null
+++ b/webrtc/api/rtpparameters.cc
@@ -0,0 +1,190 @@
+/*
+ *  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 "webrtc/api/rtpparameters.h"
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+
+#include "webrtc/rtc_base/checks.h"
+
+namespace webrtc {
+
+RtcpFeedback::RtcpFeedback() {}
+RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {}
+RtcpFeedback::RtcpFeedback(RtcpFeedbackType type,
+                           RtcpFeedbackMessageType message_type)
+    : type(type), message_type(message_type) {}
+RtcpFeedback::~RtcpFeedback() {}
+
+RtpCodecCapability::RtpCodecCapability() {}
+RtpCodecCapability::~RtpCodecCapability() {}
+
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() {}
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
+    const std::string& uri)
+    : uri(uri) {}
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
+    const std::string& uri,
+    int preferred_id)
+    : uri(uri), preferred_id(preferred_id) {}
+RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() {}
+
+RtpExtension::RtpExtension() {}
+RtpExtension::RtpExtension(const std::string& uri, int id) : uri(uri), id(id) {}
+RtpExtension::RtpExtension(const std::string& uri, int id, bool encrypt)
+    : uri(uri), id(id), encrypt(encrypt) {}
+RtpExtension::~RtpExtension() {}
+
+RtpFecParameters::RtpFecParameters() {}
+RtpFecParameters::RtpFecParameters(FecMechanism mechanism)
+    : mechanism(mechanism) {}
+RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc)
+    : ssrc(ssrc), mechanism(mechanism) {}
+RtpFecParameters::~RtpFecParameters() {}
+
+RtpRtxParameters::RtpRtxParameters() {}
+RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
+RtpRtxParameters::~RtpRtxParameters() {}
+
+RtpEncodingParameters::RtpEncodingParameters() {}
+RtpEncodingParameters::~RtpEncodingParameters() {}
+
+RtpCodecParameters::RtpCodecParameters() {}
+RtpCodecParameters::~RtpCodecParameters() {}
+
+RtpCapabilities::RtpCapabilities() {}
+RtpCapabilities::~RtpCapabilities() {}
+
+RtpParameters::RtpParameters() {}
+RtpParameters::~RtpParameters() {}
+
+std::string RtpExtension::ToString() const {
+  std::stringstream ss;
+  ss << "{uri: " << uri;
+  ss << ", id: " << id;
+  if (encrypt) {
+    ss << ", encrypt";
+  }
+  ss << '}';
+  return ss.str();
+}
+
+const char RtpExtension::kAudioLevelUri[] =
+    "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
+const int RtpExtension::kAudioLevelDefaultId = 1;
+
+const char RtpExtension::kTimestampOffsetUri[] =
+    "urn:ietf:params:rtp-hdrext:toffset";
+const int RtpExtension::kTimestampOffsetDefaultId = 2;
+
+const char RtpExtension::kAbsSendTimeUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
+const int RtpExtension::kAbsSendTimeDefaultId = 3;
+
+const char RtpExtension::kVideoRotationUri[] = "urn:3gpp:video-orientation";
+const int RtpExtension::kVideoRotationDefaultId = 4;
+
+const char RtpExtension::kTransportSequenceNumberUri[] =
+    "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
+const int RtpExtension::kTransportSequenceNumberDefaultId = 5;
+
+// This extension allows applications to adaptively limit the playout delay
+// on frames as per the current needs. For example, a gaming application
+// has very different needs on end-to-end delay compared to a video-conference
+// application.
+const char RtpExtension::kPlayoutDelayUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay";
+const int RtpExtension::kPlayoutDelayDefaultId = 6;
+
+const char RtpExtension::kVideoContentTypeUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type";
+const int RtpExtension::kVideoContentTypeDefaultId = 7;
+
+const char RtpExtension::kVideoTimingUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/video-timing";
+const int RtpExtension::kVideoTimingDefaultId = 8;
+
+const char RtpExtension::kEncryptHeaderExtensionsUri[] =
+    "urn:ietf:params:rtp-hdrext:encrypt";
+
+const int RtpExtension::kMinId = 1;
+const int RtpExtension::kMaxId = 14;
+
+bool RtpExtension::IsSupportedForAudio(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kAudioLevelUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri;
+}
+
+bool RtpExtension::IsSupportedForVideo(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kTimestampOffsetUri ||
+         uri == webrtc::RtpExtension::kAbsSendTimeUri ||
+         uri == webrtc::RtpExtension::kVideoRotationUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kPlayoutDelayUri ||
+         uri == webrtc::RtpExtension::kVideoContentTypeUri ||
+         uri == webrtc::RtpExtension::kVideoTimingUri;
+}
+
+bool RtpExtension::IsEncryptionSupported(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kAudioLevelUri ||
+         uri == webrtc::RtpExtension::kTimestampOffsetUri ||
+#if !defined(ENABLE_EXTERNAL_AUTH)
+         // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri"
+         // here and filter out later if external auth is really used in
+         // srtpfilter. External auth is used by Chromium and replaces the
+         // extension header value of "kAbsSendTimeUri", so it must not be
+         // encrypted (which can't be done by Chromium).
+         uri == webrtc::RtpExtension::kAbsSendTimeUri ||
+#endif
+         uri == webrtc::RtpExtension::kVideoRotationUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kPlayoutDelayUri ||
+         uri == webrtc::RtpExtension::kVideoContentTypeUri;
+}
+
+const RtpExtension* RtpExtension::FindHeaderExtensionByUri(
+    const std::vector<RtpExtension>& extensions,
+    const std::string& uri) {
+  for (const auto& extension : extensions) {
+    if (extension.uri == uri) {
+      return &extension;
+    }
+  }
+  return nullptr;
+}
+
+std::vector<RtpExtension> RtpExtension::FilterDuplicateNonEncrypted(
+    const std::vector<RtpExtension>& extensions) {
+  std::vector<RtpExtension> filtered;
+  for (auto extension = extensions.begin(); extension != extensions.end();
+       ++extension) {
+    if (extension->encrypt) {
+      filtered.push_back(*extension);
+      continue;
+    }
+
+    // Only add non-encrypted extension if no encrypted with the same URI
+    // is also present...
+    if (std::find_if(extension + 1, extensions.end(),
+                     [extension](const RtpExtension& check) {
+                       return extension->uri == check.uri;
+                     }) != extensions.end()) {
+      continue;
+    }
+
+    // ...and has not been added before.
+    if (!FindHeaderExtensionByUri(filtered, extension->uri)) {
+      filtered.push_back(*extension);
+    }
+  }
+  return filtered;
+}
+}  // namespace webrtc
diff --git a/webrtc/api/rtpparameters.h b/webrtc/api/rtpparameters.h
index 94d9d73..46f7139 100644
--- a/webrtc/api/rtpparameters.h
+++ b/webrtc/api/rtpparameters.h
@@ -16,7 +16,6 @@
 #include <vector>
 
 #include "webrtc/api/mediatypes.h"
-#include "webrtc/config.h"
 #include "webrtc/rtc_base/optional.h"
 
 namespace webrtc {
@@ -85,10 +84,10 @@
   rtc::Optional<RtcpFeedbackMessageType> message_type;
 
   // Constructors for convenience.
-  RtcpFeedback() {}
-  explicit RtcpFeedback(RtcpFeedbackType type) : type(type) {}
-  RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type)
-      : type(type), message_type(message_type) {}
+  RtcpFeedback();
+  explicit RtcpFeedback(RtcpFeedbackType type);
+  RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type);
+  ~RtcpFeedback();
 
   bool operator==(const RtcpFeedback& o) const {
     return type == o.type && message_type == o.message_type;
@@ -100,6 +99,9 @@
 // RtpParameters. This represents the static capabilities of an endpoint's
 // implementation of a codec.
 struct RtpCodecCapability {
+  RtpCodecCapability();
+  ~RtpCodecCapability();
+
   // Build MIME "type/subtype" string from |name| and |kind|.
   std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
 
@@ -196,10 +198,10 @@
   bool preferred_encrypt = false;
 
   // Constructors for convenience.
-  RtpHeaderExtensionCapability() = default;
-  explicit RtpHeaderExtensionCapability(const std::string& uri) : uri(uri) {}
-  RtpHeaderExtensionCapability(const std::string& uri, int preferred_id)
-      : uri(uri), preferred_id(preferred_id) {}
+  RtpHeaderExtensionCapability();
+  explicit RtpHeaderExtensionCapability(const std::string& uri);
+  RtpHeaderExtensionCapability(const std::string& uri, int preferred_id);
+  ~RtpHeaderExtensionCapability();
 
   bool operator==(const RtpHeaderExtensionCapability& o) const {
     return uri == o.uri && preferred_id == o.preferred_id &&
@@ -210,6 +212,83 @@
   }
 };
 
+// RTP header extension, see RFC 5285.
+struct RtpExtension {
+  RtpExtension();
+  RtpExtension(const std::string& uri, int id);
+  RtpExtension(const std::string& uri, int id, bool encrypt);
+  ~RtpExtension();
+  std::string ToString() const;
+  bool operator==(const RtpExtension& rhs) const {
+    return uri == rhs.uri && id == rhs.id && encrypt == rhs.encrypt;
+  }
+  static bool IsSupportedForAudio(const std::string& uri);
+  static bool IsSupportedForVideo(const std::string& uri);
+  // Return "true" if the given RTP header extension URI may be encrypted.
+  static bool IsEncryptionSupported(const std::string& uri);
+
+  // Returns the named header extension if found among all extensions,
+  // nullptr otherwise.
+  static const RtpExtension* FindHeaderExtensionByUri(
+      const std::vector<RtpExtension>& extensions,
+      const std::string& uri);
+
+  // Return a list of RTP header extensions with the non-encrypted extensions
+  // removed if both the encrypted and non-encrypted extension is present for
+  // the same URI.
+  static std::vector<RtpExtension> FilterDuplicateNonEncrypted(
+      const std::vector<RtpExtension>& extensions);
+
+  // Header extension for audio levels, as defined in:
+  // http://tools.ietf.org/html/draft-ietf-avtext-client-to-mixer-audio-level-03
+  static const char kAudioLevelUri[];
+  static const int kAudioLevelDefaultId;
+
+  // Header extension for RTP timestamp offset, see RFC 5450 for details:
+  // http://tools.ietf.org/html/rfc5450
+  static const char kTimestampOffsetUri[];
+  static const int kTimestampOffsetDefaultId;
+
+  // Header extension for absolute send time, see url for details:
+  // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+  static const char kAbsSendTimeUri[];
+  static const int kAbsSendTimeDefaultId;
+
+  // Header extension for coordination of video orientation, see url for
+  // details:
+  // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf
+  static const char kVideoRotationUri[];
+  static const int kVideoRotationDefaultId;
+
+  // Header extension for video content type. E.g. default or screenshare.
+  static const char kVideoContentTypeUri[];
+  static const int kVideoContentTypeDefaultId;
+
+  // Header extension for video timing.
+  static const char kVideoTimingUri[];
+  static const int kVideoTimingDefaultId;
+
+  // Header extension for transport sequence number, see url for details:
+  // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions
+  static const char kTransportSequenceNumberUri[];
+  static const int kTransportSequenceNumberDefaultId;
+
+  static const char kPlayoutDelayUri[];
+  static const int kPlayoutDelayDefaultId;
+
+  // Encryption of Header Extensions, see RFC 6904 for details:
+  // https://tools.ietf.org/html/rfc6904
+  static const char kEncryptHeaderExtensionsUri[];
+
+  // Inclusive min and max IDs for one-byte header extensions, per RFC5285.
+  static const int kMinId;
+  static const int kMaxId;
+
+  std::string uri;
+  int id = 0;
+  bool encrypt = false;
+};
+
 // See webrtc/config.h. Has "uri" and "id" fields.
 // TODO(deadbeef): This is missing the "encrypt" flag, which is unimplemented.
 typedef RtpExtension RtpHeaderExtensionParameters;
@@ -222,10 +301,10 @@
   FecMechanism mechanism = FecMechanism::RED;
 
   // Constructors for convenience.
-  RtpFecParameters() = default;
-  explicit RtpFecParameters(FecMechanism mechanism) : mechanism(mechanism) {}
-  RtpFecParameters(FecMechanism mechanism, uint32_t ssrc)
-      : ssrc(ssrc), mechanism(mechanism) {}
+  RtpFecParameters();
+  explicit RtpFecParameters(FecMechanism mechanism);
+  RtpFecParameters(FecMechanism mechanism, uint32_t ssrc);
+  ~RtpFecParameters();
 
   bool operator==(const RtpFecParameters& o) const {
     return ssrc == o.ssrc && mechanism == o.mechanism;
@@ -239,14 +318,18 @@
   rtc::Optional<uint32_t> ssrc;
 
   // Constructors for convenience.
-  RtpRtxParameters() = default;
-  explicit RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
+  RtpRtxParameters();
+  explicit RtpRtxParameters(uint32_t ssrc);
+  ~RtpRtxParameters();
 
   bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; }
   bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); }
 };
 
 struct RtpEncodingParameters {
+  RtpEncodingParameters();
+  ~RtpEncodingParameters();
+
   // If unset, a value is chosen by the implementation.
   //
   // Note that the chosen value is NOT returned by GetParameters, because it
@@ -338,6 +421,9 @@
 };
 
 struct RtpCodecParameters {
+  RtpCodecParameters();
+  ~RtpCodecParameters();
+
   // Build MIME "type/subtype" string from |name| and |kind|.
   std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
 
@@ -400,6 +486,9 @@
 // endpoint. An application can use these capabilities to construct an
 // RtpParameters.
 struct RtpCapabilities {
+  RtpCapabilities();
+  ~RtpCapabilities();
+
   // Supported codecs.
   std::vector<RtpCodecCapability> codecs;
 
@@ -422,6 +511,9 @@
 // RtpParameters, because our API includes an additional "RtpTransport"
 // abstraction on which RTCP parameters are set.
 struct RtpParameters {
+  RtpParameters();
+  ~RtpParameters();
+
   // Used when calling getParameters/setParameters with a PeerConnection
   // RtpSender, to ensure that outdated parameters are not unintentionally
   // applied successfully.
diff --git a/webrtc/api/rtpparameters_unittest.cc b/webrtc/api/rtpparameters_unittest.cc
new file mode 100644
index 0000000..6cb90c2
--- /dev/null
+++ b/webrtc/api/rtpparameters_unittest.cc
@@ -0,0 +1,51 @@
+/*
+ *  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 <utility>
+
+#include "webrtc/api/rtpparameters.h"
+#include "webrtc/test/gtest.h"
+
+namespace webrtc {
+
+using webrtc::RtpExtension;
+
+static const char kExtensionUri1[] = "extension-uri1";
+static const char kExtensionUri2[] = "extension-uri2";
+
+static const RtpExtension kExtension1(kExtensionUri1, 1);
+static const RtpExtension kExtension1Encrypted(kExtensionUri1, 10, true);
+static const RtpExtension kExtension2(kExtensionUri2, 2);
+
+TEST(RtpExtensionTest, FilterDuplicateNonEncrypted) {
+  std::vector<RtpExtension> extensions;
+  std::vector<RtpExtension> filtered;
+
+  extensions.push_back(kExtension1);
+  extensions.push_back(kExtension1Encrypted);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(1u, filtered.size());
+  EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered);
+
+  extensions.clear();
+  extensions.push_back(kExtension1Encrypted);
+  extensions.push_back(kExtension1);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(1u, filtered.size());
+  EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered);
+
+  extensions.clear();
+  extensions.push_back(kExtension1);
+  extensions.push_back(kExtension2);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(2u, filtered.size());
+  EXPECT_EQ(extensions, filtered);
+}
+}  // namespace webrtc