1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-25 21:42:07 +01:00

[SMACK-221][SMACK-222] - Added Keyframe Support and One-Side-Only Session

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@8214 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Thiago Camargo 2007-05-08 20:31:46 +00:00 committed by thiago
parent ff2900653c
commit 925bd389c2
13 changed files with 102 additions and 135 deletions

View file

@ -1083,7 +1083,7 @@ public abstract class JingleSession extends JingleNegotiator implements MediaRec
rc.removeCandidateEcho(); rc.removeCandidateEcho();
lc.removeCandidateEcho(); lc.removeCandidateEcho();
jingleMediaSession = jingleMediaManager.createMediaSession(pt, rc, lc); jingleMediaSession = jingleMediaManager.createMediaSession(pt, rc, lc, this);
jingleMediaSession.addMediaReceivedListener(this); jingleMediaSession.addMediaReceivedListener(this);
if (jingleMediaSession != null) { if (jingleMediaSession != null) {

View file

@ -21,6 +21,7 @@
package org.jivesoftware.smackx.jingle.media; package org.jivesoftware.smackx.jingle.media;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -60,6 +61,6 @@ public abstract class JingleMediaManager {
* @param local * @param local
* @return * @return
*/ */
public abstract JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local); public abstract JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, JingleSession jingleSession);
} }

View file

@ -20,6 +20,7 @@
package org.jivesoftware.smackx.jingle.media; package org.jivesoftware.smackx.jingle.media;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
@ -48,6 +49,8 @@ public abstract class JingleMediaSession {
private String mediaLocator; private String mediaLocator;
// Media Received Listener // Media Received Listener
private List<MediaReceivedListener> mediaReceivedListeners = new ArrayList<MediaReceivedListener>(); private List<MediaReceivedListener> mediaReceivedListeners = new ArrayList<MediaReceivedListener>();
// Jingle Session
private JingleSession jingleSession;
/** /**
* Creates a new JingleMediaSession Instance to handle Media methods. * Creates a new JingleMediaSession Instance to handle Media methods.
@ -58,11 +61,12 @@ public abstract class JingleMediaSession {
* @param mediaLocator Media Locator of the capture device * @param mediaLocator Media Locator of the capture device
*/ */
public JingleMediaSession(PayloadType payloadType, TransportCandidate remote, public JingleMediaSession(PayloadType payloadType, TransportCandidate remote,
TransportCandidate local, String mediaLocator) { TransportCandidate local, String mediaLocator, JingleSession jingleSession) {
this.local = local; this.local = local;
this.remote = remote; this.remote = remote;
this.payloadType = payloadType; this.payloadType = payloadType;
this.mediaLocator = mediaLocator; this.mediaLocator = mediaLocator;
this.jingleSession = jingleSession;
} }
/** /**
@ -177,4 +181,11 @@ public abstract class JingleMediaSession {
} }
} }
/**
* Gets associated JingleSession
* @return associated JingleSession
*/
public JingleSession getJingleSession() {
return jingleSession;
}
} }

View file

@ -23,6 +23,7 @@ package org.jivesoftware.smackx.jingle.mediaimpl.jmf;
import org.jivesoftware.smackx.jingle.media.JingleMediaSession; import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
import org.jivesoftware.smackx.jingle.media.PayloadType; import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import javax.media.MediaLocator; import javax.media.MediaLocator;
import java.io.IOException; import java.io.IOException;
@ -51,8 +52,8 @@ public class AudioMediaSession extends JingleMediaSession {
* @param locator media locator * @param locator media locator
*/ */
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
final TransportCandidate local, String locator) { final TransportCandidate local, String locator, JingleSession jingleSession) {
super(payloadType, remote, local, locator==null?"dsound://":locator); super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession);
initialize(); initialize();
} }

View file

@ -25,6 +25,7 @@ import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
import org.jivesoftware.smackx.jingle.media.PayloadType; import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit; import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -68,8 +69,8 @@ public class JmfMediaManager extends JingleMediaManager {
* @param local local Candidate * @param local local Candidate
* @return JingleMediaSession * @return JingleMediaSession
*/ */
public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) { public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
return new AudioMediaSession(payloadType, remote, local,mediaLocator); return new AudioMediaSession(payloadType, remote, local, mediaLocator, jingleSession);
} }
/** /**

View file

@ -27,6 +27,7 @@ import mil.jfcom.cie.media.srtp.packetizer.SpeexFormat;
import org.jivesoftware.smackx.jingle.media.JingleMediaSession; import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
import org.jivesoftware.smackx.jingle.media.PayloadType; import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import javax.media.NoProcessorException; import javax.media.NoProcessorException;
import javax.media.format.UnsupportedFormatException; import javax.media.format.UnsupportedFormatException;
@ -101,8 +102,8 @@ public class AudioMediaSession extends JingleMediaSession implements MediaSessio
* @param locator media locator * @param locator media locator
*/ */
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote, public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
final TransportCandidate local, String locator) { final TransportCandidate local, String locator, JingleSession jingleSession) {
super(payloadType, remote, local, locator==null?"dsound://":locator); super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession);
initialize(); initialize();
} }

View file

@ -24,6 +24,7 @@ import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
import org.jivesoftware.smackx.jingle.media.PayloadType; import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit; import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -54,8 +55,8 @@ public class SpeexMediaManager extends JingleMediaManager {
* @param local local Candidate * @param local local Candidate
* @return JingleMediaSession * @return JingleMediaSession
*/ */
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) { public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
return new AudioMediaSession(payloadType, remote, local, null); return new AudioMediaSession(payloadType, remote, local, null,null);
} }
/** /**

View file

@ -24,6 +24,7 @@ import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
import org.jivesoftware.smackx.jingle.media.JingleMediaSession; import org.jivesoftware.smackx.jingle.media.JingleMediaSession;
import org.jivesoftware.smackx.jingle.media.PayloadType; import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.*; import java.util.*;
@ -76,10 +77,10 @@ public class MultiMediaManager extends JingleMediaManager {
* @param local local Candidate * @param local local Candidate
* @return JingleMediaSession JingleMediaSession * @return JingleMediaSession JingleMediaSession
*/ */
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) { public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
for (JingleMediaManager manager : managers) { for (JingleMediaManager manager : managers) {
if (manager.getPayloads().contains(payloadType)) { if (manager.getPayloads().contains(payloadType)) {
return manager.createMediaSession(payloadType, remote, local); return manager.createMediaSession(payloadType, remote, local, jingleSession);
} }
} }
return null; return null;

View file

@ -26,6 +26,7 @@ import org.jivesoftware.smackx.jingle.media.PayloadType;
import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder; import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageEncoder;
import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder; import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageDecoder;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -72,9 +73,9 @@ public class ScreenShareMediaManager extends JingleMediaManager {
* @param local local Candidate * @param local local Candidate
* @return JingleMediaSession JingleMediaSession * @return JingleMediaSession JingleMediaSession
*/ */
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) { public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
ScreenShareSession session = null; ScreenShareSession session = null;
session = new ScreenShareSession(payloadType, remote, local, "Screen"); session = new ScreenShareSession(payloadType, remote, local, "Screen", jingleSession);
if (encoder != null) { if (encoder != null) {
session.setEncoder(encoder); session.setEncoder(encoder);
} }

View file

@ -26,6 +26,8 @@ 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.ImageReceiver;
import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageTransmitter; import org.jivesoftware.smackx.jingle.mediaimpl.sshare.api.ImageTransmitter;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate; import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import org.jivesoftware.smackx.jingle.IncomingJingleSession;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@ -33,6 +35,7 @@ import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.net.DatagramSocket;
/** /**
* This Class implements a complete JingleMediaSession. * This Class implements a complete JingleMediaSession.
@ -47,6 +50,8 @@ public class ScreenShareSession extends JingleMediaSession {
private ImageTransmitter transmitter = null; private ImageTransmitter transmitter = null;
private ImageReceiver receiver = 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 * Creates a org.jivesoftware.jingleaudio.jmf.AudioMediaSession with defined payload type, remote and local candidates
@ -57,8 +62,8 @@ public class ScreenShareSession extends JingleMediaSession {
* @param locator media locator * @param locator media locator
*/ */
public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote, public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote,
final TransportCandidate local, final String locator) { final TransportCandidate local, final String locator, JingleSession jingleSession) {
super(payloadType, remote, local, "Screen"); super(payloadType, remote, local, "Screen", jingleSession);
initialize(); initialize();
} }
@ -67,17 +72,19 @@ public class ScreenShareSession extends JingleMediaSession {
*/ */
public void initialize() { public void initialize() {
if (this.getJingleSession() instanceof IncomingJingleSession) {
JFrame window = new JFrame(); JFrame window = new JFrame();
JPanel jp = new JPanel(); JPanel jp = new JPanel();
window.add(jp); window.add(jp);
window.setLocation(0, 0); window.setLocation(0, 0);
window.setSize(400, 400); window.setSize(600, 600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try { try {
receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), 800, 600); receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), width, height);
System.out.println("Receiving on:" + receiver.getLocalPort()); System.out.println("Receiving on:" + receiver.getLocalPort());
} }
catch (UnknownHostException e) { catch (UnknownHostException e) {
@ -88,15 +95,16 @@ public class ScreenShareSession extends JingleMediaSession {
receiver.setVisible(true); receiver.setVisible(true);
window.setAlwaysOnTop(true); window.setAlwaysOnTop(true);
window.setVisible(true); window.setVisible(true);
}
else {
try { try {
InetAddress remote = InetAddress.getByName(getRemote().getIp()); InetAddress remote = InetAddress.getByName(getRemote().getIp());
transmitter = new ImageTransmitter(receiver.getDatagramSocket(), remote, getRemote().getPort(), new Rectangle(0, 0, 800, 600)); transmitter = new ImageTransmitter(new DatagramSocket(getLocal().getPort()), remote, getRemote().getPort(), new Rectangle(0, 0, width, height));
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace();
}
} }
} }
/** /**

View file

@ -31,9 +31,8 @@ public class ImageTransmitter implements Runnable {
private int tiles[][][]; private int tiles[][][];
private int maxI; private int maxI;
private int maxJ; private int maxJ;
private boolean changed = false;
private final Object sync = new Object();
private ImageEncoder encoder; private ImageEncoder encoder;
public final static int KEYFRAME = 10;
public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) { public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) {
@ -66,93 +65,23 @@ public class ImageTransmitter implements Runnable {
byte buf[] = new byte[1024]; byte buf[] = new byte[1024];
final DatagramPacket p = new DatagramPacket(buf, 1024); final DatagramPacket p = new DatagramPacket(buf, 1024);
/* int keyframe = 0;
new Thread(
new Runnable() {
public void run() {
int w = (int) area.getWidth();
int h = (int) area.getHeight();
int tiles[][][] = new int[maxI][maxJ][tileWidth * tileWidth];
while (on) {
if (transmit) {
boolean differ = false;
BufferedImage capture = robot.createScreenCapture(area);
//ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
//ColorConvertOp op = new ColorConvertOp(cs, null);
//capture = op.filter(capture, null);
QuantizeFilter filter = new QuantizeFilter();
capture = filter.filter(capture, null);
long trace = System.currentTimeMillis();
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 (!differ) {
if (!Arrays.equals(tiles[i][j], pixels)) {
differ = true;
}
}
tiles[i][j] = pixels;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (differ) {
synchronized (sync) {
changed = true;
}
}
trace = (System.currentTimeMillis() - trace);
System.err.println("Loop Time:" + trace);
if (trace < 250) {
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
).start();
*/
while (on) { while (on) {
if (transmit) { if (transmit) {
BufferedImage capture = robot.createScreenCapture(area); BufferedImage capture = robot.createScreenCapture(area);
//ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
//ColorConvertOp op = new ColorConvertOp(cs, null);
//capture = op.filter(capture, null);
QuantizeFilter filter = new QuantizeFilter(); QuantizeFilter filter = new QuantizeFilter();
capture = filter.filter(capture, null); capture = filter.filter(capture, null);
long trace = System.currentTimeMillis(); long trace = System.currentTimeMillis();
if (++keyframe > KEYFRAME) {
keyframe = 0;
}
System.out.println("KEYFRAME:" + keyframe);
for (int i = 0; i < maxI; i++) { for (int i = 0; i < maxI; i++) {
for (int j = 0; j < maxJ; j++) { for (int j = 0; j < maxJ; j++) {
@ -165,7 +94,7 @@ public class ImageTransmitter implements Runnable {
try { try {
if (pg.grabPixels()) { if (pg.grabPixels()) {
if (!Arrays.equals(tiles[i][j], pixels)) { if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) {
ByteArrayOutputStream baos = encoder.encode(bufferedImage); ByteArrayOutputStream baos = encoder.encode(bufferedImage);
@ -178,7 +107,7 @@ public class ImageTransmitter implements Runnable {
byte[] bytesOut = baos.toByteArray(); byte[] bytesOut = baos.toByteArray();
if (bytesOut.length > 400) if (bytesOut.length > 1000)
System.err.println(bytesOut.length); System.err.println(bytesOut.length);
p.setData(bytesOut); p.setData(bytesOut);
@ -225,14 +154,26 @@ public class ImageTransmitter implements Runnable {
start(); start();
} }
/**
* Set Transmit Enabled/Disabled
* @param transmit boolean Enabled/Disabled
*/
public void setTransmit(boolean transmit) { public void setTransmit(boolean transmit) {
this.transmit = transmit; this.transmit = transmit;
} }
/**
* Get the encoder used to encode Images Tiles
* @return encoder
*/
public ImageEncoder getEncoder() { public ImageEncoder getEncoder() {
return encoder; return encoder;
} }
/**
* Set the encoder used to encode Image Tiles
* @param encoder encoder
*/
public void setEncoder(ImageEncoder encoder) { public void setEncoder(ImageEncoder encoder) {
this.encoder = encoder; this.encoder = encoder;
} }

View file

@ -835,8 +835,8 @@ public class JingleManagerTest extends SmackTestCase {
JingleMediaManager jingleMediaManager = new JingleMediaManager() { JingleMediaManager jingleMediaManager = new JingleMediaManager() {
// Media Session Implementation // Media Session Implementation
public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) { public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
return new JingleMediaSession(payloadType, remote, local, null) { return new JingleMediaSession(payloadType, remote, local, null,null) {
public void initialize() { public void initialize() {

View file

@ -1,3 +1,5 @@
package org.jivesoftware.smackx.jingle;
/** /**
* $RCSfile$ * $RCSfile$
* $Revision: $ * $Revision: $
@ -277,8 +279,6 @@ public class JingleMediaTest extends SmackTestCase {
try { try {
//XMPPConnection.DEBUG_ENABLED = true;
XMPPConnection x0 = getConnection(0); XMPPConnection x0 = getConnection(0);
XMPPConnection x1 = getConnection(1); XMPPConnection x1 = getConnection(1);