title: MP3 won't stream with JMF
body: <p>Basic idea is to access .mp3 file and send it through RTP stream to other client, who will want to play that song.</p>
  
  <p>Here is RTPServer.java, which I found online and modified it to my liking.
  <code></p>
  
  <pre><code>    package server;
  
  import java.net.InetAddress;
  import javax.media.rtp.*;
  import javax.media.rtp.rtcp.*;
  import javax.media.*;
  import javax.media.protocol.*;
  import javax.media.control.*;
  
  public class RTPServer implements ControllerListener, Runnable {
      private boolean realized = false;
      private boolean configured = false;
      private String ipAddress;
      Processor p;
      MediaLocator src;
  
      public static void main (String[] args) {
          RTPServer rtp = new RTPServer("192.168.1.101", "04 - Blue.mp3");
          Thread t = new Thread(rtp);
          t.start();
      }
  
      public RTPServer(String ip, String song) {
          ipAddress = ip;
   String srcFile = "Muzika\\" + song;
   src = new MediaLocator("file:" + srcFile);
  
      }
  
      private void setTrackFormat(Processor p) {
   // Get the tracks from the processor
   TrackControl [] tracks = p.getTrackControls();
   // Do we have atleast one track?
   if (tracks == null || tracks.length &lt; 1) {
       System.out.println("Couldn't find tracks in processor");
       System.exit(1);
   }
  
   // Set the output content descriptor to RAW_RTP
   // This will limit the supported formats reported from
   // Track.getSupportedFormats to only valid RTP formats.
   ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
   p.setContentDescriptor(cd);
  
   Format supported[];
   Format chosen;
   boolean atLeastOneTrack = false;
  
   // Program the tracks.
   for (int i = 0; i &lt; tracks.length; i++) {
       Format format = tracks[i].getFormat();
              System.out.println("Trenutni format je " +format.getEncoding());
       if (tracks[i].isEnabled()) {
    supported = tracks[i].getSupportedFormats();
    for (int n = 0; n &lt; supported.length; n++)
        System.out.println("Supported format: " + supported[n]);
  
    // We've set the output content to the RAW_RTP.
    // So all the supported formats should work with RTP.
    // We'll just pick the first one.
  
    if (supported.length &gt; 0) {
        chosen = supported[0]; // this is where I tried changing formats
        tracks[i].setFormat(chosen);
        System.err.println("Track " + i + " is set to transmit as: " +chosen);
        atLeastOneTrack = true;
    } else
        tracks[i].setEnabled(false);
       } else
    tracks[i].setEnabled(false);
   }
      }
  
      private void transmit(Processor p) {
   try {
       DataSource output = p.getDataOutput();
       PushBufferDataSource pbds = (PushBufferDataSource) output;
       RTPManager rtpMgr = RTPManager.newInstance();
       SessionAddress localAddr, destAddr;
       SendStream sendStream;
       int port = 42050;
       SourceDescription srcDesList[];
       localAddr = new SessionAddress( InetAddress.getLocalHost(), port);
       InetAddress ipAddr = InetAddress.getByName(ipAddress);
       destAddr = new SessionAddress( ipAddr, port);
       rtpMgr.initialize(localAddr);
       rtpMgr.addTarget(destAddr);
       sendStream = rtpMgr.createSendStream(output, 0);
       sendStream.start();
       System.err.println( "Created RTP session: " + ipAddress + " " + port);
       p.start();
   } catch(Exception e) {
       e.printStackTrace();
   }
      }
  
      public synchronized void controllerUpdate(ControllerEvent evt) {
   if (evt instanceof RealizeCompleteEvent) {
       realized = true;
   } else  if (evt instanceof ConfigureCompleteEvent) {
       configured = true;
   } else if (evt instanceof EndOfMediaEvent) {
       System.exit(0);
   } else {
       // System.out.println(evt.toString());
   }
      }
  
      public void run() {
  
   try {
       p = Manager.createProcessor(src);
       p.addControllerListener(this);
       p.configure();
       while (! configured) {
    try {
        Thread.currentThread().sleep(100L);;
    } catch (InterruptedException e) {
        // ignore
    }
       }
  
       setTrackFormat(p);
       p.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
  
       p.realize();
       while (! realized) {
    try {
        Thread.currentThread().sleep(100L);;
    } catch (InterruptedException e) {
        // ignore
    }
       }
       transmit(p);
  
   } catch(Exception e) {
       e.printStackTrace();
       System.exit(1);
   }
      }
  }
  </code></pre>
  
  <p>And here is receiving end, RTPClient:</p>
  
  <pre><code>    package client;
  
  
  import javax.media.*;
  
  public class RTPClient implements ControllerListener, Runnable {
  
      Player p;
      MediaLocator src;
  
      public static void main(String[] args) {
          RTPClient rtp = new RTPClient("192.168.1.100");
          Thread t = new Thread(rtp);
          t.start();
  
      }
  
      public RTPClient(String ip) {
   String srcUrl = "rtp://" + ip + ":42050/audio/1";
   DataSink sink;
   src = new MediaLocator(srcUrl);
      }
      public void run() {
          try {
       p = Manager.createPlayer(src);
       p.addControllerListener(this);
       p.start();
   } catch(Exception e) {
       e.printStackTrace();
       System.exit(1);
   }
      }
  
      public synchronized void controllerUpdate(ControllerEvent evt) {
   if (evt instanceof EndOfMediaEvent) {
       System.exit(0);
   } else {
       System.out.println(evt.toString());
   }
      }
  }  
  </code></pre>
  
  <p>I figured, it successfully sends the whatever file I choose, but when I send .mp3, Client won't play it. I get:</p>
  
  <pre><code>    RTP Handler internal error:
  javax.media.ControllerErrorEvent[source=com.sun.media.content.unknown.Handler@9ed927,message=Internal
  module com.sun.media.BasicRendererModule@1386000: failed to handle a data
  format change!]
  </code></pre>
  
  <p>Interesting thing is, .wav is sent perfectly. So my guess was is the format set prior to sending. And I tried changing format to some other supported format, but then I get bunch of other errors.</p>
  
  <pre>    Failed to build a graph for the given custom options.
  Failed to realize: com.sun.media.ProcessEngine@eee36c
    Cannot build a flow graph with the customized options:
      Unable to transcode format: mpegaudio, 48000.0 Hz, 16-bit, Stereo, LittleEndian, Signed, 20000.0 frame rate, FrameSize=11264 bits
        to: ULAW/rtp, 8000.0 Hz, 8-bit, Stereo
        outputting to: RAW/RTP
  Error: Unable to realize com.sun.media.ProcessEngine@eee36c
  </code></pre>
  
  <p>Finally, I opened JMStudio (the built-in app for sending/receiving media streams in JMF), and when I try to stream .mp3, I get exact same error as when running my app. JMF is set up fine, I checked PATH and CLASSPATH, also I installed mp3plugin which is also setup fine. Everything seems fine, but it just doesn't work! At least .mp3 is not.
  So, how can I make .mp3 "go to the other end"?</p>