Pessoal,
Meu nome é Rafael e estou com um problema, eu desenvolvi uma aplicação que
transmite video em redes de computadores, essa transmissão é feita via multicast,
o problema é que o video so é visto pelos clientes do mesmo segmento que o
servidor de video. Por exemplo, se o servidor está na rede 192.168.0.0 todos os
computadores dos segmento de rede conseguem ver o video, mas os computadores
que estão no segmento 10.0.0.0, não conseguem ver o video pois o roteador não
consegue fazer o roteamento dos pacotes de video, o codigo fonte é mostrado
abaixo:
import java.awt.*;
import java.io.*;
import java.net.InetAddress;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.protocol.DataSource;
import javax.media.format.*;
import javax.media.control.TrackControl;
import javax.media.control.QualityControl;
import javax.media.rtp.*;
public class Transmit {
private MediaLocator locator;
private String ipAddress;
private int portBase;
private Processor processor = null;
private RTPManager rtpMgrs[];
private DataSource dataOutput = null;
public Transmit(MediaLocator locator, String ipAddress, String pb,
Format format) {
this.locator = locator;
this.ipAddress = ipAddress;
Integer integer = Integer.valueOf(pb);
if (integer != null)
this.portBase = integer.intValue();
}
public synchronized String start() {
String result;
result = createProcessor();
if (result != null)
return result;
result = createTransmitter();
if (result != null) {
processor.close();
processor = null;
return result;
}
processor.start();
return null;
}
public void stop() {
synchronized (this) {
if (processor != null) {
processor.stop();
processor.close();
processor = null;
for (int i = 0; i < rtpMgrs.length; i++) {
rtpMgrs[i].removeTargets("Session ended.");
rtpMgrs[i].dispose();
}
}
}
}
private String createProcessor() {
if (locator == null)
return "Locator is null";
DataSource ds;
try {
ds = javax.media.Manager.createDataSource(locator);
} catch (Exception e) {
return "Couldn't create DataSource";
}
try {
processor = javax.media.Manager.createProcessor(ds);
} catch (NoProcessorException npe) {
return "Couldn't create processor";
} catch (IOException ioe) {
return "IOException creating processor";
}
boolean result = waitForState(processor, Processor.Configured);
if (result == false)
return "Couldn't configure processor";
TrackControl[] tracks = processor.getTrackControls();
if (tracks == null || tracks.length < 1)
return "Couldn't find tracks in processor";
ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
processor.setContentDescriptor(cd);
Format supported[];
Format chosen;
boolean atLeastOneTrack = false;
for (int i = 0; i < tracks.length; i++) {
if (tracks[i].isEnabled()) {
supported = tracks[i].getSupportedFormats();
if (supported.length > 0) {
if (supported[0] instanceof VideoFormat) {
chosen = checkForVideoSizes(tracks[i].getFormat(),
supported[0]);
} else
chosen = supported[0];
tracks[i].setFormat(chosen);
System.err
.println("Track " + i + " is set to transmit as:");
System.err.println(" " + chosen);
atLeastOneTrack = true;
} else
tracks[i].setEnabled(false);
} else
tracks[i].setEnabled(false);
}
if (!atLeastOneTrack)
return "Couldn't set any of the tracks to a valid RTP format";
result = waitForState(processor, Controller.Realized);
if (result == false)
return "Couldn't realize processor";
setJPEGQuality(processor, 0.5f);
dataOutput = processor.getDataOutput();
return null;
}
private String createTransmitter() {
PushBufferDataSource pbds = (PushBufferDataSource) dataOutput;
PushBufferStream pbss[] = pbds.getStreams();
rtpMgrs = new RTPManager[pbss.length];
SendStream sendStream;
int port;
try {
InetAddress ipAddress1 = InetAddress.getByName(ipAddress);
SessionAddress multiAddress = new SessionAddress();
multiAddress.setDataHostAddress(ipAddress1);
for (int i = 0; i < pbss.length; i++) {
rtpMgrs[i] = RTPManager.newInstance();
port = portBase + 2 * i;
rtpMgrs[i].initialize(new RTPSocketAdapter(InetAddress
.getByName(ipAddress), port));
System.err.println("Created RTP session: " + ipAddress + " "
+ port);
multiAddress.setDataPort(port);
rtpMgrs[i].initialize(multiAddress);
sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
sendStream.start();
}
} catch (Exception e) {
return e.getMessage();
}
return null;
}
Format checkForVideoSizes(Format original, Format supported) {
int width, height;
Dimension size = ((VideoFormat) original).getSize();
Format jpegFmt = new Format(VideoFormat.JPEG_RTP);
Format h263Fmt = new Format(VideoFormat.H263_RTP);
if (supported.matches(jpegFmt)) {
width = (size.width % 8 == 0 ? size.width
: (int) (size.width / 8) * 8);
height = (size.height % 8 == 0 ? size.height
: (int) (size.height / 8) * 8);
} else if (supported.matches(h263Fmt)) {
if (size.width < 128) {
width = 128;
height = 96;
} else if (size.width < 176) {
width = 176;
height = 144;
} else {
width = 352;
height = 288;
}
} else {
return supported;
}
return (new VideoFormat(null, new Dimension(width, height),
Format.NOT_SPECIFIED, null, Format.NOT_SPECIFIED))
.intersects(supported);
}
void setJPEGQuality(Player p, float val) {
Control cs[] = p.getControls();
QualityControl qc = null;
VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);
for (int i = 0; i < cs.length; i++) {
if (cs[i] instanceof QualityControl && cs[i] instanceof Owned) {
Object owner = ((Owned) cs[i]).getOwner();
if (owner instanceof Codec) {
Format fmts[] = ((Codec) owner)
.getSupportedOutputFormats(null);
for (int j = 0; j < fmts.length; j++) {
if (fmts[j].matches(jpegFmt)) {
qc = (QualityControl) cs[i];
qc.setQuality(val);
System.err.println("- Setting quality to " + val
+ " on " + qc);
break;
}
}
}
if (qc != null)
break;
}
}
}
private Integer stateLock = new Integer(0);
private boolean failed = false;
Integer getStateLock() {
return stateLock;
}
void setFailed() {
failed = true;
}
private synchronized boolean waitForState(Processor p, int state) {
p.addControllerListener(new StateListener());
failed = false;
if (state == Processor.Configured) {
p.configure();
} else if (state == Processor.Realized) {
p.realize();
}
while (p.getState() < state && !failed) {
synchronized (getStateLock()) {
try {
getStateLock().wait();
} catch (InterruptedException ie) {
return false;
}
}
}
if (failed)
return false;
else
return true;
}
class StateListener implements ControllerListener {
public void controllerUpdate(ControllerEvent ce) {
if (ce instanceof ControllerClosedEvent)
setFailed();
if (ce instanceof ControllerEvent) {
synchronized (getStateLock()) {
getStateLock().notifyAll();
}
}
}
}
}
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;
public class RTPSocketAdapter implements RTPConnector {
MulticastSocket dataSock;
MulticastSocket ctrlSock;
InetAddress addr;
int port;
SockInputStream dataInStrm = null, ctrlInStrm = null;
SockOutputStream dataOutStrm = null, ctrlOutStrm = null;
public RTPSocketAdapter(InetAddress addr, int port) throws IOException {
this(addr, port, 1);
}
public RTPSocketAdapter(InetAddress addr, int port, int ttl)
throws IOException {
try {
dataSock = new MulticastSocket(port);
ctrlSock = new MulticastSocket(port + 1);
dataSock.joinGroup(addr);
dataSock.setTimeToLive(ttl);
ctrlSock.joinGroup(addr);
ctrlSock.setTimeToLive(ttl);
} catch (SocketException e) {
throw new IOException(e.getMessage());
}
this.addr = addr;
this.port = port;
}
public PushSourceStream getDataInputStream() throws IOException {
if (dataInStrm == null) {
dataInStrm = new SockInputStream(dataSock, addr, port);
dataInStrm.start();
}
return dataInStrm;
}
public OutputDataStream getDataOutputStream() throws IOException {
if (dataOutStrm == null)
dataOutStrm = new SockOutputStream(dataSock, addr, port);
return dataOutStrm;
}
public PushSourceStream getControlInputStream() throws IOException {
if (ctrlInStrm == null) {
ctrlInStrm = new SockInputStream(ctrlSock, addr, port + 1);
ctrlInStrm.start();
}
return ctrlInStrm;
}
public OutputDataStream getControlOutputStream() throws IOException {
if (ctrlOutStrm == null)
ctrlOutStrm = new SockOutputStream(ctrlSock, addr, port + 1);
return ctrlOutStrm;
}
public void close() {
if (dataInStrm != null)
dataInStrm.kill();
if (ctrlInStrm != null)
ctrlInStrm.kill();
dataSock.close();
ctrlSock.close();
}
public void setReceiveBufferSize(int size) throws IOException {
dataSock.setReceiveBufferSize(size);
}
public int getReceiveBufferSize() {
try {
return dataSock.getReceiveBufferSize();
} catch (Exception e) {
return -1;
}
}
public void setSendBufferSize(int size) throws IOException {
dataSock.setSendBufferSize(size);
}
public int getSendBufferSize() {
try {
return dataSock.getSendBufferSize();
} catch (Exception e) {
return -1;
}
}
public double getRTCPBandwidthFraction() {
return -1;
}
public double getRTCPSenderBandwidthFraction() {
return -1;
}
class SockOutputStream implements OutputDataStream {
MulticastSocket sock;
InetAddress addr;
int port;
public SockOutputStream(MulticastSocket 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;
}
}
class SockInputStream extends Thread implements PushSourceStream {
MulticastSocket sock;
InetAddress addr;
int port;
boolean done = false;
boolean dataRead = false;
SourceTransferHandler sth = null;
public SockInputStream(MulticastSocket 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;
}
public synchronized void setTransferHandler(SourceTransferHandler sth) {
this.sth = sth;
dataRead = true;
notify();
}
public ContentDescriptor getContentDescriptor() {
return null;
}
public long getContentLength() {
return LENGTH_UNKNOWN;
}
public boolean endOfStream() {
return false;
}
public Object[] getControls() {
return new Object[0];
}
public Object getControl(String type) {
return null;
}
public void run() {
while (!done) {
synchronized (this) {
while (!dataRead && !done) {
try {
wait();
} catch (InterruptedException e) {
}
}
dataRead = false;
}
if (sth != null && !done) {
sth.transferData(this);
}
}
}
}
}