- import java.io.*;
- import javax.microedition.io.*;
- /**
- * RTP audio stream. This creates a UDP socket on the server, which is then
- * connected to a client and data pumped 25x per second.
- */
- public class AudioStream implements Runnable {
- /**
- * Sequence number. This should increment with every packet sent.
- */
- private int seqnumber = 0;
- /**
- * Timestamp increments by the number of samples with every packet sent.
- */
- private int timestamp = 0;
- /**
- * Buffer containing the current sample frame.
- */
- private final byte[] data = new byte[2048];
- /**
- * Connection to the client.
- */
- private final UDPDatagramConnection socket;
- /**
- * Datagram filled and sent to the client.
- */
- private final Datagram packet;
- /**
- * Thread in which the server pumps the data.
- */
- private Thread thread;
- /**
- * Whether to continue sending data or not.
- */
- private boolean running;
- /**
- * Creates a new audio stream on the specified port. Use -1 to bind to an
- * ephemeral port.
- */
- public AudioStream(int port) throws IOException {
- String addr = "datagram://:";
- if (port >= 0) {
- addr += port;
- }
- socket = (UDPDatagramConnection) Connector.open(addr);
- packet = socket.newDatagram(data, 2048);
- // fills the buffer with noise
- for (int n = 0; n < 2048; n++) {
- data[n] = (byte) n;
- }
- }
- /**
- * Returns the local port this server is bound to.
- */
- public int getPort() throws IOException {
- return socket.getLocalPort();
- }
- /**
- * Connects to a UDP client address and starts streaming the audio.
- */
- public void play(String addr, int port) {
- if (running) {
- return;
- }
- try {
- packet.setAddress("datagram://" + addr + ":" + port);
- thread = new Thread(this);
- thread.start();
- } catch (Exception e) {
- dprint(e);
- }
- }
- /**
- * Pauses the streaming (by stopping the thread pumping the data).
- */
- public void pause() {
- running = false;
- }
- /**
- * Stops the streaming and closes the connection.
- */
- public void stop() {
- running = false;
- try {
- thread.join();
- } catch (InterruptedException e) {}
- try {
- socket.close();
- } catch (IOException e) {
- dprint(e);
- }
- }
- /**
- * Fills the UDP packet with the RTP header (the data is static in this
- * demo, so never needs updating).
- */
- public void setPayload() {
- data[0] = (byte) 128;
- data[1] = (byte) 96;
- data[2] = (byte) (seqnumber >> 8);
- data[3] = (byte) (seqnumber >> 0);
- seqnumber += 1;
- data[4] = (byte) (timestamp >> 24);
- data[5] = (byte) (timestamp >> 16);
- data[6] = (byte) (timestamp >> 8);
- data[7] = (byte) (timestamp >> 0);
- timestamp += 882;
- data[ 8] = (byte) 0;
- data[ 9] = (byte) 0;
- data[10] = (byte) 0;
- data[11] = (byte) 0;
- // 882 being one audio frame (1/25 second), 12 being the header size
- packet.setLength(882 + 12);
- }
- /**
- * The audio data pump. RTP packets are sent regularly to the client.
- */
- public void run() {
- running = true;
- dprint("Sending packetsn");
- try {
- while (running) {
- setPayload();
- socket.send(packet);
- try {
- Thread.sleep(39);
- } catch (Exception x) {}
- }
- } catch (IOException e) {
- dprint(e);
- }
- dprint("Stopping packetsn");
- }
- public void dprint(Object obj) {
- System.out.print(obj);
- }
- }