ARDSDPUtils.m 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. #import "ARDSDPUtils.h"
  11. #import "WebRTC/RTCLogging.h"
  12. #import "WebRTC/RTCSessionDescription.h"
  13. @implementation ARDSDPUtils
  14. + (RTCSessionDescription *)
  15. descriptionForDescription:(RTCSessionDescription *)description
  16. preferredVideoCodec:(NSString *)codec {
  17. NSString *sdpString = description.sdp;
  18. NSString *lineSeparator = @"\n";
  19. NSString *mLineSeparator = @" ";
  20. // Copied from PeerConnectionClient.java.
  21. // TODO(tkchin): Move this to a shared C++ file.
  22. NSMutableArray *lines =
  23. [NSMutableArray arrayWithArray:
  24. [sdpString componentsSeparatedByString:lineSeparator]];
  25. // Find the line starting with "m=video".
  26. NSInteger mLineIndex = -1;
  27. for (NSInteger i = 0; i < lines.count; ++i) {
  28. if ([lines[i] hasPrefix:@"m=video"]) {
  29. mLineIndex = i;
  30. break;
  31. }
  32. }
  33. if (mLineIndex == -1) {
  34. RTCLog(@"No m=video line, so can't prefer %@", codec);
  35. return description;
  36. }
  37. // An array with all payload types with name |codec|. The payload types are
  38. // integers in the range 96-127, but they are stored as strings here.
  39. NSMutableArray *codecPayloadTypes = [[NSMutableArray alloc] init];
  40. // a=rtpmap:<payload type> <encoding name>/<clock rate>
  41. // [/<encoding parameters>]
  42. NSString *pattern =
  43. [NSString stringWithFormat:@"^a=rtpmap:(\\d+) %@(/\\d+)+[\r]?$", codec];
  44. NSRegularExpression *regex =
  45. [NSRegularExpression regularExpressionWithPattern:pattern
  46. options:0
  47. error:nil];
  48. for (NSString *line in lines) {
  49. NSTextCheckingResult *codecMatches =
  50. [regex firstMatchInString:line
  51. options:0
  52. range:NSMakeRange(0, line.length)];
  53. if (codecMatches) {
  54. [codecPayloadTypes
  55. addObject:[line substringWithRange:[codecMatches rangeAtIndex:1]]];
  56. }
  57. }
  58. if ([codecPayloadTypes count] == 0) {
  59. RTCLog(@"No payload types with name %@", codec);
  60. return description;
  61. }
  62. NSArray *origMLineParts =
  63. [lines[mLineIndex] componentsSeparatedByString:mLineSeparator];
  64. // The format of ML should be: m=<media> <port> <proto> <fmt> ...
  65. const int kHeaderLength = 3;
  66. if (origMLineParts.count <= kHeaderLength) {
  67. RTCLogWarning(@"Wrong SDP media description format: %@", lines[mLineIndex]);
  68. return description;
  69. }
  70. // Split the line into header and payloadTypes.
  71. NSRange headerRange = NSMakeRange(0, kHeaderLength);
  72. NSRange payloadRange =
  73. NSMakeRange(kHeaderLength, origMLineParts.count - kHeaderLength);
  74. NSArray *header = [origMLineParts subarrayWithRange:headerRange];
  75. NSMutableArray *payloadTypes = [NSMutableArray
  76. arrayWithArray:[origMLineParts subarrayWithRange:payloadRange]];
  77. // Reconstruct the line with |codecPayloadTypes| moved to the beginning of the
  78. // payload types.
  79. NSMutableArray *newMLineParts = [NSMutableArray arrayWithCapacity:origMLineParts.count];
  80. [newMLineParts addObjectsFromArray:header];
  81. [newMLineParts addObjectsFromArray:codecPayloadTypes];
  82. [payloadTypes removeObjectsInArray:codecPayloadTypes];
  83. [newMLineParts addObjectsFromArray:payloadTypes];
  84. NSString *newMLine = [newMLineParts componentsJoinedByString:mLineSeparator];
  85. [lines replaceObjectAtIndex:mLineIndex
  86. withObject:newMLine];
  87. NSString *mangledSdpString = [lines componentsJoinedByString:lineSeparator];
  88. return [[RTCSessionDescription alloc] initWithType:description.type
  89. sdp:mangledSdpString];
  90. }
  91. @end