Adding "adapter" ORTC objects on top of ChannelManager/BaseChannel/etc.

This CL adds the following interfaces:
* RtpTransportController
* RtpTransport
* RtpSender
* RtpReceiver

They're implemented on top of the "BaseChannel" object, which is normally used
in a PeerConnection, and roughly corresponds to an SDP "m=" section. As a result
of this, there are several limitations:

* You can only have one of each type of sender and receiver (audio/video) on top
  of the same transport controller.
* The sender/receiver with the same media type must use the same RTP transport.
* You can't change the transport after creating the sender or receiver.
* Some of the parameters aren't supported.

Later, these "adapter" objects will be gradually replaced by real objects that don't
have these limitations, as "BaseChannel", "MediaChannel" and related code is
restructured. In this CL, we essentially have:

ORTC adapter objects -> BaseChannel -> Media engine
PeerConnection -> BaseChannel -> Media engine

And later we hope to have simply:

PeerConnection -> "Real" ORTC objects -> Media engine

See the linked bug for more context.

BUG=webrtc:7013
TBR=stefan@webrtc.org

Review-Url: https://codereview.webrtc.org/2675173003
Cr-Commit-Position: refs/heads/master@{#16842}
diff --git a/webrtc/api/BUILD.gn b/webrtc/api/BUILD.gn
index 78079b3..716f8c9 100644
--- a/webrtc/api/BUILD.gn
+++ b/webrtc/api/BUILD.gn
@@ -56,7 +56,6 @@
     "mediatypes.cc",
     "mediatypes.h",
     "notifier.h",
-    "ortcfactoryinterface.h",
     "peerconnectionfactoryproxy.h",
     "peerconnectioninterface.h",
     "peerconnectionproxy.h",
@@ -70,7 +69,6 @@
     "statstypes.cc",
     "statstypes.h",
     "streamcollection.h",
-    "udptransportinterface.h",
     "umametrics.h",
     "videosourceproxy.h",
     "videotracksource.h",
@@ -87,6 +85,27 @@
   ]
 }
 
+rtc_source_set("ortc_api") {
+  check_includes = false  # TODO(deadbeef): Remove (bugs.webrtc.org/6828)
+  sources = [
+    "ortc/ortcfactoryinterface.h",
+    "ortc/ortcrtpreceiverinterface.h",
+    "ortc/ortcrtpsenderinterface.h",
+    "ortc/packettransportinterface.h",
+    "ortc/rtptransportcontrollerinterface.h",
+    "ortc/rtptransportinterface.h",
+    "ortc/udptransportinterface.h",
+  ]
+
+  # For mediastreaminterface.h, etc.
+  # TODO(deadbeef): Create a separate target for the common things ORTC and
+  # PeerConnection code shares, so that ortc_api can depend on that instead of
+  # libjingle_peerconnection_api.
+  public_deps = [
+    ":libjingle_peerconnection_api",
+  ]
+}
+
 # TODO(ossu): Remove once downstream projects have updated.
 rtc_source_set("libjingle_peerconnection") {
   public_deps = [
diff --git a/webrtc/api/mediatypes.cc b/webrtc/api/mediatypes.cc
index 97b0189..fbcb53d 100644
--- a/webrtc/api/mediatypes.cc
+++ b/webrtc/api/mediatypes.cc
@@ -9,27 +9,39 @@
  */
 
 #include "webrtc/api/mediatypes.h"
+
+#include "webrtc/api/mediastreaminterface.h"
 #include "webrtc/base/checks.h"
 
+namespace {
+static const char* kMediaTypeData = "data";
+}  // namespace
+
 namespace cricket {
 
 std::string MediaTypeToString(MediaType type) {
-  std::string type_str;
   switch (type) {
     case MEDIA_TYPE_AUDIO:
-      type_str = "audio";
-      break;
+      return webrtc::MediaStreamTrackInterface::kAudioKind;
     case MEDIA_TYPE_VIDEO:
-      type_str = "video";
-      break;
+      return webrtc::MediaStreamTrackInterface::kVideoKind;
     case MEDIA_TYPE_DATA:
-      type_str = "data";
-      break;
-    default:
-      RTC_NOTREACHED();
-      break;
+      return kMediaTypeData;
   }
-  return type_str;
+  // Not reachable; avoids compile warning.
+  FATAL();
+}
+
+MediaType MediaTypeFromString(const std::string& type_str) {
+  if (type_str == webrtc::MediaStreamTrackInterface::kAudioKind) {
+    return MEDIA_TYPE_AUDIO;
+  } else if (type_str == webrtc::MediaStreamTrackInterface::kVideoKind) {
+    return MEDIA_TYPE_VIDEO;
+  } else if (type_str == kMediaTypeData) {
+    return MEDIA_TYPE_DATA;
+  } else {
+    FATAL();
+  }
 }
 
 }  // namespace cricket
diff --git a/webrtc/api/mediatypes.h b/webrtc/api/mediatypes.h
index 19acf4b..ec3a70a 100644
--- a/webrtc/api/mediatypes.h
+++ b/webrtc/api/mediatypes.h
@@ -22,6 +22,9 @@
 };
 
 std::string MediaTypeToString(MediaType type);
+// Aborts on invalid string. Only expected to be used on strings that are
+// guaranteed to be valid, such as MediaStreamTrackInterface::kind().
+MediaType MediaTypeFromString(const std::string& type_str);
 
 }  // namespace cricket
 
diff --git a/webrtc/api/ortc/ortcfactoryinterface.h b/webrtc/api/ortc/ortcfactoryinterface.h
new file mode 100644
index 0000000..855e3b0
--- /dev/null
+++ b/webrtc/api/ortc/ortcfactoryinterface.h
@@ -0,0 +1,230 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef WEBRTC_API_ORTC_ORTCFACTORYINTERFACE_H_
+#define WEBRTC_API_ORTC_ORTCFACTORYINTERFACE_H_
+
+#include <memory>
+#include <string>
+#include <utility>  // For std::move.
+
+#include "webrtc/api/mediaconstraintsinterface.h"
+#include "webrtc/api/mediastreaminterface.h"
+#include "webrtc/api/mediatypes.h"
+#include "webrtc/api/ortc/ortcrtpreceiverinterface.h"
+#include "webrtc/api/ortc/ortcrtpsenderinterface.h"
+#include "webrtc/api/ortc/packettransportinterface.h"
+#include "webrtc/api/ortc/rtptransportcontrollerinterface.h"
+#include "webrtc/api/ortc/rtptransportinterface.h"
+#include "webrtc/api/ortc/udptransportinterface.h"
+#include "webrtc/api/rtcerror.h"
+#include "webrtc/api/rtpparameters.h"
+#include "webrtc/base/network.h"
+#include "webrtc/base/scoped_ref_ptr.h"
+#include "webrtc/base/thread.h"
+#include "webrtc/p2p/base/packetsocketfactory.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): This should be part of /api/, but currently it's not and
+// including its header violates checkdeps rules.
+class AudioDeviceModule;
+
+// WARNING: This is experimental/under development, so use at your own risk; no
+// guarantee about API stability is guaranteed here yet.
+//
+// This class is the ORTC analog of PeerConnectionFactory. It acts as a factory
+// for ORTC objects that can be connected to each other.
+//
+// Some of these objects may not be represented by the ORTC specification, but
+// follow the same general principles.
+//
+// If one of the factory methods takes another object as an argument, it MUST
+// have been created by the same OrtcFactory.
+//
+// On object lifetimes: objects should be destroyed in this order:
+// 1. Objects created by the factory.
+// 2. The factory itself.
+// 3. Objects passed into OrtcFactoryInterface::Create.
+class OrtcFactoryInterface {
+ public:
+  // |network_thread| is the thread on which packets are sent and received.
+  // If null, a new rtc::Thread with a default socket server is created.
+  //
+  // |signaling_thread| is used for callbacks to the consumer of the API. If
+  // null, the current thread will be used, which assumes that the API consumer
+  // is running a message loop on this thread (either using an existing
+  // rtc::Thread, or by calling rtc::Thread::Current()->ProcessMessages).
+  //
+  // |network_manager| is used to determine which network interfaces are
+  // available. This is used for ICE, for example. If null, a default
+  // implementation will be used. Only accessed on |network_thread|.
+  //
+  // |socket_factory| is used (on the network thread) for creating sockets. If
+  // it's null, a default implementation will be used, which assumes
+  // |network_thread| is a normal rtc::Thread.
+  //
+  // |adm| is optional, and allows a different audio device implementation to
+  // be injected; otherwise a platform-specific module will be used that will
+  // use the default audio input.
+  //
+  // Note that the OrtcFactoryInterface does not take ownership of any of the
+  // objects passed in, and as previously stated, these objects can't be
+  // destroyed before the factory is.
+  static RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> Create(
+      rtc::Thread* network_thread,
+      rtc::Thread* signaling_thread,
+      rtc::NetworkManager* network_manager,
+      rtc::PacketSocketFactory* socket_factory,
+      AudioDeviceModule* adm);
+
+  // Constructor for convenience which uses default implementations of
+  // everything (though does still require that the current thread runs a
+  // message loop; see above).
+  static RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> Create() {
+    return Create(nullptr, nullptr, nullptr, nullptr, nullptr);
+  }
+
+  virtual ~OrtcFactoryInterface() {}
+
+  // Creates an RTP transport controller, which is used in calls to
+  // CreateRtpTransport methods. If your application has some notion of a
+  // "call", you should create one transport controller per call.
+  //
+  // However, if you only are using one RtpTransport object, this doesn't need
+  // to be called explicitly; CreateRtpTransport will create one automatically
+  // if |rtp_transport_controller| is null. See below.
+  //
+  // TODO(deadbeef): Add MediaConfig and RtcEventLog arguments?
+  virtual RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>
+  CreateRtpTransportController() = 0;
+
+  // Creates an RTP transport using the provided packet transports and
+  // transport controller.
+  //
+  // |rtp| will be used for sending RTP packets, and |rtcp| for RTCP packets.
+  //
+  // |rtp| can't be null. |rtcp| must be non-null if and only if
+  // |rtcp_parameters.mux| is false, indicating that RTCP muxing isn't used.
+  // Note that if RTCP muxing isn't enabled initially, it can still enabled
+  // later through SetRtcpParameters.
+  //
+  // If |transport_controller| is null, one will automatically be created, and
+  // its lifetime managed by the returned RtpTransport. This should only be
+  // done if a single RtpTransport is being used to communicate with the remote
+  // endpoint.
+  virtual RTCErrorOr<std::unique_ptr<RtpTransportInterface>> CreateRtpTransport(
+      const RtcpParameters& rtcp_parameters,
+      PacketTransportInterface* rtp,
+      PacketTransportInterface* rtcp,
+      RtpTransportControllerInterface* transport_controller) = 0;
+
+  // Returns the capabilities of an RTP sender of type |kind|. These
+  // capabilities can be used to determine what RtpParameters to use to create
+  // an RtpSender.
+  //
+  // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
+  virtual RtpCapabilities GetRtpSenderCapabilities(
+      cricket::MediaType kind) const = 0;
+
+  // Creates an RTP sender with |track|. Will not start sending until Send is
+  // called. This is provided as a convenience; it's equivalent to calling
+  // CreateRtpSender with a kind (see below), followed by SetTrack.
+  //
+  // |track| and |transport| must not be null.
+  virtual RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>> CreateRtpSender(
+      rtc::scoped_refptr<MediaStreamTrackInterface> track,
+      RtpTransportInterface* transport) = 0;
+
+  // Overload of CreateRtpSender allows creating the sender without a track.
+  //
+  // |kind| must be MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO.
+  virtual RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>> CreateRtpSender(
+      cricket::MediaType kind,
+      RtpTransportInterface* transport) = 0;
+
+  // Returns the capabilities of an RTP receiver of type |kind|. These
+  // capabilities can be used to determine what RtpParameters to use to create
+  // an RtpReceiver.
+  //
+  // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
+  virtual RtpCapabilities GetRtpReceiverCapabilities(
+      cricket::MediaType kind) const = 0;
+
+  // Creates an RTP receiver of type |kind|. Will not start receiving media
+  // until Receive is called.
+  //
+  // |kind| must be MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO.
+  //
+  // |transport| must not be null.
+  virtual RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>
+  CreateRtpReceiver(cricket::MediaType kind,
+                    RtpTransportInterface* transport) = 0;
+
+  // Create a UDP transport with IP address family |family|, using a port
+  // within the specified range.
+  //
+  // |family| must be AF_INET or AF_INET6.
+  //
+  // |min_port|/|max_port| values of 0 indicate no range restriction.
+  //
+  // Returns an error if the transport wasn't successfully created.
+  virtual RTCErrorOr<std::unique_ptr<UdpTransportInterface>>
+  CreateUdpTransport(int family, uint16_t min_port, uint16_t max_port) = 0;
+
+  // Method for convenience that has no port range restrictions.
+  RTCErrorOr<std::unique_ptr<UdpTransportInterface>> CreateUdpTransport(
+      int family) {
+    return CreateUdpTransport(family, 0, 0);
+  }
+
+  // NOTE: The methods below to create tracks/sources return scoped_refptrs
+  // rather than unique_ptrs, because these interfaces are also used with
+  // PeerConnection, where everything is ref-counted.
+
+  // Creates a audio source representing the default microphone input.
+  // |options| decides audio processing settings.
+  virtual rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource(
+      const cricket::AudioOptions& options) = 0;
+
+  // Version of the above method that uses default options.
+  rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource() {
+    return CreateAudioSource(cricket::AudioOptions());
+  }
+
+  // Creates a video source object wrapping and taking ownership of |capturer|.
+  //
+  // |constraints| can be used for selection of resolution and frame rate, and
+  // may be null if no constraints are desired.
+  virtual rtc::scoped_refptr<VideoTrackSourceInterface> CreateVideoSource(
+      std::unique_ptr<cricket::VideoCapturer> capturer,
+      const MediaConstraintsInterface* constraints) = 0;
+
+  // Version of the above method that omits |constraints|.
+  rtc::scoped_refptr<VideoTrackSourceInterface> CreateVideoSource(
+      std::unique_ptr<cricket::VideoCapturer> capturer) {
+    return CreateVideoSource(std::move(capturer), nullptr);
+  }
+
+  // Creates a new local video track wrapping |source|. The same |source| can
+  // be used in several tracks.
+  virtual rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
+      const std::string& id,
+      VideoTrackSourceInterface* source) = 0;
+
+  // Creates an new local audio track wrapping |source|.
+  virtual rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack(
+      const std::string& id,
+      AudioSourceInterface* source) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_ORTC_ORTCFACTORYINTERFACE_H_
diff --git a/webrtc/api/ortc/ortcrtpreceiverinterface.h b/webrtc/api/ortc/ortcrtpreceiverinterface.h
new file mode 100644
index 0000000..1fad29c
--- /dev/null
+++ b/webrtc/api/ortc/ortcrtpreceiverinterface.h
@@ -0,0 +1,84 @@
+/*
+ *  Copyright 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.
+ */
+
+// This file contains interfaces for RtpReceivers:
+// http://publications.ortc.org/2016/20161202/#rtcrtpreceiver*
+//
+// However, underneath the RtpReceiver is an RtpTransport, rather than a
+// DtlsTransport. This is to allow different types of RTP transports (besides
+// DTLS-SRTP) to be used.
+
+#ifndef WEBRTC_API_ORTC_ORTCRTPRECEIVERINTERFACE_H_
+#define WEBRTC_API_ORTC_ORTCRTPRECEIVERINTERFACE_H_
+
+#include "webrtc/api/mediastreaminterface.h"
+#include "webrtc/api/mediatypes.h"
+#include "webrtc/api/ortc/rtptransportinterface.h"
+#include "webrtc/api/rtcerror.h"
+#include "webrtc/api/rtpparameters.h"
+
+namespace webrtc {
+
+// Note: Since receiver capabilities may depend on how the OrtcFactory was
+// created, instead of a static "GetCapabilities" method on this interface,
+// there is a "GetRtpReceiverCapabilities" method on the OrtcFactory.
+class OrtcRtpReceiverInterface {
+ public:
+  virtual ~OrtcRtpReceiverInterface() {}
+
+  // Returns a track representing the media received by this receiver.
+  //
+  // Currently, this will return null until Receive has been successfully
+  // called. Also, a new track will be created every time the primary SSRC
+  // changes.
+  //
+  // If encodings are removed, GetTrack will return null. Though deactivating
+  // an encoding (setting |active| to false) will not do this.
+  //
+  // In the future, these limitations will be fixed, and GetTrack will return
+  // the same track for the lifetime of the RtpReceiver. So it's not
+  // recommended to write code that depends on this non-standard behavior.
+  virtual rtc::scoped_refptr<MediaStreamTrackInterface> GetTrack() const = 0;
+
+  // Once supported, will switch to receiving media on a new transport.
+  // However, this is not currently supported and will always return an error.
+  virtual RTCError SetTransport(RtpTransportInterface* transport) = 0;
+  // Returns previously set (or constructed-with) transport.
+  virtual RtpTransportInterface* GetTransport() const = 0;
+
+  // Start receiving media with |parameters| (if |parameters| contains an
+  // active encoding).
+  //
+  // There are no limitations to how the parameters can be changed after the
+  // initial call to Receive, as long as they're valid (for example, they can't
+  // use the same payload type for two codecs).
+  virtual RTCError Receive(const RtpParameters& parameters) = 0;
+  // Returns parameters that were last successfully passed into Receive, or
+  // empty parameters if that hasn't yet occurred.
+  //
+  // Note that for parameters that are described as having an "implementation
+  // default" value chosen, GetParameters() will return those chosen defaults,
+  // with the exception of SSRCs which have special behavior. See
+  // rtpparameters.h for more details.
+  virtual RtpParameters GetParameters() const = 0;
+
+  // Audio or video receiver?
+  //
+  // Once GetTrack() starts always returning a track, this method will be
+  // redundant, as one can call "GetTrack()->kind()". However, it's still a
+  // nice convenience, and is symmetric with OrtcRtpSenderInterface::GetKind.
+  virtual cricket::MediaType GetKind() const = 0;
+
+  // TODO(deadbeef): GetContributingSources
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_ORTC_ORTCRTPRECEIVERINTERFACE_H_
diff --git a/webrtc/api/ortc/ortcrtpsenderinterface.h b/webrtc/api/ortc/ortcrtpsenderinterface.h
new file mode 100644
index 0000000..e369b53
--- /dev/null
+++ b/webrtc/api/ortc/ortcrtpsenderinterface.h
@@ -0,0 +1,77 @@
+/*
+ *  Copyright 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.
+ */
+
+// This file contains interfaces for RtpSenders:
+// http://publications.ortc.org/2016/20161202/#rtcrtpsender*
+//
+// However, underneath the RtpSender is an RtpTransport, rather than a
+// DtlsTransport. This is to allow different types of RTP transports (besides
+// DTLS-SRTP) to be used.
+
+#ifndef WEBRTC_API_ORTC_ORTCRTPSENDERINTERFACE_H_
+#define WEBRTC_API_ORTC_ORTCRTPSENDERINTERFACE_H_
+
+#include "webrtc/api/mediatypes.h"
+#include "webrtc/api/mediastreaminterface.h"
+#include "webrtc/api/ortc/rtptransportinterface.h"
+#include "webrtc/api/rtcerror.h"
+#include "webrtc/api/rtpparameters.h"
+
+namespace webrtc {
+
+// Note: Since sender capabilities may depend on how the OrtcFactory was
+// created, instead of a static "GetCapabilities" method on this interface,
+// there is a "GetRtpSenderCapabilities" method on the OrtcFactory.
+class OrtcRtpSenderInterface {
+ public:
+  virtual ~OrtcRtpSenderInterface() {}
+
+  // Sets the source of media that will be sent by this sender.
+  //
+  // If Send has already been called, will immediately switch to sending this
+  // track. If |track| is null, will stop sending media.
+  //
+  // Returns INVALID_PARAMETER error if an audio track is set on a video
+  // RtpSender, or vice-versa.
+  virtual RTCError SetTrack(MediaStreamTrackInterface* track) = 0;
+  // Returns previously set (or constructed-with) track.
+  virtual rtc::scoped_refptr<MediaStreamTrackInterface> GetTrack() const = 0;
+
+  // Once supported, will switch to sending media on a new transport. However,
+  // this is not currently supported and will always return an error.
+  virtual RTCError SetTransport(RtpTransportInterface* transport) = 0;
+  // Returns previously set (or constructed-with) transport.
+  virtual RtpTransportInterface* GetTransport() const = 0;
+
+  // Start sending media with |parameters| (if |parameters| contains an active
+  // encoding).
+  //
+  // There are no limitations to how the parameters can be changed after the
+  // initial call to Send, as long as they're valid (for example, they can't
+  // use the same payload type for two codecs).
+  virtual RTCError Send(const RtpParameters& parameters) = 0;
+  // Returns parameters that were last successfully passed into Send, or empty
+  // parameters if that hasn't yet occurred.
+  //
+  // Note that for parameters that are described as having an "implementation
+  // default" value chosen, GetParameters() will return those chosen defaults,
+  // with the exception of SSRCs which have special behavior. See
+  // rtpparameters.h for more details.
+  virtual RtpParameters GetParameters() const = 0;
+
+  // Audio or video sender?
+  virtual cricket::MediaType GetKind() const = 0;
+
+  // TODO(deadbeef): SSRC conflict signal.
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_ORTC_ORTCRTPSENDERINTERFACE_H_
diff --git a/webrtc/api/ortc/packettransportinterface.h b/webrtc/api/ortc/packettransportinterface.h
new file mode 100644
index 0000000..2677ce6
--- /dev/null
+++ b/webrtc/api/ortc/packettransportinterface.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef WEBRTC_API_ORTC_PACKETTRANSPORTINTERFACE_H_
+#define WEBRTC_API_ORTC_PACKETTRANSPORTINTERFACE_H_
+
+namespace rtc {
+
+class PacketTransportInternal;
+
+}  // namespace rtc
+
+namespace webrtc {
+
+// Base class for different packet-based transports.
+class PacketTransportInterface {
+ public:
+  virtual ~PacketTransportInterface() {}
+
+ protected:
+  // Only for internal use. Returns a pointer to an internal interface, for use
+  // by the implementation.
+  virtual rtc::PacketTransportInternal* GetInternal() = 0;
+
+  // Classes that can use this internal interface.
+  friend class RtpTransportControllerAdapter;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_ORTC_PACKETTRANSPORTINTERFACE_H_
diff --git a/webrtc/api/ortc/rtptransportcontrollerinterface.h b/webrtc/api/ortc/rtptransportcontrollerinterface.h
new file mode 100644
index 0000000..d1d0e44
--- /dev/null
+++ b/webrtc/api/ortc/rtptransportcontrollerinterface.h
@@ -0,0 +1,57 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef WEBRTC_API_ORTC_RTPTRANSPORTCONTROLLERINTERFACE_H_
+#define WEBRTC_API_ORTC_RTPTRANSPORTCONTROLLERINTERFACE_H_
+
+#include <vector>
+
+#include "webrtc/api/ortc/rtptransportinterface.h"
+
+namespace webrtc {
+
+class RtpTransportControllerAdapter;
+
+// Used to group RTP transports between a local endpoint and the same remote
+// endpoint, for the purpose of sharing bandwidth estimation and other things.
+//
+// Comparing this to the PeerConnection model, non-budled audio/video would use
+// two RtpTransports with a single RtpTransportController, whereas bundled
+// media would use a single RtpTransport, and two PeerConnections would use
+// independent RtpTransportControllers.
+//
+// RtpTransports are associated with this controller when they're created, by
+// passing the controller into OrtcFactory's relevant "CreateRtpTransport"
+// method. When a transport is destroyed, it's automatically disassociated.
+// GetTransports returns all currently associated transports.
+//
+// This is the RTP equivalent of "IceTransportController" in ORTC; RtpTransport
+// is to RtpTransportController as IceTransport is to IceTransportController.
+class RtpTransportControllerInterface {
+ public:
+  virtual ~RtpTransportControllerInterface() {}
+
+  // Returns all transports associated with this controller (see explanation
+  // above). No ordering is guaranteed.
+  virtual std::vector<RtpTransportInterface*> GetTransports() const = 0;
+
+ protected:
+  // Only for internal use. Returns a pointer to an internal interface, for use
+  // by the implementation.
+  virtual RtpTransportControllerAdapter* GetInternal() = 0;
+
+  // Classes that can use this internal interface.
+  friend class OrtcFactory;
+  friend class RtpTransportAdapter;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_ORTC_RTPTRANSPORTCONTROLLERINTERFACE_H_
diff --git a/webrtc/api/ortc/rtptransportinterface.h b/webrtc/api/ortc/rtptransportinterface.h
new file mode 100644
index 0000000..942dc50
--- /dev/null
+++ b/webrtc/api/ortc/rtptransportinterface.h
@@ -0,0 +1,103 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef WEBRTC_API_ORTC_RTPTRANSPORTINTERFACE_H_
+#define WEBRTC_API_ORTC_RTPTRANSPORTINTERFACE_H_
+
+#include <string>
+
+#include "webrtc/api/ortc/packettransportinterface.h"
+#include "webrtc/api/rtcerror.h"
+#include "webrtc/base/optional.h"
+
+namespace webrtc {
+
+class RtpTransportAdapter;
+
+struct RtcpParameters {
+  // The SSRC to be used in the "SSRC of packet sender" field. If not set, one
+  // will be chosen by the implementation.
+  // TODO(deadbeef): Not implemented.
+  rtc::Optional<uint32_t> ssrc;
+
+  // The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages).
+  //
+  // If empty in the construction of the RtpTransport, one will be generated by
+  // the implementation, and returned in GetRtcpParameters. Multiple
+  // RtpTransports created by the same OrtcFactory will use the same generated
+  // CNAME.
+  //
+  // If empty when passed into SetRtcpParameters, the CNAME simply won't be
+  // modified.
+  std::string cname;
+
+  // Send reduced-size RTCP?
+  bool reduced_size = false;
+
+  // Send RTCP multiplexed on the RTP transport?
+  bool mux = true;
+
+  bool operator==(const RtcpParameters& o) const {
+    return ssrc == o.ssrc && cname == o.cname &&
+           reduced_size == o.reduced_size && mux == o.mux;
+  }
+  bool operator!=(const RtcpParameters& o) const { return !(*this == o); }
+};
+
+// Base class for different types of RTP transports that can be created by an
+// OrtcFactory. Used by RtpSenders/RtpReceivers.
+//
+// This is not present in the standard ORTC API, but exists here for a few
+// reasons. Firstly, it allows different types of RTP transports to be used:
+// DTLS-SRTP (which is required for the web), but also SDES-SRTP and
+// unencrypted RTP. It also simplifies the handling of RTCP muxing, and
+// provides a better API point for it.
+//
+// Note that Edge's implementation of ORTC provides a similar API point, called
+// RTCSrtpSdesTransport:
+// https://msdn.microsoft.com/en-us/library/mt502527(v=vs.85).aspx
+class RtpTransportInterface {
+ public:
+  virtual ~RtpTransportInterface() {}
+
+  // Returns packet transport that's used to send RTP packets.
+  virtual PacketTransportInterface* GetRtpPacketTransport() const = 0;
+
+  // Returns separate packet transport that's used to send RTCP packets. If
+  // RTCP multiplexing is being used, returns null.
+  virtual PacketTransportInterface* GetRtcpPacketTransport() const = 0;
+
+  // Set/get RTCP params. Can be used to enable RTCP muxing or reduced-size
+  // RTCP if initially not enabled.
+  //
+  // Changing |mux| from "true" to "false" is not allowed, and changing the
+  // CNAME is currently unsupported.
+  virtual RTCError SetRtcpParameters(const RtcpParameters& parameters) = 0;
+  // Returns last set or constructed-with parameters. If |cname| was empty in
+  // construction, the generated CNAME will be present in the returned
+  // parameters (see above).
+  virtual RtcpParameters GetRtcpParameters() const = 0;
+
+ protected:
+  // Only for internal use. Returns a pointer to an internal interface, for use
+  // by the implementation.
+  virtual RtpTransportAdapter* GetInternal() = 0;
+
+  // Classes that can use this internal interface.
+  friend class OrtcFactory;
+  friend class OrtcRtpSenderAdapter;
+  friend class OrtcRtpReceiverAdapter;
+  friend class RtpTransportControllerAdapter;
+  friend class RtpTransportAdapter;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_API_ORTC_RTPTRANSPORTINTERFACE_H_
diff --git a/webrtc/api/udptransportinterface.h b/webrtc/api/ortc/udptransportinterface.h
similarity index 71%
rename from webrtc/api/udptransportinterface.h
rename to webrtc/api/ortc/udptransportinterface.h
index 30858e6..2781076 100644
--- a/webrtc/api/udptransportinterface.h
+++ b/webrtc/api/ortc/udptransportinterface.h
@@ -8,9 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_API_UDPTRANSPORTINTERFACE_H_
-#define WEBRTC_API_UDPTRANSPORTINTERFACE_H_
+#ifndef WEBRTC_API_ORTC_UDPTRANSPORTINTERFACE_H_
+#define WEBRTC_API_ORTC_UDPTRANSPORTINTERFACE_H_
 
+#include "webrtc/api/ortc/packettransportinterface.h"
 #include "webrtc/api/proxy.h"
 #include "webrtc/base/socketaddress.h"
 
@@ -26,10 +27,8 @@
 //
 // Calling SetRemoteAddress sets the destination of outgoing packets; without a
 // destination, packets can't be sent, but they can be received.
-class UdpTransportInterface {
+class UdpTransportInterface : virtual public PacketTransportInterface {
  public:
-  virtual ~UdpTransportInterface() {}
-
   // Get the address of the socket allocated for this transport.
   virtual rtc::SocketAddress GetLocalAddress() const = 0;
 
@@ -45,15 +44,6 @@
   virtual rtc::SocketAddress GetRemoteAddress() const = 0;
 };
 
-// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
-// are called on is an implementation detail.
-BEGIN_OWNED_PROXY_MAP(UdpTransport)
-  PROXY_WORKER_THREAD_DESTRUCTOR()
-  PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetLocalAddress)
-  PROXY_WORKER_METHOD1(bool, SetRemoteAddress, const rtc::SocketAddress&)
-  PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetRemoteAddress)
-END_PROXY_MAP()
-
 }  // namespace webrtc
 
-#endif  // WEBRTC_API_UDPTRANSPORTINTERFACE_H_
+#endif  // WEBRTC_API_ORTC_UDPTRANSPORTINTERFACE_H_
diff --git a/webrtc/api/ortcfactoryinterface.h b/webrtc/api/ortcfactoryinterface.h
deleted file mode 100644
index 8d46d68..0000000
--- a/webrtc/api/ortcfactoryinterface.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  Copyright 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.
- */
-
-#ifndef WEBRTC_API_ORTCFACTORYINTERFACE_H_
-#define WEBRTC_API_ORTCFACTORYINTERFACE_H_
-
-#include <memory>
-
-#include "webrtc/api/udptransportinterface.h"
-#include "webrtc/base/network.h"
-#include "webrtc/base/thread.h"
-#include "webrtc/p2p/base/packetsocketfactory.h"
-
-namespace webrtc {
-
-// WARNING: This is experimental/under development, so use at your own risk; no
-// guarantee about API stability is guaranteed here yet.
-//
-// This class is the ORTC analog of PeerConnectionFactory. It acts as a factory
-// for ORTC objects that can be connected to each other.
-//
-// Some of these objects may not be represented by the ORTC specification, but
-// follow the same general principles.
-//
-// On object lifetimes: The factory must not be destroyed before destroying the
-// objects it created, and the objects passed into the factory must not be
-// destroyed before destroying the factory.
-class OrtcFactoryInterface {
- public:
-  // |network_thread| is the thread on which packets are sent and received.
-  // If null, a new rtc::Thread with a default socket server is created.
-  //
-  // |signaling_thread| is used for callbacks to the consumer of the API. If
-  // null, the current thread will be used, which assumes that the API consumer
-  // is running a message loop on this thread (either using an existing
-  // rtc::Thread, or by calling rtc::Thread::Current()->ProcessMessages).
-  //
-  // |network_manager| is used to determine which network interfaces are
-  // available. This is used for ICE, for example. If null, a default
-  // implementation will be used. Only accessed on |network_thread|.
-  //
-  // |socket_factory| is used (on the network thread) for creating sockets. If
-  // it's null, a default implementation will be used, which assumes
-  // |network_thread| is a normal rtc::Thread.
-  //
-  // Note that the OrtcFactoryInterface does not take ownership of any of the
-  // objects
-  // passed in, and as previously stated, these objects can't be destroyed
-  // before the factory is.
-  static std::unique_ptr<OrtcFactoryInterface> Create(
-      rtc::Thread* network_thread,
-      rtc::Thread* signaling_thread,
-      rtc::NetworkManager* network_manager,
-      rtc::PacketSocketFactory* socket_factory);
-  // Constructor for convenience which uses default implementations of
-  // everything (though does still require that the current thread runs a
-  // message loop; see above).
-  static std::unique_ptr<OrtcFactoryInterface> Create() {
-    return Create(nullptr, nullptr, nullptr, nullptr);
-  }
-
-  virtual ~OrtcFactoryInterface() {}
-
-  virtual std::unique_ptr<UdpTransportInterface>
-  CreateUdpTransport(int family, uint16_t min_port, uint16_t max_port) = 0;
-  // Method for convenience that has no port range restrictions.
-  std::unique_ptr<UdpTransportInterface> CreateUdpTransport(int family) {
-    return CreateUdpTransport(family, 0, 0);
-  }
-};
-
-}  // namespace webrtc
-
-#endif  // WEBRTC_API_ORTCFACTORYINTERFACE_H_
diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h
index a2e5e1b..69bae29 100644
--- a/webrtc/api/peerconnectioninterface.h
+++ b/webrtc/api/peerconnectioninterface.h
@@ -68,7 +68,6 @@
 #define WEBRTC_API_PEERCONNECTIONINTERFACE_H_
 
 #include <memory>
-#include <ostream>
 #include <string>
 #include <utility>
 #include <vector>
@@ -901,7 +900,7 @@
   virtual rtc::scoped_refptr<MediaStreamInterface>
       CreateLocalMediaStream(const std::string& label) = 0;
 
-  // Creates a AudioSourceInterface.
+  // Creates an AudioSourceInterface.
   // |options| decides audio processing settings.
   virtual rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource(
       const cricket::AudioOptions& options) = 0;
diff --git a/webrtc/api/proxy.h b/webrtc/api/proxy.h
index 5634cfe..46c424d 100644
--- a/webrtc/api/proxy.h
+++ b/webrtc/api/proxy.h
@@ -353,18 +353,18 @@
 
 
 // Helper macros to reduce code duplication.
-#define PROXY_MAP_BOILERPLATE(c)                                \
-  template <class INTERNAL_CLASS>                               \
-  class c##ProxyWithInternal;                                   \
-  typedef c##ProxyWithInternal<c##Interface> c##Proxy;          \
-  template <class INTERNAL_CLASS>                               \
-  class c##ProxyWithInternal : public c##Interface {            \
-   protected:                                                   \
-    typedef c##Interface C;                                     \
-                                                                \
-   public:                                                      \
-    const INTERNAL_CLASS* internal() const { return c_.get(); } \
-    INTERNAL_CLASS* internal() { return c_.get(); }
+#define PROXY_MAP_BOILERPLATE(c)                          \
+  template <class INTERNAL_CLASS>                         \
+  class c##ProxyWithInternal;                             \
+  typedef c##ProxyWithInternal<c##Interface> c##Proxy;    \
+  template <class INTERNAL_CLASS>                         \
+  class c##ProxyWithInternal : public c##Interface {      \
+   protected:                                             \
+    typedef c##Interface C;                               \
+                                                          \
+   public:                                                \
+    const INTERNAL_CLASS* internal() const { return c_; } \
+    INTERNAL_CLASS* internal() { return c_; }
 
 #define END_PROXY_MAP() \
   };
@@ -403,6 +403,11 @@
   void DestroyInternal() { c_ = nullptr; }             \
   rtc::scoped_refptr<INTERNAL_CLASS> c_;
 
+// Note: This doesn't use a unique_ptr, because it intends to handle a corner
+// case where an object's deletion triggers a callback that calls back into
+// this proxy object. If relying on a unique_ptr to delete the object, its
+// inner pointer would be set to null before this reentrant callback would have
+// a chance to run, resulting in a segfault.
 #define OWNED_PROXY_MAP_BOILERPLATE(c)                 \
  public:                                               \
   ~c##ProxyWithInternal() {                            \
@@ -412,8 +417,8 @@
   }                                                    \
                                                        \
  private:                                              \
-  void DestroyInternal() { c_.reset(nullptr); }        \
-  std::unique_ptr<INTERNAL_CLASS> c_;
+  void DestroyInternal() { delete c_; }                \
+  INTERNAL_CLASS* c_;
 
 #define BEGIN_SIGNALING_PROXY_MAP(c)                                         \
   PROXY_MAP_BOILERPLATE(c)                                                   \
@@ -438,16 +443,16 @@
                                                            worker_thread, c); \
   }
 
-#define BEGIN_OWNED_PROXY_MAP(c)                                       \
-  PROXY_MAP_BOILERPLATE(c)                                             \
-  WORKER_PROXY_MAP_BOILERPLATE(c)                                      \
-  OWNED_PROXY_MAP_BOILERPLATE(c)                                       \
- public:                                                               \
-  static std::unique_ptr<c##ProxyWithInternal> Create(                 \
-      rtc::Thread* signaling_thread, rtc::Thread* worker_thread,       \
-      INTERNAL_CLASS* c) {                                             \
-    return std::unique_ptr<c##ProxyWithInternal>(                      \
-        new c##ProxyWithInternal(signaling_thread, worker_thread, c)); \
+#define BEGIN_OWNED_PROXY_MAP(c)                                   \
+  PROXY_MAP_BOILERPLATE(c)                                         \
+  WORKER_PROXY_MAP_BOILERPLATE(c)                                  \
+  OWNED_PROXY_MAP_BOILERPLATE(c)                                   \
+ public:                                                           \
+  static std::unique_ptr<c##Interface> Create(                     \
+      rtc::Thread* signaling_thread, rtc::Thread* worker_thread,   \
+      std::unique_ptr<INTERNAL_CLASS> c) {                         \
+    return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \
+        signaling_thread, worker_thread, c.release()));            \
   }
 
 #define PROXY_SIGNALING_THREAD_DESTRUCTOR()                            \
@@ -464,95 +469,109 @@
 
 #define PROXY_METHOD0(r, method)                           \
   r method() override {                                    \
-    MethodCall0<C, r> call(c_.get(), &C::method);          \
+    MethodCall0<C, r> call(c_, &C::method);                \
     return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
   }
 
 #define PROXY_CONSTMETHOD0(r, method)                      \
   r method() const override {                              \
-    ConstMethodCall0<C, r> call(c_.get(), &C::method);     \
+    ConstMethodCall0<C, r> call(c_, &C::method);           \
     return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
   }
 
-#define PROXY_METHOD1(r, method, t1)                                 \
-  r method(t1 a1) override {                                         \
-    MethodCall1<C, r, t1> call(c_.get(), &C::method, std::move(a1)); \
-    return call.Marshal(RTC_FROM_HERE, signaling_thread_);           \
+#define PROXY_METHOD1(r, method, t1)                           \
+  r method(t1 a1) override {                                   \
+    MethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
+    return call.Marshal(RTC_FROM_HERE, signaling_thread_);     \
   }
 
-#define PROXY_CONSTMETHOD1(r, method, t1)                                 \
-  r method(t1 a1) const override {                                        \
-    ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, std::move(a1)); \
-    return call.Marshal(RTC_FROM_HERE, signaling_thread_);                \
+#define PROXY_CONSTMETHOD1(r, method, t1)                           \
+  r method(t1 a1) const override {                                  \
+    ConstMethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
+    return call.Marshal(RTC_FROM_HERE, signaling_thread_);          \
   }
 
-#define PROXY_METHOD2(r, method, t1, t2)                                \
-  r method(t1 a1, t2 a2) override {                                     \
-    MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, std::move(a1), \
-                                   std::move(a2));                      \
-    return call.Marshal(RTC_FROM_HERE, signaling_thread_);              \
+#define PROXY_METHOD2(r, method, t1, t2)                          \
+  r method(t1 a1, t2 a2) override {                               \
+    MethodCall2<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
+                                   std::move(a2));                \
+    return call.Marshal(RTC_FROM_HERE, signaling_thread_);        \
   }
 
-#define PROXY_METHOD3(r, method, t1, t2, t3)                                \
-  r method(t1 a1, t2 a2, t3 a3) override {                                  \
-    MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, std::move(a1), \
-                                       std::move(a2), std::move(a3));       \
-    return call.Marshal(RTC_FROM_HERE, signaling_thread_);                  \
+#define PROXY_METHOD3(r, method, t1, t2, t3)                          \
+  r method(t1 a1, t2 a2, t3 a3) override {                            \
+    MethodCall3<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
+                                       std::move(a2), std::move(a3)); \
+    return call.Marshal(RTC_FROM_HERE, signaling_thread_);            \
   }
 
 #define PROXY_METHOD4(r, method, t1, t2, t3, t4)                          \
   r method(t1 a1, t2 a2, t3 a3, t4 a4) override {                         \
-    MethodCall4<C, r, t1, t2, t3, t4> call(c_.get(), &C::method,          \
-                                           std::move(a1), std::move(a2),  \
-                                           std::move(a3), std::move(a4)); \
+    MethodCall4<C, r, t1, t2, t3, t4> call(c_, &C::method, std::move(a1), \
+                                           std::move(a2), std::move(a3),  \
+                                           std::move(a4));                \
     return call.Marshal(RTC_FROM_HERE, signaling_thread_);                \
   }
 
-#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5)                       \
-  r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override {                   \
-    MethodCall5<C, r, t1, t2, t3, t4, t5> call(                            \
-        c_.get(), &C::method, std::move(a1), std::move(a2), std::move(a3), \
-        std::move(a4), std::move(a5));                                     \
-    return call.Marshal(RTC_FROM_HERE, signaling_thread_);                 \
+#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5)                          \
+  r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override {                      \
+    MethodCall5<C, r, t1, t2, t3, t4, t5> call(c_, &C::method, std::move(a1), \
+                                               std::move(a2), std::move(a3),  \
+                                               std::move(a4), std::move(a5)); \
+    return call.Marshal(RTC_FROM_HERE, signaling_thread_);                    \
   }
 
 // Define methods which should be invoked on the worker thread.
 #define PROXY_WORKER_METHOD0(r, method)                 \
   r method() override {                                 \
-    MethodCall0<C, r> call(c_.get(), &C::method);       \
+    MethodCall0<C, r> call(c_, &C::method);             \
     return call.Marshal(RTC_FROM_HERE, worker_thread_); \
   }
 
 #define PROXY_WORKER_CONSTMETHOD0(r, method)            \
   r method() const override {                           \
-    ConstMethodCall0<C, r> call(c_.get(), &C::method);  \
+    ConstMethodCall0<C, r> call(c_, &C::method);        \
     return call.Marshal(RTC_FROM_HERE, worker_thread_); \
   }
 
-#define PROXY_WORKER_METHOD1(r, method, t1)                          \
-  r method(t1 a1) override {                                         \
-    MethodCall1<C, r, t1> call(c_.get(), &C::method, std::move(a1)); \
-    return call.Marshal(RTC_FROM_HERE, worker_thread_);              \
+#define PROXY_WORKER_METHOD1(r, method, t1)                    \
+  r method(t1 a1) override {                                   \
+    MethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
+    return call.Marshal(RTC_FROM_HERE, worker_thread_);        \
   }
 
-#define PROXY_WORKER_CONSTMETHOD1(r, method, t1)                          \
-  r method(t1 a1) const override {                                        \
-    ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, std::move(a1)); \
-    return call.Marshal(RTC_FROM_HERE, worker_thread_);                   \
+#define PROXY_WORKER_CONSTMETHOD1(r, method, t1)                    \
+  r method(t1 a1) const override {                                  \
+    ConstMethodCall1<C, r, t1> call(c_, &C::method, std::move(a1)); \
+    return call.Marshal(RTC_FROM_HERE, worker_thread_);             \
   }
 
-#define PROXY_WORKER_METHOD2(r, method, t1, t2)                         \
-  r method(t1 a1, t2 a2) override {                                     \
-    MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, std::move(a1), \
-                                   std::move(a2));                      \
-    return call.Marshal(RTC_FROM_HERE, worker_thread_);                 \
+#define PROXY_WORKER_METHOD2(r, method, t1, t2)                   \
+  r method(t1 a1, t2 a2) override {                               \
+    MethodCall2<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
+                                   std::move(a2));                \
+    return call.Marshal(RTC_FROM_HERE, worker_thread_);           \
   }
 
-#define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2)                         \
-  r method(t1 a1, t2 a2) const override {                                    \
-    ConstMethodCall2<C, r, t1, t2> call(c_.get(), &C::method, std::move(a1), \
-                                        std::move(a2));                      \
-    return call.Marshal(RTC_FROM_HERE, worker_thread_);                      \
+#define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2)                   \
+  r method(t1 a1, t2 a2) const override {                              \
+    ConstMethodCall2<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
+                                        std::move(a2));                \
+    return call.Marshal(RTC_FROM_HERE, worker_thread_);                \
+  }
+
+#define PROXY_WORKER_METHOD3(r, method, t1, t2, t3)                   \
+  r method(t1 a1, t2 a2, t3 a3) override {                            \
+    MethodCall3<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
+                                       std::move(a2), std::move(a3)); \
+    return call.Marshal(RTC_FROM_HERE, worker_thread_);               \
+  }
+
+#define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2)                       \
+  r method(t1 a1, t2 a2, t3 a3) const override {                           \
+    ConstMethodCall3<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
+                                            std::move(a2), std::move(a3)); \
+    return call.Marshal(RTC_FROM_HERE, worker_thread_);                    \
   }
 
 }  // namespace webrtc
diff --git a/webrtc/api/rtcerror.h b/webrtc/api/rtcerror.h
index 1c130c0..2ba7837 100644
--- a/webrtc/api/rtcerror.h
+++ b/webrtc/api/rtcerror.h
@@ -224,7 +224,7 @@
   // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type
   // so it is convenient and sensible to be able to do 'return T()'
   // when the return type is RTCErrorOr<T>.
-  RTCErrorOr(T value) : value_(std::move(value)) {}
+  RTCErrorOr(T&& value) : value_(std::move(value)) {}
 
   // Delete the copy constructor and assignment operator; there aren't any use
   // cases where you should need to copy an RTCErrorOr, as opposed to moving
diff --git a/webrtc/api/rtpparameters.h b/webrtc/api/rtpparameters.h
index f506c40..e4fe47b 100644
--- a/webrtc/api/rtpparameters.h
+++ b/webrtc/api/rtpparameters.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "webrtc/api/mediatypes.h"
+#include "webrtc/config.h"
 #include "webrtc/base/optional.h"
 
 namespace webrtc {
@@ -47,14 +48,13 @@
 
 // Used in RtcpFeedback struct.
 enum class RtcpFeedbackType {
-  ACK,
   CCM,
   NACK,
   REMB,  // "goog-remb"
   TRANSPORT_CC,
 };
 
-// Used in RtcpFeedback struct when type is ACK, NACK or CCM.
+// Used in RtcpFeedback struct when type is NACK or CCM.
 enum class RtcpFeedbackMessageType {
   // Equivalent to {type: "nack", parameter: undefined} in ORTC.
   GENERIC_NACK,
@@ -76,7 +76,7 @@
 enum class PriorityType { VERY_LOW, LOW, MEDIUM, HIGH };
 
 struct RtcpFeedback {
-  RtcpFeedbackType type = RtcpFeedbackType::ACK;
+  RtcpFeedbackType type = RtcpFeedbackType::CCM;
 
   // Equivalent to ORTC "parameter" field with slight differences:
   // 1. It's an enum instead of a string.
@@ -84,6 +84,12 @@
   //    rather than an unset "parameter" value.
   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) {}
+
   bool operator==(const RtcpFeedback& o) const {
     return type == o.type && message_type == o.message_type;
   }
@@ -126,7 +132,12 @@
   std::vector<RtcpFeedback> rtcp_feedback;
 
   // Codec-specific parameters that must be signaled to the remote party.
+  //
   // Corresponds to "a=fmtp" parameters in SDP.
+  //
+  // Contrary to ORTC, these parameters are named using all lowercase strings.
+  // This helps make the mapping to SDP simpler, if an application is using
+  // SDP. Boolean values are represented by the string "1".
   std::unordered_map<std::string, std::string> parameters;
 
   // Codec-specific parameters that may optionally be signaled to the remote
@@ -184,6 +195,12 @@
   // TODO(deadbeef): Not implemented.
   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) {}
+
   bool operator==(const RtpHeaderExtensionCapability& o) const {
     return uri == o.uri && preferred_id == o.preferred_id &&
            preferred_encrypt == o.preferred_encrypt;
@@ -193,33 +210,23 @@
   }
 };
 
-// Used in RtpParameters; represents a specific configuration of a header
-// extension.
-struct RtpHeaderExtensionParameters {
-  // URI of this extension, as defined in RFC5285.
-  std::string uri;
-
-  // ID value that goes in the packet.
-  int id = 0;
-
-  // If true, the value in the header is encrypted.
-  // TODO(deadbeef): Not implemented.
-  bool encrypt = false;
-
-  bool operator==(const RtpHeaderExtensionParameters& o) const {
-    return uri == o.uri && id == o.id && encrypt == o.encrypt;
-  }
-  bool operator!=(const RtpHeaderExtensionParameters& o) const {
-    return !(*this == o);
-  }
-};
+// See webrtc/config.h. Has "uri" and "id" fields.
+// TODO(deadbeef): This is missing the "encrypt" flag, which is unimplemented.
+typedef RtpExtension RtpHeaderExtensionParameters;
 
 struct RtpFecParameters {
   // If unset, a value is chosen by the implementation.
+  // Works just like RtpEncodingParameters::ssrc.
   rtc::Optional<uint32_t> ssrc;
 
   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) {}
+
   bool operator==(const RtpFecParameters& o) const {
     return ssrc == o.ssrc && mechanism == o.mechanism;
   }
@@ -228,33 +235,48 @@
 
 struct RtpRtxParameters {
   // If unset, a value is chosen by the implementation.
+  // Works just like RtpEncodingParameters::ssrc.
   rtc::Optional<uint32_t> ssrc;
 
+  // Constructors for convenience.
+  RtpRtxParameters() = default;
+  explicit RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
+
   bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; }
   bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); }
 };
 
 struct RtpEncodingParameters {
   // If unset, a value is chosen by the implementation.
+  //
+  // Note that the chosen value is NOT returned by GetParameters, because it
+  // may change due to an SSRC conflict, in which case the conflict is handled
+  // internally without any event. Another way of looking at this is that an
+  // unset SSRC acts as a "wildcard" SSRC.
   rtc::Optional<uint32_t> ssrc;
 
   // Can be used to reference a codec in the |codecs| member of the
   // RtpParameters that contains this RtpEncodingParameters. If unset, the
-  // implementation will choose the first possible codec.
-  // TODO(deadbeef): Not implemented.
+  // implementation will choose the first possible codec (if a sender), or
+  // prepare to receive any codec (for a receiver).
+  // TODO(deadbeef): Not implemented. Implementation of RtpSender will always
+  // choose the first codec from the list.
   rtc::Optional<int> codec_payload_type;
 
   // Specifies the FEC mechanism, if set.
-  // TODO(deadbeef): Not implemented.
+  // TODO(deadbeef): Not implemented. Current implementation will use whatever
+  // FEC codecs are available, including red+ulpfec.
   rtc::Optional<RtpFecParameters> fec;
 
   // Specifies the RTX parameters, if set.
-  // TODO(deadbeef): Not implemented.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
   rtc::Optional<RtpRtxParameters> rtx;
 
   // Only used for audio. If set, determines whether or not discontinuous
   // transmission will be used, if an available codec supports it. If not
   // set, the implementation default setting will be used.
+  // TODO(deadbeef): Not implemented. Current implementation will use a CN
+  // codec as long as it's present.
   rtc::Optional<DtxStatus> dtx;
 
   // The relative priority of this encoding.
@@ -264,7 +286,13 @@
   // If set, this represents the Transport Independent Application Specific
   // maximum bandwidth defined in RFC3890. If unset, there is no maximum
   // bitrate.
+  //
   // Just called "maxBitrate" in ORTC spec.
+  //
+  // TODO(deadbeef): With ORTC RtpSenders, this currently sets the total
+  // bandwidth for the entire bandwidth estimator (audio and video). This is
+  // just always how "b=AS" was handled, but it's not correct and should be
+  // fixed.
   rtc::Optional<int> max_bitrate_bps;
 
   // TODO(deadbeef): Not implemented.
@@ -281,7 +309,7 @@
   // For an RtpSender, set to true to cause this encoding to be sent, and false
   // for it not to be sent. For an RtpReceiver, set to true to cause the
   // encoding to be decoded, and false for it to be ignored.
-  // TODO(deadbeef): RtpReceiver part is not implemented.
+  // TODO(deadbeef): Not implemented for PeerConnection RtpReceivers.
   bool active = true;
 
   // Value to use for RID RTP header extension.
@@ -320,7 +348,7 @@
   cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
 
   // Payload type used to identify this codec in RTP packets.
-  // This MUST always be present, and must be unique across all codecs using
+  // This must always be present, and must be unique across all codecs using
   // the same transport.
   int payload_type = 0;
 
@@ -329,7 +357,9 @@
 
   // The number of audio channels used. Unset for video codecs. If unset for
   // audio, the implementation default is used.
-  // TODO(deadbeef): The "implementation default" part is unimplemented.
+  // TODO(deadbeef): The "implementation default" part isn't fully implemented.
+  // Only defaults to 1, even though some codecs (such as opus) should really
+  // default to 2.
   rtc::Optional<int> num_channels;
 
   // The maximum packetization time to be used by an RtpSender.
@@ -343,12 +373,18 @@
   rtc::Optional<int> ptime;
 
   // Feedback mechanisms to be used for this codec.
-  // TODO(deadbeef): Not implemented.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
   std::vector<RtcpFeedback> rtcp_feedback;
 
   // Codec-specific parameters that must be signaled to the remote party.
+  //
   // Corresponds to "a=fmtp" parameters in SDP.
-  // TODO(deadbeef): Not implemented.
+  //
+  // Contrary to ORTC, these parameters are named using all lowercase strings.
+  // This helps make the mapping to SDP simpler, if an application is using
+  // SDP. Boolean values are represented by the string "1".
+  //
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
   std::unordered_map<std::string, std::string> parameters;
 
   bool operator==(const RtpCodecParameters& o) const {
@@ -370,7 +406,9 @@
   // Supported RTP header extensions.
   std::vector<RtpHeaderExtensionCapability> header_extensions;
 
-  // Supported Forward Error Correction (FEC) mechanisms.
+  // Supported Forward Error Correction (FEC) mechanisms. Note that the RED,
+  // ulpfec and flexfec codecs used by these mechanisms will still appear in
+  // |codecs|.
   std::vector<FecMechanism> fec;
 
   bool operator==(const RtpCapabilities& o) const {
@@ -380,8 +418,8 @@
   bool operator!=(const RtpCapabilities& o) const { return !(*this == o); }
 };
 
-// Note that unlike in ORTC, an RtcpParameters is not included in
-// RtpParameters, because our API will include an additional "RtpTransport"
+// Note that unlike in ORTC, an RtcpParameters structure is not included in
+// RtpParameters, because our API includes an additional "RtpTransport"
 // abstraction on which RTCP parameters are set.
 struct RtpParameters {
   // Used when calling getParameters/setParameters with a PeerConnection
@@ -397,7 +435,7 @@
 
   std::vector<RtpCodecParameters> codecs;
 
-  // TODO(deadbeef): Not implemented.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
   std::vector<RtpHeaderExtensionParameters> header_extensions;
 
   std::vector<RtpEncodingParameters> encodings;