OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 package org.appspot.apprtc; | 11 package org.appspot.apprtc; |
12 | 12 |
13 import android.content.Context; | 13 import android.content.Context; |
14 import android.os.Environment; | 14 import android.os.Environment; |
15 import android.os.ParcelFileDescriptor; | 15 import android.os.ParcelFileDescriptor; |
16 import android.util.Log; | 16 import android.util.Log; |
17 import java.io.File; | 17 import java.io.File; |
18 import java.io.IOException; | 18 import java.io.IOException; |
19 import java.nio.ByteBuffer; | 19 import java.nio.ByteBuffer; |
20 import java.util.ArrayList; | |
21 import java.util.Arrays; | |
20 import java.util.Collections; | 22 import java.util.Collections; |
21 import java.util.EnumSet; | 23 import java.util.EnumSet; |
24 import java.util.Iterator; | |
22 import java.util.LinkedList; | 25 import java.util.LinkedList; |
23 import java.util.List; | 26 import java.util.List; |
24 import java.util.Timer; | 27 import java.util.Timer; |
25 import java.util.TimerTask; | 28 import java.util.TimerTask; |
26 import java.util.concurrent.Executors; | 29 import java.util.concurrent.Executors; |
27 import java.util.concurrent.ScheduledExecutorService; | 30 import java.util.concurrent.ScheduledExecutorService; |
28 import java.util.regex.Matcher; | 31 import java.util.regex.Matcher; |
29 import java.util.regex.Pattern; | 32 import java.util.regex.Pattern; |
30 import org.appspot.apprtc.AppRTCClient.SignalingParameters; | 33 import org.appspot.apprtc.AppRTCClient.SignalingParameters; |
31 import org.webrtc.AudioSource; | 34 import org.webrtc.AudioSource; |
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
962 bitrateSet = "a=fmtp:" + codecRtpMap + " " + AUDIO_CODEC_PARAM_BITRATE + "=" | 965 bitrateSet = "a=fmtp:" + codecRtpMap + " " + AUDIO_CODEC_PARAM_BITRATE + "=" |
963 + (bitrateKbps * 1000); | 966 + (bitrateKbps * 1000); |
964 } | 967 } |
965 Log.d(TAG, "Add remote SDP line: " + bitrateSet); | 968 Log.d(TAG, "Add remote SDP line: " + bitrateSet); |
966 newSdpDescription.append(bitrateSet).append("\r\n"); | 969 newSdpDescription.append(bitrateSet).append("\r\n"); |
967 } | 970 } |
968 } | 971 } |
969 return newSdpDescription.toString(); | 972 return newSdpDescription.toString(); |
970 } | 973 } |
971 | 974 |
975 // Returns the line number containing "m=audio|video", or -1 if no such line e xists. | |
sakal
2017/01/27 15:05:15
nit: Use javadoc
magjed_webrtc
2017/01/27 15:16:43
Done.
| |
976 private static int findMediaDescriptionLine(boolean isAudio, String[] sdpLines ) { | |
977 final String mediaDescription = isAudio ? "m=audio " : "m=video "; | |
978 for (int i = 0; i < sdpLines.length; ++i) { | |
979 if (sdpLines[i].startsWith(mediaDescription)) { | |
980 return i; | |
981 } | |
982 } | |
983 return -1; | |
984 } | |
985 | |
986 private static String joinString( | |
987 Iterable<? extends CharSequence> s, String delimiter, boolean delimiterAtE nd) { | |
988 Iterator<? extends CharSequence> iter = s.iterator(); | |
989 if (!iter.hasNext()) { | |
990 return ""; | |
991 } | |
992 StringBuilder buffer = new StringBuilder(iter.next()); | |
993 while (iter.hasNext()) { | |
994 buffer.append(delimiter).append(iter.next()); | |
995 } | |
996 if (delimiterAtEnd) { | |
997 buffer.append(delimiter); | |
998 } | |
999 return buffer.toString(); | |
1000 } | |
1001 | |
1002 private static String movePayloadTypesToFront(List<String> preferredPayloadTyp es, String mLine) { | |
1003 // The format of the media description line should be: m=<media> <port> <pro to> <fmt> ... | |
1004 final List<String> origLineParts = Arrays.asList(mLine.split(" ")); | |
1005 if (origLineParts.size() <= 3) { | |
1006 Log.e(TAG, "Wrong SDP media description format: " + mLine); | |
1007 return null; | |
1008 } | |
1009 final List<String> header = origLineParts.subList(0, 3); | |
1010 final List<String> unpreferredPayloadTypes = | |
1011 new ArrayList<String>(origLineParts.subList(3, origLineParts.size())); | |
1012 unpreferredPayloadTypes.removeAll(preferredPayloadTypes); | |
1013 // Reconstruct the line with |preferredPayloadTypes| moved to the beginning of the payload | |
1014 // types. | |
1015 final List<String> newLineParts = new ArrayList<String>(); | |
1016 newLineParts.addAll(header); | |
1017 newLineParts.addAll(preferredPayloadTypes); | |
sakal
2017/01/27 15:05:15
This will add all preferred payload types regardle
magjed_webrtc
2017/01/27 15:16:43
The preferred payload types are expected to exist
sakal
2017/01/27 15:21:44
Ok, apparently SDP is required to use all codec ty
| |
1018 newLineParts.addAll(unpreferredPayloadTypes); | |
1019 return joinString(newLineParts, " ", false /* delimiterAtEnd */); | |
1020 } | |
1021 | |
972 private static String preferCodec(String sdpDescription, String codec, boolean isAudio) { | 1022 private static String preferCodec(String sdpDescription, String codec, boolean isAudio) { |
973 String[] lines = sdpDescription.split("\r\n"); | 1023 final String[] lines = sdpDescription.split("\r\n"); |
974 int mLineIndex = -1; | 1024 final int mLineIndex = findMediaDescriptionLine(isAudio, lines); |
975 String codecRtpMap = null; | 1025 if (mLineIndex == -1) { |
1026 Log.w(TAG, "No mediaDescription line, so can't prefer " + codec); | |
1027 return sdpDescription; | |
1028 } | |
1029 // A list with all the payload types with name |codec|. The payload types ar e integers in the | |
1030 // range 96-127, but they are stored as strings here. | |
1031 final List<String> codecPayloadTypes = new ArrayList<String>(); | |
976 // a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding paramete rs>] | 1032 // a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding paramete rs>] |
977 String regex = "^a=rtpmap:(\\d+) " + codec + "(/\\d+)+[\r]?$"; | 1033 final Pattern codecPattern = Pattern.compile("^a=rtpmap:(\\d+) " + codec + " (/\\d+)+[\r]?$"); |
978 Pattern codecPattern = Pattern.compile(regex); | 1034 for (int i = 0; i < lines.length; ++i) { |
979 String mediaDescription = "m=video "; | |
980 if (isAudio) { | |
981 mediaDescription = "m=audio "; | |
982 } | |
983 for (int i = 0; (i < lines.length) && (mLineIndex == -1 || codecRtpMap == nu ll); i++) { | |
984 if (lines[i].startsWith(mediaDescription)) { | |
985 mLineIndex = i; | |
986 continue; | |
987 } | |
988 Matcher codecMatcher = codecPattern.matcher(lines[i]); | 1035 Matcher codecMatcher = codecPattern.matcher(lines[i]); |
989 if (codecMatcher.matches()) { | 1036 if (codecMatcher.matches()) { |
990 codecRtpMap = codecMatcher.group(1); | 1037 codecPayloadTypes.add(codecMatcher.group(1)); |
991 } | 1038 } |
992 } | 1039 } |
993 if (mLineIndex == -1) { | 1040 if (codecPayloadTypes.isEmpty()) { |
994 Log.w(TAG, "No " + mediaDescription + " line, so can't prefer " + codec); | 1041 Log.w(TAG, "No payload types with name " + codec); |
995 return sdpDescription; | 1042 return sdpDescription; |
996 } | 1043 } |
997 if (codecRtpMap == null) { | 1044 |
998 Log.w(TAG, "No rtpmap for " + codec); | 1045 final String newMLine = movePayloadTypesToFront(codecPayloadTypes, lines[mLi neIndex]); |
1046 if (newMLine == null) { | |
999 return sdpDescription; | 1047 return sdpDescription; |
1000 } | 1048 } |
1001 Log.d(TAG, "Found " + codec + " rtpmap " + codecRtpMap + ", prefer at " + li nes[mLineIndex]); | 1049 Log.d(TAG, "Change media description from: " + lines[mLineIndex] + " to " + newMLine); |
1002 String[] origMLineParts = lines[mLineIndex].split(" "); | 1050 lines[mLineIndex] = newMLine; |
1003 if (origMLineParts.length > 3) { | 1051 return joinString(Arrays.asList(lines), "\r\n", true /* delimiterAtEnd */); |
1004 StringBuilder newMLine = new StringBuilder(); | |
1005 int origPartIndex = 0; | |
1006 // Format is: m=<media> <port> <proto> <fmt> ... | |
1007 newMLine.append(origMLineParts[origPartIndex++]).append(" "); | |
1008 newMLine.append(origMLineParts[origPartIndex++]).append(" "); | |
1009 newMLine.append(origMLineParts[origPartIndex++]).append(" "); | |
1010 newMLine.append(codecRtpMap); | |
1011 for (; origPartIndex < origMLineParts.length; origPartIndex++) { | |
1012 if (!origMLineParts[origPartIndex].equals(codecRtpMap)) { | |
1013 newMLine.append(" ").append(origMLineParts[origPartIndex]); | |
1014 } | |
1015 } | |
1016 lines[mLineIndex] = newMLine.toString(); | |
1017 Log.d(TAG, "Change media description: " + lines[mLineIndex]); | |
1018 } else { | |
1019 Log.e(TAG, "Wrong SDP media description format: " + lines[mLineIndex]); | |
1020 } | |
1021 StringBuilder newSdpDescription = new StringBuilder(); | |
1022 for (String line : lines) { | |
1023 newSdpDescription.append(line).append("\r\n"); | |
1024 } | |
1025 return newSdpDescription.toString(); | |
1026 } | 1052 } |
1027 | 1053 |
1028 private void drainCandidates() { | 1054 private void drainCandidates() { |
1029 if (queuedRemoteCandidates != null) { | 1055 if (queuedRemoteCandidates != null) { |
1030 Log.d(TAG, "Add " + queuedRemoteCandidates.size() + " remote candidates"); | 1056 Log.d(TAG, "Add " + queuedRemoteCandidates.size() + " remote candidates"); |
1031 for (IceCandidate candidate : queuedRemoteCandidates) { | 1057 for (IceCandidate candidate : queuedRemoteCandidates) { |
1032 peerConnection.addIceCandidate(candidate); | 1058 peerConnection.addIceCandidate(candidate); |
1033 } | 1059 } |
1034 queuedRemoteCandidates = null; | 1060 queuedRemoteCandidates = null; |
1035 } | 1061 } |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1279 public void onCreateFailure(final String error) { | 1305 public void onCreateFailure(final String error) { |
1280 reportError("createSDP error: " + error); | 1306 reportError("createSDP error: " + error); |
1281 } | 1307 } |
1282 | 1308 |
1283 @Override | 1309 @Override |
1284 public void onSetFailure(final String error) { | 1310 public void onSetFailure(final String error) { |
1285 reportError("setSDP error: " + error); | 1311 reportError("setSDP error: " + error); |
1286 } | 1312 } |
1287 } | 1313 } |
1288 } | 1314 } |
OLD | NEW |