| Index: webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
|
| diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
|
| index cbc69e9451f1265d88a5b58b2df1a49492cda2f4..39d432d5fbb7d2aa8c97b6fc70a31a9ddb60c89c 100644
|
| --- a/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
|
| +++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java
|
| @@ -17,8 +17,11 @@ import android.util.Log;
|
| import java.io.File;
|
| import java.io.IOException;
|
| import java.nio.ByteBuffer;
|
| +import java.util.ArrayList;
|
| +import java.util.Arrays;
|
| import java.util.Collections;
|
| import java.util.EnumSet;
|
| +import java.util.Iterator;
|
| import java.util.LinkedList;
|
| import java.util.List;
|
| import java.util.Timer;
|
| @@ -969,60 +972,83 @@ public class PeerConnectionClient {
|
| return newSdpDescription.toString();
|
| }
|
|
|
| + /** Returns the line number containing "m=audio|video", or -1 if no such line exists. */
|
| + private static int findMediaDescriptionLine(boolean isAudio, String[] sdpLines) {
|
| + final String mediaDescription = isAudio ? "m=audio " : "m=video ";
|
| + for (int i = 0; i < sdpLines.length; ++i) {
|
| + if (sdpLines[i].startsWith(mediaDescription)) {
|
| + return i;
|
| + }
|
| + }
|
| + return -1;
|
| + }
|
| +
|
| + private static String joinString(
|
| + Iterable<? extends CharSequence> s, String delimiter, boolean delimiterAtEnd) {
|
| + Iterator<? extends CharSequence> iter = s.iterator();
|
| + if (!iter.hasNext()) {
|
| + return "";
|
| + }
|
| + StringBuilder buffer = new StringBuilder(iter.next());
|
| + while (iter.hasNext()) {
|
| + buffer.append(delimiter).append(iter.next());
|
| + }
|
| + if (delimiterAtEnd) {
|
| + buffer.append(delimiter);
|
| + }
|
| + return buffer.toString();
|
| + }
|
| +
|
| + private static String movePayloadTypesToFront(List<String> preferredPayloadTypes, String mLine) {
|
| + // The format of the media description line should be: m=<media> <port> <proto> <fmt> ...
|
| + final List<String> origLineParts = Arrays.asList(mLine.split(" "));
|
| + if (origLineParts.size() <= 3) {
|
| + Log.e(TAG, "Wrong SDP media description format: " + mLine);
|
| + return null;
|
| + }
|
| + final List<String> header = origLineParts.subList(0, 3);
|
| + final List<String> unpreferredPayloadTypes =
|
| + new ArrayList<String>(origLineParts.subList(3, origLineParts.size()));
|
| + unpreferredPayloadTypes.removeAll(preferredPayloadTypes);
|
| + // Reconstruct the line with |preferredPayloadTypes| moved to the beginning of the payload
|
| + // types.
|
| + final List<String> newLineParts = new ArrayList<String>();
|
| + newLineParts.addAll(header);
|
| + newLineParts.addAll(preferredPayloadTypes);
|
| + newLineParts.addAll(unpreferredPayloadTypes);
|
| + return joinString(newLineParts, " ", false /* delimiterAtEnd */);
|
| + }
|
| +
|
| private static String preferCodec(String sdpDescription, String codec, boolean isAudio) {
|
| - String[] lines = sdpDescription.split("\r\n");
|
| - int mLineIndex = -1;
|
| - String codecRtpMap = null;
|
| + final String[] lines = sdpDescription.split("\r\n");
|
| + final int mLineIndex = findMediaDescriptionLine(isAudio, lines);
|
| + if (mLineIndex == -1) {
|
| + Log.w(TAG, "No mediaDescription line, so can't prefer " + codec);
|
| + return sdpDescription;
|
| + }
|
| + // A list with all the payload types with name |codec|. The payload types are integers in the
|
| + // range 96-127, but they are stored as strings here.
|
| + final List<String> codecPayloadTypes = new ArrayList<String>();
|
| // a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
|
| - String regex = "^a=rtpmap:(\\d+) " + codec + "(/\\d+)+[\r]?$";
|
| - Pattern codecPattern = Pattern.compile(regex);
|
| - String mediaDescription = "m=video ";
|
| - if (isAudio) {
|
| - mediaDescription = "m=audio ";
|
| - }
|
| - for (int i = 0; (i < lines.length) && (mLineIndex == -1 || codecRtpMap == null); i++) {
|
| - if (lines[i].startsWith(mediaDescription)) {
|
| - mLineIndex = i;
|
| - continue;
|
| - }
|
| + final Pattern codecPattern = Pattern.compile("^a=rtpmap:(\\d+) " + codec + "(/\\d+)+[\r]?$");
|
| + for (int i = 0; i < lines.length; ++i) {
|
| Matcher codecMatcher = codecPattern.matcher(lines[i]);
|
| if (codecMatcher.matches()) {
|
| - codecRtpMap = codecMatcher.group(1);
|
| + codecPayloadTypes.add(codecMatcher.group(1));
|
| }
|
| }
|
| - if (mLineIndex == -1) {
|
| - Log.w(TAG, "No " + mediaDescription + " line, so can't prefer " + codec);
|
| + if (codecPayloadTypes.isEmpty()) {
|
| + Log.w(TAG, "No payload types with name " + codec);
|
| return sdpDescription;
|
| }
|
| - if (codecRtpMap == null) {
|
| - Log.w(TAG, "No rtpmap for " + codec);
|
| +
|
| + final String newMLine = movePayloadTypesToFront(codecPayloadTypes, lines[mLineIndex]);
|
| + if (newMLine == null) {
|
| return sdpDescription;
|
| }
|
| - Log.d(TAG, "Found " + codec + " rtpmap " + codecRtpMap + ", prefer at " + lines[mLineIndex]);
|
| - String[] origMLineParts = lines[mLineIndex].split(" ");
|
| - if (origMLineParts.length > 3) {
|
| - StringBuilder newMLine = new StringBuilder();
|
| - int origPartIndex = 0;
|
| - // Format is: m=<media> <port> <proto> <fmt> ...
|
| - newMLine.append(origMLineParts[origPartIndex++]).append(" ");
|
| - newMLine.append(origMLineParts[origPartIndex++]).append(" ");
|
| - newMLine.append(origMLineParts[origPartIndex++]).append(" ");
|
| - newMLine.append(codecRtpMap);
|
| - for (; origPartIndex < origMLineParts.length; origPartIndex++) {
|
| - if (!origMLineParts[origPartIndex].equals(codecRtpMap)) {
|
| - newMLine.append(" ").append(origMLineParts[origPartIndex]);
|
| - }
|
| - }
|
| - lines[mLineIndex] = newMLine.toString();
|
| - Log.d(TAG, "Change media description: " + lines[mLineIndex]);
|
| - } else {
|
| - Log.e(TAG, "Wrong SDP media description format: " + lines[mLineIndex]);
|
| - }
|
| - StringBuilder newSdpDescription = new StringBuilder();
|
| - for (String line : lines) {
|
| - newSdpDescription.append(line).append("\r\n");
|
| - }
|
| - return newSdpDescription.toString();
|
| + Log.d(TAG, "Change media description from: " + lines[mLineIndex] + " to " + newMLine);
|
| + lines[mLineIndex] = newMLine;
|
| + return joinString(Arrays.asList(lines), "\r\n", true /* delimiterAtEnd */);
|
| }
|
|
|
| private void drainCandidates() {
|
|
|