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
exists. */ |
| 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); |
| 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 |