/* * RTPSocketAdapter.java 21/06/07 * author: Max * MSN: zengfc@21cn.com * QQ: 22291911 * Email: zengfc@21cn.com * */ import java.io.IOException; import java.net.InetAddress; import java.net.DatagramSocket; import java.net.MulticastSocket; import java.net.DatagramPacket; import java.net.SocketException; import javax.media.protocol.PushSourceStream; import javax.media.protocol.ContentDescriptor; import javax.media.protocol.SourceTransferHandler; import javax.media.rtp.RTPConnector; import javax.media.rtp.OutputDataStream; /** * An implementation of RTPConnector based on UDP sockets. */ public class RTPSocketAdapter implements RTPConnector { DatagramSocket dataSock; DatagramSocket ctrlSock; InetAddress addr; int destDataPort; int destCtrlPort; SockInputStream dataInStrm = null, ctrlInStrm = null; SockOutputStream dataOutStrm = null, ctrlOutStrm = null; public RTPSocketAdapter(InetAddress addr, int port, int ttl) throws IOException { try { if (addr.isMulticastAddress()) { dataSock = new MulticastSocket(port); ctrlSock = new MulticastSocket(port+1); ((MulticastSocket)dataSock).joinGroup(addr); ((MulticastSocket)dataSock).setTimeToLive(ttl); ((MulticastSocket)ctrlSock).joinGroup(addr); ((MulticastSocket)ctrlSock).setTimeToLive(ttl); } else { dataSock = new DatagramSocket(port, InetAddress.getLocalHost()); ctrlSock = new DatagramSocket(port+1, InetAddress.getLocalHost()); } } catch (SocketException e) { throw new IOException(e.getMessage()); } this.addr = addr; this.destDataPort = port; } public RTPSocketAdapter(DatagramSocket dataSock, DatagramSocket ctrlSock, InetAddress addr, int destDataPort, int destCtrlPort) throws IOException { this.dataSock = dataSock; this.ctrlSock = ctrlSock; this.addr = addr; this.destDataPort = destDataPort; this.destCtrlPort = destCtrlPort; } /** * Returns an input stream to receive the RTP data. */ public PushSourceStream getDataInputStream() throws IOException { if (dataInStrm == null) { dataInStrm = new SockInputStream(dataSock, addr, destDataPort); dataInStrm.start(); } return dataInStrm; } /** * Returns an output stream to send the RTP data. */ public OutputDataStream getDataOutputStream() throws IOException { if (dataOutStrm == null) dataOutStrm = new SockOutputStream(dataSock, addr, destDataPort); return dataOutStrm; } /** * Returns an input stream to receive the RTCP data. */ public PushSourceStream getControlInputStream() throws IOException { if (ctrlInStrm == null) { ctrlInStrm = new SockInputStream(ctrlSock, addr, destCtrlPort); ctrlInStrm.start(); } return ctrlInStrm; } /** * Returns an output stream to send the RTCP data. */ public OutputDataStream getControlOutputStream() throws IOException { if (ctrlOutStrm == null) ctrlOutStrm = new SockOutputStream(ctrlSock, addr, destCtrlPort); return ctrlOutStrm; } /** * Close all the RTP, RTCP streams. */ public void close() { if (dataInStrm != null) dataInStrm.kill(); if (ctrlInStrm != null) ctrlInStrm.kill(); dataSock.close(); ctrlSock.close(); } /** * Set the receive buffer size of the RTP data channel. * This is only a hint to the implementation. The actual implementation * may not be able to do anything to this. */ public void setReceiveBufferSize( int size) throws IOException { dataSock.setReceiveBufferSize(size); } /** * Get the receive buffer size set on the RTP data channel. * Return -1 if the receive buffer size is not applicable for * the implementation. */ public int getReceiveBufferSize() { try { return dataSock.getReceiveBufferSize(); } catch (Exception e) { return -1; } } /** * Set the send buffer size of the RTP data channel. * This is only a hint to the implementation. The actual implementation * may not be able to do anything to this. */ public void setSendBufferSize( int size) throws IOException { dataSock.setSendBufferSize(size); } /** * Get the send buffer size set on the RTP data channel. * Return -1 if the send buffer size is not applicable for * the implementation. */ public int getSendBufferSize() { try { return dataSock.getSendBufferSize(); } catch (Exception e) { return -1; } } /** * Return the RTCP bandwidth fraction. This value is used to * initialize the RTPManager. Check RTPManager for more detauls. * Return -1 to use the default values. */ public double getRTCPBandwidthFraction() { return -1; } /** * Return the RTCP sender bandwidth fraction. This value is used to * initialize the RTPManager. Check RTPManager for more detauls. * Return -1 to use the default values. */ public double getRTCPSenderBandwidthFraction() { return -1; } /** * An inner class to implement an OutputDataStream based on UDP sockets. */ class SockOutputStream implements OutputDataStream { DatagramSocket sock; InetAddress addr; int port; public SockOutputStream(DatagramSocket sock, InetAddress addr, int port) { this.sock = sock; this.addr = addr; this.port = port; } public int write(byte data[], int offset, int len) { try { sock.send(new DatagramPacket(data, offset, len, addr, port)); } catch (Exception e) { return -1; } return len; } } /** * An inner class to implement an PushSourceStream based on UDP sockets. */ class SockInputStream extends Thread implements PushSourceStream { DatagramSocket sock; InetAddress addr; int port; boolean done = false; boolean dataRead = false; SourceTransferHandler sth = null; public SockInputStream(DatagramSocket sock, InetAddress addr, int port) { this.sock = sock; this.addr = addr; this.port = port; } public int read(byte buffer[], int offset, int length) { DatagramPacket p = new DatagramPacket(buffer, offset, length, addr, port); try { sock.receive(p); } catch (IOException e) { return -1; } synchronized (this) { dataRead = true; notify(); } return p.getLength(); } public synchronized void start() { super.start(); if (sth != null) { dataRead = true; notify(); } } public synchronized void kill() { done = true; notify(); } public int getMinimumTransferSize() { return 2 * 1024; // twice the MTU size, just to be safe. } public synchronized void setTransferHandler(SourceTransferHandler sth) { this.sth = sth; dataRead = true; notify(); } // Not applicable. public ContentDescriptor getContentDescriptor() { return null; } // Not applicable. public long getContentLength() { return LENGTH_UNKNOWN; } // Not applicable. public boolean endOfStream() { return false; } // Not applicable. public Object[] getControls() { return new Object[0]; } // Not applicable. public Object getControl(String type) { return null; } /** * Loop and notify the transfer handler of new data. */ public void run() { while (!done) { synchronized (this) { while (!dataRead && !done) { try { wait(); } catch (InterruptedException e) { } } dataRead = false; } if (sth != null && !done) { sth.transferData(this); } } } } }
最近下载更多
3263394665 LV9
2023年12月1日
killeroppo LV2
2023年7月31日
laogou LV4
2023年4月4日
jinyu LV2
2022年5月12日
zpf24156 LV1
2022年1月19日
jichenyu LV1
2021年10月12日
leihtg LV1
2021年8月18日
562903829 LV1
2021年5月29日
asdf1122aa LV1
2021年4月6日
zhoucq LV1
2021年2月19日
最近浏览更多
3993zby LV2
11月12日
28128觅北 LV2
5月22日
3334004690 LV10
3月20日
pangzhihui LV14
2023年12月15日
3263394665 LV9
2023年12月1日
killeroppo LV2
2023年7月31日
1529860026 LV24
2023年6月28日
子木Lee LV12
2023年4月10日
laogou LV4
2023年4月4日
athoulen LV2
2023年2月28日