src/org/sipdroid/media/RtpStreamSender.java
changeset 835 4e40f3481f23
parent 834 e8d6255306f8
child 836 2f2f5e24ac6a
--- a/src/org/sipdroid/media/RtpStreamSender.java	Sat Jan 23 22:19:43 2010 +0100
+++ b/src/org/sipdroid/media/RtpStreamSender.java	Sun Jan 24 00:42:29 2010 +0100
@@ -19,22 +19,23 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-package src.org.sipdroid.media;
+package org.sipdroid.media;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetAddress;
 import java.util.Random;
 
-import org.sipdroid.sipua.UserAgent;
-import org.sipdroid.sipua.ui.Receiver;
-import org.sipdroid.sipua.ui.Settings;
-import org.sipdroid.sipua.ui.Sipdroid;
+
 import org.sipdroid.pjlib.Codec;
 
-import src.org.sipdroid.net.RtpPacket;
-import src.org.sipdroid.net.RtpSocket;
-import src.org.sipdroid.net.SipdroidSocket;
+import org.sipdroid.media.RtpStreamReceiver;
+import org.sipdroid.net.RtpPacket;
+import org.sipdroid.net.RtpSocket;
+import org.sipdroid.net.SipdroidSocket;
+
+import com.beem.project.beem.ui.Call;
+import com.beem.project.beem.utils.BeemConnectivity;
 
 import android.content.Context;
 import android.media.AudioFormat;
@@ -42,6 +43,7 @@
 import android.media.AudioRecord;
 import android.media.MediaRecorder;
 import android.preference.PreferenceManager;
+import android.provider.Settings;
 import android.telephony.TelephonyManager;
 
 /**
@@ -49,331 +51,326 @@
  * it through RTP.
  */
 public class RtpStreamSender extends Thread {
-	/** Whether working in debug mode. */
-	public static boolean DEBUG = true;
+    /** Whether working in debug mode. */
+    public static boolean DEBUG = true;
+
+    /** The RtpSocket */
+    RtpSocket rtp_socket = null;
 
-	/** The RtpSocket */
-	RtpSocket rtp_socket = null;
+    /** Payload type */
+    int p_type;
+
+    /** Number of frame per second */
+    long frame_rate;
 
-	/** Payload type */
-	int p_type;
+    /** Number of bytes per frame */
+    int frame_size;
 
-	/** Number of frame per second */
-	long frame_rate;
+    /**
+     * Whether it works synchronously with a local clock, or it it acts as slave
+     * of the InputStream
+     */
+    boolean do_sync = true;
 
-	/** Number of bytes per frame */
-	int frame_size;
+    /**
+     * Synchronization correction value, in milliseconds. It accellarates the
+     * sending rate respect to the nominal value, in order to compensate program
+     * latencies.
+     */
+    int sync_adj = 0;
 
-	/**
-	 * Whether it works synchronously with a local clock, or it it acts as slave
-	 * of the InputStream
-	 */
-	boolean do_sync = true;
+    /** Whether it is running */
+    boolean running = false;
+    boolean muted = false;
 
-	/**
-	 * Synchronization correction value, in milliseconds. It accellarates the
-	 * sending rate respect to the nominal value, in order to compensate program
-	 * latencies.
-	 */
-	int sync_adj = 0;
-
-	/** Whether it is running */
-	boolean running = false;
-	boolean muted = false;
+    /**
+     * Constructs a RtpStreamSender.
+     * 
+     * @param input_stream
+     *            the stream to be sent
+     * @param do_sync
+     *            whether time synchronization must be performed by the
+     *            RtpStreamSender, or it is performed by the InputStream (e.g.
+     *            the system audio input)
+     * @param payload_type
+     *            the payload type
+     * @param frame_rate
+     *            the frame rate, i.e. the number of frames that should be sent
+     *            per second; it is used to calculate the nominal packet time
+     *            and,in case of do_sync==true, the next departure time
+     * @param frame_size
+     *            the size of the payload
+     * @param src_socket
+     *            the socket used to send the RTP packet
+     * @param dest_addr
+     *            the destination address
+     * @param dest_port
+     *            the destination port
+     */
+    public RtpStreamSender(boolean do_sync,
+	int payload_type, long frame_rate, int frame_size,
+	SipdroidSocket src_socket, String dest_addr, int dest_port) {
+	init(do_sync, payload_type, frame_rate, frame_size,
+	    src_socket, dest_addr, dest_port);
+    }
 
-	/**
-	 * Constructs a RtpStreamSender.
-	 * 
-	 * @param input_stream
-	 *            the stream to be sent
-	 * @param do_sync
-	 *            whether time synchronization must be performed by the
-	 *            RtpStreamSender, or it is performed by the InputStream (e.g.
-	 *            the system audio input)
-	 * @param payload_type
-	 *            the payload type
-	 * @param frame_rate
-	 *            the frame rate, i.e. the number of frames that should be sent
-	 *            per second; it is used to calculate the nominal packet time
-	 *            and,in case of do_sync==true, the next departure time
-	 * @param frame_size
-	 *            the size of the payload
-	 * @param src_socket
-	 *            the socket used to send the RTP packet
-	 * @param dest_addr
-	 *            the destination address
-	 * @param dest_port
-	 *            the destination port
-	 */
-	public RtpStreamSender(boolean do_sync,
-			int payload_type, long frame_rate, int frame_size,
-			SipdroidSocket src_socket, String dest_addr, int dest_port) {
-		init(do_sync, payload_type, frame_rate, frame_size,
-				src_socket, dest_addr, dest_port);
+    /** Inits the RtpStreamSender */
+    private void init(boolean do_sync,
+	int payload_type, long frame_rate, int frame_size,
+	SipdroidSocket src_socket, String dest_addr,
+	int dest_port) {
+	this.p_type = payload_type;
+	this.frame_rate = frame_rate;
+	this.frame_size = frame_size;
+	this.do_sync = do_sync;
+	try {
+	    rtp_socket = new RtpSocket(src_socket, InetAddress
+		.getByName(dest_addr), dest_port);
+	} catch (Exception e) {
+	    e.printStackTrace();
 	}
+    }
+
+    /** Sets the synchronization adjustment time (in milliseconds). */
+    public void setSyncAdj(int millisecs) {
+	sync_adj = millisecs;
+    }
+
+    /** Whether is running */
+    public boolean isRunning() {
+	return running;
+    }
+
+    public boolean mute() {
+	return muted = !muted;
+    }
+
+    public static int delay = 0;
 
-	/** Inits the RtpStreamSender */
-	private void init(boolean do_sync,
-			int payload_type, long frame_rate, int frame_size,
-			SipdroidSocket src_socket, String dest_addr,
-			int dest_port) {
-		this.p_type = payload_type;
-		this.frame_rate = frame_rate;
-		this.frame_size = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getString("server","").equals("pbxes.org")?
-				(payload_type == 3?960:1024):frame_size; //15
-		this.do_sync = do_sync;
-		try {
-			rtp_socket = new RtpSocket(src_socket, InetAddress
-					.getByName(dest_addr), dest_port);
-		} catch (Exception e) {
-			if (!Sipdroid.release) e.printStackTrace();
-		}
-	}
+    /** Stops running */
+    public void halt() {
+	running = false;
+    }
+
+    Random random;
+    double smin = 200,s;
+    int nearend;
+
+    void calc(short[] lin,int off,int len) {
+	int i,j;
+	double sm = 30000,r;
 
-	/** Sets the synchronization adjustment time (in milliseconds). */
-	public void setSyncAdj(int millisecs) {
-		sync_adj = millisecs;
-	}
-
-	/** Whether is running */
-	public boolean isRunning() {
-		return running;
+	for (i = 0; i < len; i += 5) {
+	    j = lin[i+off];
+	    s = 0.03*Math.abs(j) + 0.97*s;
+	    if (s < sm) sm = s;
+	    if (s > smin) nearend = 3000/5;
+	    else if (nearend > 0) nearend--;
 	}
-	
-	public boolean mute() {
-		return muted = !muted;
+	for (i = 0; i < len; i++) {
+	    j = lin[i+off];
+	    if (j > 6550)
+		lin[i+off] = 6550*5;
+	    else if (j < -6550)
+		lin[i+off] = -6550*5;
+	    else
+		lin[i+off] = (short)(j*5);
 	}
+	r = (double)len/100000;
+	smin = sm*r + smin*(1-r);
+    }
 
-	public static int delay = 0;
-	
-	/** Stops running */
-	public void halt() {
-		running = false;
+    void calc1(short[] lin,int off,int len) {
+	int i,j;
+
+	for (i = 0; i < len; i++) {
+	    j = lin[i+off];
+	    lin[i+off] = (short)(j>>1);
 	}
+    }
 
-	Random random;
-	double smin = 200,s;
-	int nearend;
-	
-	void calc(short[] lin,int off,int len) {
-		int i,j;
-		double sm = 30000,r;
-		
-		for (i = 0; i < len; i += 5) {
-			j = lin[i+off];
-			s = 0.03*Math.abs(j) + 0.97*s;
-			if (s < sm) sm = s;
-			if (s > smin) nearend = 3000/5;
-			else if (nearend > 0) nearend--;
-		}
-		for (i = 0; i < len; i++) {
-			j = lin[i+off];
-			if (j > 6550)
-				lin[i+off] = 6550*5;
-			else if (j < -6550)
-				lin[i+off] = -6550*5;
-			else
-				lin[i+off] = (short)(j*5);
-		}
-		r = (double)len/100000;
-		smin = sm*r + smin*(1-r);
+    void calc5(short[] lin,int off,int len) {
+	int i,j;
+
+	for (i = 0; i < len; i++) {
+	    j = lin[i+off];
+	    if (j > 16350)
+		lin[i+off] = 16350<<1;
+	    else if (j < -16350)
+		lin[i+off] = -16350<<1;
+	    else
+		lin[i+off] = (short)(j<<1);
+	}
+    }
+
+    void calc10(short[] lin,int off,int len) {
+	int i,j;
+
+	for (i = 0; i < len; i++) {
+	    j = lin[i+off];
+	    if (j > 8150)
+		lin[i+off] = 8150<<2;
+	    else if (j < -8150)
+		lin[i+off] = -8150<<2;
+	    else
+		lin[i+off] = (short)(j<<2);
 	}
+    }
 
-	void calc1(short[] lin,int off,int len) {
-		int i,j;
-		
-		for (i = 0; i < len; i++) {
-			j = lin[i+off];
-			lin[i+off] = (short)(j>>1);
-		}
-	}
+    void noise(short[] lin,int off,int len,double power) {
+	int i,r = (int)(power*2);
+	short ran;
 
-	void calc5(short[] lin,int off,int len) {
-		int i,j;
-		
-		for (i = 0; i < len; i++) {
-			j = lin[i+off];
-			if (j > 16350)
-				lin[i+off] = 16350<<1;
-			else if (j < -16350)
-				lin[i+off] = -16350<<1;
-			else
-				lin[i+off] = (short)(j<<1);
-		}
+	if (r == 0) r = 1;
+	for (i = 0; i < len; i += 4) {
+	    ran = (short)(random.nextInt(r*2)-r);
+	    lin[i+off] = ran;
+	    lin[i+off+1] = ran;
+	    lin[i+off+2] = ran;
+	    lin[i+off+3] = ran;
 	}
+    }
+    public static float getMicGain() {
+	if (Call.headset > 0)
+	    return Float.valueOf(PreferenceManager.getDefaultSharedPreferences(Call.mContext).getString("hmicgain", "1.0"));
+	return Float.valueOf(PreferenceManager.getDefaultSharedPreferences(Call.mContext).getString("micgain", "0.25"));
+    }
+
+    /** Runs it in a new Thread. */
+    public void run() {
+	if (rtp_socket == null)
+	    return;
+	byte[] buffer = new byte[frame_size + 12];
+	RtpPacket rtp_packet = new RtpPacket(buffer, 0);
+	rtp_packet.setPayloadType(p_type);
+	int seqn = 0;
+	long time = 0;
+	double p = 0;
+	TelephonyManager tm = (TelephonyManager) Call.mContext.getSystemService(Context.TELEPHONY_SERVICE);
+	boolean improve = PreferenceManager.getDefaultSharedPreferences(Call.mContext).getBoolean("improve",false);
+	boolean useGSM = !PreferenceManager.getDefaultSharedPreferences(Call.mContext).getString("compression","edge").equals("never");
+	int micgain = (int)(getMicGain()*10);
+	running = true;
+
+	if (DEBUG)
+	    println("Reading blocks of " + buffer.length + " bytes");
 
-	void calc10(short[] lin,int off,int len) {
-		int i,j;
-		
-		for (i = 0; i < len; i++) {
-			j = lin[i+off];
-			if (j > 8150)
-				lin[i+off] = 8150<<2;
-			else if (j < -8150)
-				lin[i+off] = -8150<<2;
-			else
-				lin[i+off] = (short)(j<<2);
-		}
+	android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
+	AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
+	    AudioRecord.getMinBufferSize(8000, 
+		AudioFormat.CHANNEL_CONFIGURATION_MONO, 
+		AudioFormat.ENCODING_PCM_16BIT)*3/2);
+	short[] lin = new short[frame_size*11];
+	int num,ring = 0;
+	random = new Random();
+	InputStream alerting = null;
+	try {
+	    alerting = Call.mContext.getAssets().open("alerting");
+	} catch (IOException e2) {
+	    e2.printStackTrace();
 	}
-
-	void noise(short[] lin,int off,int len,double power) {
-		int i,r = (int)(power*2);
-		short ran;
-
-		if (r == 0) r = 1;
-		for (i = 0; i < len; i += 4) {
-			ran = (short)(random.nextInt(r*2)-r);
-			lin[i+off] = ran;
-			lin[i+off+1] = ran;
-			lin[i+off+2] = ran;
-			lin[i+off+3] = ran;
-		}
+	switch (p_type) {
+	    case 3:
+		Codec.init();
+		break;
+	    case 0:
+	    case 8:
+		G711.init();
+		break;
 	}
-	
-	public static int m;
-	
-	/** Runs it in a new Thread. */
-	public void run() {
-		if (rtp_socket == null)
-			return;
-		byte[] buffer = new byte[frame_size + 12];
-		RtpPacket rtp_packet = new RtpPacket(buffer, 0);
-		rtp_packet.setPayloadType(p_type);
-		int seqn = 0;
-		long time = 0;
-		double p = 0;
-		TelephonyManager tm = (TelephonyManager) Receiver.mContext.getSystemService(Context.TELEPHONY_SERVICE);
-		boolean improve = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("improve",false);
-		boolean useGSM = !PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getString("compression","edge").equals("never");
-		int micgain = (int)(Settings.getMicGain()*10);
-		running = true;
-		m = 1;
+	record.startRecording();
+	while (running) {
+	    if (muted || Call.call_state == Call.UA_STATE_HOLD) {
+		record.stop();
+		while (running && (muted || Call.call_state == Call.UA_STATE_HOLD)) {
+		    try {
+			sleep(1000);
+		    } catch (InterruptedException e1) {
+			e1.printStackTrace();
+		    }
+		}
+		record.startRecording();
+	    }
+	    num = record.read(lin,(ring+delay)%(frame_size*11),frame_size);
 
-		if (DEBUG)
-			println("Reading blocks of " + buffer.length + " bytes");
-
-		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
-		AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
-				AudioRecord.getMinBufferSize(8000, 
-						AudioFormat.CHANNEL_CONFIGURATION_MONO, 
-						AudioFormat.ENCODING_PCM_16BIT)*3/2);
-		short[] lin = new short[frame_size*11];
-		int num,ring = 0;
-		random = new Random();
-		InputStream alerting = null;
+	    if (RtpStreamReceiver.speakermode == AudioManager.MODE_NORMAL) {
+		calc(lin,(ring+delay)%(frame_size*11),num);
+		if (RtpStreamReceiver.nearend != 0)
+		    noise(lin,(ring+delay)%(frame_size*11),num,p);
+		else if (RtpStreamReceiver.nearend == 0)
+		    p = 0.9*p + 0.1*s;
+	    } else switch (micgain) {
+		case 1:
+		    calc1(lin,(ring+delay)%(frame_size*11),num);
+		    break;
+		case 5:
+		    calc5(lin,(ring+delay)%(frame_size*11),num);
+		    break;
+		case 10:
+		    calc10(lin,(ring+delay)%(frame_size*11),num);
+		    break;
+	    }
+	    if (Call.call_state != Call.UA_STATE_INCALL && alerting != null) {
 		try {
-			alerting = Receiver.mContext.getAssets().open("alerting");
-		} catch (IOException e2) {
-			if (!Sipdroid.release) e2.printStackTrace();
+		    if (alerting.available() < num)
+			alerting.reset();
+		    alerting.read(buffer,12,num);
+		} catch (IOException e) {
+		    e.printStackTrace();
 		}
-		switch (p_type) {
-		case 3:
-			Codec.init();
+		switch (p_type) {// have to add ulaw case?
+		    case 3:
+			G711.alaw2linear(buffer, lin, num);
+			num = Codec.encode(lin, 0, buffer, num);
 			break;
-		case 0:
-		case 8:
-			G711.init();
+		    case 0:
+			G711.alaw2linear(buffer, lin, num);
+			G711.linear2ulaw(lin, 0, buffer, num);
 			break;
 		}
-		record.startRecording();
-		while (running) {
-			 if (muted || Receiver.call_state == UserAgent.UA_STATE_HOLD) {
-				record.stop();
-				while (running && (muted || Receiver.call_state == UserAgent.UA_STATE_HOLD)) {
-					try {
-						sleep(1000);
-					} catch (InterruptedException e1) {
-					}
-				}
-				record.startRecording();
-			 }
-			 num = record.read(lin,(ring+delay)%(frame_size*11),frame_size);
+	    } else {
+		switch (p_type) {
+		    case 3:
+			num = Codec.encode(lin, ring%(frame_size*11), buffer, num);
+			break;
+		    case 0:
+			G711.linear2ulaw(lin, ring%(frame_size*11), buffer, num);
+			break;
+		    case 8:
+			G711.linear2alaw(lin, ring%(frame_size*11), buffer, num);
+			break;
+		}
+	    }
+	    ring += frame_size;
+	    rtp_packet.setSequenceNumber(seqn++);
+	    rtp_packet.setTimestamp(time);
+	    rtp_packet.setPayloadLength(num);
+	    try {
+		rtp_socket.send(rtp_packet);
+	    } catch (IOException e) {
+		e.printStackTrace();
+	    }
+	    time += frame_size;
+	    if (useGSM && p_type == 8 && !BeemConnectivity.isWifi(Call.mContext) && tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_EDGE) {
+		rtp_packet.setPayloadType(p_type = 3);
+		if (frame_size == 1024) {
+		    frame_size = 960;
+		    ring = 0;
+		}
+	    }
+	}
+	record.stop();
 
-			 if (RtpStreamReceiver.speakermode == AudioManager.MODE_NORMAL) {
- 				 calc(lin,(ring+delay)%(frame_size*11),num);
- 	 			 if (RtpStreamReceiver.nearend != 0)
-	 				 noise(lin,(ring+delay)%(frame_size*11),num,p);
-	 			 else if (nearend == 0)
-	 				 p = 0.9*p + 0.1*s;
- 			 } else switch (micgain) {
- 			 case 1:
- 				 calc1(lin,(ring+delay)%(frame_size*11),num);
- 				 break;
- 			 case 5:
- 				 calc5(lin,(ring+delay)%(frame_size*11),num);
- 				 break;
- 			 case 10:
- 				 calc10(lin,(ring+delay)%(frame_size*11),num);
- 				 break;
- 			 }
-			 if (Receiver.call_state != UserAgent.UA_STATE_INCALL && alerting != null) {
-				 try {
-					if (alerting.available() < num)
-						alerting.reset();
-					alerting.read(buffer,12,num);
-				 } catch (IOException e) {
-					if (!Sipdroid.release) e.printStackTrace();
-				 }
-				 switch (p_type) {// have to add ulaw case?
-				 case 3:
-					 G711.alaw2linear(buffer, lin, num);
-					 num = Codec.encode(lin, 0, buffer, num);
-					 break;
-				 case 0:
-					 G711.alaw2linear(buffer, lin, num);
-					 G711.linear2ulaw(lin, 0, buffer, num);
-					 break;
-				 }
-			 } else {
-				 switch (p_type) {
-				 case 3:
-					 num = Codec.encode(lin, ring%(frame_size*11), buffer, num);
-					 break;
-				 case 0:
-					 G711.linear2ulaw(lin, ring%(frame_size*11), buffer, num);
-					 break;
-				 case 8:
-					 G711.linear2alaw(lin, ring%(frame_size*11), buffer, num);
-					 break;
-				 }
-			 }
- 			 ring += frame_size;
- 			 rtp_packet.setSequenceNumber(seqn++);
- 			 rtp_packet.setTimestamp(time);
- 			 rtp_packet.setPayloadLength(num);
- 			 try {
- 				 rtp_socket.send(rtp_packet);
- 				 if (m == 2)
- 					 rtp_socket.send(rtp_packet);
- 			 } catch (IOException e) {
- 			 }
-			 time += frame_size;
- 			 if (improve && RtpStreamReceiver.good != 0 &&
- 					 RtpStreamReceiver.loss/RtpStreamReceiver.good > 0.01 &&
- 					 (Receiver.on_wlan || tm.getNetworkType() != TelephonyManager.NETWORK_TYPE_EDGE))        	
- 				 m = 2;
- 			 else
- 				 m = 1;
- 			 if (useGSM && p_type == 8 && !Receiver.on_wlan && tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_EDGE) {
- 				 rtp_packet.setPayloadType(p_type = 3);
- 				 if (frame_size == 1024) {
- 					 frame_size = 960;
- 					 ring = 0;
- 				 }
- 			 }
-		}
-		record.stop();
-		
-		rtp_socket.close();
-		rtp_socket = null;
+	rtp_socket.close();
+	rtp_socket = null;
 
-		if (DEBUG)
-			println("rtp sender terminated");
-	}
+	if (DEBUG)
+	    println("rtp sender terminated");
+    }
 
-	/** Debug output */
-	private static void println(String str) {
-		if (!Sipdroid.release) System.out.println("RtpStreamSender: " + str);
-	}
+    /** Debug output */
+    private static void println(String str) {
+	System.out.println("RtpStreamSender: " + str);
+    }
 
 }
\ No newline at end of file