Problema com o roteamento de pacotes de video com JMF em Multicast

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

}

}

}

}

}