Skip to content

Commit e60f020

Browse files
Hnoo112233Commit bot
authored and
Commit bot
committed
iOS AppRTCMobile: Fix SDP video codec reordering for multiple H264 profiles
BUG=webrtc:6738 Review-Url: https://codereview.webrtc.org/2520933002 Cr-Commit-Position: refs/heads/master@{#15198}
1 parent 8271d04 commit e60f020

File tree

2 files changed

+96
-47
lines changed

2 files changed

+96
-47
lines changed

webrtc/examples/objc/AppRTCMobile/ARDSDPUtils.m

+42-36
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,21 @@ @implementation ARDSDPUtils
2626
NSMutableArray *lines =
2727
[NSMutableArray arrayWithArray:
2828
[sdpString componentsSeparatedByString:lineSeparator]];
29+
// Find the line starting with "m=video".
2930
NSInteger mLineIndex = -1;
30-
NSString *codecRtpMap = nil;
31+
for (NSInteger i = 0; i < lines.count; ++i) {
32+
if ([lines[i] hasPrefix:@"m=video"]) {
33+
mLineIndex = i;
34+
break;
35+
}
36+
}
37+
if (mLineIndex == -1) {
38+
RTCLog(@"No m=video line, so can't prefer %@", codec);
39+
return description;
40+
}
41+
// An array with all payload types with name |codec|. The payload types are
42+
// integers in the range 96-127, but they are stored as strings here.
43+
NSMutableArray *codecPayloadTypes = [[NSMutableArray alloc] init];
3144
// a=rtpmap:<payload type> <encoding name>/<clock rate>
3245
// [/<encoding parameters>]
3346
NSString *pattern =
@@ -36,54 +49,47 @@ @implementation ARDSDPUtils
3649
[NSRegularExpression regularExpressionWithPattern:pattern
3750
options:0
3851
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-
}
52+
for (NSString *line in lines) {
4653
NSTextCheckingResult *codecMatches =
4754
[regex firstMatchInString:line
4855
options:0
4956
range:NSMakeRange(0, line.length)];
5057
if (codecMatches) {
51-
codecRtpMap =
52-
[line substringWithRange:[codecMatches rangeAtIndex:1]];
53-
continue;
58+
[codecPayloadTypes
59+
addObject:[line substringWithRange:[codecMatches rangeAtIndex:1]]];
5460
}
5561
}
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+
if ([codecPayloadTypes count] == 0) {
63+
RTCLog(@"No payload types with name %@", codec);
6264
return description;
6365
}
6466
NSArray *origMLineParts =
6567
[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 {
68+
// The format of ML should be: m=<media> <port> <proto> <fmt> ...
69+
const int kHeaderLength = 3;
70+
if (origMLineParts.count <= kHeaderLength) {
8571
RTCLogWarning(@"Wrong SDP media description format: %@", lines[mLineIndex]);
72+
return description;
8673
}
74+
// Split the line into header and payloadTypes.
75+
NSRange headerRange = NSMakeRange(0, kHeaderLength);
76+
NSRange payloadRange =
77+
NSMakeRange(kHeaderLength, origMLineParts.count - kHeaderLength);
78+
NSArray *header = [origMLineParts subarrayWithRange:headerRange];
79+
NSMutableArray *payloadTypes = [NSMutableArray
80+
arrayWithArray:[origMLineParts subarrayWithRange:payloadRange]];
81+
// Reconstruct the line with |codecPayloadTypes| moved to the beginning of the
82+
// payload types.
83+
NSMutableArray *newMLineParts = [NSMutableArray arrayWithCapacity:origMLineParts.count];
84+
[newMLineParts addObjectsFromArray:header];
85+
[newMLineParts addObjectsFromArray:codecPayloadTypes];
86+
[payloadTypes removeObjectsInArray:codecPayloadTypes];
87+
[newMLineParts addObjectsFromArray:payloadTypes];
88+
89+
NSString *newMLine = [newMLineParts componentsJoinedByString:mLineSeparator];
90+
[lines replaceObjectAtIndex:mLineIndex
91+
withObject:newMLine];
92+
8793
NSString *mangledSdpString = [lines componentsJoinedByString:lineSeparator];
8894
return [[RTCSessionDescription alloc] initWithType:description.type
8995
sdp:mangledSdpString];

webrtc/examples/objc/AppRTCMobile/tests/ARDAppClientTest.mm

+54-11
Original file line numberDiff line numberDiff line change
@@ -354,22 +354,23 @@ - (void)testSessionShouldGetLocalVideoTrackCallback {
354354
@end
355355

356356
@interface ARDSDPUtilsTest : ARDTestCase
357-
- (void)testPreferVideoCodec;
357+
- (void)testPreferVideoCodec:(NSString *)codec
358+
sdp:(NSString *)sdp
359+
expectedSdp:(NSString *)expectedSdp;
358360
@end
359361

360362
@implementation ARDSDPUtilsTest
361363

362-
- (void)testPreferVideoCodec {
363-
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120\n"
364-
"a=rtpmap:120 H264/90000\n");
365-
NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 100 116 117 96\n"
366-
"a=rtpmap:120 H264/90000\n");
364+
- (void)testPreferVideoCodec:(NSString *)codec
365+
sdp:(NSString *)sdp
366+
expectedSdp:(NSString *)expectedSdp {
367367
RTCSessionDescription* desc =
368368
[[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp];
369-
RTCSessionDescription *h264Desc =
369+
RTCSessionDescription *outputDesc =
370370
[ARDSDPUtils descriptionForDescription:desc
371-
preferredVideoCodec:@"H264"];
372-
EXPECT_TRUE([h264Desc.description rangeOfString:expectedSdp].location != NSNotFound);
371+
preferredVideoCodec:codec];
372+
EXPECT_TRUE([outputDesc.description rangeOfString:expectedSdp].location !=
373+
NSNotFound);
373374
}
374375

375376
@end
@@ -401,10 +402,52 @@ static void TearDownTestCase() {
401402
}
402403
#endif
403404

404-
TEST_F(SignalingTest, SDPTest) {
405+
TEST_F(SignalingTest, SdpH264Test) {
405406
@autoreleasepool {
406407
ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
407-
[test testPreferVideoCodec];
408+
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n"
409+
"a=rtpmap:120 H264/90000\n"
410+
"a=rtpmap:97 H264/90000\n");
411+
NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 97 100 116 117 96\n"
412+
"a=rtpmap:120 H264/90000\n"
413+
"a=rtpmap:97 H264/90000\n");
414+
[test testPreferVideoCodec:@"H264"
415+
sdp:sdp
416+
expectedSdp:expectedSdp];
417+
}
418+
}
419+
420+
TEST_F(SignalingTest, SdpVp8Test) {
421+
@autoreleasepool {
422+
ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
423+
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n"
424+
"a=rtpmap:116 VP8/90000\n");
425+
NSString *expectedSdp = @("m=video 9 RTP/SAVPF 116 100 117 96 120 97\n"
426+
"a=rtpmap:116 VP8/90000\n");
427+
[test testPreferVideoCodec:@"VP8"
428+
sdp:sdp
429+
expectedSdp:expectedSdp];
430+
}
431+
}
432+
433+
TEST_F(SignalingTest, SdpNoMLineTest) {
434+
@autoreleasepool {
435+
ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
436+
NSString *sdp = @("a=rtpmap:116 VP8/90000\n");
437+
[test testPreferVideoCodec:@"VP8"
438+
sdp:sdp
439+
expectedSdp:sdp];
440+
}
441+
}
442+
443+
TEST_F(SignalingTest, SdpMissingCodecTest) {
444+
@autoreleasepool {
445+
ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
446+
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\n"
447+
"a=rtpmap:116 VP8/90000\n");
448+
[test testPreferVideoCodec:@"foo"
449+
sdp:sdp
450+
expectedSdp:sdp];
408451
}
409452
}
410453

0 commit comments

Comments
 (0)