Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@
</intent-filter>
</activity>
</application>

</manifest>
2 changes: 1 addition & 1 deletion project.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# This file is automatically generated by IntelliJ IDEA
# Project target.
target=android-17
target=android-19
163 changes: 163 additions & 0 deletions src/deepak/rathi/RTCAudioActivity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package deepak.rathi;

/**
* Copyright Deepak Rathi (https://github.com/deepak-rathi)
*
* STEPS FOLLOWED TO CREATE AUDIO CALL
* - In WebRtcClient :
create a new method that does the same thing as setCamera but without video
:

public void setAudio(){
lMS = factory.createLocalMediaStream("ARDAMS");
lMS.addTrack(factory.createAudioTrack("ARDAMSa0"));

mListener.onLocalStream(lMS);
}

- In RTCactivity :
in startCam() call setAudio() instead of setCamera(...)

At this point, you should still have audio working and a green (or black)
screen.
You can then :
- Remove the videoStreamsView and videoRenderer from RTCactivity
- Change the PeerConnection Constraints "OfferToReceiveVideo" to false
*/

import fr.pchab.AndroidRTC.R;
import fr.pchab.AndroidRTC.VideoStreamsView;
import fr.pchab.AndroidRTC.WebRtcClient;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Window;
import android.widget.Toast;
import org.json.JSONException;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnectionFactory;
//import org.webrtc.VideoRenderer;

import java.util.List;

public class RTCAudioActivity extends Activity implements WebRtcClient.RTCListener{
private final static int AUDIO_CALL_SENT = 666;
private VideoStreamsView vsv;
private WebRtcClient client;
private String mSocketAddress;
private String callerId;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mSocketAddress = "http://" + getResources().getString(R.string.host);
mSocketAddress += (":"+getResources().getString(R.string.port)+"/");

PeerConnectionFactory.initializeAndroidGlobals(this);

// Camera display view
Point displaySize = new Point();
getWindowManager().getDefaultDisplay().getSize(displaySize);
vsv = new VideoStreamsView(this, displaySize);
client = new WebRtcClient(this, mSocketAddress);

final Intent intent = getIntent();
final String action = intent.getAction();

if (Intent.ACTION_VIEW.equals(action)) {
final List<String> segments = intent.getData().getPathSegments();
callerId = segments.get(0);
//callerId = "R9lEjFqo4sb1ZbeM9r0i"; static room id for testing
}
}

public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}

@Override
public void onPause() {
super.onPause();
vsv.onPause();
}

@Override
public void onResume() {
super.onResume();
vsv.onResume();
}

@Override
public void onCallReady(String callId) {
//callerId = "R9lEjFqo4sb1ZbeM9r0i"; a static room id for testing
if(callerId != null) {
try {
answer(callerId);
} catch (JSONException e) {
e.printStackTrace();
}
} else {
call(callId);
}
}

public void answer(String callerId) throws JSONException {
client.sendMessage(callerId, "init", null);
startCam();
}

public void call(String callId) {
Intent msg = new Intent(Intent.ACTION_SEND);
msg.putExtra(Intent.EXTRA_TEXT, mSocketAddress + callId);
msg.setType("text/plain");
startActivityForResult(Intent.createChooser(msg, "Call someone :"), AUDIO_CALL_SENT);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == AUDIO_CALL_SENT) {
startCam();
}
}

public void startCam() {
setContentView(vsv);
// Audio call settings

client.setAudio();
client.start("android_test", true);
}

@Override
public void onStatusChanged(final String newStatus) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), newStatus, Toast.LENGTH_SHORT).show();
}
});
}

@Override
public void onLocalStream(MediaStream localStream) {

}

@Override
public void onAddRemoteStream(MediaStream remoteStream, int endPoint) {

}

@Override
public void onRemoveRemoteStream(MediaStream remoteStream, int endPoint) {

}

}
3 changes: 1 addition & 2 deletions src/fr/pchab/AndroidRTC/RTCActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.webrtc.MediaStream;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.VideoRenderer;

import java.util.List;

public class RTCActivity extends Activity implements WebRtcClient.RTCListener{
Expand Down Expand Up @@ -133,7 +132,7 @@ public void onRemoveRemoteStream(MediaStream remoteStream, int endPoint) {

// Implementation detail: bridge the VideoRenderer.Callbacks interface to the
// VideoStreamsView implementation.
private class VideoCallbacks implements VideoRenderer.Callbacks {
public class VideoCallbacks implements VideoRenderer.Callbacks {
private final VideoStreamsView view;
private final int stream;

Expand Down
65 changes: 62 additions & 3 deletions src/fr/pchab/AndroidRTC/WebRtcClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import java.util.HashMap;
import java.util.LinkedList;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
Expand All @@ -25,7 +26,7 @@
import com.koushikdutta.async.http.socketio.EventCallback;
import com.koushikdutta.async.http.socketio.SocketIOClient;

class WebRtcClient {
public class WebRtcClient {
private final static int MAX_PEER = 2;
private boolean[] endPoints = new boolean[MAX_PEER];
private PeerConnectionFactory factory;
Expand Down Expand Up @@ -161,8 +162,11 @@ private class Peer implements SdpObserver, PeerConnection.Observer{
private int endPoint;

@Override
public void onCreateSuccess(final SessionDescription sdp) {
public void onCreateSuccess(final SessionDescription origSdp) {
try {
//changed default audio codec from OPUCS(ossy audio codec format) to iSAC
SessionDescription sdp = new SessionDescription(origSdp.type,
preferISAC(origSdp.description));
JSONObject payload = new JSONObject();
payload.put("type", sdp.type.canonicalForm());
payload.put("sdp", sdp.description);
Expand Down Expand Up @@ -282,6 +286,12 @@ public void setCamera(String cameraFacing, String height, String width){

mListener.onLocalStream(lMS);
}

public void setAudio() {
lMS = factory.createLocalMediaStream("ARDAMS");
lMS.addTrack(factory.createAudioTrack("ARDAMSa0"));
mListener.onLocalStream(lMS);
}

private int findEndPoint() {
for(int i = 0; i < MAX_PEER; i++) {
Expand Down Expand Up @@ -335,4 +345,53 @@ private void removePeer(String id) {

endPoints[peer.endPoint] = false;
}

//Mangle SDP to prefer ISAC/16000 over any other audio codec.
private String preferISAC(String sdpDescription) {
String[] lines = sdpDescription.split("\n");
int mLineIndex = -1;
String isac16kRtpMap = null;
Pattern isac16kPattern = Pattern
.compile("^a=rtpmap:(\\d+) ISAC/16000[\r]?$");
for (int i = 0; (i < lines.length)
&& (mLineIndex == -1 || isac16kRtpMap == null); ++i) {
if (lines[i].startsWith("m=audio ")) {
mLineIndex = i;
continue;
}
Matcher isac16kMatcher = isac16kPattern.matcher(lines[i]);
if (isac16kMatcher.matches()) {
isac16kRtpMap = isac16kMatcher.group(1);
continue;
}
}
if (mLineIndex == -1) {
Log.d(TAG, "No m=audio line, so can't prefer iSAC");
return sdpDescription;
}
if (isac16kRtpMap == null) {
Log.d(TAG, "No ISAC/16000 line, so can't prefer iSAC");
return sdpDescription;
}
String[] origMLineParts = lines[mLineIndex].split(" ");
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(isac16kRtpMap).append(" ");
for (; origPartIndex < origMLineParts.length; ++origPartIndex) {
if (!origMLineParts[origPartIndex].equals(isac16kRtpMap)) {
newMLine.append(origMLineParts[origPartIndex]).append(" ");
}
}
lines[mLineIndex] = newMLine.toString();
StringBuilder newSdpDescription = new StringBuilder();
for (String line : lines) {
newSdpDescription.append(line).append("\n");
}
return newSdpDescription.toString();
}

}