Files
platform-external-webrtc/webrtc/examples/objc/AppRTCMobile/ARDSDPUtils.m
kthelgason 6644c8b733 Fix a bug in the SDP parser in AppRTCMobile.
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}
2017-08-28 07:48:18 +00:00

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