blob: 9aefc18ebbb2db565cecba5e668d4275b46a237d [file] [log] [blame]
Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaSession.java (working copy)
@@ -1,92 +0,0 @@
-/**
- * $RCSfile: TestMediaSession.java,v $
- * $Revision: 1.1 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jivesoftware.smackx.jingle.mediaimpl.test;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-/**
- * This Class implements a complete JingleMediaSession for unit testing.
- *
- * @author Thiago Camargo
- */
-public class TestMediaSession extends JingleMediaSession {
-
- /**
- * Creates a TestMediaSession with defined payload type, remote and local candidates
- *
- * @param payloadType Payload of the jmf
- * @param remote the remote information. The candidate that the jmf will be sent to.
- * @param local the local information. The candidate that will receive the jmf
- * @param locator media locator
- */
- public TestMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local,
- final String locator, JingleSession jingleSession) {
- super(payloadType, remote, local, "Test", jingleSession);
- initialize();
- }
-
- /**
- * Initialize the screen share channels.
- */
- public void initialize() {
-
- }
-
- /**
- * Starts transmission and for NAT Traversal reasons start receiving also.
- */
- public void startTrasmit() {
-
- }
-
- /**
- * Set transmit activity. If the active is true, the instance should trasmit.
- * If it is set to false, the instance should pause transmit.
- *
- * @param active active state
- */
- public void setTrasmit(boolean active) {
-
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void startReceive() {
- // Do nothing
- }
-
- /**
- * Stops transmission and for NAT Traversal reasons stop receiving also.
- */
- public void stopTrasmit() {
-
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void stopReceive() {
-
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/test/TestMediaManager.java (working copy)
@@ -1,93 +0,0 @@
-/**
- * $RCSfile: TestMediaManager.java,v $
- * $Revision: 1.3 $
- * $Date: 25/12/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.test;
-
-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-import org.jivesoftware.smackx.jingle.JingleSession;
-
-import java.util.*;
-
-/**
- * Implements a MediaManager for test purposes.
- *
- * @author Thiago Camargo
- */
-
-public class TestMediaManager extends JingleMediaManager {
-
- public static final String MEDIA_NAME = "TestMedia";
-
- private List<PayloadType> payloads = new ArrayList<PayloadType>();
-
- private PayloadType preferredPayloadType = null;
-
- public TestMediaManager(JingleTransportManager transportManager) {
- super(transportManager);
- }
-
- /**
- * Return all supported Payloads for this Manager.
- *
- * @return The Payload List
- */
- public List<PayloadType> getPayloads() {
- return payloads;
- }
-
- public void setPayloads(List<PayloadType> payloads) {
- this.payloads.addAll(payloads);
- }
-
- /**
- * Returns a new JingleMediaSession
- *
- * @param payloadType payloadType
- * @param remote remote Candidate
- * @param local local Candidate
- * @return JingleMediaSession JingleMediaSession
- */
- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote,
- final TransportCandidate local, final JingleSession jingleSession) {
- TestMediaSession session = null;
-
- session = new TestMediaSession(payloadType, remote, local, "", jingleSession);
-
- return session;
- }
-
- public PayloadType getPreferredPayloadType() {
- if (preferredPayloadType != null)
- return preferredPayloadType;
- return super.getPreferredPayloadType();
- }
-
- public void setPreferredPayloadType(PayloadType preferredPayloadType) {
- this.preferredPayloadType = preferredPayloadType;
- }
-
- public String getName() {
- return MEDIA_NAME;
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/JMFInit.java (working copy)
@@ -1,282 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl;
-
-import java.awt.Frame;
-import java.awt.TextArea;
-import java.awt.Toolkit;
-import java.util.Vector;
-
-import javax.media.Format;
-import javax.media.PlugInManager;
-import javax.media.Renderer;
-import javax.media.format.AudioFormat;
-
-import org.jivesoftware.smackx.jingle.SmackLogger;
-
-import com.sun.media.ExclusiveUse;
-import com.sun.media.util.Registry;
-
-public class JMFInit extends Frame implements Runnable {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(JMFInit.class);
-
- private String tempDir = "/tmp";
-
- private boolean done = false;
-
- private String userHome;
-
- private boolean visible = false;
-
- public JMFInit(String[] args, boolean visible) {
- super("Initializing JMF...");
-
- this.visible = visible;
-
- Registry.set("secure.allowCaptureFromApplets", true);
- Registry.set("secure.allowSaveFileFromApplets", true);
-
- updateTemp(args);
-
- try {
- Registry.commit();
- }
- catch (Exception e) {
-
- message("Failed to commit to JMFRegistry!");
- }
-
- Thread detectThread = new Thread(this);
- detectThread.run();
-
- /*
- * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try {
- * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { }
- * slept += 500; }
- *
- * if (!done) { console.error("Detection is taking too long!
- * Aborting!"); message("Detection is taking too long! Aborting!"); }
- *
- * try { Thread.currentThread().sleep(2000); } catch
- * (InterruptedException ie) { }
- */
- }
-
- public void run() {
- detectDirectAudio();
- detectS8DirectAudio();
- detectCaptureDevices();
- done = true;
- }
-
- private void updateTemp(String[] args) {
- if (args != null && args.length > 0) {
- tempDir = args[0];
-
- message("Setting cache directory to " + tempDir);
- Registry r = new Registry();
- try {
- r.set("secure.cacheDir", tempDir);
- r.commit();
-
- message("Updated registry");
- }
- catch (Exception e) {
- message("Couldn't update registry!");
- }
- }
- }
-
- private void detectCaptureDevices() {
- // check if JavaSound capture is available
- message("Looking for Audio capturer");
- Class dsauto;
- try {
- dsauto = Class.forName("DirectSoundAuto");
- dsauto.newInstance();
- message("Finished detecting DirectSound capturer");
- }
- catch (ThreadDeath td) {
- throw td;
- }
- catch (Throwable t) {
- //Do nothing
- }
-
- Class jsauto;
- try {
- jsauto = Class.forName("JavaSoundAuto");
- jsauto.newInstance();
- message("Finished detecting javasound capturer");
- }
- catch (ThreadDeath td) {
- throw td;
- }
- catch (Throwable t) {
- message("JavaSound capturer detection failed!");
- }
-
- /*
- // Check if VFWAuto or SunVideoAuto is available
- message("Looking for video capture devices");
- Class auto = null;
- Class autoPlus = null;
- try {
- auto = Class.forName("VFWAuto");
- }
- catch (Exception e) {
- }
- if (auto == null) {
- try {
- auto = Class.forName("SunVideoAuto");
- }
- catch (Exception ee) {
-
- }
- try {
- autoPlus = Class.forName("SunVideoPlusAuto");
- }
- catch (Exception ee) {
-
- }
- }
- if (auto == null) {
- try {
- auto = Class.forName("V4LAuto");
- }
- catch (Exception ee) {
-
- }
- }
- try {
- Object instance = auto.newInstance();
- if (autoPlus != null) {
- Object instancePlus = autoPlus.newInstance();
- }
-
- message("Finished detecting video capture devices");
- }
- catch (ThreadDeath td) {
- throw td;
- }
- catch (Throwable t) {
-
- message("Capture device detection failed!");
- }
- */
- }
-
- private void detectDirectAudio() {
- Class cls;
- int plType = PlugInManager.RENDERER;
- String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
- try {
- // Check if this is the Windows Performance Pack - hack
- cls = Class.forName("VFWAuto");
- // Check if DS capture is supported, otherwise fail DS renderer
- // since NT doesn't have capture
- cls = Class.forName("com.sun.media.protocol.dsound.DSound");
- // Find the renderer class and instantiate it.
- cls = Class.forName(dar);
-
- Renderer rend = (Renderer) cls.newInstance();
- try {
- // Set the format and open the device
- AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16,
- 2);
- rend.setInputFormat(af);
- rend.open();
- Format[] inputFormats = rend.getSupportedInputFormats();
- // Register the device
- PlugInManager.addPlugIn(dar, inputFormats, new Format[0],
- plType);
- // Move it to the top of the list
- Vector rendList = PlugInManager.getPlugInList(null, null,
- plType);
- int listSize = rendList.size();
- if (rendList.elementAt(listSize - 1).equals(dar)) {
- rendList.removeElementAt(listSize - 1);
- rendList.insertElementAt(dar, 0);
- PlugInManager.setPlugInList(rendList, plType);
- PlugInManager.commit();
- // Log.debug("registered");
- }
- rend.close();
- }
- catch (Throwable t) {
- // Log.debug("Error " + t);
- }
- }
- catch (Throwable tt) {
- //Do nothing
- }
- }
-
- private void detectS8DirectAudio() {
- Class cls;
- int plType = PlugInManager.RENDERER;
- String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
- try {
- // Check if this is the solaris Performance Pack - hack
- cls = Class.forName("SunVideoAuto");
-
- // Find the renderer class and instantiate it.
- cls = Class.forName(dar);
-
- Renderer rend = (Renderer) cls.newInstance();
-
- if (rend instanceof ExclusiveUse
- && !((ExclusiveUse) rend).isExclusive()) {
- // sol8+, DAR supports mixing
- Vector rendList = PlugInManager.getPlugInList(null, null,
- plType);
- int listSize = rendList.size();
- boolean found = false;
- String rname = null;
-
- for (int i = 0; i < listSize; i++) {
- rname = (String) (rendList.elementAt(i));
- if (rname.equals(dar)) { // DAR is in the registry
- found = true;
- rendList.removeElementAt(i);
- break;
- }
- }
-
- if (found) {
- rendList.insertElementAt(dar, 0);
- PlugInManager.setPlugInList(rendList, plType);
- PlugInManager.commit();
- }
- }
- }
- catch (Throwable tt) {
- //Do nothing
- }
- }
-
- private void message(String mesg) {
- LOGGER.debug(mesg);
- }
-
- private void createGUI() {
- TextArea textBox = new TextArea(5, 50);
- add("Center", textBox);
- textBox.setEditable(false);
- addNotify();
- pack();
-
- int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize()
- .getWidth();
- int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize()
- .getHeight();
-
- setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2);
-
- setVisible(visible);
-
- }
-
- public static void start(boolean visible) {
- new JMFInit(null, visible);
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/demo/Demo.java (working copy)
@@ -1,174 +0,0 @@
-/**
- * $RCSfile: Demo.java,v $
- * $Revision: 1.3 $
- * $Date: 28/12/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jivesoftware.smackx.jingle.mediaimpl.demo;
-
-import org.jivesoftware.smack.Connection;
-import org.jivesoftware.smack.XMPPConnection;
-import org.jivesoftware.smack.XMPPException;
-import org.jivesoftware.smackx.jingle.JingleManager;
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.JingleSessionRequest;
-import org.jivesoftware.smackx.jingle.listeners.JingleSessionRequestListener;
-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
-import org.jivesoftware.smackx.jingle.mediaimpl.jspeex.SpeexMediaManager;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.ScreenShareMediaManager;
-import org.jivesoftware.smackx.jingle.nat.ICETransportManager;
-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Jingle Demo Application. It register in a XMPP Server and let users place calls using a full JID and auto-receive calls.
- * Parameters: Server User Pass.
- */
-public class Demo extends JFrame {
-
- private JingleTransportManager transportManager = null;
- private Connection xmppConnection = null;
-
- private String server = null;
- private String user = null;
- private String pass = null;
-
- private JingleManager jm = null;
- private JingleSession incoming = null;
- private JingleSession outgoing = null;
-
- private JTextField jid;
-
- public Demo(String server, String user, String pass) {
-
- this.server = server;
- this.user = user;
- this.pass = pass;
-
- if (user.equals("jeffw")) {
- jid = new JTextField("eowyn" + "@" + server + "/Smack");
- } else {
- jid = new JTextField("jeffw" + "@" + server + "/Smack");
- }
-
- xmppConnection = new XMPPConnection(server);
- try {
- xmppConnection.connect();
- xmppConnection.login(user, pass);
- initialize();
- }
- catch (XMPPException e) {
- e.printStackTrace();
- }
- }
-
- public void initialize() {
- ICETransportManager icetm0 = new ICETransportManager(xmppConnection, "10.47.47.53", 3478);
- List<JingleMediaManager> mediaManagers = new ArrayList<JingleMediaManager>();
- //mediaManagers.add(new JmfMediaManager(icetm0));
- mediaManagers.add(new SpeexMediaManager(icetm0));
- mediaManagers.add(new ScreenShareMediaManager(icetm0));
- jm = new JingleManager(xmppConnection, mediaManagers);
- jm.addCreationListener(icetm0);
-
- jm.addJingleSessionRequestListener(new JingleSessionRequestListener() {
- public void sessionRequested(JingleSessionRequest request) {
-
-// if (incoming != null)
-// return;
-
- try {
- // Accept the call
- incoming = request.accept();
-
- // Start the call
- incoming.startIncoming();
- }
- catch (XMPPException e) {
- e.printStackTrace();
- }
-
- }
- });
- createGUI();
- }
-
- public void createGUI() {
-
- JPanel jPanel = new JPanel();
-
- jPanel.add(jid);
-
- jPanel.add(new JButton(new AbstractAction("Call") {
- public void actionPerformed(ActionEvent e) {
- if (outgoing != null) return;
- try {
- outgoing = jm.createOutgoingJingleSession(jid.getText());
- outgoing.startOutgoing();
- }
- catch (XMPPException e1) {
- e1.printStackTrace();
- }
- }
- }));
-
- jPanel.add(new JButton(new AbstractAction("Hangup") {
- public void actionPerformed(ActionEvent e) {
- if (outgoing != null)
- try {
- outgoing.terminate();
- }
- catch (XMPPException e1) {
- e1.printStackTrace();
- }
- finally {
- outgoing = null;
- }
- if (incoming != null)
- try {
- incoming.terminate();
- }
- catch (XMPPException e1) {
- e1.printStackTrace();
- }
- finally {
- incoming = null;
- }
- }
- }));
-
- this.add(jPanel);
-
- }
-
- public static void main(String args[]) {
-
- Demo demo = null;
-
- if (args.length > 2) {
- demo = new Demo(args[0], args[1], args[2]);
- demo.pack();
- demo.setVisible(true);
- demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- }
-
- }
-
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareSession.java (working copy)
@@ -1,206 +0,0 @@
-/**
- * $RCSfile: ScreenShareSession.java,v $
- * $Revision: 1.2 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare;
-
-import java.awt.Rectangle;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.UnknownHostException;
-
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageReceiver;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageTransmitter;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-/**
- * This Class implements a complete JingleMediaSession.
- * It sould be used to transmit and receive captured images from the Display.
- * This Class should be automaticly controlled by JingleSession.
- * For better NAT Traversal support this implementation don't support only receive or only transmit.
- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
- *
- * @author Thiago Camargo
- */
-public class ScreenShareSession extends JingleMediaSession {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(ScreenShareSession.class);
-
- private ImageTransmitter transmitter = null;
- private ImageReceiver receiver = null;
- private int width = 600;
- private int height = 600;
-
- /**
- * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates
- *
- * @param payloadType Payload of the jmf
- * @param remote the remote information. The candidate that the jmf will be sent to.
- * @param local the local information. The candidate that will receive the jmf
- * @param locator media locator
- */
- public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local,
- final String locator, JingleSession jingleSession) {
- super(payloadType, remote, local, "Screen", jingleSession);
- initialize();
- }
-
- /**
- * Initialize the screen share channels.
- */
- public void initialize() {
-
- JingleSession session = getJingleSession();
- if ((session != null) && (session.getInitiator().equals(session.getConnection().getUser()))) {
- // If the initiator of the jingle session is us then we transmit a screen share.
- try {
- InetAddress remote = InetAddress.getByName(getRemote().getIp());
- transmitter = new ImageTransmitter(new DatagramSocket(getLocal().getPort()), remote, getRemote().getPort(),
- new Rectangle(0, 0, width, height));
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- } else {
- // Otherwise we receive a screen share.
- JFrame window = new JFrame();
- JPanel jp = new JPanel();
- window.add(jp);
-
- window.setLocation(0, 0);
- window.setSize(600, 600);
-
- window.addWindowListener(new WindowAdapter() {
- public void windowClosed(WindowEvent e) {
- receiver.stop();
- }
- });
-
- try {
- receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), width,
- height);
- LOGGER.debug("Receiving on:" + receiver.getLocalPort());
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
-
- jp.add(receiver);
- receiver.setVisible(true);
- window.setAlwaysOnTop(true);
- window.setVisible(true);
- }
- }
-
- /**
- * Starts transmission and for NAT Traversal reasons start receiving also.
- */
- public void startTrasmit() {
- new Thread(transmitter).start();
- }
-
- /**
- * Set transmit activity. If the active is true, the instance should trasmit.
- * If it is set to false, the instance should pause transmit.
- *
- * @param active active state
- */
- public void setTrasmit(boolean active) {
- transmitter.setTransmit(true);
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void startReceive() {
- // Do nothing
- }
-
- /**
- * Stops transmission and for NAT Traversal reasons stop receiving also.
- */
- public void stopTrasmit() {
- if (transmitter != null) {
- transmitter.stop();
- }
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void stopReceive() {
- if (receiver != null) {
- receiver.stop();
- }
- }
-
- /**
- * Obtain a free port we can use.
- *
- * @return A free port number.
- */
- protected int getFreePort() {
- ServerSocket ss;
- int freePort = 0;
-
- for (int i = 0; i < 10; i++) {
- freePort = (int) (10000 + Math.round(Math.random() * 10000));
- freePort = freePort % 2 == 0 ? freePort : freePort + 1;
- try {
- ss = new ServerSocket(freePort);
- freePort = ss.getLocalPort();
- ss.close();
- return freePort;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- try {
- ss = new ServerSocket(0);
- freePort = ss.getLocalPort();
- ss.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return freePort;
- }
-
- public void setEncoder(ImageEncoder encoder) {
- if (encoder != null) {
- this.transmitter.setEncoder(encoder);
- }
- }
-
- public void setDecoder(ImageDecoder decoder) {
- if (decoder != null) {
- this.receiver.setDecoder(decoder);
- }
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageTransmitter.java (working copy)
@@ -1,204 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.AWTException;
-import java.awt.Rectangle;
-import java.awt.Robot;
-import java.awt.image.BufferedImage;
-import java.awt.image.PixelGrabber;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.util.Arrays;
-
-import org.jivesoftware.smackx.jingle.SmackLogger;
-
-/**
- * UDP Image Receiver.
- * It uses PNG Tiles into UDP packets.
- *
- * @author Thiago Rocha Camargo
- */
-public class ImageTransmitter implements Runnable {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(ImageTransmitter.class);
-
- private Robot robot;
- private InetAddress localHost;
- private InetAddress remoteHost;
- private int localPort;
- private int remotePort;
- public static final int tileWidth = 25;
- private boolean on = true;
- private boolean transmit = false;
- private DatagramSocket socket;
- private Rectangle area;
- private int tiles[][][];
- private int maxI;
- private int maxJ;
- private ImageEncoder encoder;
- public final static int KEYFRAME = 10;
-
- public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) {
-
- try {
- robot = new Robot();
-
- maxI = (int) Math.ceil(area.getWidth() / tileWidth);
- maxJ = (int) Math.ceil(area.getHeight() / tileWidth);
-
- tiles = new int[maxI][maxJ][tileWidth * tileWidth];
-
- this.area = area;
- this.socket = socket;
- localHost = socket.getLocalAddress();
- localPort = socket.getLocalPort();
- this.remoteHost = remoteHost;
- this.remotePort = remotePort;
- this.encoder = new DefaultEncoder();
-
- transmit = true;
-
- }
- catch (AWTException e) {
- e.printStackTrace();
- }
-
- }
-
- public void start() {
- byte buf[] = new byte[1024];
- final DatagramPacket p = new DatagramPacket(buf, 1024);
-
- int keyframe = 0;
-
- while (on) {
- if (transmit) {
-
- BufferedImage capture = robot.createScreenCapture(area);
-
- QuantizeFilter filter = new QuantizeFilter();
- capture = filter.filter(capture, null);
-
- long trace = System.currentTimeMillis();
-
- if (++keyframe > KEYFRAME) {
- keyframe = 0;
- }
- LOGGER.debug("KEYFRAME:" + keyframe);
-
- for (int i = 0; i < maxI; i++) {
- for (int j = 0; j < maxJ; j++) {
-
- final BufferedImage bufferedImage = capture.getSubimage(i * tileWidth, j * tileWidth, tileWidth, tileWidth);
-
- int pixels[] = new int[tileWidth * tileWidth];
-
- PixelGrabber pg = new PixelGrabber(bufferedImage, 0, 0, tileWidth, tileWidth, pixels, 0, tileWidth);
-
- try {
- if (pg.grabPixels()) {
-
- if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) {
-
- ByteArrayOutputStream baos = encoder.encode(bufferedImage);
-
- if (baos != null) {
-
- try {
-
- Thread.sleep(1);
-
- baos.write(i);
- baos.write(j);
-
- byte[] bytesOut = baos.toByteArray();
-
- if (bytesOut.length > 1000)
- LOGGER.error("Bytes out > 1000. Equals " + bytesOut.length);
-
- p.setData(bytesOut);
- p.setAddress(remoteHost);
- p.setPort(remotePort);
-
- try {
- socket.send(p);
- }
- catch (IOException e) {
- e.printStackTrace();
- }
-
- tiles[i][j] = pixels;
-
- }
- catch (Exception e) {
- }
-
- }
-
- }
-
- }
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- trace = (System.currentTimeMillis() - trace);
- LOGGER.debug("Loop Time:" + trace);
-
- if (trace < 500) {
- try {
- Thread.sleep(500 - trace);
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- }
-
- public void run() {
- start();
- }
-
- /**
- * Set Transmit Enabled/Disabled
- *
- * @param transmit boolean Enabled/Disabled
- */
- public void setTransmit(boolean transmit) {
- this.transmit = transmit;
- }
-
- /**
- * Get the encoder used to encode Images Tiles
- *
- * @return encoder
- */
- public ImageEncoder getEncoder() {
- return encoder;
- }
-
- /**
- * Set the encoder used to encode Image Tiles
- *
- * @param encoder encoder
- */
- public void setEncoder(ImageEncoder encoder) {
- this.encoder = encoder;
- }
-
- /**
- * Stops Transmitter
- */
- public void stop() {
- this.transmit = false;
- this.on = false;
- socket.close();
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageEncoder.java (working copy)
@@ -1,13 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-
-/**
- * Image Encoder Interface use this interface if you want to change the default encoder
- *
- * @author Thiago Rocha Camargo
- */
-public interface ImageEncoder {
- public ByteArrayOutputStream encode(BufferedImage bufferedImage);
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/PixelUtils.java (working copy)
@@ -1,223 +0,0 @@
-/*
-Copyright 2006 Jerry Huxtable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.*;
-import java.util.Random;
-
-/**
- * Some more useful math functions for image processing.
- * These are becoming obsolete as we move to Java2D. Use MiscComposite instead.
- */
-public class PixelUtils {
-
- public final static int REPLACE = 0;
- public final static int NORMAL = 1;
- public final static int MIN = 2;
- public final static int MAX = 3;
- public final static int ADD = 4;
- public final static int SUBTRACT = 5;
- public final static int DIFFERENCE = 6;
- public final static int MULTIPLY = 7;
- public final static int HUE = 8;
- public final static int SATURATION = 9;
- public final static int VALUE = 10;
- public final static int COLOR = 11;
- public final static int SCREEN = 12;
- public final static int AVERAGE = 13;
- public final static int OVERLAY = 14;
- public final static int CLEAR = 15;
- public final static int EXCHANGE = 16;
- public final static int DISSOLVE = 17;
- public final static int DST_IN = 18;
- public final static int ALPHA = 19;
- public final static int ALPHA_TO_GRAY = 20;
-
- private static Random randomGenerator = new Random();
-
- /**
- * Clamp a value to the range 0..255
- */
- public static int clamp(int c) {
- if (c < 0)
- return 0;
- if (c > 255)
- return 255;
- return c;
- }
-
- public static int interpolate(int v1, int v2, float f) {
- return clamp((int)(v1+f*(v2-v1)));
- }
-
- public static int brightness(int rgb) {
- int r = (rgb >> 16) & 0xff;
- int g = (rgb >> 8) & 0xff;
- int b = rgb & 0xff;
- return (r+g+b)/3;
- }
-
- public static boolean nearColors(int rgb1, int rgb2, int tolerance) {
- int r1 = (rgb1 >> 16) & 0xff;
- int g1 = (rgb1 >> 8) & 0xff;
- int b1 = rgb1 & 0xff;
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
- return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance;
- }
-
- private final static float hsb1[] = new float[3];//FIXME-not thread safe
- private final static float hsb2[] = new float[3];//FIXME-not thread safe
-
- // Return rgb1 painted onto rgb2
- public static int combinePixels(int rgb1, int rgb2, int op) {
- return combinePixels(rgb1, rgb2, op, 0xff);
- }
-
- public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha, int channelMask) {
- return (rgb2 & ~channelMask) | combinePixels(rgb1 & channelMask, rgb2, op, extraAlpha);
- }
-
- public static int combinePixels(int rgb1, int rgb2, int op, int extraAlpha) {
- if (op == REPLACE)
- return rgb1;
- int a1 = (rgb1 >> 24) & 0xff;
- int r1 = (rgb1 >> 16) & 0xff;
- int g1 = (rgb1 >> 8) & 0xff;
- int b1 = rgb1 & 0xff;
- int a2 = (rgb2 >> 24) & 0xff;
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
-
- switch (op) {
- case NORMAL:
- break;
- case MIN:
- r1 = Math.min(r1, r2);
- g1 = Math.min(g1, g2);
- b1 = Math.min(b1, b2);
- break;
- case MAX:
- r1 = Math.max(r1, r2);
- g1 = Math.max(g1, g2);
- b1 = Math.max(b1, b2);
- break;
- case ADD:
- r1 = clamp(r1+r2);
- g1 = clamp(g1+g2);
- b1 = clamp(b1+b2);
- break;
- case SUBTRACT:
- r1 = clamp(r2-r1);
- g1 = clamp(g2-g1);
- b1 = clamp(b2-b1);
- break;
- case DIFFERENCE:
- r1 = clamp(Math.abs(r1-r2));
- g1 = clamp(Math.abs(g1-g2));
- b1 = clamp(Math.abs(b1-b2));
- break;
- case MULTIPLY:
- r1 = clamp(r1*r2/255);
- g1 = clamp(g1*g2/255);
- b1 = clamp(b1*b2/255);
- break;
- case DISSOLVE:
- if ((randomGenerator.nextInt() & 0xff) <= a1) {
- r1 = r2;
- g1 = g2;
- b1 = b2;
- }
- break;
- case AVERAGE:
- r1 = (r1+r2)/2;
- g1 = (g1+g2)/2;
- b1 = (b1+b2)/2;
- break;
- case HUE:
- case SATURATION:
- case VALUE:
- case COLOR:
- Color.RGBtoHSB(r1, g1, b1, hsb1);
- Color.RGBtoHSB(r2, g2, b2, hsb2);
- switch (op) {
- case HUE:
- hsb2[0] = hsb1[0];
- break;
- case SATURATION:
- hsb2[1] = hsb1[1];
- break;
- case VALUE:
- hsb2[2] = hsb1[2];
- break;
- case COLOR:
- hsb2[0] = hsb1[0];
- hsb2[1] = hsb1[1];
- break;
- }
- rgb1 = Color.HSBtoRGB(hsb2[0], hsb2[1], hsb2[2]);
- r1 = (rgb1 >> 16) & 0xff;
- g1 = (rgb1 >> 8) & 0xff;
- b1 = rgb1 & 0xff;
- break;
- case SCREEN:
- r1 = 255 - ((255 - r1) * (255 - r2)) / 255;
- g1 = 255 - ((255 - g1) * (255 - g2)) / 255;
- b1 = 255 - ((255 - b1) * (255 - b2)) / 255;
- break;
- case OVERLAY:
- int m, s;
- s = 255 - ((255 - r1) * (255 - r2)) / 255;
- m = r1 * r2 / 255;
- r1 = (s * r1 + m * (255 - r1)) / 255;
- s = 255 - ((255 - g1) * (255 - g2)) / 255;
- m = g1 * g2 / 255;
- g1 = (s * g1 + m * (255 - g1)) / 255;
- s = 255 - ((255 - b1) * (255 - b2)) / 255;
- m = b1 * b2 / 255;
- b1 = (s * b1 + m * (255 - b1)) / 255;
- break;
- case CLEAR:
- r1 = g1 = b1 = 0xff;
- break;
- case DST_IN:
- r1 = clamp((r2*a1)/255);
- g1 = clamp((g2*a1)/255);
- b1 = clamp((b2*a1)/255);
- a1 = clamp((a2*a1)/255);
- return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;
- case ALPHA:
- a1 = a1*a2/255;
- return (a1 << 24) | (r2 << 16) | (g2 << 8) | b2;
- case ALPHA_TO_GRAY:
- int na = 255-a1;
- return (a1 << 24) | (na << 16) | (na << 8) | na;
- }
- if (extraAlpha != 0xff || a1 != 0xff) {
- a1 = a1*extraAlpha/255;
- int a3 = (255-a1)*a2/255;
- r1 = clamp((r1*a1+r2*a3)/255);
- g1 = clamp((g1*a1+g2*a3)/255);
- b1 = clamp((b1*a1+b2*a3)/255);
- a1 = clamp(a1+a3);
- }
- return (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;
- }
-
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/Quantizer.java (working copy)
@@ -1,53 +0,0 @@
-/*
-Copyright 2006 Jerry Huxtable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-/**
- * The interface for an image quantizer. The addColor method is called (repeatedly
- * if necessary) with all the image pixels. A color table can then be returned by
- * calling the buildColorTable method.
- */
-public interface Quantizer {
- /**
- * Initialize the quantizer. This should be called before adding any pixels.
- * @param numColors the number of colors we're quantizing to.
- */
- public void setup(int numColors);
-
- /**
- * Add pixels to the quantizer.
- * @param pixels the array of ARGB pixels
- * @param offset the offset into the array
- * @param count the count of pixels
- */
- public void addPixels(int[] pixels, int offset, int count);
-
- /**
- * Build a color table from the added pixels.
- * @return an array of ARGB pixels representing a color table
- */
- public int[] buildColorTable();
-
- /**
- * Using the previously-built color table, return the index into that table for a pixel.
- * This is guaranteed to return a valid index - returning the index of a color closer
- * to that requested if necessary.
- * @param rgb the pixel to find
- * @return the pixel's index in the color table
- */
- public int getIndexForColor(int rgb);
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultEncoder.java (working copy)
@@ -1,24 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-/**
- * Implements a default PNG Encoder
- */
-public class DefaultEncoder implements ImageEncoder{
-
- public ByteArrayOutputStream encode(BufferedImage bufferedImage) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try {
- ImageIO.write(bufferedImage, "png", baos);
- }
- catch (IOException e) {
- e.printStackTrace();
- baos = null;
- }
- return baos;
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/QuantizeFilter.java (working copy)
@@ -1,178 +0,0 @@
-/*
-Copyright 2006 Jerry Huxtable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.*;
-
-/**
- * A filter which quantizes an image to a set number of colors - useful for producing
- * images which are to be encoded using an index color model. The filter can perform
- * Floyd-Steinberg error-diffusion dithering if required. At present, the quantization
- * is done using an octtree algorithm but I eventually hope to add more quantization
- * methods such as median cut. Note: at present, the filter produces an image which
- * uses the RGB color model (because the application it was written for required it).
- * I hope to extend it to produce an IndexColorModel by request.
- */
-public class QuantizeFilter extends WholeImageFilter {
-
- /**
- * Floyd-Steinberg dithering matrix.
- */
- protected final static int[] matrix = {
- 0, 0, 0,
- 0, 0, 7,
- 3, 5, 1,
- };
- private int sum = 3+5+7+1;
-
- private boolean dither;
- private int numColors = 256;
- private boolean serpentine = true;
-
- /**
- * Set the number of colors to quantize to.
- * @param numColors the number of colors. The default is 256.
- */
- public void setNumColors(int numColors) {
- this.numColors = Math.min(Math.max(numColors, 8), 256);
- }
-
- /**
- * Get the number of colors to quantize to.
- * @return the number of colors.
- */
- public int getNumColors() {
- return numColors;
- }
-
- /**
- * Set whether to use dithering or not. If not, the image is posterized.
- * @param dither true to use dithering
- */
- public void setDither(boolean dither) {
- this.dither = dither;
- }
-
- /**
- * Return the dithering setting
- * @return the current setting
- */
- public boolean getDither() {
- return dither;
- }
-
- /**
- * Set whether to use a serpentine pattern for return or not. This can reduce 'avalanche' artifacts in the output.
- * @param serpentine true to use serpentine pattern
- */
- public void setSerpentine(boolean serpentine) {
- this.serpentine = serpentine;
- }
-
- /**
- * Return the serpentine setting
- * @return the current setting
- */
- public boolean getSerpentine() {
- return serpentine;
- }
-
- public void quantize(int[] inPixels, int[] outPixels, int width, int height, int numColors, boolean dither, boolean serpentine) {
- int count = width*height;
- Quantizer quantizer = new OctTreeQuantizer();
- quantizer.setup(numColors);
- quantizer.addPixels(inPixels, 0, count);
- int[] table = quantizer.buildColorTable();
-
- if (!dither) {
- for (int i = 0; i < count; i++)
- outPixels[i] = table[quantizer.getIndexForColor(inPixels[i])];
- } else {
- int index = 0;
- for (int y = 0; y < height; y++) {
- boolean reverse = serpentine && (y & 1) == 1;
- int direction;
- if (reverse) {
- index = y*width+width-1;
- direction = -1;
- } else {
- index = y*width;
- direction = 1;
- }
- for (int x = 0; x < width; x++) {
- int rgb1 = inPixels[index];
- int rgb2 = table[quantizer.getIndexForColor(rgb1)];
-
- outPixels[index] = rgb2;
-
- int r1 = (rgb1 >> 16) & 0xff;
- int g1 = (rgb1 >> 8) & 0xff;
- int b1 = rgb1 & 0xff;
-
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
-
- int er = r1-r2;
- int eg = g1-g2;
- int eb = b1-b2;
-
- for (int i = -1; i <= 1; i++) {
- int iy = i+y;
- if (0 <= iy && iy < height) {
- for (int j = -1; j <= 1; j++) {
- int jx = j+x;
- if (0 <= jx && jx < width) {
- int w;
- if (reverse)
- w = matrix[(i+1)*3-j+1];
- else
- w = matrix[(i+1)*3+j+1];
- if (w != 0) {
- int k = reverse ? index - j : index + j;
- rgb1 = inPixels[k];
- r1 = (rgb1 >> 16) & 0xff;
- g1 = (rgb1 >> 8) & 0xff;
- b1 = rgb1 & 0xff;
- r1 += er * w/sum;
- g1 += eg * w/sum;
- b1 += eb * w/sum;
- inPixels[k] = (PixelUtils.clamp(r1) << 16) | (PixelUtils.clamp(g1) << 8) | PixelUtils.clamp(b1);
- }
- }
- }
- }
- }
- index += direction;
- }
- }
- }
- }
-
- protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
- int[] outPixels = new int[width*height];
-
- quantize(inPixels, outPixels, width, height, numColors, dither, serpentine);
-
- return outPixels;
- }
-
- public String toString() {
- return "Colors/Quantize...";
- }
-
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageReceiver.java (working copy)
@@ -1,150 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.SocketException;
-
-/**
- * UDP Image Receiver.
- * It uses PNG Tiles into UDP packets.
- *
- * @author Thiago Rocha Camargo
- */
-public class ImageReceiver extends Canvas {
-
- private boolean on = true;
- private DatagramSocket socket;
- private BufferedImage tiles[][];
- private static final int tileWidth = ImageTransmitter.tileWidth;
- private InetAddress localHost;
- private InetAddress remoteHost;
- private int localPort;
- private int remotePort;
- private ImageDecoder decoder;
-
- public ImageReceiver(final InetAddress remoteHost, final int remotePort, final int localPort, int width, int height) {
- tiles = new BufferedImage[width][height];
-
- try {
-
- socket = new DatagramSocket(localPort);
- localHost = socket.getLocalAddress();
- this.remoteHost = remoteHost;
- this.remotePort = remotePort;
- this.localPort = localPort;
- this.decoder = new DefaultDecoder();
-
- new Thread(new Runnable() {
- public void run() {
- byte buf[] = new byte[1024];
- DatagramPacket p = new DatagramPacket(buf, 1024);
- try {
- while (on) {
- socket.receive(p);
-
- int length = p.getLength();
-
- BufferedImage bufferedImage = decoder.decode(new ByteArrayInputStream(p.getData(), 0, length - 2));
-
- if (bufferedImage != null) {
-
- int x = p.getData()[length - 2];
- int y = p.getData()[length - 1];
-
- drawTile(x, y, bufferedImage);
-
- }
-
- }
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- }).start();
-
- new Thread(new Runnable() {
- public void run() {
- byte buf[] = new byte[1024];
- DatagramPacket p = new DatagramPacket(buf, 1024);
- try {
- while (on) {
-
- p.setAddress(remoteHost);
- p.setPort(remotePort);
- socket.send(p);
-
- try {
- Thread.sleep(1000);
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- }
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- }).start();
-
- }
- catch (SocketException e) {
- e.printStackTrace();
- }
- this.setSize(width, height);
- }
-
- public InetAddress getLocalHost() {
- return localHost;
- }
-
- public InetAddress getRemoteHost() {
- return remoteHost;
- }
-
- public int getLocalPort() {
- return localPort;
- }
-
- public int getRemotePort() {
- return remotePort;
- }
-
- public DatagramSocket getDatagramSocket() {
- return socket;
- }
-
- public void drawTile(int x, int y, BufferedImage bufferedImage) {
- tiles[x][y] = bufferedImage;
- //repaint(x * tileWidth, y * tileWidth, tileWidth, tileWidth);
- this.getGraphics().drawImage(bufferedImage, tileWidth * x, tileWidth * y, this);
- }
-
- public void paint(Graphics g) {
- for (int i = 0; i < tiles.length; i++) {
- for (int j = 0; j < tiles[0].length; j++) {
- g.drawImage(tiles[i][j], tileWidth * i, tileWidth * j, this);
- }
- }
- }
-
- public ImageDecoder getDecoder() {
- return decoder;
- }
-
- public void setDecoder(ImageDecoder decoder) {
- this.decoder = decoder;
- }
-
- public void stop(){
- this.on=false;
- socket.close();
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/WholeImageFilter.java (working copy)
@@ -1,86 +0,0 @@
-/*
-Copyright 2006 Jerry Huxtable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.WritableRaster;
-
-/**
- * A filter which acts as a superclass for filters which need to have the whole image in memory
- * to do their stuff.
- */
-public abstract class WholeImageFilter extends AbstractBufferedImageOp {
-
- /**
- * The output image bounds.
- */
- protected Rectangle transformedSpace;
-
- /**
- * The input image bounds.
- */
- protected Rectangle originalSpace;
-
- /**
- * Construct a WholeImageFilter.
- */
- public WholeImageFilter() {
- }
-
- public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
- int width = src.getWidth();
- int height = src.getHeight();
- int type = src.getType();
- WritableRaster srcRaster = src.getRaster();
-
- originalSpace = new Rectangle(0, 0, width, height);
- transformedSpace = new Rectangle(0, 0, width, height);
- transformSpace(transformedSpace);
-
- if ( dst == null ) {
- ColorModel dstCM = src.getColorModel();
- dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height), dstCM.isAlphaPremultiplied(), null);
- }
- WritableRaster dstRaster = dst.getRaster();
-
- int[] inPixels = getRGB( src, 0, 0, width, height, null );
- inPixels = filterPixels( width, height, inPixels, transformedSpace );
- setRGB( dst, 0, 0, transformedSpace.width, transformedSpace.height, inPixels );
-
- return dst;
- }
-
- /**
- * Calculate output bounds for given input bounds.
- * @param rect input and output rectangle
- */
- protected void transformSpace(Rectangle rect) {
- }
-
- /**
- * Actually filter the pixels.
- * @param width the image width
- * @param height the image height
- * @param inPixels the image pixels
- * @param transformedSpace the output bounds
- * @return the output pixels
- */
- protected abstract int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace );
-}
-
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/AbstractBufferedImageOp.java (working copy)
@@ -1,98 +0,0 @@
-/*
-Copyright 2006 Jerry Huxtable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.*;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorModel;
-
-/**
- * A convenience class which implements those methods of BufferedImageOp which are rarely changed.
- */
-public abstract class AbstractBufferedImageOp implements BufferedImageOp, Cloneable {
-
- public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
- if ( dstCM == null )
- dstCM = src.getColorModel();
- return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);
- }
-
- public Rectangle2D getBounds2D( BufferedImage src ) {
- return new Rectangle(0, 0, src.getWidth(), src.getHeight());
- }
-
- public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) {
- if ( dstPt == null )
- dstPt = new Point2D.Double();
- dstPt.setLocation( srcPt.getX(), srcPt.getY() );
- return dstPt;
- }
-
- public RenderingHints getRenderingHints() {
- return null;
- }
-
- /**
- * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance
- * penalty of BufferedImage.getRGB unmanaging the image.
- * @param image a BufferedImage object
- * @param x the left edge of the pixel block
- * @param y the right edge of the pixel block
- * @param width the width of the pixel arry
- * @param height the height of the pixel arry
- * @param pixels the array to hold the returned pixels. May be null.
- * @return the pixels
- * @see #setRGB
- */
- public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
- int type = image.getType();
- if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
- return (int [])image.getRaster().getDataElements( x, y, width, height, pixels );
- return image.getRGB( x, y, width, height, pixels, 0, width );
- }
-
- /**
- * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance
- * penalty of BufferedImage.setRGB unmanaging the image.
- * @param image a BufferedImage object
- * @param x the left edge of the pixel block
- * @param y the right edge of the pixel block
- * @param width the width of the pixel arry
- * @param height the height of the pixel arry
- * @param pixels the array of pixels to set
- * @see #getRGB
- */
- public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
- int type = image.getType();
- if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
- image.getRaster().setDataElements( x, y, width, height, pixels );
- else
- image.setRGB( x, y, width, height, pixels, 0, width );
- }
-
- public Object clone() {
- try {
- return super.clone();
- }
- catch ( CloneNotSupportedException e ) {
- return null;
- }
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/ImageDecoder.java (working copy)
@@ -1,15 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-
-/**
- * Image Decoder Interface use this interface if you want to change the default decoder
- *
- * @author Thiago Rocha Camargo
- */
-public interface ImageDecoder {
-
- public BufferedImage decode(ByteArrayInputStream stream) throws IOException;
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/OctTreeQuantizer.java (working copy)
@@ -1,287 +0,0 @@
-/*
-Copyright 2006 Jerry Huxtable
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import java.io.PrintStream;
-import java.util.Vector;
-
-import org.jivesoftware.smackx.jingle.SmackLogger;
-
-/**
- * An image Quantizer based on the Octree algorithm. This is a very basic implementation
- * at present and could be much improved by picking the nodes to reduce more carefully
- * (i.e. not completely at random) when I get the time.
- */
-public class OctTreeQuantizer implements Quantizer {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(OctTreeQuantizer.class);
-
- /**
- * The greatest depth the tree is allowed to reach
- */
- final static int MAX_LEVEL = 5;
-
- /**
- * An Octtree node.
- */
- class OctTreeNode {
- int children;
- int level;
- OctTreeNode parent;
- OctTreeNode leaf[] = new OctTreeNode[8];
- boolean isLeaf;
- int count;
- int totalRed;
- int totalGreen;
- int totalBlue;
- int index;
-
- /**
- * A debugging method which prints the tree out.
- */
- public void list(PrintStream s, int level) {
- String indentStr = "";
- for (int i = 0; i < level; i++)
- indentStr += " ";
- if (count == 0)
- LOGGER.debug(indentStr + index + ": count=" + count);
- else
- LOGGER.debug(indentStr + index + ": count=" + count + " red=" + (totalRed/count) + " green=" + (totalGreen / count) + " blue=" + (totalBlue / count));
- for (int i = 0; i < 8; i++)
- if (leaf[i] != null)
- leaf[i].list(s, level+2);
- }
- }
-
- private int nodes = 0;
- private OctTreeNode root;
- private int reduceColors;
- private int maximumColors;
- private int colors = 0;
- private Vector[] colorList;
-
- public OctTreeQuantizer() {
- setup(256);
- colorList = new Vector[MAX_LEVEL+1];
- for (int i = 0; i < MAX_LEVEL+1; i++)
- colorList[i] = new Vector();
- root = new OctTreeNode();
- }
-
- /**
- * Initialize the quantizer. This should be called before adding any pixels.
- * @param numColors the number of colors we're quantizing to.
- */
- public void setup(int numColors) {
- maximumColors = numColors;
- reduceColors = Math.max(512, numColors * 2);
- }
-
- /**
- * Add pixels to the quantizer.
- * @param pixels the array of ARGB pixels
- * @param offset the offset into the array
- * @param count the count of pixels
- */
- public void addPixels(int[] pixels, int offset, int count) {
- for (int i = 0; i < count; i++) {
- insertColor(pixels[i+offset]);
- if (colors > reduceColors)
- reduceTree(reduceColors);
- }
- }
-
- /**
- * Get the color table index for a color.
- * @param rgb the color
- * @return the index
- */
- public int getIndexForColor(int rgb) {
- int red = (rgb >> 16) & 0xff;
- int green = (rgb >> 8) & 0xff;
- int blue = rgb & 0xff;
-
- OctTreeNode node = root;
-
- for (int level = 0; level <= MAX_LEVEL; level++) {
- OctTreeNode child;
- int bit = 0x80 >> level;
-
- int index = 0;
- if ((red & bit) != 0)
- index += 4;
- if ((green & bit) != 0)
- index += 2;
- if ((blue & bit) != 0)
- index += 1;
-
- child = node.leaf[index];
-
- if (child == null)
- return node.index;
- else if (child.isLeaf)
- return child.index;
- else
- node = child;
- }
- LOGGER.debug("getIndexForColor failed");
- return 0;
- }
-
- private void insertColor(int rgb) {
- int red = (rgb >> 16) & 0xff;
- int green = (rgb >> 8) & 0xff;
- int blue = rgb & 0xff;
-
- OctTreeNode node = root;
-
-// LOGGER.debug("insertColor="+Integer.toHexString(rgb));
- for (int level = 0; level <= MAX_LEVEL; level++) {
- OctTreeNode child;
- int bit = 0x80 >> level;
-
- int index = 0;
- if ((red & bit) != 0)
- index += 4;
- if ((green & bit) != 0)
- index += 2;
- if ((blue & bit) != 0)
- index += 1;
-
- child = node.leaf[index];
-
- if (child == null) {
- node.children++;
-
- child = new OctTreeNode();
- child.parent = node;
- node.leaf[index] = child;
- node.isLeaf = false;
- nodes++;
- colorList[level].addElement(child);
-
- if (level == MAX_LEVEL) {
- child.isLeaf = true;
- child.count = 1;
- child.totalRed = red;
- child.totalGreen = green;
- child.totalBlue = blue;
- child.level = level;
- colors++;
- return;
- }
-
- node = child;
- } else if (child.isLeaf) {
- child.count++;
- child.totalRed += red;
- child.totalGreen += green;
- child.totalBlue += blue;
- return;
- } else
- node = child;
- }
- LOGGER.debug("insertColor failed");
- }
-
- private void reduceTree(int numColors) {
- for (int level = MAX_LEVEL-1; level >= 0; level--) {
- Vector v = colorList[level];
- if (v != null && v.size() > 0) {
- for (int j = 0; j < v.size(); j++) {
- OctTreeNode node = (OctTreeNode)v.elementAt(j);
- if (node.children > 0) {
- for (int i = 0; i < 8; i++) {
- OctTreeNode child = node.leaf[i];
- if (child != null) {
- if (!child.isLeaf)
- LOGGER.debug("not a leaf!");
- node.count += child.count;
- node.totalRed += child.totalRed;
- node.totalGreen += child.totalGreen;
- node.totalBlue += child.totalBlue;
- node.leaf[i] = null;
- node.children--;
- colors--;
- nodes--;
- colorList[level+1].removeElement(child);
- }
- }
- node.isLeaf = true;
- colors++;
- if (colors <= numColors)
- return;
- }
- }
- }
- }
-
- LOGGER.debug("Unable to reduce the OctTree");
- }
-
- /**
- * Build the color table.
- * @return the color table
- */
- public int[] buildColorTable() {
- int[] table = new int[colors];
- buildColorTable(root, table, 0);
- return table;
- }
-
- /**
- * A quick way to use the quantizer. Just create a table the right size and pass in the pixels.
- * @param inPixels the input colors
- * @param table the output color table
- */
- public void buildColorTable(int[] inPixels, int[] table) {
- int count = inPixels.length;
- maximumColors = table.length;
- for (int i = 0; i < count; i++) {
- insertColor(inPixels[i]);
- if (colors > reduceColors)
- reduceTree(reduceColors);
- }
- if (colors > maximumColors)
- reduceTree(maximumColors);
- buildColorTable(root, table, 0);
- }
-
- private int buildColorTable(OctTreeNode node, int[] table, int index) {
- if (colors > maximumColors)
- reduceTree(maximumColors);
-
- if (node.isLeaf) {
- int count = node.count;
- table[index] = 0xff000000 |
- ((node.totalRed/count) << 16) |
- ((node.totalGreen/count) << 8) |
- node.totalBlue/count;
- node.index = index++;
- } else {
- for (int i = 0; i < 8; i++) {
- if (node.leaf[i] != null) {
- node.index = index;
- index = buildColorTable(node.leaf[i], table, index);
- }
- }
- }
- return index;
- }
-
-}
-
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/api/DefaultDecoder.java (working copy)
@@ -1,16 +0,0 @@
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare.api;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-
-/**
- * Implements a default PNG decoder.
- */
-public class DefaultDecoder implements ImageDecoder {
-
- public BufferedImage decode(ByteArrayInputStream stream) throws IOException {
- return ImageIO.read(stream);
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/sshare/ScreenShareMediaManager.java (working copy)
@@ -1,115 +0,0 @@
-/**
- * $RCSfile: ScreenShareMediaManager.java,v $
- * $Revision: 1.3 $
- * $Date: 25/12/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.sshare;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder;
-import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder;
-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implements a JingleMediaManager for ScreenSharing.
- * It currently uses an Audio payload Type. Which needs to be fixed in the next version.
- *
- * @author Thiago Camargo
- */
-
-public class ScreenShareMediaManager extends JingleMediaManager {
-
- public static final String MEDIA_NAME = "ScreenShare";
-
- private List<PayloadType> payloads = new ArrayList<PayloadType>();
-
- private ImageDecoder decoder = null;
- private ImageEncoder encoder = null;
-
- public ScreenShareMediaManager(JingleTransportManager transportManager) {
- super(transportManager);
- setupPayloads();
- }
-
- /**
- * Setup API supported Payloads
- */
- private void setupPayloads() {
- payloads.add(new PayloadType.Audio(30, "sshare"));
- }
-
- /**
- * Return all supported Payloads for this Manager.
- *
- * @return The Payload List
- */
- public List<PayloadType> getPayloads() {
- return payloads;
- }
-
- /**
- * Returns a new JingleMediaSession
- *
- * @param payloadType payloadType
- * @param remote remote Candidate
- * @param local local Candidate
- * @return JingleMediaSession JingleMediaSession
- */
- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
- ScreenShareSession session = null;
- session = new ScreenShareSession(payloadType, remote, local, "Screen", jingleSession);
- if (encoder != null) {
- session.setEncoder(encoder);
- }
- if (decoder != null) {
- session.setDecoder(decoder);
- }
- return session;
- }
-
- public PayloadType getPreferredPayloadType() {
- return super.getPreferredPayloadType();
- }
-
- public ImageDecoder getDecoder() {
- return decoder;
- }
-
- public void setDecoder(ImageDecoder decoder) {
- this.decoder = decoder;
- }
-
- public ImageEncoder getEncoder() {
- return encoder;
- }
-
- public void setEncoder(ImageEncoder encoder) {
- this.encoder = encoder;
- }
-
- public String getName() {
- return MEDIA_NAME;
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/multi/MultiMediaManager.java (working copy)
@@ -1,106 +0,0 @@
-/**
- * $RCSfile: MultiMediaManager.java,v $
- * $Revision: 1.3 $
- * $Date: 25/12/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.multi;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implements a MultiMediaManager using other JingleMediaManager implementations.
- * It supports every Codecs that JingleMediaManagers added has.
- *
- * @author Thiago Camargo
- */
-
-public class MultiMediaManager extends JingleMediaManager {
-
- public static final String MEDIA_NAME = "Multi";
-
- private List<JingleMediaManager> managers = new ArrayList<JingleMediaManager>();
-
- private PayloadType preferredPayloadType = null;
-
- public MultiMediaManager(JingleTransportManager transportManager) {
- super(transportManager);
- }
-
- public void addMediaManager(JingleMediaManager manager) {
- managers.add(manager);
- }
-
- public void removeMediaManager(JingleMediaManager manager) {
- managers.remove(manager);
- }
-
- /**
- * Return all supported Payloads for this Manager.
- *
- * @return The Payload List
- */
- public List<PayloadType> getPayloads() {
- List<PayloadType> list = new ArrayList<PayloadType>();
- if (preferredPayloadType != null) list.add(preferredPayloadType);
- for (JingleMediaManager manager : managers) {
- for (PayloadType payloadType : manager.getPayloads()) {
- if (!list.contains(payloadType) && !payloadType.equals(preferredPayloadType))
- list.add(payloadType);
- }
- }
- return list;
- }
-
- /**
- * Returns a new JingleMediaSession
- *
- * @param payloadType payloadType
- * @param remote remote Candidate
- * @param local local Candidate
- * @return JingleMediaSession JingleMediaSession
- */
- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
- for (JingleMediaManager manager : managers) {
- if (manager.getPayloads().contains(payloadType)) {
- return manager.createMediaSession(payloadType, remote, local, jingleSession);
- }
- }
- return null;
- }
-
- public PayloadType getPreferredPayloadType() {
- if (preferredPayloadType != null) return preferredPayloadType;
- return super.getPreferredPayloadType();
- }
-
- public void setPreferredPayloadType(PayloadType preferredPayloadType) {
- this.preferredPayloadType = preferredPayloadType;
- }
-
- public String getName() {
- return MEDIA_NAME;
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioMediaSession.java (working copy)
@@ -1,165 +0,0 @@
-/**
- * $RCSfile: AudioMediaSession.java,v $
- * $Revision: 1.1 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-
-import javax.media.MediaLocator;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-/**
- * This Class implements a complete JingleMediaSession.
- * It sould be used to transmit and receive audio captured from the Mic.
- * This Class should be automaticly controlled by JingleSession.
- * But you could also use in any VOIP application.
- * For better NAT Traversal support this implementation don't support only receive or only transmit.
- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
- *
- * @author Thiago Camargo
- */
-public class AudioMediaSession extends JingleMediaSession {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);
-
- private AudioChannel audioChannel;
-
- /**
- * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates
- *
- * @param payloadType Payload of the jmf
- * @param remote the remote information. The candidate that the jmf will be sent to.
- * @param local the local information. The candidate that will receive the jmf
- * @param locator media locator
- */
- public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
- final TransportCandidate local, String locator, JingleSession jingleSession) {
- super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession);
- initialize();
- }
-
- /**
- * Initialize the Audio Channel to make it able to send and receive audio
- */
- public void initialize() {
-
- String ip;
- String localIp;
- int localPort;
- int remotePort;
-
- if (this.getLocal().getSymmetric() != null) {
- ip = this.getLocal().getIp();
- localIp = this.getLocal().getLocalIp();
- localPort = getFreePort();
- remotePort = this.getLocal().getSymmetric().getPort();
-
- LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);
-
- }
- else {
- ip = this.getRemote().getIp();
- localIp = this.getLocal().getLocalIp();
- localPort = this.getLocal().getPort();
- remotePort = this.getRemote().getPort();
- }
-
- audioChannel = new AudioChannel(new MediaLocator(this.getMediaLocator()), localIp, ip, localPort, remotePort, AudioFormatUtils.getAudioFormat(this.getPayloadType()),this);
- }
-
- /**
- * Starts transmission and for NAT Traversal reasons start receiving also.
- */
- public void startTrasmit() {
- audioChannel.start();
- }
-
- /**
- * Set transmit activity. If the active is true, the instance should trasmit.
- * If it is set to false, the instance should pause transmit.
- *
- * @param active active state
- */
- public void setTrasmit(boolean active) {
- audioChannel.setTrasmit(active);
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void startReceive() {
- // Do nothing
- }
-
- /**
- * Stops transmission and for NAT Traversal reasons stop receiving also.
- */
- public void stopTrasmit() {
- if (audioChannel != null)
- audioChannel.stop();
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void stopReceive() {
- // Do nothing
- }
-
- /**
- * Obtain a free port we can use.
- *
- * @return A free port number.
- */
- protected int getFreePort() {
- ServerSocket ss;
- int freePort = 0;
-
- for (int i = 0; i < 10; i++) {
- freePort = (int) (10000 + Math.round(Math.random() * 10000));
- freePort = freePort % 2 == 0 ? freePort : freePort + 1;
- try {
- ss = new ServerSocket(freePort);
- freePort = ss.getLocalPort();
- ss.close();
- return freePort;
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- try {
- ss = new ServerSocket(0);
- freePort = ss.getLocalPort();
- ss.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- return freePort;
- }
-
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioReceiver.java (working copy)
@@ -1,171 +0,0 @@
-/**
- * $RCSfile: AudioReceiver.java,v $
- * $Revision: 1.1 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
-
-import javax.media.ControllerErrorEvent;
-import javax.media.ControllerEvent;
-import javax.media.ControllerListener;
-import javax.media.Player;
-import javax.media.RealizeCompleteEvent;
-import javax.media.protocol.DataSource;
-import javax.media.rtp.Participant;
-import javax.media.rtp.RTPControl;
-import javax.media.rtp.ReceiveStream;
-import javax.media.rtp.ReceiveStreamListener;
-import javax.media.rtp.SessionListener;
-import javax.media.rtp.event.ByeEvent;
-import javax.media.rtp.event.NewParticipantEvent;
-import javax.media.rtp.event.NewReceiveStreamEvent;
-import javax.media.rtp.event.ReceiveStreamEvent;
-import javax.media.rtp.event.RemotePayloadChangeEvent;
-import javax.media.rtp.event.SessionEvent;
-import javax.media.rtp.event.StreamMappedEvent;
-
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-
-/**
- * This class implements receive methods and listeners to be used in AudioChannel
- *
- * @author Thiago Camargo
- */
-public class AudioReceiver implements ReceiveStreamListener, SessionListener,
- ControllerListener {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioReceiver.class);
-
- boolean dataReceived = false;
-
- Object dataSync;
- JingleMediaSession jingleMediaSession;
-
- public AudioReceiver(final Object dataSync, final JingleMediaSession jingleMediaSession) {
- this.dataSync = dataSync;
- this.jingleMediaSession = jingleMediaSession;
- }
-
- /**
- * JingleSessionListener.
- */
- public synchronized void update(SessionEvent evt) {
- if (evt instanceof NewParticipantEvent) {
- Participant p = ((NewParticipantEvent) evt).getParticipant();
- LOGGER.error(" - A new participant had just joined: " + p.getCNAME());
- }
- }
-
- /**
- * ReceiveStreamListener
- */
- public synchronized void update(ReceiveStreamEvent evt) {
-
- Participant participant = evt.getParticipant(); // could be null.
- ReceiveStream stream = evt.getReceiveStream(); // could be null.
-
- if (evt instanceof RemotePayloadChangeEvent) {
- LOGGER.error(" - Received an RTP PayloadChangeEvent.");
- LOGGER.error("Sorry, cannot handle payload change.");
-
- }
- else if (evt instanceof NewReceiveStreamEvent) {
-
- try {
- stream = evt.getReceiveStream();
- DataSource ds = stream.getDataSource();
-
- // Find out the formats.
- RTPControl ctl = (RTPControl) ds.getControl("javax.jmf.rtp.RTPControl");
- if (ctl != null) {
- LOGGER.error(" - Recevied new RTP stream: " + ctl.getFormat());
- }
- else
- LOGGER.error(" - Recevied new RTP stream");
-
- if (participant == null)
- LOGGER.error(" The sender of this stream had yet to be identified.");
- else {
- LOGGER.error(" 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();
- jingleMediaSession.mediaReceived(participant != null ? participant.getCNAME() : "");
-
- // Notify intialize() that a new stream had arrived.
- synchronized (dataSync) {
- dataReceived = true;
- dataSync.notifyAll();
- }
-
- }
- catch (Exception e) {
- LOGGER.error("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.jmf.rtp.RTPControl");
- LOGGER.error(" - The previously unidentified stream ");
- if (ctl != null)
- LOGGER.error(" " + ctl.getFormat());
- LOGGER.error(" had now been identified as sent by: " + participant.getCNAME());
- }
- }
- else if (evt instanceof ByeEvent) {
-
- LOGGER.error(" - Got \"bye\" from: " + participant.getCNAME());
-
- }
-
- }
-
- /**
- * 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) {
- p.start();
- }
-
- if (ce instanceof ControllerErrorEvent) {
- p.removeControllerListener(this);
- LOGGER.error("Receiver internal error: " + ce);
- }
-
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/JmfMediaManager.java (working copy)
@@ -1,170 +0,0 @@
-/**
- * $RCSfile: JmfMediaManager.java,v $
- * $Revision: 1.3 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-/**
- * Implements a jingleMediaManager using JMF based API.
- * It supports GSM and G723 codecs.
- * <i>This API only currently works on windows and Mac.</i>
- *
- * @author Thiago Camargo
- */
-public class JmfMediaManager extends JingleMediaManager {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(JmfMediaManager.class);
-
- public static final String MEDIA_NAME = "JMF";
-
-
- private List<PayloadType> payloads = new ArrayList<PayloadType>();
- private String mediaLocator = null;
-
- /**
- * Creates a Media Manager instance
- */
- public JmfMediaManager(JingleTransportManager transportManager) {
- super(transportManager);
- setupPayloads();
- }
-
- /**
- * Creates a Media Manager instance
- *
- * @param mediaLocator Media Locator
- */
- public JmfMediaManager(String mediaLocator, JingleTransportManager transportManager) {
- super(transportManager);
- this.mediaLocator = mediaLocator;
- setupPayloads();
- }
-
- /**
- * Returns a new jingleMediaSession
- *
- * @param payloadType payloadType
- * @param remote remote Candidate
- * @param local local Candidate
- * @return JingleMediaSession
- */
- public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
- return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession);
- }
-
- /**
- * Setup API supported Payloads
- */
- private void setupPayloads() {
- payloads.add(new PayloadType.Audio(3, "gsm"));
- payloads.add(new PayloadType.Audio(4, "g723"));
- payloads.add(new PayloadType.Audio(0, "PCMU", 16000));
- }
-
- /**
- * Return all supported Payloads for this Manager
- *
- * @return The Payload List
- */
- public List<PayloadType> getPayloads() {
- return payloads;
- }
-
- /**
- * Return the media locator or null if not defined
- *
- * @return media locator
- */
- public String getMediaLocator() {
- return mediaLocator;
- }
-
- /**
- * Set the media locator
- *
- * @param mediaLocator media locator or null to use default
- */
- public void setMediaLocator(String mediaLocator) {
- this.mediaLocator = mediaLocator;
- }
-
- /**
- * Runs JMFInit the first time the application is started so that capture
- * devices are properly detected and initialized by JMF.
- */
- public static void setupJMF() {
- // .jmf is the place where we store the jmf.properties file used
- // by JMF. if the directory does not exist or it does not contain
- // a jmf.properties file. or if the jmf.properties file has 0 length
- // then this is the first time we're running and should continue to
- // with JMFInit
- String homeDir = System.getProperty("user.home");
- File jmfDir = new File(homeDir, ".jmf");
- String classpath = System.getProperty("java.class.path");
- classpath += System.getProperty("path.separator")
- + jmfDir.getAbsolutePath();
- System.setProperty("java.class.path", classpath);
-
- if (!jmfDir.exists())
- jmfDir.mkdir();
-
- File jmfProperties = new File(jmfDir, "jmf.properties");
-
- if (!jmfProperties.exists()) {
- try {
- jmfProperties.createNewFile();
- }
- catch (IOException ex) {
- LOGGER.debug("Failed to create jmf.properties");
- ex.printStackTrace();
- }
- }
-
- // if we're running on linux checkout that libjmutil.so is where it
- // should be and put it there.
- runLinuxPreInstall();
-
- //if (jmfProperties.length() == 0) {
- new JMFInit(null, false);
- //}
-
- }
-
- private static void runLinuxPreInstall() {
- // @TODO Implement Linux Pre-Install
- }
-
- public String getName() {
- return MEDIA_NAME;
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioChannel.java (working copy)
@@ -1,553 +0,0 @@
-/**
- * $RCSfile: AudioChannel.java,v $
- * $Revision: 1.1 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.media.Codec;
-import javax.media.Controller;
-import javax.media.ControllerClosedEvent;
-import javax.media.ControllerEvent;
-import javax.media.ControllerListener;
-import javax.media.Format;
-import javax.media.MediaLocator;
-import javax.media.NoProcessorException;
-import javax.media.Processor;
-import javax.media.UnsupportedPlugInException;
-import javax.media.control.BufferControl;
-import javax.media.control.PacketSizeControl;
-import javax.media.control.TrackControl;
-import javax.media.format.AudioFormat;
-import javax.media.protocol.ContentDescriptor;
-import javax.media.protocol.DataSource;
-import javax.media.protocol.PushBufferDataSource;
-import javax.media.protocol.PushBufferStream;
-import javax.media.rtp.InvalidSessionAddressException;
-import javax.media.rtp.RTPManager;
-import javax.media.rtp.SendStream;
-import javax.media.rtp.SessionAddress;
-
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-
-/**
- * An Easy to use Audio Channel implemented using JMF.
- * It sends and receives jmf for and from desired IPs and ports.
- * Also has a rport Symetric behavior for better NAT Traversal.
- * It send data from a defined port and receive data in the same port, making NAT binds easier.
- * <p/>
- * Send from portA to portB and receive from portB in portA.
- * <p/>
- * Sending
- * portA ---> portB
- * <p/>
- * Receiving
- * portB ---> portA
- * <p/>
- * <i>Transmit and Receive are interdependents. To receive you MUST trasmit. </i>
- *
- * @author Thiago Camargo
- */
-public class AudioChannel {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioChannel.class);
-
- private MediaLocator locator;
- private String localIpAddress;
- private String remoteIpAddress;
- private int localPort;
- private int portBase;
- private Format format;
-
- private Processor processor = null;
- private RTPManager rtpMgrs[];
- private DataSource dataOutput = null;
- private AudioReceiver audioReceiver;
-
- private List<SendStream> sendStreams = new ArrayList<SendStream>();
-
- private JingleMediaSession jingleMediaSession;
-
- private boolean started = false;
-
- /**
- * Creates an Audio Channel for a desired jmf locator. For instance: new MediaLocator("dsound://")
- *
- * @param locator media locator
- * @param localIpAddress local IP address
- * @param remoteIpAddress remote IP address
- * @param localPort local port number
- * @param remotePort remote port number
- * @param format audio format
- */
- public AudioChannel(MediaLocator locator,
- String localIpAddress,
- String remoteIpAddress,
- int localPort,
- int remotePort,
- Format format, JingleMediaSession jingleMediaSession) {
-
- this.locator = locator;
- this.localIpAddress = localIpAddress;
- this.remoteIpAddress = remoteIpAddress;
- this.localPort = localPort;
- this.portBase = remotePort;
- this.format = format;
- this.jingleMediaSession = jingleMediaSession;
- }
-
- /**
- * Starts the transmission. Returns null if transmission started ok.
- * Otherwise it returns a string with the reason why the setup failed.
- * Starts receive also.
- *
- * @return result description
- */
- public synchronized String start() {
- if (started) return null;
-
- // Create a processor for the specified jmf locator
- String result = createProcessor();
- if (result != null) {
- started = false;
- }
-
- // 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;
- started = false;
- }
- else {
- started = true;
- }
-
- // Start the transmission
- processor.start();
-
- return null;
- }
-
- /**
- * Stops the transmission if already started.
- * Stops the receiver also.
- */
- public void stop() {
- if (!started) return;
- synchronized (this) {
- try {
- started = false;
- if (processor != null) {
- processor.stop();
- processor = null;
-
- for (RTPManager rtpMgr : rtpMgrs) {
- rtpMgr.removeReceiveStreamListener(audioReceiver);
- rtpMgr.removeSessionListener(audioReceiver);
- rtpMgr.removeTargets("Session ended.");
- rtpMgr.dispose();
- }
-
- sendStreams.clear();
-
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private String createProcessor() {
- if (locator == null)
- return "Locator is null";
-
- DataSource ds;
-
- try {
- ds = javax.media.Manager.createDataSource(locator);
- }
- catch (Exception e) {
- // Try JavaSound Locator as a last resort
- try {
- ds = javax.media.Manager.createDataSource(new MediaLocator("javasound://"));
- }
- catch (Exception ee) {
- return "Couldn't create DataSource";
- }
- }
-
- // Try to create a processor to handle the input jmf locator
- try {
- processor = javax.media.Manager.createProcessor(ds);
- }
- catch (NoProcessorException npe) {
- npe.printStackTrace();
- return "Couldn't create processor";
- }
- catch (IOException ioe) {
- ioe.printStackTrace();
- return "IOException creating processor";
- }
-
- // Wait for it to configure
- boolean result = waitForState(processor, Processor.Configured);
- if (!result){
- 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 = null;
- boolean atLeastOneTrack = false;
-
- // Program the tracks.
- for (int i = 0; i < tracks.length; i++) {
- if (tracks[i].isEnabled()) {
-
- supported = tracks[i].getSupportedFormats();
-
- if (supported.length > 0) {
- for (Format format : supported) {
- if (format instanceof AudioFormat) {
- if (this.format.matches(format))
- chosen = format;
- }
- }
- if (chosen != null) {
- tracks[i].setFormat(chosen);
- LOGGER.error("Track " + i + " is set to transmit as:");
- LOGGER.error(" " + chosen);
-
- if (tracks[i].getFormat() instanceof AudioFormat) {
- int packetRate = 20;
- PacketSizeControl pktCtrl = (PacketSizeControl) processor.getControl(PacketSizeControl.class.getName());
- if (pktCtrl != null) {
- try {
- pktCtrl.setPacketSize(getPacketSize(tracks[i].getFormat(), packetRate));
- }
- catch (IllegalArgumentException e) {
- pktCtrl.setPacketSize(80);
- // Do nothing
- }
- }
-
- if (tracks[i].getFormat().getEncoding().equals(AudioFormat.ULAW_RTP)) {
- Codec codec[] = new Codec[3];
-
- codec[0] = new com.ibm.media.codec.audio.rc.RCModule();
- codec[1] = new com.ibm.media.codec.audio.ulaw.JavaEncoder();
- codec[2] = new com.sun.media.codec.audio.ulaw.Packetizer();
- ((com.sun.media.codec.audio.ulaw.Packetizer) codec
- [2]).setPacketSize(160);
-
- try {
- tracks[i].setCodecChain(codec);
- }
- catch (UnsupportedPlugInException e) {
- e.printStackTrace();
- }
- }
-
- }
-
- 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)
- return "Couldn't realize processor";
-
- // Get the output data source of the processor
- dataOutput = processor.getDataOutput();
-
- return null;
- }
-
- /**
- * Get the best packet size for a given codec and a codec rate
- *
- * @param codecFormat
- * @param milliseconds
- * @return
- * @throws IllegalArgumentException
- */
- private int getPacketSize(Format codecFormat, int milliseconds) throws IllegalArgumentException {
- String encoding = codecFormat.getEncoding();
- if (encoding.equalsIgnoreCase(AudioFormat.GSM) ||
- encoding.equalsIgnoreCase(AudioFormat.GSM_RTP)) {
- return milliseconds * 4; // 1 byte per millisec
- }
- else if (encoding.equalsIgnoreCase(AudioFormat.ULAW) ||
- encoding.equalsIgnoreCase(AudioFormat.ULAW_RTP)) {
- return milliseconds * 8;
- }
- else {
- throw new IllegalArgumentException("Unknown codec type");
- }
- }
-
- /**
- * Use the RTPManager API to create sessions for each jmf
- * track of the processor.
- *
- * @return description
- */
- 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;
- audioReceiver = new AudioReceiver(this, jingleMediaSession);
- int port;
-
- for (int i = 0; i < pbss.length; i++) {
- try {
- rtpMgrs[i] = RTPManager.newInstance();
-
- port = portBase + 2 * i;
- ipAddr = InetAddress.getByName(remoteIpAddress);
-
- localAddr = new SessionAddress(InetAddress.getByName(this.localIpAddress),
- localPort);
-
- destAddr = new SessionAddress(ipAddr, port);
-
- rtpMgrs[i].addReceiveStreamListener(audioReceiver);
- rtpMgrs[i].addSessionListener(audioReceiver);
-
- BufferControl bc = (BufferControl) rtpMgrs[i].getControl("javax.media.control.BufferControl");
- if (bc != null) {
- int bl = 160;
- bc.setBufferLength(bl);
- }
-
- try {
-
- rtpMgrs[i].initialize(localAddr);
-
- }
- catch (InvalidSessionAddressException e) {
- // In case the local address is not allowed to read, we user another local address
- SessionAddress sessAddr = new SessionAddress();
- localAddr = new SessionAddress(sessAddr.getDataAddress(),
- localPort);
- rtpMgrs[i].initialize(localAddr);
- }
-
- rtpMgrs[i].addTarget(destAddr);
-
- LOGGER.error("Created RTP session at " + localPort + " to: " + remoteIpAddress + " " + port);
-
- sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
-
- sendStreams.add(sendStream);
-
- sendStream.start();
-
- }
- catch (Exception e) {
- e.printStackTrace();
- return e.getMessage();
- }
- }
-
- return null;
- }
-
- /**
- * Set transmit activity. If the active is true, the instance should trasmit.
- * If it is set to false, the instance should pause transmit.
- *
- * @param active active state
- */
- public void setTrasmit(boolean active) {
- for (SendStream sendStream : sendStreams) {
- try {
- if (active) {
- sendStream.start();
- LOGGER.debug("START");
- }
- else {
- sendStream.stop();
- LOGGER.debug("STOP");
- }
- }
- catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- }
-
- /**
- * *************************************************************
- * Convenience methods to handle processor's state changes.
- * **************************************************************
- */
-
- private Integer stateLock = 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;
-
- // 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;
- }
- }
- }
-
- return !failed;
- }
-
- /**
- * *************************************************************
- * 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 != null) {
- synchronized (getStateLock()) {
- getStateLock().notifyAll();
- }
- }
- }
- }
-
- public static void main(String args[]) {
-
- InetAddress localhost;
- try {
- localhost = InetAddress.getLocalHost();
-
- AudioChannel audioChannel0 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7002, 7020, new AudioFormat(AudioFormat.GSM_RTP), null);
- AudioChannel audioChannel1 = new AudioChannel(new MediaLocator("javasound://8000"), localhost.getHostAddress(), localhost.getHostAddress(), 7020, 7002, new AudioFormat(AudioFormat.GSM_RTP), null);
-
- audioChannel0.start();
- audioChannel1.start();
-
- try {
- Thread.sleep(5000);
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- audioChannel0.setTrasmit(false);
- audioChannel1.setTrasmit(false);
-
- try {
- Thread.sleep(5000);
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- audioChannel0.setTrasmit(true);
- audioChannel1.setTrasmit(true);
-
- try {
- Thread.sleep(5000);
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- audioChannel0.stop();
- audioChannel1.stop();
-
- }
- catch (UnknownHostException e) {
- e.printStackTrace();
- }
-
- }
-}
\ No newline at end of file
Index: org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jmf/AudioFormatUtils.java (working copy)
@@ -1,55 +0,0 @@
-/**
- * $RCSfile: AudioFormatUtils.java,v $
- * $Revision: 1.1 $
- * $Date: 08/11/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
-
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-
-import javax.media.format.AudioFormat;
-
-/**
- * Audio Format Utils.
- *
- * @author Thiago Camargo
- */
-public class AudioFormatUtils {
-
- /**
- * Return a JMF AudioFormat for a given Jingle Payload type.
- * Return null if the payload is not supported by this jmf API.
- *
- * @param payloadtype payloadtype
- * @return correspondent audioType
- */
- public static AudioFormat getAudioFormat(PayloadType payloadtype) {
-
- switch (payloadtype.getId()) {
- case 0:
- return new AudioFormat(AudioFormat.ULAW_RTP);
- case 3:
- return new AudioFormat(AudioFormat.GSM_RTP);
- case 4:
- return new AudioFormat(AudioFormat.G723_RTP);
- default:
- return null;
- }
-
- }
-
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/SpeexMediaManager.java (working copy)
@@ -1,134 +0,0 @@
-/**
- * $RCSfile: SpeexMediaManager.java,v $
- * $Revision: 1.3 $
- * $Date: 25/12/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jivesoftware.smackx.jingle.mediaimpl.jspeex;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
-import org.jivesoftware.smackx.jingle.nat.JingleTransportManager;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-/**
- * Implements a jingleMediaManager using JMF based API and JSpeex.
- * It supports Speex codec.
- * <i>This API only currently works on windows.</i>
- *
- * @author Thiago Camargo
- */
-public class SpeexMediaManager extends JingleMediaManager {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(SpeexMediaManager.class);
-
- public static final String MEDIA_NAME = "Speex";
-
- private List<PayloadType> payloads = new ArrayList<PayloadType>();
-
- public SpeexMediaManager(JingleTransportManager transportManager) {
- super(transportManager);
- setupPayloads();
- setupJMF();
- }
-
- /**
- * Returns a new jingleMediaSession
- *
- * @param payloadType payloadType
- * @param remote remote Candidate
- * @param local local Candidate
- * @return JingleMediaSession
- */
- public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
- return new AudioMediaSession(payloadType, remote, local, null,null);
- }
-
- /**
- * Setup API supported Payloads
- */
- private void setupPayloads() {
- payloads.add(new PayloadType.Audio(15, "speex"));
- }
-
- /**
- * Return all supported Payloads for this Manager
- *
- * @return The Payload List
- */
- public List<PayloadType> getPayloads() {
- return payloads;
- }
-
- /**
- * Runs JMFInit the first time the application is started so that capture
- * devices are properly detected and initialized by JMF.
- */
- public static void setupJMF() {
- // .jmf is the place where we store the jmf.properties file used
- // by JMF. if the directory does not exist or it does not contain
- // a jmf.properties file. or if the jmf.properties file has 0 length
- // then this is the first time we're running and should continue to
- // with JMFInit
- String homeDir = System.getProperty("user.home");
- File jmfDir = new File(homeDir, ".jmf");
- String classpath = System.getProperty("java.class.path");
- classpath += System.getProperty("path.separator")
- + jmfDir.getAbsolutePath();
- System.setProperty("java.class.path", classpath);
-
- if (!jmfDir.exists())
- jmfDir.mkdir();
-
- File jmfProperties = new File(jmfDir, "jmf.properties");
-
- if (!jmfProperties.exists()) {
- try {
- jmfProperties.createNewFile();
- }
- catch (IOException ex) {
- LOGGER.debug("Failed to create jmf.properties");
- ex.printStackTrace();
- }
- }
-
- // if we're running on linux checkout that libjmutil.so is where it
- // should be and put it there.
- runLinuxPreInstall();
-
- if (jmfProperties.length() == 0) {
- new JMFInit(null, false);
- }
-
- }
-
- private static void runLinuxPreInstall() {
- // @TODO Implement Linux Pre-Install
- }
-
- public String getName() {
- return MEDIA_NAME;
- }
-}
Index: org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java
===================================================================
--- org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java (revision 11644)
+++ org/jivesoftware/smackx/jingle/mediaimpl/jspeex/AudioMediaSession.java (working copy)
@@ -1,245 +0,0 @@
-/**
- * $RCSfile: AudioMediaSession.java,v $
- * $Revision: 1.1 $
- * $Date: 25/12/2006
- * <p/>
- * Copyright 2003-2006 Jive Software.
- * <p/>
- * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jivesoftware.smackx.jingle.mediaimpl.jspeex;
-
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.security.GeneralSecurityException;
-
-import javax.media.NoProcessorException;
-import javax.media.format.UnsupportedFormatException;
-import javax.media.rtp.rtcp.SenderReport;
-import javax.media.rtp.rtcp.SourceDescription;
-
-import mil.jfcom.cie.media.session.MediaSession;
-import mil.jfcom.cie.media.session.MediaSessionListener;
-import mil.jfcom.cie.media.session.StreamPlayer;
-import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat;
-
-import org.jivesoftware.smackx.jingle.JingleSession;
-import org.jivesoftware.smackx.jingle.SmackLogger;
-import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
-import org.jivesoftware.smackx.jingle.media.PayloadType;
-import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
-
-/**
- * This Class implements a complete JingleMediaSession.
- * It sould be used to transmit and receive audio captured from the Mic.
- * This Class should be automaticly controlled by JingleSession.
- * But you could also use in any VOIP application.
- * For better NAT Traversal support this implementation don't support only receive or only transmit.
- * To receive you MUST transmit. So the only implemented and functionally methods are startTransmit() and stopTransmit()
- *
- * @author Thiago Camargo
- */
-
-public class AudioMediaSession extends JingleMediaSession implements MediaSessionListener {
-
- private static final SmackLogger LOGGER = SmackLogger.getLogger(AudioMediaSession.class);
-
- private MediaSession mediaSession;
-
- /**
- * Create a Session using Speex Codec
- *
- * @param localhost localHost
- * @param localPort localPort
- * @param remoteHost remoteHost
- * @param remotePort remotePort
- * @param eventHandler eventHandler
- * @param quality quality
- * @param secure secure
- * @param micOn micOn
- * @return MediaSession
- * @throws NoProcessorException
- * @throws UnsupportedFormatException
- * @throws IOException
- * @throws GeneralSecurityException
- */
- public static MediaSession createSession(String localhost, int localPort, String remoteHost, int remotePort, MediaSessionListener eventHandler, int quality, boolean secure, boolean micOn) throws NoProcessorException, UnsupportedFormatException, IOException, GeneralSecurityException {
-
- SpeexFormat.setFramesPerPacket(1);
- /**
- * The master key. Hardcoded for now.
- */
- byte[] masterKey = new byte[]{(byte) 0xE1, (byte) 0xF9, 0x7A, 0x0D, 0x3E, 0x01, (byte) 0x8B, (byte) 0xE0, (byte) 0xD6, 0x4F, (byte) 0xA3, 0x2C, 0x06, (byte) 0xDE, 0x41, 0x39};
-
- /**
- * The master salt. Hardcoded for now.
- */
- byte[] masterSalt = new byte[]{0x0E, (byte) 0xC6, 0x75, (byte) 0xAD, 0x49, (byte) 0x8A, (byte) 0xFE, (byte) 0xEB, (byte) 0xB6, (byte) 0x96, 0x0B, 0x3A, (byte) 0xAB, (byte) 0xE6};
-
- DatagramSocket[] localPorts = MediaSession.getLocalPorts(InetAddress.getByName(localhost), localPort);
- MediaSession session = MediaSession.createInstance(remoteHost, remotePort, localPorts, quality, secure, masterKey, masterSalt);
- session.setListener(eventHandler);
-
- session.setSourceDescription(new SourceDescription[]{new SourceDescription(SourceDescription.SOURCE_DESC_NAME, "Superman", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_EMAIL, "cdcie.tester@je.jfcom.mil", 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_LOC, InetAddress.getByName(localhost) + " Port " + session.getLocalDataPort(), 1, false), new SourceDescription(SourceDescription.SOURCE_DESC_TOOL, "JFCOM CDCIE Audio Chat", 1, false)});
- return session;
- }
-
-
- /**
- * Creates a org.jivesoftware.jingleaudio.jspeex.AudioMediaSession with defined payload type, remote and local candidates
- *
- * @param payloadType Payload of the jmf
- * @param remote the remote information. The candidate that the jmf will be sent to.
- * @param local the local information. The candidate that will receive the jmf
- * @param locator media locator
- */
- public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
- final TransportCandidate local, String locator, JingleSession jingleSession) {
- super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession);
- initialize();
- }
-
- /**
- * Initialize the Audio Channel to make it able to send and receive audio
- */
- public void initialize() {
-
- String ip;
- String localIp;
- int localPort;
- int remotePort;
-
- if (this.getLocal().getSymmetric() != null) {
- ip = this.getLocal().getIp();
- localIp = this.getLocal().getLocalIp();
- localPort = getFreePort();
- remotePort = this.getLocal().getSymmetric().getPort();
-
- LOGGER.debug(this.getLocal().getConnection() + " " + ip + ": " + localPort + "->" + remotePort);
-
- }
- else {
- ip = this.getRemote().getIp();
- localIp = this.getLocal().getLocalIp();
- localPort = this.getLocal().getPort();
- remotePort = this.getRemote().getPort();
- }
-
- try {
- mediaSession = createSession(localIp, localPort, ip, remotePort, this, 2, false, true);
- }
- catch (NoProcessorException e) {
- e.printStackTrace();
- }
- catch (UnsupportedFormatException e) {
- e.printStackTrace();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- catch (GeneralSecurityException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Starts transmission and for NAT Traversal reasons start receiving also.
- */
- public void startTrasmit() {
- try {
- LOGGER.debug("start");
- mediaSession.start(true);
- this.mediaReceived("");
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Set transmit activity. If the active is true, the instance should trasmit.
- * If it is set to false, the instance should pause transmit.
- *
- * @param active active state
- */
- public void setTrasmit(boolean active) {
- // Do nothing
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void startReceive() {
- // Do nothing
- }
-
- /**
- * Stops transmission and for NAT Traversal reasons stop receiving also.
- */
- public void stopTrasmit() {
- if (mediaSession != null)
- mediaSession.close();
- }
-
- /**
- * For NAT Reasons this method does nothing. Use startTransmit() to start transmit and receive jmf
- */
- public void stopReceive() {
- // Do nothing
- }
-
- public void newStreamIdentified(StreamPlayer streamPlayer) {
- }
-
- public void senderReportReceived(SenderReport report) {
- }
-
- public void streamClosed(StreamPlayer stream, boolean timeout) {
- }
-
- /**
- * Obtain a free port we can use.
- *
- * @return A free port number.
- */
- protected int getFreePort() {
- ServerSocket ss;
- int freePort = 0;
-
- for (int i = 0; i < 10; i++) {
- freePort = (int) (10000 + Math.round(Math.random() * 10000));
- freePort = freePort % 2 == 0 ? freePort : freePort + 1;
- try {
- ss = new ServerSocket(freePort);
- freePort = ss.getLocalPort();
- ss.close();
- return freePort;
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- }
- try {
- ss = new ServerSocket(0);
- freePort = ss.getLocalPort();
- ss.close();
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- return freePort;
- }
-}