1/*
2 *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import "ARDSDPUtils.h"
12
13#import "RTCLogging.h"
14#import "RTCSessionDescription.h"
15
16@implementation ARDSDPUtils
17
18+ (RTCSessionDescription *)
19    descriptionForDescription:(RTCSessionDescription *)description
20          preferredVideoCodec:(NSString *)codec {
21  NSString *sdpString = description.description;
22  NSString *lineSeparator = @"\n";
23  NSString *mLineSeparator = @" ";
24  // Copied from PeerConnectionClient.java.
25  // TODO(tkchin): Move this to a shared C++ file.
26  NSMutableArray *lines =
27      [NSMutableArray arrayWithArray:
28          [sdpString componentsSeparatedByString:lineSeparator]];
29  NSInteger mLineIndex = -1;
30  NSString *codecRtpMap = nil;
31  // a=rtpmap:<payload type> <encoding name>/<clock rate>
32  // [/<encoding parameters>]
33  NSString *pattern =
34      [NSString stringWithFormat:@"^a=rtpmap:(\\d+) %@(/\\d+)+[\r]?$", codec];
35  NSRegularExpression *regex =
36      [NSRegularExpression regularExpressionWithPattern:pattern
37                                                options:0
38                                                  error:nil];
39  for (NSInteger i = 0; (i < lines.count) && (mLineIndex == -1 || !codecRtpMap);
40       ++i) {
41    NSString *line = lines[i];
42    if ([line hasPrefix:@"m=video"]) {
43      mLineIndex = i;
44      continue;
45    }
46    NSTextCheckingResult *codecMatches =
47        [regex firstMatchInString:line
48                          options:0
49                            range:NSMakeRange(0, line.length)];
50    if (codecMatches) {
51      codecRtpMap =
52          [line substringWithRange:[codecMatches rangeAtIndex:1]];
53      continue;
54    }
55  }
56  if (mLineIndex == -1) {
57    RTCLog(@"No m=video line, so can't prefer %@", codec);
58    return description;
59  }
60  if (!codecRtpMap) {
61    RTCLog(@"No rtpmap for %@", codec);
62    return description;
63  }
64  NSArray *origMLineParts =
65      [lines[mLineIndex] componentsSeparatedByString:mLineSeparator];
66  if (origMLineParts.count > 3) {
67    NSMutableArray *newMLineParts =
68        [NSMutableArray arrayWithCapacity:origMLineParts.count];
69    NSInteger origPartIndex = 0;
70    // Format is: m=<media> <port> <proto> <fmt> ...
71    [newMLineParts addObject:origMLineParts[origPartIndex++]];
72    [newMLineParts addObject:origMLineParts[origPartIndex++]];
73    [newMLineParts addObject:origMLineParts[origPartIndex++]];
74    [newMLineParts addObject:codecRtpMap];
75    for (; origPartIndex < origMLineParts.count; ++origPartIndex) {
76      if (![codecRtpMap isEqualToString:origMLineParts[origPartIndex]]) {
77        [newMLineParts addObject:origMLineParts[origPartIndex]];
78      }
79    }
80    NSString *newMLine =
81        [newMLineParts componentsJoinedByString:mLineSeparator];
82    [lines replaceObjectAtIndex:mLineIndex
83                     withObject:newMLine];
84  } else {
85    RTCLogWarning(@"Wrong SDP media description format: %@", lines[mLineIndex]);
86  }
87  NSString *mangledSdpString = [lines componentsJoinedByString:lineSeparator];
88  return [[RTCSessionDescription alloc] initWithType:description.type
89                                                 sdp:mangledSdpString];
90}
91
92@end
93