It would leave a trailing carriage return character in the payload list, causing the preferred codec to appear twice if it was at the back of the list originally. This causes problems down the line and results in that codec not being negotiated successfully. BUG=webrtc:8129 Review-Url: https://codereview.webrtc.org/3001363002 Cr-Commit-Position: refs/heads/master@{#19552}
99 lines
3.9 KiB
Objective-C
99 lines
3.9 KiB
Objective-C
/*
|
|
* Copyright 2015 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 "ARDSDPUtils.h"
|
|
|
|
#import "WebRTC/RTCLogging.h"
|
|
#import "WebRTC/RTCSessionDescription.h"
|
|
|
|
@implementation ARDSDPUtils
|
|
|
|
+ (RTCSessionDescription *)
|
|
descriptionForDescription:(RTCSessionDescription *)description
|
|
preferredVideoCodec:(NSString *)codec {
|
|
NSString *sdpString = description.sdp;
|
|
NSString *lineSeparator = @"\r\n";
|
|
NSString *mLineSeparator = @" ";
|
|
// Copied from PeerConnectionClient.java.
|
|
// TODO(tkchin): Move this to a shared C++ file.
|
|
NSMutableArray *lines =
|
|
[NSMutableArray arrayWithArray:
|
|
[sdpString componentsSeparatedByString:lineSeparator]];
|
|
// Find the line starting with "m=video".
|
|
NSInteger mLineIndex = -1;
|
|
for (NSInteger i = 0; i < lines.count; ++i) {
|
|
if ([lines[i] hasPrefix:@"m=video"]) {
|
|
mLineIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
if (mLineIndex == -1) {
|
|
RTCLog(@"No m=video line, so can't prefer %@", codec);
|
|
return description;
|
|
}
|
|
// An array with all payload types with name |codec|. The payload types are
|
|
// integers in the range 96-127, but they are stored as strings here.
|
|
NSMutableArray *codecPayloadTypes = [[NSMutableArray alloc] init];
|
|
// a=rtpmap:<payload type> <encoding name>/<clock rate>
|
|
// [/<encoding parameters>]
|
|
NSString *pattern =
|
|
[NSString stringWithFormat:@"^a=rtpmap:(\\d+) %@(/\\d+)+[\r]?$", codec];
|
|
NSRegularExpression *regex =
|
|
[NSRegularExpression regularExpressionWithPattern:pattern
|
|
options:0
|
|
error:nil];
|
|
for (NSString *line in lines) {
|
|
NSTextCheckingResult *codecMatches =
|
|
[regex firstMatchInString:line
|
|
options:0
|
|
range:NSMakeRange(0, line.length)];
|
|
if (codecMatches) {
|
|
[codecPayloadTypes
|
|
addObject:[line substringWithRange:[codecMatches rangeAtIndex:1]]];
|
|
}
|
|
}
|
|
if ([codecPayloadTypes count] == 0) {
|
|
RTCLog(@"No payload types with name %@", codec);
|
|
return description;
|
|
}
|
|
NSArray *origMLineParts =
|
|
[lines[mLineIndex] componentsSeparatedByString:mLineSeparator];
|
|
// The format of ML should be: m=<media> <port> <proto> <fmt> ...
|
|
const int kHeaderLength = 3;
|
|
if (origMLineParts.count <= kHeaderLength) {
|
|
RTCLogWarning(@"Wrong SDP media description format: %@", lines[mLineIndex]);
|
|
return description;
|
|
}
|
|
// Split the line into header and payloadTypes.
|
|
NSRange headerRange = NSMakeRange(0, kHeaderLength);
|
|
NSRange payloadRange =
|
|
NSMakeRange(kHeaderLength, origMLineParts.count - kHeaderLength);
|
|
NSArray *header = [origMLineParts subarrayWithRange:headerRange];
|
|
NSMutableArray *payloadTypes = [NSMutableArray
|
|
arrayWithArray:[origMLineParts subarrayWithRange:payloadRange]];
|
|
// Reconstruct the line with |codecPayloadTypes| moved to the beginning of the
|
|
// payload types.
|
|
NSMutableArray *newMLineParts = [NSMutableArray arrayWithCapacity:origMLineParts.count];
|
|
[newMLineParts addObjectsFromArray:header];
|
|
[newMLineParts addObjectsFromArray:codecPayloadTypes];
|
|
[payloadTypes removeObjectsInArray:codecPayloadTypes];
|
|
[newMLineParts addObjectsFromArray:payloadTypes];
|
|
|
|
NSString *newMLine = [newMLineParts componentsJoinedByString:mLineSeparator];
|
|
[lines replaceObjectAtIndex:mLineIndex
|
|
withObject:newMLine];
|
|
|
|
NSString *mangledSdpString = [lines componentsJoinedByString:lineSeparator];
|
|
return [[RTCSessionDescription alloc] initWithType:description.type
|
|
sdp:mangledSdpString];
|
|
}
|
|
|
|
@end
|