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; |
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 } |