/* * 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 = @"\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: / // [/] 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= ... 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