src/org/sipdroid/media/RtpStreamReceiver.java
changeset 834 e8d6255306f8
parent 830 c8b4ace735ea
child 835 4e40f3481f23
equal deleted inserted replaced
833:f5a5d9237d69 834:e8d6255306f8
    17  * You should have received a copy of the GNU General Public License
    17  * You should have received a copy of the GNU General Public License
    18  * along with this source code; if not, write to the Free Software
    18  * along with this source code; if not, write to the Free Software
    19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    20  */
    20  */
    21 
    21 
    22 package org.sipdroid.media;
    22 package src.org.sipdroid.media;
    23 
    23 
    24 import jlibrtp.AppCallerThread;
    24 import java.io.IOException;
    25 import jlibrtp.DataFrame;
    25 import java.net.SocketException;
    26 import jlibrtp.Participant;
    26 
    27 import jlibrtp.RTPAppIntf;
    27 import org.sipdroid.sipua.UserAgent;
    28 import jlibrtp.RTPReceiverThread;
    28 import org.sipdroid.sipua.ui.Receiver;
    29 import jlibrtp.RTPSession;
    29 import org.sipdroid.sipua.ui.Sipdroid;
    30 
    30 import org.sipdroid.pjlib.Codec;
    31 import org.sipdroid.media.codecs.Codec;
    31 
    32 import org.sipdroid.net.tools.DataFramePool;
    32 import src.org.sipdroid.net.RtpPacket;
    33 import org.sipdroid.net.tools.DatagramPool;
    33 import src.org.sipdroid.net.RtpSocket;
       
    34 import src.org.sipdroid.net.SipdroidSocket;
    34 
    35 
    35 import android.content.ContentResolver;
    36 import android.content.ContentResolver;
    36 import android.content.Context;
    37 import android.content.Context;
    37 import android.content.SharedPreferences.Editor;
    38 import android.content.SharedPreferences.Editor;
    38 import android.media.AudioFormat;
    39 import android.media.AudioFormat;
    39 import android.media.AudioManager;
    40 import android.media.AudioManager;
    40 import android.media.AudioTrack;
    41 import android.media.AudioTrack;
    41 import android.media.ToneGenerator;
    42 import android.media.ToneGenerator;
       
    43 import android.os.PowerManager;
    42 import android.preference.PreferenceManager;
    44 import android.preference.PreferenceManager;
    43 import android.provider.Settings;
    45 import android.provider.Settings;
    44 
    46 
    45 /**
    47 /**
    46  * RtpStreamReceiver is a generic stream receiver. It receives packets from RTP
    48  * RtpStreamReceiver is a generic stream receiver. It receives packets from RTP
    47  * and writes them into an OutputStream.
    49  * and writes them into an OutputStream.
    48  */
    50  */
    49 public class RtpStreamReceiver extends Thread implements RTPAppIntf{
    51 public class RtpStreamReceiver extends Thread {
    50 
    52 
    51 	/** Whether working in debug mode. */
    53 	/** Whether working in debug mode. */
    52 	public static boolean DEBUG = true;
    54 	public static boolean DEBUG = true;
    53 
    55 
       
    56 	/** Payload type */
       
    57 	int p_type;
       
    58 
    54 	/** Size of the read buffer */
    59 	/** Size of the read buffer */
    55 	public static final int BUFFER_SIZE = 1024;
    60 	public static final int BUFFER_SIZE = 1024;
    56 
    61 
    57 	/** Maximum blocking time, spent waiting for reading new bytes [milliseconds] */
    62 	/** Maximum blocking time, spent waiting for reading new bytes [milliseconds] */
    58 	public static final int SO_TIMEOUT = 200;
    63 	public static final int SO_TIMEOUT = 200;
    59 
    64 
    60 	/** The RtpSocket */
    65 	/** The RtpSocket */
    61 	RTPSession rtpSession = null;
    66 	RtpSocket rtp_socket = null;
    62 	byte[] buffer;
       
    63 
       
    64 	/** The codec */
       
    65 	private Codec codec;
       
    66 	private Context mContext;
       
    67 
       
    68 	private int frame_size;
       
    69 	private int codec_frame_size;
       
    70 	private int sampling_rate;
       
    71 
    67 
    72 	/** Whether it is running */
    68 	/** Whether it is running */
    73 	boolean running;
    69 	boolean running;
    74 	AudioManager am;
    70 	AudioManager am;
    75 	ContentResolver cr;
    71 	ContentResolver cr;
    76 
       
    77 	private int codec_divider;
       
    78 	public static int speakermode;
    72 	public static int speakermode;
    79 
    73 	
    80 	short lin[];
       
    81 	short lin2[];
       
    82 	int user, server, lserver, luser, cnt, todo, headroom, len, timeout = 1, seq = 0, cnt2 = 0, m = 1,
       
    83 	expseq, getseq, vm = 1, gap, oldvol;
       
    84 	boolean islate;
       
    85 
       
    86 	Codec.Context codecCtx;
       
    87 
       
    88 	AudioTrack track;
       
    89 
       
    90 	/**
    74 	/**
    91 	 * Constructs a RtpStreamReceiver.
    75 	 * Constructs a RtpStreamReceiver.
    92 	 * @param ctx 
       
    93 	 * @param remoteAddr 
       
    94 	 * 
    76 	 * 
    95 	 * @param output_stream
    77 	 * @param output_stream
    96 	 *            the stream sink
    78 	 *            the stream sink
    97 	 * @param socket
    79 	 * @param socket
    98 	 *            the local receiver SipdroidSocket
    80 	 *            the local receiver SipdroidSocket
    99 	 */
    81 	 */
   100 	public RtpStreamReceiver(Codec ci, RTPSession rtpSession, Context ctx) {
    82 	public RtpStreamReceiver(SipdroidSocket socket, int payload_type) {
   101 		init(ci, rtpSession, ctx);
    83 		init(socket);
   102 	}
    84 		p_type = payload_type;
   103 
    85 	}
   104 	/** Inits the RtpStreamReceiver 
    86 
   105 	 * @param ctx 
    87 	/** Inits the RtpStreamReceiver */
   106 	 * @param remoteAddr
    88 	private void init(SipdroidSocket socket) {
   107 	 **/
    89 		if (socket != null)
   108 	private void init(Codec ci, RTPSession rtpSession, Context ctx) {
    90 			rtp_socket = new RtpSocket(socket);
   109 		this.rtpSession = rtpSession;
       
   110 		codec = ci;
       
   111 		codec_frame_size = codec.getInfo().codecFrameSize;		
       
   112 		codec_divider = codec.getInfo().rtpSampleDivider;
       
   113 		frame_size = 160 * codec_divider;
       
   114 		sampling_rate = codec.getInfo().samplingRate;
       
   115 		mContext = ctx;
       
   116 	}
    91 	}
   117 
    92 
   118 	/** Whether is running */
    93 	/** Whether is running */
   119 	public boolean isRunning() {
    94 	public boolean isRunning() {
   120 		return running;
    95 		return running;
   122 
    97 
   123 	/** Stops running */
    98 	/** Stops running */
   124 	public void halt() {
    99 	public void halt() {
   125 		running = false;
   100 		running = false;
   126 	}
   101 	}
   127 
   102 	
   128 	public int speaker(int mode) {
   103 	public int speaker(int mode) {
   129 		int old = speakermode;
   104 		int old = speakermode;
   130 
   105 		
       
   106 		if (Receiver.headset > 0 && mode == AudioManager.MODE_NORMAL)
       
   107 			return old;
   131 		saveVolume();
   108 		saveVolume();
   132 		speakermode = mode;
   109 		setMode(speakermode = mode);
   133 		restoreVolume();
   110 		restoreVolume();
   134 		return old;
   111 		return old;
   135 	}
   112 	}
   136 
   113 
   137 	double smin = 200,s;
   114 	double smin = 200,s;
   138 
       
   139 	private int REAL_BUFFER_SIZE;
       
   140 	public static int nearend;
   115 	public static int nearend;
   141 
   116 	
   142 	void calc(short[] lin,int off,int len) {
   117 	void calc(short[] lin,int off,int len) {
   143 		int i,j;
   118 		int i,j;
   144 		double sm = 30000,r;
   119 		double sm = 30000,r;
   145 
   120 		
   146 		for (i = 0; i < len; i += 5) {
   121 		for (i = 0; i < len; i += 5) {
   147 			j = lin[i+off];
   122 			j = lin[i+off];
   148 			s = 0.03*Math.abs(j) + 0.97*s;
   123 			s = 0.03*Math.abs(j) + 0.97*s;
   149 			if (s < sm) sm = s;
   124 			if (s < sm) sm = s;
   150 			if (s > smin) nearend = 3000/5;
   125 			if (s > smin) nearend = 3000/5;
   160 				lin[i+off] = (short)(j*5);
   135 				lin[i+off] = (short)(j*5);
   161 		}
   136 		}
   162 		r = (double)len/100000;
   137 		r = (double)len/100000;
   163 		smin = sm*r + smin*(1-r);
   138 		smin = sm*r + smin*(1-r);
   164 	}
   139 	}
   165 
   140 	
       
   141 	static void setStreamVolume(final int stream,final int vol,final int flags) {
       
   142         (new Thread() {
       
   143 			public void run() {
       
   144 				AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
       
   145 				am.setStreamVolume(stream, vol, flags);
       
   146 				if (stream == AudioManager.STREAM_MUSIC) restored = true;
       
   147 			}
       
   148         }).start();
       
   149 	}
       
   150 	
       
   151 	static boolean restored;
       
   152 	
   166 	void restoreVolume() {
   153 	void restoreVolume() {
   167 		am.setStreamVolume(AudioManager.STREAM_MUSIC,
   154 		switch (am.getMode()) {
   168 				PreferenceManager.getDefaultSharedPreferences(mContext).getInt("volume"+speakermode, 
   155 		case AudioManager.MODE_IN_CALL:
   169 						am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)*
   156 				setStreamVolume(AudioManager.STREAM_RING,(int)(
   170 						(speakermode == AudioManager.MODE_NORMAL?4:3)/4
   157 						am.getStreamMaxVolume(AudioManager.STREAM_RING)*
       
   158 						org.sipdroid.sipua.ui.Settings.getEarGain()), 0);
       
   159 				track.setStereoVolume(AudioTrack.getMaxVolume()*
       
   160 						org.sipdroid.sipua.ui.Settings.getEarGain()
       
   161 						,AudioTrack.getMaxVolume()*
       
   162 						org.sipdroid.sipua.ui.Settings.getEarGain());
       
   163 				break;
       
   164 		case AudioManager.MODE_NORMAL:
       
   165 				track.setStereoVolume(AudioTrack.getMaxVolume(),AudioTrack.getMaxVolume());
       
   166 				break;
       
   167 		}
       
   168 		setStreamVolume(AudioManager.STREAM_MUSIC,
       
   169 				PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("volume"+speakermode, 
       
   170 				am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)*
       
   171 				(speakermode == AudioManager.MODE_NORMAL?4:3)/4
   171 				),0);
   172 				),0);
   172 	}
   173 	}
   173 
   174 	
   174 	void saveVolume() {
   175 	void saveVolume() {
   175 		Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
   176 		if (restored) {
   176 		edit.putInt("volume"+speakermode,am.getStreamVolume(AudioManager.STREAM_MUSIC));
   177 			Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
   177 		edit.commit();
   178 			edit.putInt("volume"+speakermode,am.getStreamVolume(AudioManager.STREAM_MUSIC));
   178 	}
   179 			edit.commit();
   179 
   180 		}
       
   181 	}
       
   182 	
   180 	void saveSettings() {
   183 	void saveSettings() {
   181 		if (!PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean("oldvalid",false)) {
   184 		if (!PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("oldvalid",false)) {
   182 			int oldvibrate = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
   185 			int oldvibrate = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
   183 			int oldvibrate2 = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
   186 			int oldvibrate2 = am.getVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
   184 			if (!PreferenceManager.getDefaultSharedPreferences(mContext).contains("oldvibrate2"))
   187 			if (!PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).contains("oldvibrate2"))
   185 				oldvibrate2 = AudioManager.VIBRATE_SETTING_ON;
   188 				oldvibrate2 = AudioManager.VIBRATE_SETTING_ON;
   186 			int oldpolicy = android.provider.Settings.System.getInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, 
   189 			int oldpolicy = android.provider.Settings.System.getInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, 
   187 					Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
   190 					Settings.System.WIFI_SLEEP_POLICY_DEFAULT);
   188 			Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
   191 			Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
   189 			edit.putInt("oldvibrate", oldvibrate);
   192 			edit.putInt("oldvibrate", oldvibrate);
   190 			edit.putInt("oldvibrate2", oldvibrate2);
   193 			edit.putInt("oldvibrate2", oldvibrate2);
   191 			edit.putInt("oldpolicy", oldpolicy);
   194 			edit.putInt("oldpolicy", oldpolicy);
   192 			edit.putInt("oldring",am.getStreamVolume(AudioManager.STREAM_RING));
   195 			edit.putInt("oldring",am.getStreamVolume(AudioManager.STREAM_RING));
   193 			edit.putBoolean("oldvalid", true);
   196 			edit.putBoolean("oldvalid", true);
   194 			edit.commit();
   197 			edit.commit();
   195 		}
   198 		}
   196 	}
   199 	}
   197 
   200 	
   198 	void restoreSettings() {
   201 	public static void setMode(int mode) {
   199 		int oldvibrate = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldvibrate",0);
   202 		Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
   200 		int oldvibrate2 = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldvibrate2",0);
   203 		edit.putBoolean("setmode", mode != AudioManager.MODE_NORMAL);
   201 		int oldpolicy = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldpolicy",0);
       
   202 		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,oldvibrate);
       
   203 		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,oldvibrate2);
       
   204 		Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY, oldpolicy);
       
   205 		am.setStreamVolume(AudioManager.STREAM_RING, PreferenceManager.getDefaultSharedPreferences(mContext).getInt("oldring",0), 0);
       
   206 		Editor edit = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
       
   207 		edit.putBoolean("oldvalid", false);
       
   208 		edit.commit();
   204 		edit.commit();
       
   205 		AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
       
   206 		am.setMode(mode);
       
   207 	}
       
   208 	
       
   209 	public static void restoreMode() {
       
   210 		if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("setmode",true)) {
       
   211 			if (Receiver.pstn_state == null || Receiver.pstn_state.equals("IDLE"))
       
   212 				setMode(AudioManager.MODE_NORMAL);
       
   213 			else {
       
   214 				Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
       
   215 				edit.putBoolean("setmode", false);
       
   216 				edit.commit();
       
   217 			}
       
   218 		}
       
   219 	}
       
   220 
       
   221 	public static void restoreSettings() {
       
   222 		if (PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("oldvalid",true)) {
       
   223 			AudioManager am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
       
   224 	        ContentResolver cr = Receiver.mContext.getContentResolver();
       
   225 			int oldvibrate = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldvibrate",0);
       
   226 			int oldvibrate2 = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldvibrate2",0);
       
   227 			int oldpolicy = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldpolicy",0);
       
   228 			am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,oldvibrate);
       
   229 			am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,oldvibrate2);
       
   230 			Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY, oldpolicy);
       
   231 			setStreamVolume(AudioManager.STREAM_RING, PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getInt("oldring",0), 0);
       
   232 			Editor edit = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).edit();
       
   233 			edit.putBoolean("oldvalid", false);
       
   234 			edit.commit();
       
   235 			PowerManager pm = (PowerManager) Receiver.mContext.getSystemService(Context.POWER_SERVICE);
       
   236 			PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
       
   237 					PowerManager.ACQUIRE_CAUSES_WAKEUP, "Sipdroid.RtpStreamReceiver");
       
   238 			wl.acquire(1000);
       
   239 		}
       
   240 		restoreMode();
   209 	}
   241 	}
   210 
   242 
   211 	public static float good, late, lost, loss;
   243 	public static float good, late, lost, loss;
   212 
   244 	public static int timeout;
       
   245 	
       
   246 	void empty() {
       
   247 		try {
       
   248 			rtp_socket.getDatagramSocket().setSoTimeout(1);
       
   249 			for (;;)
       
   250 				rtp_socket.receive(rtp_packet);
       
   251 		} catch (SocketException e2) {
       
   252 			if (!Sipdroid.release) e2.printStackTrace();
       
   253 		} catch (IOException e) {
       
   254 		}
       
   255 		try {
       
   256 			rtp_socket.getDatagramSocket().setSoTimeout(1000);
       
   257 		} catch (SocketException e2) {
       
   258 			if (!Sipdroid.release) e2.printStackTrace();
       
   259 		}
       
   260 	}
       
   261 	
       
   262 	RtpPacket rtp_packet;
       
   263 	AudioTrack track;
       
   264 	
   213 	/** Runs it in a new Thread. */
   265 	/** Runs it in a new Thread. */
   214 	@Override
       
   215 	public void run() {
   266 	public void run() {
   216 		REAL_BUFFER_SIZE = BUFFER_SIZE * codec_divider;
   267 		boolean nodata = PreferenceManager.getDefaultSharedPreferences(Receiver.mContext).getBoolean("nodata",false);
   217 		speakermode = AudioManager.MODE_IN_CALL;
   268 		
       
   269 		if (rtp_socket == null) {
       
   270 			if (DEBUG)
       
   271 				println("ERROR: RTP socket is null");
       
   272 			return;
       
   273 		}
       
   274 
       
   275 		byte[] buffer = new byte[BUFFER_SIZE+12];
       
   276 		byte[] buffer_gsm = new byte[33+12];
       
   277 		int i;
       
   278 		rtp_packet = new RtpPacket(buffer, 0);
       
   279 
       
   280 		if (DEBUG)
       
   281 			println("Reading blocks of max " + buffer.length + " bytes");
       
   282 
       
   283 		running = true;
       
   284 		speakermode = Receiver.docked > 0?AudioManager.MODE_NORMAL:AudioManager.MODE_IN_CALL;
       
   285 		restored = false;
       
   286 
   218 		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
   287 		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
   219 		am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
   288 		am = (AudioManager) Receiver.mContext.getSystemService(Context.AUDIO_SERVICE);
   220 		cr = mContext.getContentResolver();
   289         cr = Receiver.mContext.getContentResolver();
   221 		//saveSettings();
   290 		saveSettings();
   222 
       
   223 		Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,Settings.System.WIFI_SLEEP_POLICY_NEVER);
   291 		Settings.System.putInt(cr, Settings.System.WIFI_SLEEP_POLICY,Settings.System.WIFI_SLEEP_POLICY_NEVER);
   224 		//am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,AudioManager.VIBRATE_SETTING_OFF);
   292 		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,AudioManager.VIBRATE_SETTING_OFF);
   225 		//am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,AudioManager.VIBRATE_SETTING_OFF);
   293 		am.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,AudioManager.VIBRATE_SETTING_OFF);
   226 		//oldvol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
   294 		int oldvol = am.getStreamVolume(AudioManager.STREAM_MUSIC);
   227 		restoreVolume();
   295 		track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
   228 
   296 				BUFFER_SIZE*2*2, AudioTrack.MODE_STREAM);
   229 		track = new AudioTrack(AudioManager.STREAM_MUSIC, sampling_rate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,
   297 		short lin[] = new short[BUFFER_SIZE];
   230 				REAL_BUFFER_SIZE*2*2, AudioTrack.MODE_STREAM);
   298 		short lin2[] = new short[BUFFER_SIZE];
       
   299 		int user, server, lserver, luser, cnt, todo, headroom, len = 0, seq = 0, cnt2 = 0, m = 1,
       
   300 			expseq, getseq, vm = 1, gap, gseq;
       
   301 		timeout = 1;
       
   302 		boolean islate;
       
   303 		user = 0;
       
   304 		lserver = 0;
       
   305 		luser = -8000;
       
   306 		cnt = 0;
       
   307 		switch (p_type) {
       
   308 		case 3:
       
   309 			Codec.init();
       
   310 			break;
       
   311 		case 0:
       
   312 		case 8:
       
   313 			G711.init();
       
   314 			break;
       
   315 		}
       
   316 		ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_MUSIC,(int)(ToneGenerator.MAX_VOLUME*2*org.sipdroid.sipua.ui.Settings.getEarGain()));
   231 		track.play();
   317 		track.play();
   232 		lin = new short[REAL_BUFFER_SIZE];
   318 		if (Receiver.headset > 0 && Receiver.oRingtone != null) {
   233 		lin2 = new short[REAL_BUFFER_SIZE];
   319 			ToneGenerator tg2 = new ToneGenerator(AudioManager.STREAM_RING,(int)(ToneGenerator.MAX_VOLUME*2*org.sipdroid.sipua.ui.Settings.getEarGain()));
   234 		user = 0; //number of samples written
   320 			tg2.startTone(ToneGenerator.TONE_SUP_RINGTONE);
   235 		server = 0; // number of samples played
   321 			System.gc();
   236 		lserver = 0; // last number of samples played
   322 			tg2.stopTone();
   237 		luser = -sampling_rate; // last number of samples written
   323 		} else
   238 		cnt = 0;
   324 			System.gc();
   239 		codecCtx = codec.initDecoder(); 
       
   240 		System.gc();
       
   241 		println("DEBUG: rtpStreamReceiver session launch");
       
   242 		running = true;
       
   243 		AppCallerThread appCall = rtpSession.getAppCallerThrd();
       
   244 		RTPReceiverThread recv = rtpSession.getRTPRecvThrd();
       
   245 		DataFrame frame = null;
       
   246 		recv.init();
       
   247 		while (running) {
   325 		while (running) {
   248 			recv.readPacketToBuffer();
   326 			if (Receiver.call_state == UserAgent.UA_STATE_HOLD) {
   249 			frame = appCall.getNextDataFrame();
   327 				tg.stopTone();
   250 			if (frame == null)
   328 				track.pause();
   251 				continue;
   329 				while (running && Receiver.call_state == UserAgent.UA_STATE_HOLD) {
   252 			buffer = (frame.getPkt()[0]).getPayload();
       
   253 			if (timeout != 0) { //on ecrit du blanc sur l'audiotrack
       
   254 				user += track.write(lin,0,REAL_BUFFER_SIZE);
       
   255 				user += track.write(lin,0,REAL_BUFFER_SIZE);
       
   256 			}
       
   257 			timeout = 0;
       
   258 			if (running) {
       
   259 
       
   260 				//println("seq " + seq + " frame seq " + (frame.getPkt()[0]).getSeqNumber());
       
   261 				if (seq == (frame.getPkt()[0]).getSeqNumber()) {
       
   262 					m++;
       
   263 					continue;
       
   264 				}
       
   265 
       
   266 				codec.decode(codecCtx, buffer, 12, codec_frame_size, lin, 0);
       
   267 				len = frame_size;
       
   268 
       
   269 				if (speakermode == AudioManager.MODE_NORMAL)
       
   270 					calc(lin,0,len);
       
   271 
       
   272 				server = track.getPlaybackHeadPosition(); // on récupère la position actuel de la tete de lecture
       
   273 				headroom = user-server; // on recalcule la différence entre la position de la tete de lecture et ce qu'on a écrit sur la piste
       
   274 				//println("headroom " + headroom + " user " + user + " server " + server);
       
   275 				if (headroom < 250 * codec_divider) { // si le headroom est trop petit, il faut rattraper le retard en écrivant du blanc/répétant ce qu'il y a à ecrire
       
   276 					todo = 625 * codec_divider - headroom;
       
   277 					//println("insert "+todo);
       
   278 					android.util.Log.d("RECV", "insert");
       
   279 					islate = true;
       
   280 					if (todo < len)
       
   281 						user += track.write(lin,0,todo); // on écrit le packet reçu tel quel
       
   282 					else
       
   283 						user += track.write(lin2,0,todo); // ecriture de blanc de taille 625 - headroom, avant l'écriture du packet
       
   284 				} else
       
   285 					islate = false;
       
   286 
       
   287 				if (headroom > 1000 * codec_divider) // si le headroom est trop grand, on calcule l'écart.
       
   288 					cnt += len; // on additione le nombre de sample ou il y a eu un headroom supérieur a 1000
       
   289 				else
       
   290 					cnt = 0;
       
   291 
       
   292 				if (lserver == server) // on compte le nombre de boucle que l'on a fait sans qu'aucun sample n'ai été joué.
       
   293 					cnt2++;
       
   294 				else
       
   295 					cnt2 = 0;
       
   296 
       
   297 				if (cnt > 1000 * codec_divider && cnt2 < 2) { // si la position de la tete de lecture n'a pas bougé durant 2 tours et que le nombre de sample ou le headroom a été supérieur à 1000 est > 1000
       
   298 					todo = headroom - 625 * codec_divider;
       
   299 					try {
   330 					try {
   300 						//android.util.Log.d("RECV", "cut");
   331 						sleep(1000);
   301 						sleep(20);
   332 					} catch (InterruptedException e1) {
   302 					} catch (InterruptedException e) {
       
   303 						// TODO Auto-generated catch block
       
   304 						e.printStackTrace();
       
   305 					}
   333 					}
   306 				}
   334 				}
   307 				user += track.write(lin,0,len);
   335 				track.play();
   308 				m = 1;
   336 				System.gc();
   309 				seq = (frame.getPkt()[0]).getSeqNumber();
   337 				timeout = 1;
   310 				DataFramePool.getInstance().returnFrame(frame);
   338 				seq = 0;
   311 				//println("headroom " + headroom + " user " + user + " server " + server + " luser " + luser + " lserver " + lserver);
   339 			}
   312 				if (user >= luser + sampling_rate) {
   340 			try {
   313 					/*if (am.getMode() != speakermode) {
   341 				rtp_socket.receive(rtp_packet);
   314 						am.setMode(speakermode);
   342 				if (timeout != 0) {
   315 						switch (speakermode) {
   343 					tg.stopTone();
   316 						case AudioManager.MODE_IN_CALL:
   344 					track.pause();
   317 							am.setStreamVolume(AudioManager.STREAM_RING,(int)(
   345 					user += track.write(lin2,0,BUFFER_SIZE);
   318 									am.getStreamMaxVolume(AudioManager.STREAM_RING)*
   346 					user += track.write(lin2,0,BUFFER_SIZE);
   319 									com.mbdsys.sfrdroid.ui.Settings.getEarGain()), 0);
   347 					track.play();
   320 							track.setStereoVolume(AudioTrack.getMaxVolume()*
   348 					cnt += 2*BUFFER_SIZE;
   321 									com.mbdsys.sfrdroid.ui.Settings.getEarGain()
   349 					empty();
   322 									,AudioTrack.getMaxVolume()*
       
   323 									com.mbdsys.sfrdroid.ui.Settings.getEarGain());
       
   324 							//running = false;
       
   325 						case AudioManager.MODE_NORMAL:
       
   326 							track.setStereoVolume(AudioTrack.getMaxVolume(),AudioTrack.getMaxVolume());
       
   327 							//running = false;
       
   328 						}
       
   329 					}*/
       
   330 					luser = user;
       
   331 				}
   350 				}
   332 				lserver = server;
   351 				timeout = 0;
   333 				System.arraycopy(lin, 0, lin2, 0, REAL_BUFFER_SIZE);
   352 			} catch (IOException e) {
       
   353 				if (timeout == 0 && nodata) {
       
   354 					tg.startTone(ToneGenerator.TONE_SUP_RINGTONE);
       
   355 				}
       
   356 				rtp_socket.getDatagramSocket().disconnect();
       
   357 				if (++timeout > 22) {
       
   358 					Receiver.engine(Receiver.mContext).rejectcall();
       
   359 					break;
       
   360 				}
   334 			}
   361 			}
       
   362 			if (running && timeout == 0) {		
       
   363 				 gseq = rtp_packet.getSequenceNumber();
       
   364 				 if (seq == gseq) {
       
   365 					 m++;
       
   366 					 continue;
       
   367 				 }
       
   368 				 
       
   369 				 server = track.getPlaybackHeadPosition();
       
   370 				 headroom = user-server;
       
   371 				 
       
   372 				 if (headroom > 1500)
       
   373 					 cnt += len;
       
   374 				 else
       
   375 					 cnt = 0;
       
   376 				 
       
   377 				 if (lserver == server)
       
   378 					 cnt2++;
       
   379 				 else
       
   380 					 cnt2 = 0;
       
   381 
       
   382 				 if (cnt <= 500 || cnt2 >= 2 || headroom - 875 < len) {
       
   383 					 switch (rtp_packet.getPayloadType()) {
       
   384 					 case 0:
       
   385 						 len = rtp_packet.getPayloadLength();
       
   386 						 G711.ulaw2linear(buffer, lin, len);
       
   387 						 break;
       
   388 					 case 8:
       
   389 						 len = rtp_packet.getPayloadLength();
       
   390 						 G711.alaw2linear(buffer, lin, len);
       
   391 						 break;
       
   392 					 case 3:
       
   393 						 for (i = 12; i < 45; i++)
       
   394 							 buffer_gsm[i] = buffer[i];
       
   395 						 len = Codec.decode(buffer_gsm, lin, 0);
       
   396 						 break;
       
   397 					 }
       
   398 					 
       
   399 		 			 if (speakermode == AudioManager.MODE_NORMAL)
       
   400 		 				 calc(lin,0,len);
       
   401 				 }
       
   402 				 
       
   403 	 			 if (headroom < 250) { 
       
   404 					todo = 875 - headroom;
       
   405 					println("insert "+todo);
       
   406 					islate = true;
       
   407 					user += track.write(lin2,0,todo);
       
   408 				 } else
       
   409 					islate = false;
       
   410 
       
   411 				 if (cnt > 500 && cnt2 < 2) {
       
   412 					 todo = headroom - 875;
       
   413 					 println("cut "+todo);
       
   414 					 if (todo < len)
       
   415 						 user += track.write(lin,todo,len-todo);
       
   416 				 } else
       
   417 					 user += track.write(lin,0,len);
       
   418 				 
       
   419 				 if (seq != 0) {
       
   420 					 getseq = gseq&0xff;
       
   421 					 expseq = ++seq&0xff;
       
   422 					 if (m == RtpStreamSender.m) vm = m;
       
   423 					 gap = (getseq - expseq) & 0xff;
       
   424 					 if (gap > 0) {
       
   425 						 if (gap > 100) gap = 1;
       
   426 						 loss += gap;
       
   427 						 lost += gap;
       
   428 						 good += gap - 1;
       
   429 					 } else {
       
   430 						 if (m < vm)
       
   431 							 loss++;
       
   432 						 if (islate)
       
   433 							 late++;
       
   434 					 }
       
   435 					 good++;
       
   436 					 if (good > 100) {
       
   437 						 good *= 0.99;
       
   438 						 lost *= 0.99;
       
   439 						 loss *= 0.99;
       
   440 						 late *= 0.99;
       
   441 					 }
       
   442 				 }
       
   443 				 m = 1;
       
   444 				 seq = gseq;
       
   445 				 
       
   446 				 if (user >= luser + 8000 && Receiver.call_state == UserAgent.UA_STATE_INCALL) {
       
   447 					 if (luser == -8000 || am.getMode() != speakermode) {
       
   448 						 saveVolume();
       
   449 						 setMode(speakermode);
       
   450 						 restoreVolume();
       
   451 					 }
       
   452 					 luser = user;
       
   453 				 }
       
   454 				 lserver = server;
       
   455 			}
   335 		}
   456 		}
   336 		track.stop();
   457 		track.stop();
   337 		ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_RING,ToneGenerator.MAX_VOLUME/4*3);
   458 		saveVolume();
       
   459 		setStreamVolume(AudioManager.STREAM_MUSIC,oldvol,0);
       
   460 		restoreSettings();
       
   461 		setStreamVolume(AudioManager.STREAM_MUSIC,oldvol,0);
       
   462 		tg.stopTone();
       
   463 		tg = new ToneGenerator(AudioManager.STREAM_RING,ToneGenerator.MAX_VOLUME/4*3);
   338 		tg.startTone(ToneGenerator.TONE_PROP_PROMPT);
   464 		tg.startTone(ToneGenerator.TONE_PROP_PROMPT);
   339 		try {
   465 		try {
   340 			Thread.sleep(500);
   466 			sleep(500);
   341 		} catch (InterruptedException e) {
   467 		} catch (InterruptedException e) {
   342 		}
   468 		}
   343 		tg.stopTone();
   469 		tg.stopTone();
   344 		rtpSession = null;
   470 		
   345 		track = null;
   471 		rtp_socket.close();
   346 		codec.cleanDecoder(codecCtx);
   472 		rtp_socket = null;
   347 		codec = null;
   473 
   348 		println("rtp receiver terminated");
   474 		if (DEBUG)
       
   475 			println("rtp receiver terminated");
   349 	}
   476 	}
   350 
   477 
   351 	/** Debug output */
   478 	/** Debug output */
   352 	static int i = 0;
       
   353 	private static void println(String str) {
   479 	private static void println(String str) {
   354 		System.out.println("RtpStreamReceiver "+ i++ +": " + str);
   480 		if (!Sipdroid.release) System.out.println("RtpStreamReceiver: " + str);
   355 	}
   481 	}
   356 
   482 
   357 	public static int byte2int(byte b) { // return (b>=0)? b : -((b^0xFF)+1);
   483 	public static int byte2int(byte b) { // return (b>=0)? b : -((b^0xFF)+1);
   358 		// return (b>=0)? b : b+0x100;
   484 		// return (b>=0)? b : b+0x100;
   359 		return (b + 0x100) % 0x100;
   485 		return (b + 0x100) % 0x100;
   360 	}
   486 	}
   361 
   487 
   362 	public static int byte2int(byte b1, byte b2) {
   488 	public static int byte2int(byte b1, byte b2) {
   363 		return (((b1 + 0x100) % 0x100) << 8) + (b2 + 0x100) % 0x100;
   489 		return (((b1 + 0x100) % 0x100) << 8) + (b2 + 0x100) % 0x100;
   364 	}
   490 	}
   365 
       
   366 	@Override
       
   367 	public int frameSize(int payloadType) {
       
   368 		// TODO Auto-generated method stub
       
   369 		return 0;
       
   370 	}
       
   371 
       
   372 	@Override
       
   373 	public void receiveData(DataFrame frame, Participant participant) {
       
   374 		// TODO Auto-generated method stub
       
   375 
       
   376 	}
       
   377 
       
   378 	@Override
       
   379 	public void userEvent(int type, Participant[] participant) {
       
   380 		// TODO Auto-generated method stub
       
   381 
       
   382 	}
       
   383 
       
   384 }
   491 }