[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();
lc.removeCandidateEcho();
jingleMediaSession = jingleMediaManager.createMediaSession(pt, rc, lc);
jingleMediaSession = jingleMediaManager.createMediaSession(pt, rc, lc, this);
jingleMediaSession.addMediaReceivedListener(this);
if (jingleMediaSession != null) {

View File

@ -21,6 +21,7 @@
package org.jivesoftware.smackx.jingle.media;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.ArrayList;
import java.util.List;
@ -60,6 +61,6 @@ public abstract class JingleMediaManager {
* @param local
* @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;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.List;
import java.util.ArrayList;
@ -48,6 +49,8 @@ public abstract class JingleMediaSession {
private String mediaLocator;
// Media Received Listener
private List<MediaReceivedListener> mediaReceivedListeners = new ArrayList<MediaReceivedListener>();
// Jingle Session
private JingleSession jingleSession;
/**
* 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
*/
public JingleMediaSession(PayloadType payloadType, TransportCandidate remote,
TransportCandidate local, String mediaLocator) {
TransportCandidate local, String mediaLocator, JingleSession jingleSession) {
this.local = local;
this.remote = remote;
this.payloadType = payloadType;
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.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import javax.media.MediaLocator;
import java.io.IOException;
@ -51,8 +52,8 @@ public class AudioMediaSession extends JingleMediaSession {
* @param locator media locator
*/
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
final TransportCandidate local, String locator) {
super(payloadType, remote, local, locator==null?"dsound://":locator);
final TransportCandidate local, String locator, JingleSession jingleSession) {
super(payloadType, remote, local, locator==null?"dsound://":locator,jingleSession);
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.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.io.File;
import java.io.IOException;
@ -68,8 +69,8 @@ public class JmfMediaManager extends JingleMediaManager {
* @param local local Candidate
* @return JingleMediaSession
*/
public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) {
return new AudioMediaSession(payloadType, remote, local,mediaLocator);
public JingleMediaSession createMediaSession(final PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
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.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import javax.media.NoProcessorException;
import javax.media.format.UnsupportedFormatException;
@ -55,15 +56,15 @@ public class AudioMediaSession extends JingleMediaSession implements MediaSessio
/**
* Create a Session using Speex Codec
*
* @param localhost localHost
* @param localPort localPort
* @param remoteHost remoteHost
* @param remotePort remotePort
*
* @param localhost localHost
* @param localPort localPort
* @param remoteHost remoteHost
* @param remotePort remotePort
* @param eventHandler eventHandler
* @param quality quality
* @param secure secure
* @param micOn micOn
* @param quality quality
* @param secure secure
* @param micOn micOn
* @return MediaSession
* @throws NoProcessorException
* @throws UnsupportedFormatException
@ -101,8 +102,8 @@ public class AudioMediaSession extends JingleMediaSession implements MediaSessio
* @param locator media locator
*/
public AudioMediaSession(final PayloadType payloadType, final TransportCandidate remote,
final TransportCandidate local, String locator) {
super(payloadType, remote, local, locator==null?"dsound://":locator);
final TransportCandidate local, String locator, JingleSession jingleSession) {
super(payloadType, remote, local, locator == null ? "dsound://" : locator, jingleSession);
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.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.mediaimpl.JMFInit;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.io.File;
import java.io.IOException;
@ -54,8 +55,8 @@ public class SpeexMediaManager extends JingleMediaManager {
* @param local local Candidate
* @return JingleMediaSession
*/
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local) {
return new AudioMediaSession(payloadType, remote, local, null);
public JingleMediaSession createMediaSession(PayloadType payloadType, final TransportCandidate remote, final TransportCandidate local, final JingleSession jingleSession) {
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.PayloadType;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.*;
@ -76,10 +77,10 @@ public class MultiMediaManager extends JingleMediaManager {
* @param local local Candidate
* @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) {
if (manager.getPayloads().contains(payloadType)) {
return manager.createMediaSession(payloadType, remote, local);
return manager.createMediaSession(payloadType, remote, local, jingleSession);
}
}
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.ImageDecoder;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import java.util.ArrayList;
import java.util.List;
@ -72,9 +73,9 @@ public class ScreenShareMediaManager extends JingleMediaManager {
* @param local local Candidate
* @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;
session = new ScreenShareSession(payloadType, remote, local, "Screen");
session = new ScreenShareSession(payloadType, remote, local, "Screen", jingleSession);
if (encoder != null) {
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.ImageTransmitter;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
import org.jivesoftware.smackx.jingle.JingleSession;
import org.jivesoftware.smackx.jingle.IncomingJingleSession;
import javax.swing.*;
import java.awt.*;
@ -33,6 +35,7 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.net.DatagramSocket;
/**
* This Class implements a complete JingleMediaSession.
@ -47,6 +50,8 @@ public class ScreenShareSession extends JingleMediaSession {
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
@ -57,8 +62,8 @@ public class ScreenShareSession extends JingleMediaSession {
* @param locator media locator
*/
public ScreenShareSession(final PayloadType payloadType, final TransportCandidate remote,
final TransportCandidate local, final String locator) {
super(payloadType, remote, local, "Screen");
final TransportCandidate local, final String locator, JingleSession jingleSession) {
super(payloadType, remote, local, "Screen", jingleSession);
initialize();
}
@ -67,36 +72,39 @@ public class ScreenShareSession extends JingleMediaSession {
*/
public void initialize() {
JFrame window = new JFrame();
JPanel jp = new JPanel();
window.add(jp);
if (this.getJingleSession() instanceof IncomingJingleSession) {
window.setLocation(0, 0);
window.setSize(400, 400);
JFrame window = new JFrame();
JPanel jp = new JPanel();
window.add(jp);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocation(0, 0);
window.setSize(600, 600);
try {
receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), 800, 600);
System.out.println("Receiving on:" + receiver.getLocalPort());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
receiver = new ImageReceiver(InetAddress.getByName("0.0.0.0"), getRemote().getPort(), getLocal().getPort(), width, height);
System.out.println("Receiving on:" + receiver.getLocalPort());
}
catch (UnknownHostException e) {
e.printStackTrace();
}
jp.add(receiver);
receiver.setVisible(true);
window.setAlwaysOnTop(true);
window.setVisible(true);
}
catch (UnknownHostException e) {
e.printStackTrace();
else {
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();
}
}
jp.add(receiver);
receiver.setVisible(true);
window.setAlwaysOnTop(true);
window.setVisible(true);
try {
InetAddress remote = InetAddress.getByName(getRemote().getIp());
transmitter = new ImageTransmitter(receiver.getDatagramSocket(), remote, getRemote().getPort(), new Rectangle(0, 0, 800, 600));
}
catch (Exception e) {
}
}
/**

View File

@ -31,9 +31,8 @@ public class ImageTransmitter implements Runnable {
private int tiles[][][];
private int maxI;
private int maxJ;
private boolean changed = false;
private final Object sync = new Object();
private ImageEncoder encoder;
public final static int KEYFRAME = 10;
public ImageTransmitter(DatagramSocket socket, InetAddress remoteHost, int remotePort, Rectangle area) {
@ -66,93 +65,23 @@ public class ImageTransmitter implements Runnable {
byte buf[] = new byte[1024];
final DatagramPacket p = new DatagramPacket(buf, 1024);
/*
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();
*/
int keyframe = 0;
while (on) {
if (transmit) {
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();
if (++keyframe > KEYFRAME) {
keyframe = 0;
}
System.out.println("KEYFRAME:" + keyframe);
for (int i = 0; i < maxI; i++) {
for (int j = 0; j < maxJ; j++) {
@ -165,7 +94,7 @@ public class ImageTransmitter implements Runnable {
try {
if (pg.grabPixels()) {
if (!Arrays.equals(tiles[i][j], pixels)) {
if (keyframe == KEYFRAME || !Arrays.equals(tiles[i][j], pixels)) {
ByteArrayOutputStream baos = encoder.encode(bufferedImage);
@ -178,7 +107,7 @@ public class ImageTransmitter implements Runnable {
byte[] bytesOut = baos.toByteArray();
if (bytesOut.length > 400)
if (bytesOut.length > 1000)
System.err.println(bytesOut.length);
p.setData(bytesOut);
@ -225,14 +154,26 @@ public class ImageTransmitter implements Runnable {
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;
}

View File

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

View File

@ -1,3 +1,5 @@
package org.jivesoftware.smackx.jingle;
/**
* $RCSfile$
* $Revision: $
@ -277,8 +279,6 @@ public class JingleMediaTest extends SmackTestCase {
try {
//XMPPConnection.DEBUG_ENABLED = true;
XMPPConnection x0 = getConnection(0);
XMPPConnection x1 = getConnection(1);
@ -297,7 +297,7 @@ public class JingleMediaTest extends SmackTestCase {
public void sessionRequested(final JingleSessionRequest request) {
try {
IncomingJingleSession session = request.accept(jm1.getMediaManager().getPayloads());
session.start(request);