Propagate bitrate setting to RTCRtpSender.

This CL wires everything up and enables actual setting of the max bitrate encoding parameter
on the video RTP sender.
The following changes were made
* Add maxbitrate property to the settings model and settings store. Make sure to store and
read the maxbitrate from storage (to persist between app launches and make testing easier)
* Fix setup of encoding parameters for the rtp sender as previous timing was not right.
* Fix header of RTCRtpSender to expose needed parameter
BUG=webrtc:6654

Review-Url: https://codereview.webrtc.org/2492693003
Cr-Commit-Position: refs/heads/master@{#15120}
diff --git a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m
index cfcb356..40a2be7 100644
--- a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m
+++ b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m
@@ -50,12 +50,14 @@
 static NSString * const kARDMediaStreamId = @"ARDAMS";
 static NSString * const kARDAudioTrackId = @"ARDAMSa0";
 static NSString * const kARDVideoTrackId = @"ARDAMSv0";
+static NSString * const kARDVideoTrackKind = @"video";
 
 // TODO(tkchin): Add these as UI options.
 static BOOL const kARDAppClientEnableTracing = NO;
 static BOOL const kARDAppClientEnableRtcEventLog = YES;
 static int64_t const kARDAppClientAecDumpMaxSizeInBytes = 5e6;  // 5 MB.
 static int64_t const kARDAppClientRtcEventLogMaxSizeInBytes = 5e6;  // 5 MB.
+static int const kKbpsMultiplier = 1000;
 
 // We need a proxy to NSTimer because it causes a strong retain cycle. When
 // using the proxy, |invalidate| must be called before it properly deallocs.
@@ -476,6 +478,7 @@
         [[ARDSessionDescriptionMessage alloc]
             initWithDescription:sdpPreferringH264];
     [self sendSignalingMessage:message];
+    [self setMaxBitrateForPeerConnectionVideoSender];
   });
 }
 
@@ -680,23 +683,37 @@
   RTCRtpSender *sender =
       [_peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo
                              streamId:kARDMediaStreamId];
-
-  [self setMaxBitrate:_maxBitrate forVideoSender:sender];
-
   RTCVideoTrack *track = [self createLocalVideoTrack];
   if (track) {
     sender.track = track;
     [_delegate appClient:self didReceiveLocalVideoTrack:track];
   }
+
   return sender;
 }
 
-- (void)setMaxBitrate:(NSNumber *)maxBitrate forVideoSender:(RTCRtpSender *)sender {
-  for (RTCRtpEncodingParameters *encoding in sender.parameters.encodings) {
-    encoding.maxBitrateBps = maxBitrate;
+- (void)setMaxBitrateForPeerConnectionVideoSender {
+  for (RTCRtpSender *sender in _peerConnection.senders) {
+    if (sender.track != nil) {
+      if ([sender.track.kind isEqualToString:kARDVideoTrackKind]) {
+        [self setMaxBitrate:_maxBitrate forVideoSender:sender];
+      }
+    }
   }
 }
 
+- (void)setMaxBitrate:(NSNumber *)maxBitrate forVideoSender:(RTCRtpSender *)sender {
+  if (maxBitrate.intValue <= 0) {
+    return;
+  }
+
+  RTCRtpParameters *parametersToModify = sender.parameters;
+  for (RTCRtpEncodingParameters *encoding in parametersToModify.encodings) {
+    encoding.maxBitrateBps = @(maxBitrate.intValue * kKbpsMultiplier);
+  }
+  [sender setParameters:parametersToModify];
+}
+
 - (RTCRtpSender *)createAudioSender {
   RTCMediaConstraints *constraints = [self defaultMediaAudioConstraints];
   RTCAudioSource *source = [_factory audioSourceWithConstraints:constraints];
diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.h b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.h
index 9c8b5c5..602a464 100644
--- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.h
+++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.h
@@ -55,5 +55,18 @@
  * @return NSDictionary with RTC width and height parameters
  */
 - (nullable NSDictionary *)currentMediaConstraintFromStoreAsRTCDictionary;
+
+/**
+ * Returns current max bitrate setting from store if present.
+ */
+- (nullable NSNumber *)currentMaxBitrateSettingFromStore;
+
+/**
+ * Stores the provided bitrate value into the store.
+ *
+ * @param bitrate NSNumber representation of the max bitrate value.
+ */
+- (void)storeMaxBitrateSetting:(nullable NSNumber *)bitrate;
+
 @end
 NS_ASSUME_NONNULL_END
diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.m
index 61b5c50..eda0275 100644
--- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.m
+++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsModel.m
@@ -29,11 +29,11 @@
 }
 
 - (NSString *)currentVideoResoultionConstraintFromStore {
-  NSString *constraint = [[self settingsStore] videoResolutionConstraintsSetting];
+  NSString *constraint = [[self settingsStore] videoResolutionConstraints];
   if (!constraint) {
     constraint = [self defaultVideoResolutionMediaConstraint];
     // To ensure consistency add the default to the store.
-    [[self settingsStore] setVideoResolutionConstraintsSetting:constraint];
+    [[self settingsStore] setVideoResolutionConstraints:constraint];
   }
   return constraint;
 }
@@ -42,10 +42,18 @@
   if (![[self availableVideoResoultionsMediaConstraints] containsObject:constraint]) {
     return NO;
   }
-  [[self settingsStore] setVideoResolutionConstraintsSetting:constraint];
+  [[self settingsStore] setVideoResolutionConstraints:constraint];
   return YES;
 }
 
+- (nullable NSNumber *)currentMaxBitrateSettingFromStore {
+  return [[self settingsStore] maxBitrate];
+}
+
+- (void)storeMaxBitrateSetting:(nullable NSNumber *)bitrate {
+  [[self settingsStore] setMaxBitrate:bitrate];
+}
+
 #pragma mark - Testable
 
 - (ARDSettingsStore *)settingsStore {
diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.h b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.h
index 1541e2d..69e10e3 100644
--- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.h
+++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.h
@@ -22,13 +22,24 @@
 /**
  * Returns current video resolution media constraint string stored in the store.
  */
-- (nullable NSString *)videoResolutionConstraintsSetting;
+- (nullable NSString *)videoResolutionConstraints;
 
 /**
  * Stores the provided value as video resolution media constraint.
  * @param value the string to be stored
  */
-- (void)setVideoResolutionConstraintsSetting:(NSString *)value;
+- (void)setVideoResolutionConstraints:(NSString *)value;
+
+/**
+ * Returns current max bitrate number stored in the store.
+ */
+- (nullable NSNumber *)maxBitrate;
+
+/**
+ * Stores the provided value as maximum bitrate setting.
+ * @param value the number to be stored
+ */
+- (void)setMaxBitrate:(nullable NSNumber *)value;
 
 @end
 NS_ASSUME_NONNULL_END
diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.m
index 6b3642e..fd396b5 100644
--- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.m
+++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsStore.m
@@ -10,19 +10,41 @@
 
 #import "ARDSettingsStore.h"
 
-static NSString *const kUserDefaultsMediaConstraintsKey =
-    @"rtc_video_resolution_media_constraints_key";
+static NSString *const kMediaConstraintsKey = @"rtc_video_resolution_media_constraints_key";
+static NSString *const kBitrateKey = @"rtc_max_bitrate_key";
 
 NS_ASSUME_NONNULL_BEGIN
+@interface ARDSettingsStore () {
+  NSUserDefaults *_storage;
+}
+@property(nonatomic, strong) NSUserDefaults *storage;
+@end
+
 @implementation ARDSettingsStore
 
-- (nullable NSString *)videoResolutionConstraintsSetting {
-  return [[NSUserDefaults standardUserDefaults] objectForKey:kUserDefaultsMediaConstraintsKey];
+- (NSUserDefaults *)storage {
+  if (!_storage) {
+    _storage = [NSUserDefaults standardUserDefaults];
+  }
+  return _storage;
 }
 
-- (void)setVideoResolutionConstraintsSetting:(NSString *)constraintsString {
-  [[NSUserDefaults standardUserDefaults] setObject:constraintsString
-                                            forKey:kUserDefaultsMediaConstraintsKey];
+- (nullable NSString *)videoResolutionConstraints {
+  return [self.storage objectForKey:kMediaConstraintsKey];
+}
+
+- (void)setVideoResolutionConstraints:(NSString *)constraintsString {
+  [self.storage setObject:constraintsString forKey:kMediaConstraintsKey];
+  [self.storage synchronize];
+}
+
+- (nullable NSNumber *)maxBitrate {
+  return [self.storage objectForKey:kBitrateKey];
+}
+
+- (void)setMaxBitrate:(nullable NSNumber *)value {
+  [self.storage setObject:value forKey:kBitrateKey];
+  [self.storage synchronize];
 }
 
 @end
diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m
index 0abcc1e..815b147 100644
--- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m
+++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m
@@ -18,7 +18,7 @@
   ARDSettingsSectionBitRate
 };
 
-@interface ARDSettingsViewController () {
+@interface ARDSettingsViewController () <UITextFieldDelegate> {
   ARDSettingsModel *_settingsModel;
 }
 
@@ -200,8 +200,11 @@
 
     UITextField *textField = [[UITextField alloc]
         initWithFrame:CGRectMake(10, 0, cell.bounds.size.width - 20, cell.bounds.size.height)];
+    NSString *currentMaxBitrate = [_settingsModel currentMaxBitrateSettingFromStore].stringValue;
+    textField.text = currentMaxBitrate;
     textField.placeholder = @"Enter max bit rate (kbps)";
     textField.keyboardType = UIKeyboardTypeNumberPad;
+    textField.delegate = self;
 
     // Numerical keyboards have no return button, we need to add one manually.
     UIToolbar *numberToolbar =
@@ -227,5 +230,15 @@
   [self.view endEditing:YES];
 }
 
+- (void)textFieldDidEndEditing:(UITextField *)textField {
+  NSNumber *bitrateNumber = nil;
+
+  if (textField.text.length != 0) {
+    bitrateNumber = [NSNumber numberWithInteger:textField.text.intValue];
+  }
+
+  [_settingsModel storeMaxBitrateSetting:bitrateNumber];
+}
+
 @end
 NS_ASSUME_NONNULL_END
diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m
index 5e05866..9e17951 100644
--- a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m
+++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m
@@ -51,6 +51,7 @@
         initWithMandatoryConstraints:nil
                  optionalConstraints:[settingsModel
                                          currentMediaConstraintFromStoreAsRTCDictionary]];
+    [_client setMaxBitrate:[settingsModel currentMaxBitrateSettingFromStore]];
     [_client setCameraConstraints:cameraConstraints];
     [_client connectToRoomWithId:room
                       isLoopback:isLoopback
diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm
index 4ceac81..45a1045 100644
--- a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm
+++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModelTests.mm
@@ -39,7 +39,7 @@
 
 - (id)setupMockStoreWithMediaConstraintString:(NSString *)constraintString {
   id storeMock = [OCMockObject mockForClass:[ARDSettingsStore class]];
-  [([[storeMock stub] andReturn:constraintString]) videoResolutionConstraintsSetting];
+  [([[storeMock stub] andReturn:constraintString]) videoResolutionConstraints];
 
   id partialMock = [OCMockObject partialMockForObject:_model];
   [[[partialMock stub] andReturn:storeMock] settingsStore];
@@ -51,7 +51,7 @@
   // given
   id storeMock = [self setupMockStoreWithMediaConstraintString:nil];
 
-  [[storeMock expect] setVideoResolutionConstraintsSetting:@"640x480"];
+  [[storeMock expect] setVideoResolutionConstraints:@"640x480"];
 
   // when
   NSString *string = [_model currentVideoResoultionConstraintFromStore];