Transmitting audio stream by RTP

Hello:
I am trying to transmit audio stream with this code, but i dont get it work well.
The output is:
C:\RUN\EX14>java AVTransmit2 file:/c:/run/format/au/drip.au 1.1.9.147 45200
Track 0 is set to transmit as:
ULAW/rtp, 8000.0 Hz, 8-bit, Mono, FrameSize=8 bits
Created RTP session: 1.1.9.147 45200
Start transmission for 60 seconds...
Code to AVTransmit2.java:
* Use the RTPManager API to create sessions for each media track of the processor.
private String createTransmitter() {
     // Cheated. Should have checked the type.
     PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
     PushBufferStream pbss[] = pbds.getStreams();
     rtpMgrs = new RTPManager[pbss.length];
     SessionAddress localAddr, destAddr;
     InetAddress ipAddr;
     SendStream sendStream;
     int port;
     SourceDescription srcDesList[];
     for (int i = 0; i < pbss.length; i++) {
     try {
          rtpMgrs[i] = RTPManager.newInstance();     
// The local session address will be created on the
// same port as the the target port. This is necessary
// if you use AVTransmit2 in conjunction with JMStudio.
// JMStudio assumes - in a unicast session - that the
// transmitter transmits from the same port it is receiving
// on and sends RTCP Receiver Reports back to this port of
// the transmitting host.
          port = portBase + 2*i;
          ipAddr = InetAddress.getByName(ipAddress);
          localAddr = new SessionAddress();
//*          InetAddress.getLocalHost(),
//*                                   port);
          destAddr = new SessionAddress( ipAddr,
                              port);
          rtpMgrs.initialize( localAddr);
          rtpMgrs[i].addTarget( destAddr);
          System.err.println( "Created RTP session: " + ipAddress + " " + port);
          sendStream = rtpMgrs[i].createSendStream(dataOutput, i);          
          sendStream.start();
     } catch (Exception e) {
          return e.getMessage();
     return null;
The code receptor is working well, because I tried it with JMStudio.
Why it doesnt transmit ?
I need your greatly help.
Thanks.

What is different from your previous question ?

Similar Messages

  • Problem in transmitting audio stream

    Hi,
    i tried the files AVCustomTrans.java and AVCustomrecv.java file it is working fine if i start the transmission first and the receiver next. but if i start the receiver and then the transmitter it is giving error. Can anybody tell me what the problem might be.

    hey!!
    i am also getting the same problem .....have u got the solution then plz let me know...
    regards,
    sumit

  • How to synchronize audio and video rtp-streams

    Hi everyone!
    I've tried to make one of the processors, processor1, control the other processor, processor2, with processor1.addController(processor2) but I get a
    javax.media.IncompatibleTimeBaseException. I need to synchronize audio and video rtp-streams because they are sometimes completely out of sync.
    In JMF API Guide I've read:
    "2. Determine which Player object's time base is going to be used to drive
    the other Player objects and set the time base for the synchronized
    Player objects. Not all Player objects can assume a new time base.
    For example, if one of the Player objects you want to synchronize has
    a *push-data-source*, that Player object's time base must be used to
    drive the other Player objects."
    I'm using a custom AVReceive3 to receive rtp-streams and then I create processors for the incoming stream's datasource's, and they are ALL PushBufferDataSource's.
    Does this mean I can't synchronize these. If so is there any way I can change them into Pull...DataSources ?
    How are you supposed to sync audio and video if not with as above ?

    camelstrike wrote:
    Hi everyone!
    I've tried to make one of the processors, processor1, control the other processor, processor2, with processor1.addController(processor2) but I get a
    javax.media.IncompatibleTimeBaseException. I need to synchronize audio and video rtp-streams because they are sometimes completely out of sync.
    In JMF API Guide I've read:
    "2. Determine which Player object's time base is going to be used to drive
    the other Player objects and set the time base for the synchronized
    Player objects. Not all Player objects can assume a new time base.
    For example, if one of the Player objects you want to synchronize has
    a *push-data-source*, that Player object's time base must be used to
    drive the other Player objects."
    I'm using a custom AVReceive3 to receive rtp-streams and then I create processors for the incoming stream's datasource's, and they are ALL PushBufferDataSource's.
    Does this mean I can't synchronize these. If so is there any way I can change them into Pull...DataSources ?The RTP packets are timestamped when they leave, and they are played in order. You can't change the timebase on an RTP stream because, for all intensive purposes, it's "live" data. It plays at the speed the transmitting RTP server wants it to play, and it never gets behind because it drops out of order and old data packets.
    If your RTP streams aren't synced correctly on the receiving end, it means they aren't being synced on the transmitting end...so you should look into the other side of the equation.

  • About transmitting audio by RTP

    Hi, there,
    I want to create a simple application that transfers audio online through RTP. both the sender machine and receiver machine have public ip address. I tried JMStudio and AVTransmit2/AVReceiver2 without success till now! it drives me crazy. I really don't know what's wrong here. is there anyone really make it work?
    even I can see the receiver machine keep receiving data through the port I specify to transfer data(the port is 22224), the JMStudio or AVReceiver2 on receiver machine just waiting for data, also I can see the statistic of JMStudio on sender machine reports transfer successful and the data keeping transferred. I also tried to use broadcast way, that is, changing the last part of sender's ip address to 255, still no luck! the receiver can't receive any data!
    since I use Ubuntu, there is no firewall, no port is blocked. I can access from receiver to sender or vice versa using SSH. I don't think there is any connection problem, also I can see the receiver keeping receive data.
    I transfer a mp3 file through RTP session. I installed mp3 plugin on both receiver machine and sender machine. I can play it using JMStudio on both receiver machine and sender machine locally.
    could anyone kindly let me know how I should do, or if there is any very very simple java program to transfer anything using RTP on internet? could you please tell me your configuration if you happen to make it work?
    any hint will great appreciate!
    Sam

    if you have a microphone in your pc, AVTranmit2 and AVReceive2 command should be:
    on your own pc:
    java AVTransmit2 dsound:// targetIP 42050
    on target pc:
    java AVReceive2 yourIP/42050
    since the same port cannot be used simutaneously by two applications(avreceive2 and avtransmit2), the above command can only be used on two different pcs (your pc and target pc).
    if you wanna execute AVReceive2 and AVTransmit2 on the same pc, you have to modify the source codes. I have done that.
    commond
    java AVTransmit2 dsound:// yourip 42050 42100
    java AVReceive2 yourip/42050 yourip/42100
    the modified source files are as follows:
    /*****************AVReceive2.java**********************************/
    * @(#)AVReceive2.java     1.3 01/03/13
    * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
    * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
    * modify and redistribute this software in source and binary code form,
    * provided that i) this copyright notice and license appear on all copies of
    * the software; and ii) Licensee does not utilize the software in a manner
    * which is disparaging to Sun.
    * This software is provided "AS IS," without a warranty of any kind. ALL
    * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
    * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
    * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
    * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
    * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
    * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
    * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
    * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
    * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
    * POSSIBILITY OF SUCH DAMAGES.
    * This software is not designed or intended for use in on-line control of
    * aircraft, air traffic, aircraft navigation or aircraft communications; or in
    * the design, construction, operation or maintenance of any nuclear
    * facility. Licensee represents and warrants that it will not use or
    * redistribute the Software for such purposes.
    import java.io.*;
    import java.awt.*;
    import java.net.*;
    import java.awt.event.*;
    import java.util.Vector;
    import javax.media.*;
    import javax.media.rtp.*;
    import javax.media.rtp.event.*;
    import javax.media.rtp.rtcp.*;
    import javax.media.protocol.*;
    import javax.media.protocol.DataSource;
    import javax.media.format.AudioFormat;
    import javax.media.format.VideoFormat;
    import javax.media.Format;
    import javax.media.format.FormatChangeEvent;
    import javax.media.control.BufferControl;
    * AVReceive2 to receive RTP transmission using the new RTP API.
    public class AVReceive2 implements ReceiveStreamListener, SessionListener,
         ControllerListener
    String sessions[] = null;
    RTPManager mgrs[] = null;
    Vector playerWindows = null;
    boolean dataReceived = false;
    Object dataSync = new Object();
    public AVReceive2(String sessions[]) {
         this.sessions = sessions;
    protected boolean initialize() {
    try {
         InetAddress ipAddr;
         SessionAddress localAddr = new SessionAddress();
         SessionAddress destAddr;
         mgrs = new RTPManager[sessions.length];
         playerWindows = new Vector();
         SessionLabel session;
         // Open the RTP sessions.
         for (int i = 0; i < sessions.length; i++) {
              // Parse the session addresses.
              try {
              session = new SessionLabel(sessions);
              } catch (IllegalArgumentException e) {
              System.err.println("Failed to parse the session address given: " + sessions[i]);
              return false;
              System.err.println(" - Open RTP session for: addr: " + session.addr + " port: " + session.port + " ttl: " + session.ttl);
              mgrs[i] = (RTPManager) RTPManager.newInstance();
              mgrs[i].addSessionListener(this);
              mgrs[i].addReceiveStreamListener(this);
              ipAddr = InetAddress.getByName(session.addr);
              if( ipAddr.isMulticastAddress()) {
              // local and remote address pairs are identical:
              localAddr= new SessionAddress( ipAddr,
                                  session.port,
                                  session.ttl);
              destAddr = new SessionAddress( ipAddr,
                                  session.port,
                                  session.ttl);
              } else {
              localAddr= new SessionAddress( InetAddress.getLocalHost(),
                        42100+2*i);
                             //session.port);
    destAddr = new SessionAddress( ipAddr,
              42050+2*i);
              //session.port);
              mgrs[i].initialize( localAddr);
              // You can try out some other buffer size to see
              // if you can get better smoothness.
              BufferControl bc = (BufferControl)mgrs[i].getControl("javax.media.control.BufferControl");
              if (bc != null)
              bc.setBufferLength(350);
              mgrs[i].addTarget(destAddr);
    } catch (Exception e){
    System.err.println("Cannot create the RTP Session: " + e.getMessage());
    return false;
         // Wait for data to arrive before moving on.
         long then = System.currentTimeMillis();
         long waitingPeriod = 30000; // wait for a maximum of 30 secs.
         try{
         synchronized (dataSync) {
              while (!dataReceived &&
                   System.currentTimeMillis() - then < waitingPeriod) {
              if (!dataReceived)
                   System.err.println(" - Waiting for RTP data to arrive...");
              dataSync.wait(1000);
         } catch (Exception e) {}
         if (!dataReceived) {
         System.err.println("No RTP data was received.");
         close();
         return false;
    return true;
    public boolean isDone() {
         return playerWindows.size() == 0;
    * Close the players and the session managers.
    protected void close() {
         for (int i = 0; i < playerWindows.size(); i++) {
         try {
              ((PlayerWindow)playerWindows.elementAt(i)).close();
         } catch (Exception e) {}
         playerWindows.removeAllElements();
         // close the RTP session.
         for (int i = 0; i < mgrs.length; i++) {
         if (mgrs[i] != null) {
    mgrs[i].removeTargets( "Closing session from AVReceive2");
    mgrs[i].dispose();
              mgrs[i] = null;
    PlayerWindow find(Player p) {
         for (int i = 0; i < playerWindows.size(); i++) {
         PlayerWindow pw = (PlayerWindow)playerWindows.elementAt(i);
         if (pw.player == p)
              return pw;
         return null;
    PlayerWindow find(ReceiveStream strm) {
         for (int i = 0; i < playerWindows.size(); i++) {
         PlayerWindow pw = (PlayerWindow)playerWindows.elementAt(i);
         if (pw.stream == strm)
              return pw;
         return null;
    * SessionListener.
    public synchronized void update(SessionEvent evt) {
         if (evt instanceof NewParticipantEvent) {
         Participant p = ((NewParticipantEvent)evt).getParticipant();
         System.err.println(" - A new participant had just joined: " + p.getCNAME());
    * ReceiveStreamListener
    public synchronized void update( ReceiveStreamEvent evt) {
         RTPManager mgr = (RTPManager)evt.getSource();
         Participant participant = evt.getParticipant();     // could be null.
         ReceiveStream stream = evt.getReceiveStream(); // could be null.
         if (evt instanceof RemotePayloadChangeEvent) {
         System.err.println(" - Received an RTP PayloadChangeEvent.");
         System.err.println("Sorry, cannot handle payload change.");
         System.exit(0);
         else if (evt instanceof NewReceiveStreamEvent) {
         try {
              stream = ((NewReceiveStreamEvent)evt).getReceiveStream();
              DataSource ds = stream.getDataSource();
              // Find out the formats.
              RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
              if (ctl != null){
              System.err.println(" - Recevied new RTP stream: " + ctl.getFormat());
              } else
              System.err.println(" - Recevied new RTP stream");
              if (participant == null)
              System.err.println(" The sender of this stream had yet to be identified.");
              else {
              System.err.println(" The stream comes from: " + participant.getCNAME());
              // create a player by passing datasource to the Media Manager
              Player p = javax.media.Manager.createPlayer(ds);
              if (p == null)
              return;
              p.addControllerListener(this);
              p.realize();
              PlayerWindow pw = new PlayerWindow(p, stream);
              playerWindows.addElement(pw);
              // Notify intialize() that a new stream had arrived.
              synchronized (dataSync) {
              dataReceived = true;
              dataSync.notifyAll();
         } catch (Exception e) {
              System.err.println("NewReceiveStreamEvent exception " + e.getMessage());
              return;
         else if (evt instanceof StreamMappedEvent) {
         if (stream != null && stream.getDataSource() != null) {
              DataSource ds = stream.getDataSource();
              // Find out the formats.
              RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
              System.err.println(" - The previously unidentified stream ");
              if (ctl != null)
              System.err.println(" " + ctl.getFormat());
              System.err.println(" had now been identified as sent by: " + participant.getCNAME());
         else if (evt instanceof ByeEvent) {
         System.err.println(" - Got \"bye\" from: " + participant.getCNAME());
         PlayerWindow pw = find(stream);
         if (pw != null) {
              pw.close();
              playerWindows.removeElement(pw);
    * ControllerListener for the Players.
    public synchronized void controllerUpdate(ControllerEvent ce) {
         Player p = (Player)ce.getSourceController();
         if (p == null)
         return;
         // Get this when the internal players are realized.
         if (ce instanceof RealizeCompleteEvent) {
         PlayerWindow pw = find(p);
         if (pw == null) {
              // Some strange happened.
              System.err.println("Internal error!");
              System.exit(-1);
         pw.initialize();
         pw.setVisible(true);
         p.start();
         if (ce instanceof ControllerErrorEvent) {
         p.removeControllerListener(this);
         PlayerWindow pw = find(p);
         if (pw != null) {
              pw.close();     
              playerWindows.removeElement(pw);
         System.err.println("AVReceive2 internal error: " + ce);
    * A utility class to parse the session addresses.
    class SessionLabel {
         public String addr = null;
         public int port;
         public int ttl = 1;
         SessionLabel(String session) throws IllegalArgumentException {
         int off;
         String portStr = null, ttlStr = null;
         if (session != null && session.length() > 0) {
              while (session.length() > 1 && session.charAt(0) == '/')
              session = session.substring(1);
              // Now see if there's a addr specified.
              off = session.indexOf('/');
              if (off == -1) {
              if (!session.equals(""))
                   addr = session;
              } else {
              addr = session.substring(0, off);
              session = session.substring(off + 1);
              // Now see if there's a port specified
              off = session.indexOf('/');
              if (off == -1) {
                   if (!session.equals(""))
                   portStr = session;
              } else {
                   portStr = session.substring(0, off);
                   session = session.substring(off + 1);
                   // Now see if there's a ttl specified
                   off = session.indexOf('/');
                   if (off == -1) {
                   if (!session.equals(""))
                        ttlStr = session;
                   } else {
                   ttlStr = session.substring(0, off);
         if (addr == null)
              throw new IllegalArgumentException();
         if (portStr != null) {
              try {
              Integer integer = Integer.valueOf(portStr);
              if (integer != null)
                   port = integer.intValue();
              } catch (Throwable t) {
              throw new IllegalArgumentException();
         } else
              throw new IllegalArgumentException();
         if (ttlStr != null) {
              try {
              Integer integer = Integer.valueOf(ttlStr);
              if (integer != null)
                   ttl = integer.intValue();
              } catch (Throwable t) {
              throw new IllegalArgumentException();
    * GUI classes for the Player.
    class PlayerWindow extends Frame {
         Player player;
         ReceiveStream stream;
         PlayerWindow(Player p, ReceiveStream strm) {
         player = p;
         stream = strm;
         public void initialize() {
         add(new PlayerPanel(player));
         public void close() {
         player.close();
         setVisible(false);
         dispose();
         public void addNotify() {
         super.addNotify();
         pack();
    * GUI classes for the Player.
    class PlayerPanel extends Panel {
         Component vc, cc;
         PlayerPanel(Player p) {
         setLayout(new BorderLayout());
         if ((vc = p.getVisualComponent()) != null)
              add("Center", vc);
         if ((cc = p.getControlPanelComponent()) != null)
              add("South", cc);
         public Dimension getPreferredSize() {
         int w = 0, h = 0;
         if (vc != null) {
              Dimension size = vc.getPreferredSize();
              w = size.width;
              h = size.height;
         if (cc != null) {
              Dimension size = cc.getPreferredSize();
              if (w == 0)
              w = size.width;
              h += size.height;
         if (w < 160)
              w = 160;
         return new Dimension(w, h);
    public static void main(String argv[]) {
         if (argv.length == 0)
         prUsage();
         AVReceive2 avReceive = new AVReceive2(argv);
         if (!avReceive.initialize()) {
         System.err.println("Failed to initialize the sessions.");
         System.exit(-1);
         // Check to see if AVReceive2 is done.
         try {
         while (!avReceive.isDone())
              Thread.sleep(1000);
         } catch (Exception e) {}
         System.err.println("Exiting AVReceive2");
    static void prUsage() {
         System.err.println("Usage: AVReceive2 <session> <session> ...");
         System.err.println(" <session>: <address>/<port>/<ttl>");
         System.exit(0);
    }// end of AVReceive2
    /****************************AVTransmit2.java****************************/
    * @(#)AVTransmit2.java     1.4 01/03/13
    * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
    * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
    * modify and redistribute this software in source and binary code form,
    * provided that i) this copyright notice and license appear on all copies of
    * the software; and ii) Licensee does not utilize the software in a manner
    * which is disparaging to Sun.
    * This software is provided "AS IS," without a warranty of any kind. ALL
    * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
    * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
    * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
    * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
    * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
    * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
    * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
    * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
    * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
    * POSSIBILITY OF SUCH DAMAGES.
    * This software is not designed or intended for use in on-line control of
    * aircraft, air traffic, aircraft navigation or aircraft communications; or in
    * the design, construction, operation or maintenance of any nuclear
    * facility. Licensee represents and warrants that it will not use or
    * redistribute the Software for such purposes.
    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.*;
    import javax.media.rtp.rtcp.*;
    import com.sun.media.rtp.*;
    public class AVTransmit2 {
    // Input MediaLocator
    // Can be a file or http or capture source
    private MediaLocator locator;
    private String ipAddress;
    // private int portBase;
         private int localPortBase;
         private int remotePortBase;
    private Processor processor = null;
    private RTPManager rtpMgrs[];
    private DataSource dataOutput = null;
    public AVTransmit2(MediaLocator locator,
                   String ipAddress,
                   String localPB,
                   String remotePB,
                   Format format) {
    Integer int1 = Integer.valueOf(remotePB);
    if(int1 != null)
         this.remotePortBase = int1.intValue();
         this.locator = locator;
         this.ipAddress = ipAddress;
         Integer int2 = Integer.valueOf(localPB);
         if (int2 != null)
         this.localPortBase = int2.intValue();
    * Starts the transmission. Returns null if transmission started ok.
    * Otherwise it returns a string with the reason why the setup failed.
    public synchronized String start() {
         String result;
         // Create a processor for the specified media locator
         // and program it to output JPEG/RTP
         result = createProcessor();
         if (result != null)
         return result;
         // Create an RTP session to transmit the output of the
         // processor to the specified IP address and port no.
         result = createTransmitter();
         if (result != null) {
         processor.close();
         processor = null;
         return result;
         // Start the transmission
         processor.start();
         return null;
    * Stops the transmission if already started
    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;
         DataSource clone;
         try {
         ds = javax.media.Manager.createDataSource(locator);
         } catch (Exception e) {
         return "Couldn't create DataSource";
         // Try to create a processor to handle the input media locator
         try {
         processor = javax.media.Manager.createProcessor(ds);
         } catch (NoProcessorException npe) {
         return "Couldn't create processor";
         } catch (IOException ioe) {
         return "IOException creating processor";
         // Wait for it to configure
         boolean result = waitForState(processor, Processor.Configured);
         if (result == false)
         return "Couldn't configure processor";
         // Get the tracks from the processor
         TrackControl [] tracks = processor.getTrackControls();
         // Do we have atleast one track?
         if (tracks == null || tracks.length < 1)
         return "Couldn't find tracks in processor";
         // 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);
         processor.setContentDescriptor(cd);
         Format supported[];
         Format chosen;
         boolean atLeastOneTrack = false;
         // Program the tracks.
         for (int i = 0; i < tracks.length; i++) {
         Format format = tracks[i].getFormat();
         if (tracks[i].isEnabled()) {
              supported = tracks[i].getSupportedFormats();
              // 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 > 0) {
              if (supported[0] instanceof VideoFormat) {
                   // For video formats, we should double check the
                   // sizes since not all formats work in all sizes.
                   chosen = checkForVideoSizes(tracks[i].getFormat(),
                                       supported[0]);//select the first supported format for convenice
              } 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";
         // Realize the processor. This will internally create a flow
         // graph and attempt to create an output datasource for JPEG/RTP
         // audio frames.
         result = waitForState(processor, Controller.Realized);
         if (result == false)
         return "Couldn't realize processor";
         // Set the JPEG quality to .5.
         setJPEGQuality(processor, 0.5f);//no effect if not JPEG format
         // Get the output data source of the processor
         dataOutput = processor.getDataOutput();
         return null;
    * Use the RTPManager API to create sessions for each media
    * track of the processor.
    private String createTransmitter() {
         // Cheated. Should have checked the type.
         PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
         PushBufferStream pbss[] = pbds.getStreams();
         rtpMgrs = new RTPManager[pbss.length];
         SessionAddress localAddr, destAddr;
         InetAddress ipAddr;
         SendStream sendStream;
         int localPort;
         int remotePort;
         SourceDescription srcDesList[];
         for (int i = 0; i < pbss.length; i++) {
         try {
              rtpMgrs[i] = RTPManager.newInstance();     
              // The local session address will be created on the
              // same port as the the target port. This is necessary
              // if you use AVTransmit2 in conjunction with JMStudio.
              // JMStudio assumes - in a unicast session - that the
              // transmitter transmits from the same port it is receiving
              // on and sends RTCP Receiver Reports back to this port of
              // the transmitting host.
              localPort = localPortBase + 2*i;
              remotePort = remotePortBase + 2*i;
              ipAddr = InetAddress.getByName(ipAddress);
              localAddr = new SessionAddress( InetAddress.getLocalHost(),
                                  localPort);
              destAddr = new SessionAddress( ipAddr, remotePort);
              rtpMgrs[i].initialize( localAddr);
              rtpMgrs[i].addTarget( destAddr);
              System.err.println( "Created RTP session ("+pbss[i].getFormat().getClass() + "):"+localAddr.getControlHostAddress()
                        +":"+localAddr.getDataPort()+"->"+destAddr.getControlHostAddress()+":"+ destAddr.getDataPort());
              sendStream = rtpMgrs[i].createSendStream(dataOutput, i);     
              sendStream.start();
         } catch (Exception e) {
              return e.getMessage();
         return null;
    * For JPEG and H263, we know that they only work for particular
    * sizes. So we'll perform extra checking here to make sure they
    * are of the right sizes.
    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)) {
         // For JPEG, make sure width and height are divisible by 8.
         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)) {
         // For H.263, we only support some specific sizes.
         if (size.width < 128) {
              width = 128;
              height = 96;
         } else if (size.width < 176) {
              width = 176;
              height = 144;
         } else {
              width = 352;
              height = 288;
         } else {
         // We don't know this particular format. We'll just
         // leave it alone then.
         return supported;
         return (new VideoFormat(null,
                        new Dimension(width, height),
                        Format.NOT_SPECIFIED,
                        null,
                        Format.NOT_SPECIFIED)).intersects(supported);
    * Setting the encoding quality to the specified value on the JPEG encoder.
    * 0.5 is a good default.
    void setJPEGQuality(Player p, float val) {
         Control cs[] = p.getControls();
         QualityControl qc = null;
         VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);
         // Loop through the controls to find the Quality control for
         // the JPEG encoder.
         for (int i = 0; i < cs.length; i++) {
         if (cs[i] instanceof QualityControl &&
              cs[i] instanceof Owned) {
              Object owner = ((Owned)cs[i]).getOwner();
              // Check to see if the owner is a Codec.
              // Then check for the output format.
              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;
    * Convenience methods to handle processor's state changes.
    private Integer stateLock = new Integer(0);
    private boolean failed = false;
    Integer getStateLock() {
         return stateLock;
    void setFailed() {
         failed = true;
    private boolean waitForState(Processor p, int state) {
         p.addControllerListener(new StateListener());
         failed = false;
         // Call the required method on the processor
         if (state == Processor.Configured) {
         p.configure();
         } else if (state == Processor.Realized) {
         p.realize();
         // Wait until we get an event that confirms the
         // success of the method, or a failure event.
         // See StateListener inner class
         while (p.getState() < state && !failed) {
         synchronized (getStateLock()) {
              try {
              getStateLock().wait();
              } catch (InterruptedException ie) {
              return false;
         if (failed)
         return false;
         else
         return true;
    * Inner Classes
    class StateListener implements ControllerListener {
         public void controllerUpdate(ControllerEvent ce) {
         // If there was an error during configure or
         // realize, the processor will be closed
         if (ce instanceof ControllerClosedEvent)
              setFailed();
         // All controller events, send a notification
         // to the waiting thread in waitForState method.
         if (ce instanceof ControllerEvent) {
              synchronized (getStateLock()) {
              getStateLock().notifyAll();
    * Sample Usage for AVTransmit2 class
    public static void main(String [] args) {
         // We need three parameters to do the transmission
         // For example,
         // java AVTransmit2 file:/C:/media/test.mov 129.130.131.132 42050
         if (args.length < 3) {
         prUsage();
         Format fmt = null;
         int i = 0;
         MediaLocator ml = new MediaLocator(args[i]);
         // Create a audio transmit object with the specified params.
         AVTransmit2 at = new AVTransmit2(ml,
                             args[i+1], args[i+2], args[i+3], fmt);
         // Start the transmission
         String result = at.start();
         // result will be non-null if there was an error. The return
         // value is a String describing the possible error. Print it.
         if (result != null) {
         System.err.println("Error : " + result);
         System.exit(0);
         System.err.println("Start transmission for 60 seconds...");
         // Transmit for 60 seconds and then close the processor
         // This is a safeguard when using a capture data source
         // so that the capture device will be properly released
         // before quitting.
         // The right thing to do would be to have a GUI with a
         // "Stop" button that would call stop on AVTransmit2
         try {
         Thread.currentThread().sleep(60000);
         } catch (InterruptedException ie) {
         // Stop the transmission
         at.stop();
         System.err.println("...transmission ended.");
         System.exit(0);
    static void prUsage() {
         System.err.println("Usage: AVTransmit2 <sourceURL> <destIP> <destPortBase>");
         System.err.println(" <sourceURL>: input URL or file name");
         System.err.println(" <destIP>: multicast, broadcast or unicast IP address for the transmission");
         System.err.println(" <destPortBase>: network port numbers for the transmission.");
         System.err.println(" The first track will use the destPortBase.");
         System.err.println(" The next track will use destPortBase + 2 and so on.\n");
         System.exit(0);
    if you have any further problems, it's my pleasure to discuss with you.
    [email protected]

  • How to set captured audio stream to be inputstream of socket?

    Hello everyone,
    I am doing a project on Voice Chat Room. I am success to captured the live audio from a microphone and I would like to use socket to tranmit those live audio data. I have the basic knowledge of socket, but I don't know how to set those audio stream to be the inputstream of socket.
    Can you tell me whether it is possible to do this? And can you give me some hints how to do this?
    Cheers!!
    Andrew

    Hi there is code available at http://java.sun.com/products/java-media/jmf/2.1.1/solutions/index.html for capturing and transmiting through RTP the is also a custom protocol impplementation that uses UDP sokets it could be of help.
    Does anyone know how to enable computers behind routers video conference ??
    please mail me at [email protected]
    thanks
    Xerxes

  • Monitoring local transmitted audio

    I use JMF RTP API Manager to send and receive audio streams. I'm using AVTransmit2.java. I worked for the code and When i want to transmit to another machine. Unfortunately on my local computer didn't play the audio, it's not like JM Studio that has monitor audio when audio transmitted. So, what can I do to add this audio mointoring for my transmitted audio file. What must I do? Make antoher player from cloneable datasource, or worked with processor that was on.
    Edited by: 831279 on Apr 1, 2011 1:06 AM

    831279 wrote:
    What must I do? Make antoher player from cloneable datasource, or worked with processor that was on.You can do the clone/player thing (play the clone, btw, not the original datasource)...
    Or you can get the MonitorControl from the processor and use that.
    Or you could add yourself as a target for the RTP stream and then run an instance of AVReceive2 to play the stream...

  • How to merging two audio stream using jmf?

    I have received two rtp audio stream,i want to merging this to one but createMergingDataSource dou work well。please help 。

    You might use an alternative approach: Run exec task and use a external tool to do the encoding.
    You can for example use "The Swiss army knive of Sound" :) SoX: http://sox.sourceforge.net/
    I think from a performance point of view or to handle large files it would be even recommended in using such tools rather then encoding inside your application ... that might be different if you need to do the encoding in real-time ...
    Sebastian

  • Handling Audio streams accross a network

    Hi,
    I have written a Computer Telephony Interface package for a SIP based PBX system and I'm currently exploring the possibility of turning it into a fully functional SIP softphone. The program has a basic SIP stack which I have extended to include the call setup messages, I just need some advice in how I can handle RTP properly.
    The PBX uses G.711 A-law audio codec and I have noticed that the JMF doesn't support type 8 RTP for A-law.
    Here is the scenario, a call comes into the program over the network using a standard Datagram socket, when my program answers the call I can see a load of bytes fired into my system every 20ms (160 bytes audio), I need a solution to convert those bytes into an audio stream and play them through my computer speakers.
    Can anyone give me any guidance on this?
    Thanks
    Brett

    I'm currently doing something similar, and I think this explains a lot
    http://java.sun.com/developer/JDCTechTips/2002/tt0319.html#tip1
    atleast how to play those data bytes as audio and how to do some
    encodings.
    If you're using datagram socket, the packets come in in a random order,
    so doesn't your audio sound a bit weird? Unless you have some mechanism
    to put the packets in correct order.
    kari-matti

  • JMF and audio streams

    Hi all,
    I am writing an application that reads an audio stream and performs some analysis on the audio samples (e.g. detection of dtmf tones). I'd like to be able to write some code that works both on streams from files and from RTP connections (in order to easily write test classes). I made a little test program that reads a wav file with javasound and does some audio analysis.
    public static void main(String[] args)
       AudioInputStream sound = AudioSystem.getAudioInputStream(new File(args[0]));
       int length = (int) sound.getFrameLength();
       for(int i=0; i<length; i++)
          byte[] sample = new byte[2];
          int res = in.read(sample, 0, sample.length);
          if(res != sample.length)
             throw new RuntimeException(
                "Couldn't read a 2 bytes sample from audio stream.");
          if(!in.getFormat().isBigEndian())
             byte tmp = sample[0];
             sample[0] = sample[1];
             sample[1] = tmp;
          DataInputStream ds = new DataInputStream(
             new ByteArrayInputStream(sample));
          goertzel(ds.readShort());
    }Now, I tried to do the same using JMF but I failed. More specific in JMF:
    1) How can I get informations about the stream I'm reading? (e.g. all infos I can get from AudioInputStream's getFormat() method)
    2) Is there a way to get a stream from a DataSource and determine at runtime if the stream is in a particular format I'm expecting, WITHOUT bothering if it is coming form RTP, audio file or something else?
    3) Eventually, Is it hard to use the stream I'm reading to create a new DataSource that some other component will use?

    Sorry but.. I don't know which is the appropriate subclass: I can't find it. I guess you missed "instanceof" in Java 101, eh?
    Moreover I'd like to find a class that is not something like "RTPStream" or "AudioFileInputStream" but something representing just the audio stream itself.There are ways you can get access to the raw data as it flows through the system, but as far as I know, there's no way of gaining random access to the audio stream itself...
    Note that a solution could be to use javasound AudioInputStream class and a simple java rtp library. I could implement my Audio analysis methods in order to work on "abstract streams" (given a particular audio format), then write a test class that work with audio files and a real application that gets input streams from RTP connections.
    I just want to know whether JMF allows me do do that or not?It'd be relatively simple to use JMF to receive an RTP stream and "export" it to JavaSound... you'd just need to write a custom DataSink.

  • Audio stream - record and listen simultaneously

    Hi!
    I would like to record and listen RTP stream simultaneously, but I don't know how... I can record to a file OR listen in headphone but just separately.
    If i create a datasink for recording on a port I cannot use that port to listen. But in this case how can I listen the audio stream on headphone?
    Maybe the good solution would be for me if I could clone the stream but I cannot do, because I get an exception
    javax.media.NoProcessorException: Cannot find a Processor for: com.ibm.media.protocol.CloneablePushBufferDataSource@1d8957fThis is the code:
    DataSource ds = Manager.createCloneableDataSource(Manager.createDataSource(media_locator));
    processor = Manager.createRealizedProcessor(new ProcessorModel(ds, formats, outputType));Has anybody got any idea?
    Thanks!
    Ric Flair

    rflair wrote:
    Thank You, it was not a big help for me...That's too bad. But considering that JavaSound doesn't handle RTP, and all of the code you've posted in JMF code, that doesn't change the fact that it's a JMF question...

  • Transmitting audio and video using JMStudio

    1. Can any one give me the procedure to send audio and video from one system to another using JMStudio .. I am getting an exception like : "Unable to create Session Manager" .. (Note : I used the same Port address on both the systems)
    2. Also in one of the programs for RTP transmission i came across a statement like :
    URL l="rtp://123.12.123.1:5000/audio/1
    123.12.123.1 denotes IP Address to which the data is to be sent..
    5000 is the Port address..
    What does the part "audio/1" mean..
    Thanks in advance..

    Then one more doubt.. Cant we merge the audio and video and then send the merged media through RTP.. Yes! using 'Manager.createMergingDataSource(DataSource[])'
    If we can send then what is that I must use in place of '{color:#ff6600}audio{color}' in
    URL l=rtp://123.12.123.1:15000/audioI am sorry, I don't know...... actually I have never send Audio/Video using rtp-urls, rather I have always used RTPManager. But, yes on the receiver side these rtp urls come in handy and you just have to createPlayer using these rtp MediaLoactors, all locators which I gave in previous reply work for receiver. Perhaps, rtp urls are meant for receiving only, not for transmitting and that makes sense.
    For transmitting I think following code (which is severly stripped down version of AVTransmit2 and written hastily) can help you get started:
    import java.awt.BorderLayout;
    import java.net.InetAddress;
    import javax.media.*;
    import javax.media.control.MonitorControl;
    import javax.media.format.VideoFormat;
    import javax.media.protocol.ContentDescriptor;
    import javax.media.rtp.*;
    import javax.swing.*;
    * @author talha
    public class RTPexp extends JFrame {
        Processor p = null;
        RTPManager manager;
        JPanel jp1, jp2, jp3;
        JButton jb1, jb2;
        public RTPexp() {
            setSize(300,400);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            try {
                jp1 = new JPanel(new BorderLayout());
                jp2 = new JPanel(new BorderLayout());
                jp3 = new JPanel(new BorderLayout());
                this.setContentPane(jp1);
                jb1 = new JButton("Start");
                jb2 = new JButton("Stop");
                jb1.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        jb1ActionPerformed();
                jb2.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        jb2ActionPerformed();
                jp2.add(jb1, BorderLayout.WEST);
                jp2.add(jb2, BorderLayout.EAST);
                jp1.add(jp2, BorderLayout.SOUTH);
                jp1.add(jp3, BorderLayout.CENTER);
                p = Manager.createProcessor(new MediaLocator("vfw://0"));   // video capture device locator
                p.configure();
                Thread.sleep(2000);
                p.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
                p.getTrackControls()[0].setFormat(new VideoFormat(VideoFormat.JPEG_RTP)); //transmitting in Jpeg/rtp, there can be errors here....
                p.realize();
                Thread.sleep(2000);
                manager = RTPManager.newInstance();
                manager.initialize(new SessionAddress(InetAddress.getLocalHost(), SessionAddress.ANY_PORT)); // initializing rtp manager, ANY_PORT allows receiving on the same system
                manager.addTarget(new SessionAddress(InetAddress.getByName("192.168.1.3"), 3000)); // the receivers address and port
                validate();
            } catch (Exception ex) {
                ex.printStackTrace();
        private void jb1ActionPerformed() {
            try {
                p.start();
                SendStream s = manager.createSendStream(p.getDataOutput(), 0);
                s.start();
                MonitorControl mc = (MonitorControl) p.getControl("javax.media.control.MonitorControl");
                Control controls[] = p.getControls();
                boolean flag = false;           // the next statements to search the right monitor control, which happens to be the 2nd one....
                for (int i = 0; i < controls.length; i++) {
                    if (controls[i] instanceof MonitorControl) {
                        if (flag) {
                            mc = (MonitorControl) controls;
    mc.setEnabled(true);
    if (mc.getControlComponent() != null) {
    jp3.add("Center", mc.getControlComponent());
    } else {
    flag = true;
    if (p.getControlPanelComponent() != null) {
    jp3.add(p.getControlPanelComponent(), BorderLayout.SOUTH);
    validate();
    } catch (Exception ex) {
    ex.printStackTrace();
    private void jb2ActionPerformed() {
    p.stop();
    p.close();
    jp3.removeAll();
    jp3.validate();
    public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new
    Runnable() {
    public void run() {
    new RTPexp().setVisible(true);
    Thanks!                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

  • Audio Streaming with NetStream on LCDS or FDS

    Hi. I can't make audio streaming working on FDS neither on
    LCDS. I want to record audio on server.
    When trying to :
    quote:
    new NetStream(this.netConnection);
    i get
    quote:
    01:19:48,140 INFO [STDOUT] [Flex]
    Thread[RTMP-Worker-2,5,jboss]: Closing due to unhandled exception
    in reader thread: java.lang.IndexOutOfBoundsException: Index: 0,
    Size: 0
    at java.util.ArrayList.RangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at
    flex.messaging.io.tcchunk.TCCommand.getArg(TCCommand.java:260)
    at
    flex.messaging.endpoints.rtmp.AbstractRTMPServer.dispatchMessage(AbstractRTMPServer.java: 821)
    at
    flex.messaging.endpoints.rtmp.NIORTMPConnection$RTMPReader.run(NIORTMPConnection.java:424 )
    at
    edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPo olExecutor.java:665)
    at
    edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolEx ecutor.java:690)
    at java.lang.Thread.run(Unknown Source)
    The same code works fine on RED5.
    What's wrong?
    RTMP channel definition is :
    quote:
    <channel-definition id="my-rtmp"
    class="mx.messaging.channels.RTMPChannel">
    <endpoint uri="rtmp://{server.name}:2040"
    class="flex.messaging.endpoints.RTMPEndpoint"/>
    <properties>
    <idle-timeout-minutes>20</idle-timeout-minutes>
    <client-to-server-maxbps>100K</client-to-server-maxbps>
    <server-to-client-maxbps>100K</server-to-client-maxbps>
    </properties>
    </channel-definition>

    There are seeral apps that play music over wifi or 3G
    Pandora, I(heart)music, Bing100, all free,

  • Can I deal with the audio stream while recording?How?

    Hi, All,
    I am doing a project about SIP phone using J2ME. I am quite new to this area. I want to mask the audio stream before it sends out. I want to know if it can be achieved in J2Me. if yes, would you give me some reference? Thanks for any reply.

    Is anyone who knows how to achieve this&#65311;

  • I want to be able to use airplay to stream audio to another iOS device, and then use that audio stream to be used when recording video instead of the built in microphone / microphone input. Is this possible?

    I want to be able to use airplay to stream audio to another iOS device, and then use that audio stream to be used when recording video instead of the built in microphone / microphone input. Is this possible?

    A third-party app probably cannot obtain a stream from another app. To the best of my knowledge, such a capability is not provided in the software development kit, apps being "sandboxed" from each other and so allowed to communicate only in very specific and limited ways.
    I'm not completely sure what you mean by "limitations on video capture". An iPhone, to the best of my knowledge, can natively record video only through it's built-in camera, and audio while doing video recording only through the built-in microphone or mic/headphone jack. There might be a video recording app that would allow audio input from an external device connected to the dock connector, but I'm not sure.
    Regards.

  • Can I use the new Apple TV without a display for audio streaming only?

    Here's my situation...
    I have an Airport Express in my living room connected to my DSL modem to create a wifi network. I also have a current model MacBook Pro and would like to add an Apple TV to my bedroom system for music and Netflix audio streaming. I do not own a TV to do any setup.
    If I bought an ATV for my bedroom and connected the optical output to my DAC, would I be able to accomplish my goal or is there a setup procedure on the ATV which mandates a display?
    I realize I could just buy another Airport Express for easy audio streaming, but then I wouldn't have the Netflix audio capability which I would like since I watch movies on my MBP. I'm hoping like an Airport Express, the ATV would configure itself for audio streaming once connected to my wifi network.
    Thanks for any help or ideas.

    If you're planning to stream from iTunes to the AppleTV controlling the material via iTunes, I suspect it may just appear as an Airtunes speaker option for iTunes without any setup needed.
    No Netflix in UK so don't know much about it, but I suspect you'd need to control the AppleTV directly for this unless you were viewing on the MBP and used something like Rogue Amoeba's Airfoil to transmit audio.
    If you have no desire for controlling AppleTV either on an TV or using Remote app for iPhone etc (and you'd need to set AppleTV up with a TV for Netflix or AppleTV controlled streaming anyway), you might want to consider using another Express upstairs and hook it's optical out to your DAC if you're just after stereo audio.
    AC

Maybe you are looking for