Fri Apr 10, 2009 9:44 pm
**** THE CODE****
package project1;
import javax.media.*;
import javax.media.format.*;
import javax.media.protocol.*;
import java.util.*;
/*******************************************************************************
* A simple application to allow users to capture video through devices
* connected to the PC. Via command-line arguments the user specifies whether
* video (-v) capture, the duration of the capture (-d) in
* seconds, and the file to write the media to (-f).
*
* The application would be far more useful and versatile if it provided control
* over the formats of the audio and video captured as well as the content type
* of the output.
*
* The class searches for capture devices that support the particular default
* track formats: linear for audio and Cinepak for video. As a fall-back two
* device names are hard-coded into the application as an example of how to
* obtain DeviceInfo when a device's name is known. The user may force the
* application to use these names by using the -k (known devices) flag.
*
* The class is static but employs the earlier Location2Location example to
* perform all the Processor and DataSink related work. Thus the application
* chiefly involves CaptureDevice related operations.
*
* @author Michael (Spike) Barlow
******************************************************************************/
public class SimpleRecorder {
/////////////////////////////////////////////////////////////
// Names for the audio and video capture devices on the
// author's system. These will vary system to system but are
// only used as a fallback.
/////////////////////////////////////////////////////////////
private static final String VIDEO_DEVICE_NAME = "vfw:Microsoft WDM Image Capture (Win32):0";
///////////////////////////////////////////////////////////
// Default names for the files to write the output to for
// the case where they are not supplie by the user.
//////////////////////////////////////////////////////////
private static final String DEFAULT_VIDEO_NAME = "file:D:\\M1"+new Date().toString().replace(":", ";")+".avi";
///////////////////////////////////////////
// Type of capture requested by the user.
//////////////////////////////////////////
private static final String VIDEO = "video";
////////////////////////////////////////////////////////////////////
// The only audio and video formats that the particular application
// supports. A better program would allow user selection of formats
// but would grow past the small example size.
////////////////////////////////////////////////////////////////////
private static final Format VIDEO_FORMAT = new VideoFormat(
VideoFormat.CINEPAK);
public SimpleRecorder()
{
//////////////////////////////////////////////////////
// Object to handle the processing and sinking of the
// data captured from the device.
//////////////////////////////////////////////////////
Location2Location capture;
/////////////////////////////////////
// Audio and video capture devices.
////////////////////////////////////
// CaptureDeviceInfo audioDevice = null;
CaptureDeviceInfo videoDevice = null;
/////////////////////////////////////////////////////////////
// Capture device's "location" plus the name and location of
// the destination.
/////////////////////////////////////////////////////////////
MediaLocator captureLocation = null;
MediaLocator destinationLocation;
String destinationName = null;
////////////////////////////////////////////////////////////
// Formats the Processor (in Location2Location) must match.
////////////////////////////////////////////////////////////
Format[] formats = new Format[1];
///////////////////////////////////////////////
// Content type for an audio or video capture.
//////////////////////////////////////////////
ContentDescriptor videoContainer = new ContentDescriptor(
FileTypeDescriptor.MSVIDEO);
ContentDescriptor container = null;
////////////////////////////////////////////////////////////////////
// Duration of recording (in seconds) and period to wait afterwards
///////////////////////////////////////////////////////////////////
double duration = 10;
int waitFor = 0;
//////////////////////////
// Audio or video capture?
//////////////////////////
String selected =VIDEO ;
////////////////////////////////////////////////////////
// All devices that support the format in question.
// A means of "ensuring" the program works on different
// machines with different capture devices.
////////////////////////////////////////////////////////
Vector devices;
//////////////////////////////////////////////////////////
// Whether to search for capture devices that support the
// format or use the devices whos names are already
// known to the application.
//////////////////////////////////////////////////////////
boolean useKnownDevices = false;
/////////////////////////////////////////////////////////////////
// Perform setup for video capture. Includes finding a suitable
// device, obatining its MediaLocator and setting the content
// type.
////////////////////////////////////////////////////////////////
if (selected.equals(VIDEO)) {
devices = CaptureDeviceManager.getDeviceList(VIDEO_FORMAT);
if (devices.size() > 0 && !useKnownDevices)
videoDevice = (CaptureDeviceInfo) devices.elementAt(0);
else
videoDevice = CaptureDeviceManager.getDevice(VIDEO_DEVICE_NAME);
if (videoDevice == null) {
System.out.println("Can't find suitable video device. Exiting");
System.exit(1);
}
captureLocation = videoDevice.getLocator();
formats[0] = VIDEO_FORMAT;
if (destinationName == null)
destinationName = DEFAULT_VIDEO_NAME;
container = videoContainer;
////////////////////////////////////////////////////////////////////
// Perform all the necessary Processor and DataSink preparation via
// the Location2Location class.
////////////////////////////////////////////////////////////////////
destinationLocation = new MediaLocator(destinationName);
System.out.println("Configuring for capture. Please wait.");
capture = new Location2Location(captureLocation, destinationLocation,
formats, container, 4.0);
/////////////////////////////////////////////////////////////////////////////
// Start the recording and tell the user. Specify the length of the
// recording. Then wait around for up to 4-times the duration of
// recording
// (can take longer to sink/write the data so should wait a bit incase).
/////////////////////////////////////////////////////////////////////////////
System.out.println("Started recording " + duration + " seconds of "
+ selected + " ...");
capture.setStopTime(new Time(duration));
if (waitFor == 0)
waitFor = (int) (4000 * duration);
else
waitFor *= 1000;
int waited = capture.transfer(waitFor);
/////////////////////////////////////////////////////////
// Report on the success (or otherwise) of the recording.
/////////////////////////////////////////////////////////
int state = capture.getState();
if (state == Location2Location.FINISHED)
System.out.println(selected
+ " capture successful in approximately "
+ ((int) ((waited + 500) / 1000))
+ " seconds. Data written to " + destinationName);
else if (state == Location2Location.FAILED)
System.out.println(selected
+ " capture failed after approximately "
+ ((int) ((waited + 500) / 1000)) + " seconds");
else {
System.out.println(selected
+ " capture still ongoing after approximately "
+ ((int) ((waited + 500) / 1000)) + " seconds");
System.out.println("Process likely to have failed");
}
System.exit(0);
}
}
}
[color=#0000FF]the second class [/color]
package project1;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.datasink.*;
public class Location2Location implements ControllerListener {
/** Output of the Processor: the transcoded media. */
protected DataSource source;
/** Sink used to "write" out the transcoded media. */
protected DataSink sink;
/** Processor used to transcode the media. */
protected Processor processor;
/** Model used in constructing the processor, and which
* specifies track formats and output content type */
protected ProcessorModel model;
/** State the object is in. */
protected int state;
/** Location that the media will be "written" to. */
protected MediaLocator sinkLocation;
/** The rate of translation. */
protected float translationRate;
/** Process has failed. */
public static final int FAILED = 0;
/** Processor is working but not finished. DataSink is yet
* to start. */
public static final int TRANSLATING = 1;
/** DataSink has started but not finished. */
public static final int TRANSFERRING = 3;
/** Transcoding and transfer is complete. */
public static final int FINISHED = 4;
/** String names for each of the states. More user friendly */
private static final String[] STATE_NAMES = {
"Failed", "Translating", "<UNUSED>", "Transferring",
"Finished"};
/** Period (in milliseconds) between checks for the blocking
* transfer method. */
public static final int WAIT_PERIOD = 50;
/** Wait an "indefinite" period of time for the transfer
* method to complete. i.e., pass to transfer() if the
* user wishes to block till the process is complete,
* regardless of how long it will take. */
public static final int INDEFINITE = Integer.MAX_VALUE;
/*******************************************************************
* Construct a transfer/transcode object that transfers media from
* sourceLocation to destinationLocation, transcoding the tracks as
* specified by the outputFormats. The output media is to have a
* content type of outputContainer and the process should (if
* possible) run at the passed rate.
*********************************************************************/
Location2Location(MediaLocator sourceLocation,
MediaLocator destinationLocation, Format[] outputFormats,
ContentDescriptor outputContainer, double rate) {
//////////////////////////////////////////////
// Construct the processor for the transcoding
//////////////////////////////////////////////
state = TRANSLATING;
sinkLocation = destinationLocation;
try {
if (sourceLocation==null)
model = new ProcessorModel(outputFormats,outputContainer);
else
model = new ProcessorModel(sourceLocation,
outputFormats,outputContainer);
processor = Manager.createRealizedProcessor(model);
}
catch (Exception e) {
state = FAILED;
return;
}
translationRate = processor.setRate((float)Math.abs(rate));
processor.addControllerListener(this);
////////////////////////////////////////////////////////////
// Construct the DataSink and employ an anonymous class as
// a DataSink listener in order that the end of transfer
// (completion of task) can be detected.
///////////////////////////////////////////////////////////
source = processor.getDataOutput();
try {
sink = Manager.createDataSink(source,sinkLocation);
}
catch (Exception sinkException) {
state = FAILED;
processor.removeControllerListener(this);
processor.close();
processor = null;
return;
}
sink.addDataSinkListener(new DataSinkListener() {
public void dataSinkUpdate(DataSinkEvent e) {
if (e instanceof EndOfStreamEvent) {
sink.close();
source.disconnect();
if (state!=FAILED)
state = FINISHED;
}
else if (e instanceof DataSinkErrorEvent) {
if (sink!=null)
sink.close();
if (source!=null)
source.disconnect();
state = FAILED;
}
}
});
// Start the transcoding
processor.start();
}
/**************************************************************
* Respond to events from the Processor performing the transcoding.
* If its task is completed (end of media) close it down. If there
* is an error close it down and mark the process as FAILED.
*****************************************************************/
public synchronized void controllerUpdate(ControllerEvent e) {
if (state==FAILED)
return;
// Transcoding complete.
if (e instanceof StopEvent) {
processor.removeControllerListener(this);
processor.close();
if (state==TRANSLATING)
state = TRANSFERRING;
}
// Transcoding failed.
else if (e instanceof ControllerErrorEvent) {
processor.removeControllerListener(this);
processor.close();
state = FAILED;
}
}
/***********************************************************
* Initiate the transfer through a DataSink to the destination
* and wait (block) until the process is complete (or failed)
* or the supplied number of milliseconds timeout has passed.
* The method returns the total amount of time it blocked.
*************************************************************/
public int transfer(int timeOut) {
// Can't initiate: Processor already failed to transcode
if (state==FAILED)
return -1;
// Start the DataSink
try {
sink.open();
sink.start();
}
catch (Exception e) {
state = FAILED;
return -1;
}
if (state==TRANSLATING)
state = TRANSFERRING;
if (timeOut<=0)
return timeOut;
// Wait till the process is complete, failed, or the
// prescribed time has passed.
/////////////////////////////////////////////////////
int waited = 0;
while (state!=FAILED && state!=FINISHED && waited<timeOut) {
try { Thread.sleep(WAIT_PERIOD); }
catch (InterruptedException ie) { }
waited += WAIT_PERIOD;
}
return waited;
}
/***************************************************
* Initiate the transfer through a DataSink to the
* destination but return immediately to the caller.
****************************************************/
public void transfer() {
transfer(-1);
}
/***************************************************
* Determine the object's current state. Returns one
* of the class constants.
****************************************************/
public int getState() {
return state;
}
/***************************************************
* Returns the object's state as a String. A more
* user friendly version of getState().
****************************************************/
public String getStateName() {
return STATE_NAMES[state];
}
/***************************************************
* Obtain the rate being used for the process. This
* is often 1, despite what the user may have supplied
* as Clocks (hence Processors) don't have to support
* any other rate than 1 (and will default to that).
****************************************************/
public float getRate() {
return translationRate;
}
/***************************************************
* Set the time at which media processing will stop.
* Specification is in media time. This means only
* the first "when" amount of the media will be
* transferred.
****************************************************/
public void setStopTime(Time when) {
if (processor!=null)
processor.setStopTime(when);
}
/***************************************************
* Stop the processing and hence transfer. This
* gives user control over the duration of a
* transfer. It could be started with the transfer()
* call and after a specified period stop() could
* be called.
****************************************************/
public void stop() {
if (processor!=null)
processor.stop();
}
}
Sat Apr 11, 2009 8:18 am
Sat Apr 11, 2009 8:39 am
Codemiles.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com
Powered by phpBB © phpBB Group.