Hello,
In my project I have to capture screen activity (including audio) to a video file. I try using JMF for this. I don't know how to use those two classes: DataSource.java and LiveStream.java. I read them line by line. I probably have to create a Processor and feed it with that DataSource. Can someone give me a hint? Or CODE? I read a lot of examples but I couldn't understand yet how to create a screen-captur using JMF and save it to disk.
The two classes:
//DataSource
import javax.media.Time;
import javax.media.protocol.*;
import java.io.IOException;
/**
* This DataSource captures live frames from the screen.
* You can specify the location, size and frame rate in the
* URL string as follows:
* screen://x,y,width,height/framespersecond
* Eg:
* screen://20,40,160,120/12.5
* Note:
* Requires JDK 1.3+ to compile and run
*/
public class DataSource extends PushBufferDataSource {
protected Object [] controls = new Object[0];
protected boolean started = false;
protected String contentType = "raw";
protected boolean connected = false;
protected Time duration = DURATION_UNBOUNDED;
protected LiveStream [] streams = null;
protected LiveStream stream = null;
public DataSource() {
}
public String getContentType() {
if (!connected){
System.err.println("Error: DataSource not connected");
return null;
}
return contentType;
}
public void connect() throws IOException {
if (connected)
return;
connected = true;
}
public void disconnect() {
try {
if (started)
stop();
} catch (IOException e) {}
connected = false;
}
public void start() throws IOException {
// we need to throw error if connect() has not been called
if (!connected)
throw new java.lang.Error("DataSource must be connected before it can be started");
if (started)
return;
started = true;
stream.start(true);
}
public void stop() throws IOException {
if ((!connected) || (!started))
return;
started = false;
stream.start(false);
}
public Object [] getControls() {
return controls;
}
public Object getControl(String controlType) {
return null;
}
public Time getDuration() {
return duration;
}
public PushBufferStream [] getStreams() {
if (streams == null) {
streams = new LiveStream[1];
stream = streams[0] = new LiveStream(getLocator());
}
return streams;
}
}
//LiveStream - this takes snapshots and feeds it to DataSource
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.media.*;
import javax.media.format.*;
import javax.media.protocol.*;
import java.io.IOException;
import java.util.StringTokenizer;
public class LiveStream implements PushBufferStream, Runnable {
protected ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW);
protected int maxDataLength;
protected int [] data;
protected Dimension size;
protected RGBFormat rgbFormat;
protected boolean started;
protected Thread thread;
protected float frameRate = 1f;
protected BufferTransferHandler transferHandler;
protected Control [] controls = new Control[0];
protected int x, y, width, height;
protected Robot robot = null;
public LiveStream(MediaLocator locator) {
try {
parseLocator(locator);
} catch (Exception e) {
System.err.println(e);
}
//size = Toolkit.getDefaultToolkit().getScreenSize();
size = new Dimension(width, height);
try {
robot = new Robot();
} catch (AWTException awe) {
throw new RuntimeException("");
}
maxDataLength = size.width * size.height * 3;
rgbFormat = new RGBFormat(size, maxDataLength,
Format.intArray,
frameRate,
32,
0xFF0000, 0xFF00, 0xFF,
1, size.width,
VideoFormat.FALSE,
Format.NOT_SPECIFIED);
// generate the data
data = new int[maxDataLength];
thread = new Thread(this, "Screen Grabber");
}
protected void parseLocator(MediaLocator locator) {
// this parses the locator. e.g.: screen://x,y,width,height/fps
String rem = locator.getRemainder();
// Strip off starting slashes
while (rem.startsWith("/") && rem.length() > 1)
rem = rem.substring(1);
StringTokenizer st = new StringTokenizer(rem, "/");
if (st.hasMoreTokens()) {
// Parse the position
String position = st.nextToken();
StringTokenizer nums = new StringTokenizer(position, ",");
String stX = nums.nextToken();
String stY = nums.nextToken();
String stW = nums.nextToken();
String stH = nums.nextToken();
x = Integer.parseInt(stX);
y = Integer.parseInt(stY);
width = Integer.parseInt(stW);
height = Integer.parseInt(stH);
}
if (st.hasMoreTokens()) {
// Parse the frame rate
String stFPS = st.nextToken();
frameRate = (Double.valueOf(stFPS)).floatValue();
}
}
/***************************************************************************
* SourceStream
***************************************************************************/
public ContentDescriptor getContentDescriptor() {
return cd;
}
public long getContentLength() {
return LENGTH_UNKNOWN;
}
public boolean endOfStream() {
return false;
}
/***************************************************************************
* PushBufferStream
***************************************************************************/
int seqNo = 0;
public Format getFormat() {
return rgbFormat;
}
public void read(Buffer buffer) throws IOException {
synchronized (this) {
Object outdata = buffer.getData();
if (outdata == null || !(outdata.getClass() == Format.intArray) ||
((int[])outdata).length < maxDataLength) {
outdata = new int[maxDataLength];
buffer.setData(outdata);
}
buffer.setFormat( rgbFormat );
buffer.setTimeStamp( (long) (seqNo * (1000 / frameRate) * 1000000) );
BufferedImage bi = robot.createScreenCapture(new Rectangle(x, y, width, height));
bi.getRGB(0, 0, width, height,
(int[])outdata, 0, width);
buffer.setSequenceNumber( seqNo );
buffer.setLength(maxDataLength);
buffer.setFlags(Buffer.FLAG_KEY_FRAME);
buffer.setHeader( null );
seqNo++;
}
}
public void setTransferHandler(BufferTransferHandler transferHandler) {
synchronized (this) {
this.transferHandler = transferHandler;
notifyAll();
}
}
void start(boolean started) {
synchronized ( this ) {
this.started = started;
if (started && !thread.isAlive()) {
thread = new Thread(this);
thread.start();
}
notifyAll();
}
}
/***************************************************************************
* Runnable
***************************************************************************/
public void run() {
while (started) {
synchronized (this) {
while (transferHandler == null && started) {
try {
wait(1000);
} catch (InterruptedException ie) {
}
} // while
}
if (started && transferHandler != null) {
transferHandler.transferData(this);
try {
Thread.currentThread().sleep( 10 );
} catch (InterruptedException ise) {
}
}
} // while (started)
} // run
// Controls
public Object [] getControls() {
return controls;
}
public Object getControl(String controlType) {
try {
Class cls = Class.forName(controlType);
Object cs[] = getControls();
for (int i = 0; i < cs.length; i++) {
if (cls.isInstance(cs[i]))
return cs[i];
}
return null;
} catch (Exception e) { // no such controlType or such control
return null;
}
}
}
Some other resources:
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules/java-3d/com/db/layers/underlay/Capturer.java.htm
(I read about screen graber and all those sun examples and I googled so much... spent days...)
I didn't find a full example that captures the screen to a video file yet. Somebody help please? I would apreciate it so much...