Add new PeerConnection APIs to the ObjC SDK

This CL adds wrappers for the following PeerConnection native
APIs to the Objective C API:
- SdpSemantics enum added to the RTCConfiguration
- RTCRtpTransceiver
- RTCPeerConnection.addTrack
- RTCPeerConnection.removeTrack
- RTCPeerConnection.addTransceiver
- RTCPeerConnection.transceivers

Bug: webrtc:8870
Change-Id: I9449df9742a59e90894712dc7749ca30b569d94b
Reviewed-on: https://webrtc-review.googlesource.com/54780
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22214}
diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCConfiguration.h b/sdk/objc/Framework/Headers/WebRTC/RTCConfiguration.h
index f3a8d3f..97cc5a4 100644
--- a/sdk/objc/Framework/Headers/WebRTC/RTCConfiguration.h
+++ b/sdk/objc/Framework/Headers/WebRTC/RTCConfiguration.h
@@ -63,6 +63,13 @@
   RTCEncryptionKeyTypeECDSA,
 };
 
+/** Represents the chosen SDP semantics for the RTCPeerConnection. */
+typedef NS_ENUM(NSInteger, RTCSdpSemantics) {
+  RTCSdpSemanticsDefault,
+  RTCSdpSemanticsPlanB,
+  RTCSdpSemanticsUnifiedPlan,
+};
+
 NS_ASSUME_NONNULL_BEGIN
 
 RTC_EXPORT
@@ -132,6 +139,33 @@
  */
 @property(nonatomic, strong, nullable) RTCIntervalRange *iceRegatherIntervalRange;
 
+/** Configure the SDP semantics used by this PeerConnection. Note that the
+ *  WebRTC 1.0 specification requires UnifiedPlan semantics. The
+ *  RTCRtpTransceiver API is only available with UnifiedPlan semantics.
+ *
+ *  PlanB will cause RTCPeerConnection to create offers and answers with at
+ *  most one audio and one video m= section with multiple RTCRtpSenders and
+ *  RTCRtpReceivers specified as multiple a=ssrc lines within the section. This
+ *  will also cause RTCPeerConnection to ignore all but the first m= section of
+ *  the same media type.
+ *
+ *  UnifiedPlan will cause RTCPeerConnection to create offers and answers with
+ *  multiple m= sections where each m= section maps to one RTCRtpSender and one
+ *  RTCRtpReceiver (an RTCRtpTransceiver), either both audio or both video. This
+ *  will also cause RTCPeerConnection to ignore all but the first a=ssrc lines
+ *  that form a Plan B stream.
+ *
+ *  For users who only send at most one audio and one video track, this
+ *  choice does not matter and should be left as Default.
+ *
+ *  For users who wish to send multiple audio/video streams and need to stay
+ *  interoperable with legacy WebRTC implementations, specify PlanB.
+ *
+ *  For users who wish to send multiple audio/video streams and/or wish to
+ *  use the new RTCRtpTransceiver API, specify UnifiedPlan.
+ */
+@property(nonatomic, assign) RTCSdpSemantics sdpSemantics;
+
 - (instancetype)init;
 
 @end
diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h b/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h
index a4c113b..8b69804 100644
--- a/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h
+++ b/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h
@@ -22,9 +22,13 @@
 @class RTCPeerConnectionFactory;
 @class RTCRtpReceiver;
 @class RTCRtpSender;
+@class RTCRtpTransceiver;
+@class RTCRtpTransceiverInit;
 @class RTCSessionDescription;
 @class RTCLegacyStatsReport;
 
+typedef NS_ENUM(NSInteger, RTCRtpMediaType);
+
 NS_ASSUME_NONNULL_BEGIN
 
 extern NSString * const kRTCPeerConnectionErrorDomain;
@@ -79,7 +83,9 @@
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
           didAddStream:(RTCMediaStream *)stream;
 
-/** Called when a remote peer closes a stream. */
+/** Called when a remote peer closes a stream.
+ *  This is not called when RTCSdpSemanticsUnifiedPlan is specified.
+ */
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
        didRemoveStream:(RTCMediaStream *)stream;
 
@@ -106,6 +112,14 @@
 - (void)peerConnection:(RTCPeerConnection *)peerConnection
     didOpenDataChannel:(RTCDataChannel *)dataChannel;
 
+/** Called when signaling indicates a transceiver will be receiving media from
+ *  the remote endpoint.
+ *  This is only called with RTCSdpSemanticsUnifiedPlan specified.
+ */
+@optional
+- (void)peerConnection:(RTCPeerConnection *)peerConnection
+    didStartReceivingOnTransceiver:(RTCRtpTransceiver *)transceiver;
+
 @end
 
 RTC_EXPORT
@@ -115,6 +129,9 @@
  *  streams being added or removed.
  */
 @property(nonatomic, weak, nullable) id<RTCPeerConnectionDelegate> delegate;
+/** This property is not available with RTCSdpSemanticsUnifiedPlan. Please use
+ *  |senders| instead.
+ */
 @property(nonatomic, readonly) NSArray<RTCMediaStream *> *localStreams;
 @property(nonatomic, readonly, nullable)
     RTCSessionDescription *localDescription;
@@ -137,6 +154,14 @@
  */
 @property(nonatomic, readonly) NSArray<RTCRtpReceiver *> *receivers;
 
+/** Gets all RTCRtpTransceivers associated with this peer connection.
+ *  Note: reading this property returns different instances of
+ *  RTCRtpTransceiver. Use isEqual: instead of == to compare RTCRtpTransceiver
+ *  instances.
+ *  This is only available with RTCSdpSemanticsUnifiedPlan specified.
+ */
+@property(nonatomic, readonly) NSArray<RTCRtpTransceiver *> *transceivers;
+
 - (instancetype)init NS_UNAVAILABLE;
 
 /** Sets the PeerConnection's global configuration to |configuration|.
@@ -156,12 +181,70 @@
 /** Remove a group of remote candidates from the ICE Agent. */
 - (void)removeIceCandidates:(NSArray<RTCIceCandidate *> *)candidates;
 
-/** Add a new media stream to be sent on this peer connection. */
+/** Add a new media stream to be sent on this peer connection.
+ *  This method is not supported with RTCSdpSemanticsUnifiedPlan. Please use
+ *  addTrack instead.
+ */
 - (void)addStream:(RTCMediaStream *)stream;
 
-/** Remove the given media stream from this peer connection. */
+/** Remove the given media stream from this peer connection.
+ *  This method is not supported with RTCSdpSemanticsUnifiedPlan. Please use
+ *  removeTrack instead.
+ */
 - (void)removeStream:(RTCMediaStream *)stream;
 
+/** Add a new media stream track to be sent on this peer connection, and return
+ *  the newly created RTCRtpSender. The RTCRtpSender will be associated with
+ *  the streams specified in the |streamLabels| list.
+ *
+ *  Errors: If an error occurs, returns nil. An error can occur if:
+ *  - A sender already exists for the track.
+ *  - The peer connection is closed.
+ */
+- (RTCRtpSender *)addTrack:(RTCMediaStreamTrack *)track
+              streamLabels:(NSArray<NSString *> *)streamLabels;
+
+/** With PlanB semantics, removes an RTCRtpSender from this peer connection.
+ *
+ *  With UnifiedPlan semantics, sets sender's track to null and removes the
+ *  send component from the associated RTCRtpTransceiver's direction.
+ *
+ *  Returns YES on success.
+ */
+- (BOOL)removeTrack:(RTCRtpSender *)sender;
+
+/** addTransceiver creates a new RTCRtpTransceiver and adds it to the set of
+ *  transceivers. Adding a transceiver will cause future calls to CreateOffer
+ *  to add a media description for the corresponding transceiver.
+ *
+ *  The initial value of |mid| in the returned transceiver is nil. Setting a
+ *  new session description may change it to a non-nil value.
+ *
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
+ *
+ *  Optionally, an RtpTransceiverInit structure can be specified to configure
+ *  the transceiver from construction. If not specified, the transceiver will
+ *  default to having a direction of kSendRecv and not be part of any streams.
+ *
+ *  These methods are only available when Unified Plan is enabled (see
+ *  RTCConfiguration).
+ */
+
+/** Adds a transceiver with a sender set to transmit the given track. The kind
+ *  of the transceiver (and sender/receiver) will be derived from the kind of
+ *  the track.
+ */
+- (RTCRtpTransceiver *)addTransceiverWithTrack:(RTCMediaStreamTrack *)track;
+- (RTCRtpTransceiver *)addTransceiverWithTrack:(RTCMediaStreamTrack *)track
+                                          init:(RTCRtpTransceiverInit *)init;
+
+/** Adds a transceiver with the given kind. Can either be RTCRtpMediaTypeAudio
+ *  or RTCRtpMediaTypeVideo.
+ */
+- (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType;
+- (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType
+                                       init:(RTCRtpTransceiverInit *)init;
+
 /** Generate an SDP offer. */
 - (void)offerForConstraints:(RTCMediaConstraints *)constraints
           completionHandler:(nullable void (^)
@@ -204,6 +287,8 @@
 
 /** Create an RTCRtpSender with the specified kind and media stream ID.
  *  See RTCMediaStreamTrack.h for available kinds.
+ *  This method is not supported with RTCSdpSemanticsUnifiedPlan. Please use
+ *  addTransceiver instead.
  */
 - (RTCRtpSender *)senderWithKind:(NSString *)kind streamId:(NSString *)streamId;
 
diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCRtpTransceiver.h b/sdk/objc/Framework/Headers/WebRTC/RTCRtpTransceiver.h
new file mode 100644
index 0000000..a670e2b
--- /dev/null
+++ b/sdk/objc/Framework/Headers/WebRTC/RTCRtpTransceiver.h
@@ -0,0 +1,128 @@
+/*
+ *  Copyright 2018 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.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import <WebRTC/RTCMacros.h>
+#import <WebRTC/RTCRtpReceiver.h>
+#import <WebRTC/RTCRtpSender.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection */
+typedef NS_ENUM(NSInteger, RTCRtpTransceiverDirection) {
+  RTCRtpTransceiverDirectionSendRecv,
+  RTCRtpTransceiverDirectionSendOnly,
+  RTCRtpTransceiverDirectionRecvOnly,
+  RTCRtpTransceiverDirectionInactive,
+};
+
+/** Structure for initializing an RTCRtpTransceiver in a call to
+ *  RTCPeerConnection.addTransceiver.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
+ */
+@interface RTCRtpTransceiverInit : NSObject
+
+/** Direction of the RTCRtpTransceiver. See RTCRtpTransceiver.direction. */
+@property(nonatomic) RTCRtpTransceiverDirection direction;
+
+/** The added RTCRtpTransceiver will be added to these streams. */
+@property(nonatomic) NSArray<NSString *> *streamLabels;
+
+/** TODO(bugs.webrtc.org/7600): Not implemented. */
+@property(nonatomic) NSArray<RTCRtpEncodingParameters *> *sendEncodings;
+
+@end
+
+@class RTCRtpTransceiver;
+
+/** The RTCRtpTransceiver maps to the RTCRtpTransceiver defined by the WebRTC
+ *  specification. A transceiver represents a combination of an RTCRtpSender
+ *  and an RTCRtpReceiver that share a common mid. As defined in JSEP, an
+ *  RTCRtpTransceiver is said to be associated with a media description if its
+ *  mid property is non-nil; otherwise, it is said to be disassociated.
+ *  JSEP: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24
+ *
+ *  Note that RTCRtpTransceivers are only supported when using
+ *  RTCPeerConnection with Unified Plan SDP.
+ *
+ *  WebRTC specification for RTCRtpTransceiver, the JavaScript analog:
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver
+ */
+RTC_EXPORT
+@protocol RTCRtpTransceiver <NSObject>
+
+/** Media type of the transceiver. The sender and receiver will also have this
+ *  type.
+ */
+@property(nonatomic, readonly) RTCRtpMediaType mediaType;
+
+/** The mid attribute is the mid negotiated and present in the local and
+ *  remote descriptions. Before negotiation is complete, the mid value may be
+ *  nil. After rollbacks, the value may change from a non-nil value to nil.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid
+ */
+@property(nonatomic, readonly) NSString *mid;
+
+/** The sender attribute exposes the RTCRtpSender corresponding to the RTP
+ *  media that may be sent with the transceiver's mid. The sender is always
+ *  present, regardless of the direction of media.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-sender
+ */
+@property(nonatomic, readonly) RTCRtpSender *sender;
+
+/** The receiver attribute exposes the RTCRtpReceiver corresponding to the RTP
+ *  media that may be received with the transceiver's mid. The receiver is
+ *  always present, regardless of the direction of media.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-receiver
+ */
+@property(nonatomic, readonly) RTCRtpReceiver *receiver;
+
+/** The isStopped attribute indicates that the sender of this transceiver will
+ *  no longer send, and that the receiver will no longer receive. It is true if
+ *  either stop has been called or if setting the local or remote description
+ *  has caused the RTCRtpTransceiver to be stopped.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped
+ */
+@property(nonatomic, readonly) BOOL isStopped;
+
+/** The direction attribute indicates the preferred direction of this
+ *  transceiver, which will be used in calls to createOffer and createAnswer.
+ *  An update of directionality does not take effect immediately. Instead,
+ *  future calls to createOffer and createAnswer mark the corresponding media
+ *  descriptions as sendrecv, sendonly, recvonly, or inactive.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+ */
+@property(nonatomic) RTCRtpTransceiverDirection direction;
+
+/** The currentDirection attribute indicates the current direction negotiated
+ *  for this transceiver. If this transceiver has never been represented in an
+ *  offer/answer exchange, or if the transceiver is stopped, the value is not
+ *  present and this method returns NO.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection
+ */
+- (BOOL)currentDirection:(RTCRtpTransceiverDirection *)currentDirectionOut;
+
+/** The stop method irreversibly stops the RTCRtpTransceiver. The sender of
+ *  this transceiver will no longer send, the receiver will no longer receive.
+ *  https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop
+ */
+- (void)stop;
+
+@end
+
+RTC_EXPORT
+@interface RTCRtpTransceiver : NSObject <RTCRtpTransceiver>
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+NS_ASSUME_NONNULL_END