I am trying to encode some images of same resolution into a video file using, For that I have tried:
jCodec
jcodec..example description
But it is very time consuming and not a proper tool to encode large number of images and it creates a quick time extension.
FFMPEG
FFMPEG..example description
But ffmpeg only able to create video from image files. Images need to be create on physical system.
I have heard Xuggler that its APIs can be used in java program to create video file but as its site seems broken. I am unable to try it.
Does anybody know how to encode images in java format into a video file Please help!
THanks in Advance !
Xuggler is deprecated, use Humble-Video instead. It already comes with some demo projects, including how to take screenshots and convert it to a video file: RecordAndEncodeVideo.java
/*******************************************************************************
* Copyright (c) 2014, Art Clarke. All rights reserved.
* <p>
* This file is part of Humble-Video.
* <p>
* Humble-Video is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* <p>
* Humble-Video is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* <p>
* You should have received a copy of the GNU Affero General Public License
* along with Humble-Video. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package io.humble.video.demos;
import io.humble.video.*;
import io.humble.video.awt.MediaPictureConverter;
import io.humble.video.awt.MediaPictureConverterFactory;
import org.apache.commons.cli.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
* Records the contents of your computer screen to a media file for the passed in duration.
* This is meant as a demonstration program to teach the use of the Humble API.
* <p>
* Concepts introduced:
* </p>
* <ul>
* <li>Muxer: A {#link Muxer} object is a container you can write media data to.</li>
* <li>Encoders: An {#link Encoder} object lets you convert {#link MediaAudio} or {#link MediaPicture} objects into {#link MediaPacket} objects
* so they can be written to {#link Muxer} objects.</li>
* </ul>
*
* <p>
* To run from maven, do:
* </p>
* <pre>
* mvn install exec:java -Dexec.mainClass="io.humble.video.demos.RecordAndEncodeVideo" -Dexec.args="filename.mp4"
* </pre>
*
* #author aclarke
*
*/
public class RecordAndEncodeVideo
{
/**
* Records the screen
*/
private static void recordScreen (String filename, String formatname, String codecname, int duration, int snapsPerSecond) throws AWTException, InterruptedException, IOException
{
/**
* Set up the AWT infrastructure to take screenshots of the desktop.
*/
final Robot robot = new Robot();
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Rectangle screenbounds = new Rectangle(toolkit.getScreenSize());
final Rational framerate = Rational.make(1, snapsPerSecond);
/** First we create a muxer using the passed in filename and formatname if given. */
final Muxer muxer = Muxer.make(filename, null, formatname);
/** Now, we need to decide what type of codec to use to encode video. Muxers
* have limited sets of codecs they can use. We're going to pick the first one that
* works, or if the user supplied a codec name, we're going to force-fit that
* in instead.
*/
final MuxerFormat format = muxer.getFormat();
final Codec codec;
if (codecname != null)
{
codec = Codec.findEncodingCodecByName(codecname);
}
else
{
codec = Codec.findEncodingCodec(format.getDefaultVideoCodecId());
}
/**
* Now that we know what codec, we need to create an encoder
*/
Encoder encoder = Encoder.make(codec);
/**
* Video encoders need to know at a minimum:
* width
* height
* pixel format
* Some also need to know frame-rate (older codecs that had a fixed rate at which video files could
* be written needed this). There are many other options you can set on an encoder, but we're
* going to keep it simpler here.
*/
encoder.setWidth(screenbounds.width);
encoder.setHeight(screenbounds.height);
// We are going to use 420P as the format because that's what most video formats these days use
final PixelFormat.Type pixelformat = PixelFormat.Type.PIX_FMT_YUV420P;
encoder.setPixelFormat(pixelformat);
encoder.setTimeBase(framerate);
/** An annoynace of some formats is that they need global (rather than per-stream) headers,
* and in that case you have to tell the encoder. And since Encoders are decoupled from
* Muxers, there is no easy way to know this beyond
*/
if (format.getFlag(MuxerFormat.Flag.GLOBAL_HEADER))
{
encoder.setFlag(Encoder.Flag.FLAG_GLOBAL_HEADER, true);
}
/** Open the encoder. */
encoder.open(null, null);
/** Add this stream to the muxer. */
muxer.addNewStream(encoder);
/** And open the muxer for business. */
muxer.open(null, null);
/** Next, we need to make sure we have the right MediaPicture format objects
* to encode data with. Java (and most on-screen graphics programs) use some
* variant of Red-Green-Blue image encoding (a.k.a. RGB or BGR). Most video
* codecs use some variant of YCrCb formatting. So we're going to have to
* convert. To do that, we'll introduce a MediaPictureConverter object later. object.
*/
MediaPictureConverter converter = null;
final MediaPicture picture = MediaPicture.make(encoder.getWidth(), encoder.getHeight(), pixelformat);
picture.setTimeBase(framerate);
/** Now begin our main loop of taking screen snaps.
* We're going to encode and then write out any resulting packets. */
final MediaPacket packet = MediaPacket.make();
for (int i = 0; i < duration / framerate.getDouble(); i++)
{
/** Make the screen capture && convert image to TYPE_3BYTE_BGR */
final BufferedImage screen = convertToType(robot.createScreenCapture(screenbounds), BufferedImage.TYPE_3BYTE_BGR);
/** This is LIKELY not in YUV420P format, so we're going to convert it using some handy utilities. */
if (converter == null)
{
converter = MediaPictureConverterFactory.createConverter(screen, picture);
}
converter.toPicture(picture, screen, i);
do
{
encoder.encode(packet, picture);
if (packet.isComplete())
{
muxer.write(packet, false);
}
} while (packet.isComplete());
/** now we'll sleep until it's time to take the next snapshot. */
Thread.sleep((long) (1000 * framerate.getDouble()));
}
/** Encoders, like decoders, sometimes cache pictures so it can do the right key-frame optimizations.
* So, they need to be flushed as well. As with the decoders, the convention is to pass in a null
* input until the output is not complete.
*/
do
{
encoder.encode(packet, null);
if (packet.isComplete())
{
muxer.write(packet, false);
}
} while (packet.isComplete());
/** Finally, let's clean up after ourselves. */
muxer.close();
}
#SuppressWarnings("static-access")
public static void main (String[] args) throws InterruptedException, IOException, AWTException
{
final Options options = new Options();
options.addOption("h", "help", false, "displays help");
options.addOption("v", "version", false, "version of this library");
options.addOption(OptionBuilder.withArgName("format").withLongOpt("format").hasArg().
withDescription("muxer format to use. If unspecified, we will guess from filename").create("f"));
options.addOption(OptionBuilder.withArgName("codec")
.withLongOpt("codec")
.hasArg()
.withDescription("codec to use when encoding video; If unspecified, we will guess from format")
.create("c"));
options.addOption(OptionBuilder.withArgName("duration")
.withLongOpt("duration")
.hasArg()
.withDescription("number of seconds of screenshot to record; defaults to 10.")
.create("d"));
options.addOption(OptionBuilder.withArgName("snaps per second")
.withLongOpt("snaps")
.hasArg()
.withDescription("number of pictures to take per second (i.e. the frame rate); defaults to 5")
.create("s"));
final CommandLineParser parser = new org.apache.commons.cli.BasicParser();
try
{
final CommandLine cmd = parser.parse(options, args);
final String[] parsedArgs = cmd.getArgs();
if (cmd.hasOption("version"))
{
// let's find what version of the library we're running
final String version = io.humble.video_native.Version.getVersionInfo();
System.out.println("Humble Version: " + version);
}
else if (cmd.hasOption("help") || parsedArgs.length != 1)
{
final HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(RecordAndEncodeVideo.class.getCanonicalName() + " <filename>", options);
}
else
{
/**
* Read in some option values and their defaults.
*/
final int duration = Integer.parseInt(cmd.getOptionValue("duration", "10"));
if (duration <= 0)
{
throw new IllegalArgumentException("duration must be > 0");
}
final int snaps = Integer.parseInt(cmd.getOptionValue("snaps", "5"));
if (snaps <= 0)
{
throw new IllegalArgumentException("snaps must be > 0");
}
final String codecname = cmd.getOptionValue("codec");
final String formatname = cmd.getOptionValue("format");
final String filename = cmd.getArgs()[0];
recordScreen(filename, formatname, codecname, duration, snaps);
}
} catch (ParseException e)
{
System.err.println("Exception parsing command line: " + e.getLocalizedMessage());
}
}
/**
* Convert a {#link BufferedImage} of any type, to {#link BufferedImage} of a
* specified type. If the source image is the same type as the target type,
* then original image is returned, otherwise new image of the correct type is
* created and the content of the source image is copied into the new image.
*
* #param sourceImage
* the image to be converted
* #param targetType
* the desired BufferedImage type
*
* #return a BufferedImage of the specifed target type.
*
* #see BufferedImage
*/
public static BufferedImage convertToType (BufferedImage sourceImage, int targetType)
{
BufferedImage image;
// if the source image is already the target type, return the source image
if (sourceImage.getType() == targetType)
{
image = sourceImage;
}
// otherwise create a new image of the target type and draw the new
// image
else
{
image = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), targetType);
image.getGraphics().drawImage(sourceImage, 0, 0, null);
}
return image;
}
}
Check other demos too : humble-video-demos
I am using it for real time using on a webapp.
If you will gonna stream this in real time you will need a RTSP server. You can either use big frameworks like Red 5 Server, Wowza Streaming Engine or you can built your own server using Netty which has a built in RTSP codec since version 3.2.
Using command line, there are various ways to convert image to video. You can use those command in java for saving. You can get those commands from the following link:
Using ffmpeg to convert a set of images into a video
Create a video slideshow from images
I am sharing a code snippet to solve the issue:
code to save png image from HTML5 canvas
Base64 decoder = new Base64();
byte[] pic = decoder.decodeBase64(request.getParameter("pic"));
String frameCount = request.getParameter("frame");
InputStream in = new ByteArrayInputStream(pic);
BufferedImage bImageFromConvert = ImageIO.read(in);
String outdir = "output\\"+frameCount;
//Random rand = new Random();
File file = new File(outdir);
if(file.isFile()){
if(file.delete()){
File writefile = new File(outdir);
ImageIO.write(bImageFromConvert, "png", file);
}
}
Code for creating image from video
String filePath = "D:\\temp\\some.mpg";
String outdir = "output";
File file = new File(outdir);
file.mkdirs();
Map<String, String> m = System.getenv();
/*
* String command[] =
* {"D:\\ffmpeg-win32-static\\bin\\ffmpeg","-i",filePath
* ,"-r 30","-f","image2",outdir,"\\user%03d.jpg"};
*
* ProcessBuilder pb = new ProcessBuilder(command); pb.start();
*/
String commands = "D:\\ffmpeg-win32-static\\bin\\ffmpeg -i " + filePath
+ " -r 30 -f image2 " + outdir + "\\image%5d.png";
Process p = Runtime.getRuntime().exec(commands);
code for creating video from image
String filePath = "output";
File fileP = new File(filePath);
String commands = "D:\\ffmpeg-win32-static\\bin\\ffmpeg -f image2 -i "
+ fileP + "\\image%5d.png " + fileP + "\\video.mp4";
System.out.println(commands);
Runtime.getRuntime().exec(commands);
System.out.println(fileP.getAbsolutePath());
Credit goes to #yashprit
Another approach for Android developers:
Create a temporary folder inside the Android.
Copy your images in the new folder
First, rename your pictures to follow a numerical sequence. For
example, img1.jpg, img2.jpg, img3.jpg,... Then you may run:
Run this program programmetcally ffmpeg -f image2 -i img%d.jpg
/tmp/a.mpg To run this programmatically,
Use the following code:
void convertImg_to_vid()
{
Process chperm;
try {
chperm=Runtime.getRuntime().exec("su");
DataOutputStream os =
new DataOutputStream(chperm.getOutputStream());
os.writeBytes("ffmpeg -f image2 -i img%d.jpg /tmp/a.mpg\n");
os.flush();
chperm.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Resource Link:
Create a Video file from images using ffmpeg
There is a utility in Java Media Framework which, It can create Video from List of Jpeg Images Link
Here is the source code:
JpegImagesToMovie.java
/*
* #(#)JpegImagesToMovie.java 1.3 01/03/13
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
package imagetovideo;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.util.Vector;
import javax.media.Buffer;
import javax.media.ConfigureCompleteEvent;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.DataSink;
import javax.media.EndOfMediaEvent;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.PrefetchCompleteEvent;
import javax.media.Processor;
import javax.media.RealizeCompleteEvent;
import javax.media.ResourceUnavailableEvent;
import javax.media.Time;
import javax.media.control.TrackControl;
import javax.media.datasink.DataSinkErrorEvent;
import javax.media.datasink.DataSinkEvent;
import javax.media.datasink.DataSinkListener;
import javax.media.datasink.EndOfStreamEvent;
import javax.media.format.VideoFormat;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
import javax.media.protocol.FileTypeDescriptor;
import javax.media.protocol.PullBufferDataSource;
import javax.media.protocol.PullBufferStream;
/**
* This program takes a list of JPEG image files and convert them into a
* QuickTime movie.
*/
public class JpegImagesToMovie implements ControllerListener, DataSinkListener {
public boolean doIt(int width, int height, int frameRate, Vector inFiles,
MediaLocator outML) throws MalformedURLException {
ImageDataSource ids = new ImageDataSource(width, height, frameRate,
inFiles);
Processor p;
try {
//System.err
// .println("- create processor for the image datasource ...");
p = Manager.createProcessor(ids);
} catch (Exception e) {
System.err
.println("Yikes! Cannot create a processor from the data source.");
return false;
}
p.addControllerListener(this);
// Put the Processor into configured state so we can set
// some processing options on the processor.
p.configure();
if (!waitForState(p, p.Configured)) {
System.err.println("Failed to configure the processor.");
return false;
}
// Set the output content descriptor to QuickTime.
p.setContentDescriptor(new ContentDescriptor(
FileTypeDescriptor.QUICKTIME));
// Query for the processor for supported formats.
// Then set it on the processor.
TrackControl tcs[] = p.getTrackControls();
Format f[] = tcs[0].getSupportedFormats();
if (f == null || f.length <= 0) {
System.err.println("The mux does not support the input format: "
+ tcs[0].getFormat());
return false;
}
tcs[0].setFormat(f[0]);
//System.err.println("Setting the track format to: " + f[0]);
// We are done with programming the processor. Let's just
// realize it.
p.realize();
if (!waitForState(p, p.Realized)) {
System.err.println("Failed to realize the processor.");
return false;
}
// Now, we'll need to create a DataSink.
DataSink dsink;
if ((dsink = createDataSink(p, outML)) == null) {
System.err
.println("Failed to create a DataSink for the given output MediaLocator: "
+ outML);
return false;
}
dsink.addDataSinkListener(this);
fileDone = false;
System.out.println("Generating the video : "+outML.getURL().toString());
// OK, we can now start the actual transcoding.
try {
p.start();
dsink.start();
} catch (IOException e) {
System.err.println("IO error during processing");
return false;
}
// Wait for EndOfStream event.
waitForFileDone();
// Cleanup.
try {
dsink.close();
} catch (Exception e) {
}
p.removeControllerListener(this);
System.out.println("Video creation completed!!!!!");
return true;
}
/**
* Create the DataSink.
*/
DataSink createDataSink(Processor p, MediaLocator outML) {
DataSource ds;
if ((ds = p.getDataOutput()) == null) {
System.err
.println("Something is really wrong: the processor does not have an output DataSource");
return null;
}
DataSink dsink;
try {
//System.err.println("- create DataSink for: " + outML);
dsink = Manager.createDataSink(ds, outML);
dsink.open();
} catch (Exception e) {
System.err.println("Cannot create the DataSink: " + e);
return null;
}
return dsink;
}
Object waitSync = new Object();
boolean stateTransitionOK = true;
/**
* Block until the processor has transitioned to the given state. Return
* false if the transition failed.
*/
boolean waitForState(Processor p, int state) {
synchronized (waitSync) {
try {
while (p.getState() < state && stateTransitionOK)
waitSync.wait();
} catch (Exception e) {
}
}
return stateTransitionOK;
}
/**
* Controller Listener.
*/
public void controllerUpdate(ControllerEvent evt) {
if (evt instanceof ConfigureCompleteEvent
|| evt instanceof RealizeCompleteEvent
|| evt instanceof PrefetchCompleteEvent) {
synchronized (waitSync) {
stateTransitionOK = true;
waitSync.notifyAll();
}
} else if (evt instanceof ResourceUnavailableEvent) {
synchronized (waitSync) {
stateTransitionOK = false;
waitSync.notifyAll();
}
} else if (evt instanceof EndOfMediaEvent) {
evt.getSourceController().stop();
evt.getSourceController().close();
}
}
Object waitFileSync = new Object();
boolean fileDone = false;
boolean fileSuccess = true;
/**
* Block until file writing is done.
*/
boolean waitForFileDone() {
synchronized (waitFileSync) {
try {
while (!fileDone)
waitFileSync.wait();
} catch (Exception e) {
}
}
return fileSuccess;
}
/**
* Event handler for the file writer.
*/
public void dataSinkUpdate(DataSinkEvent evt) {
if (evt instanceof EndOfStreamEvent) {
synchronized (waitFileSync) {
fileDone = true;
waitFileSync.notifyAll();
}
} else if (evt instanceof DataSinkErrorEvent) {
synchronized (waitFileSync) {
fileDone = true;
fileSuccess = false;
waitFileSync.notifyAll();
}
}
}
/*public static void main(String args[]) {
if (args.length == 0)
prUsage();
// Parse the arguments.
int i = 0;
int width = -1, height = -1, frameRate = 1;
Vector inputFiles = new Vector();
String outputURL = null;
while (i < args.length) {
if (args[i].equals("-w")) {
i++;
if (i >= args.length)
prUsage();
width = new Integer(args[i]).intValue();
} else if (args[i].equals("-h")) {
i++;
if (i >= args.length)
prUsage();
height = new Integer(args[i]).intValue();
} else if (args[i].equals("-f")) {
i++;
if (i >= args.length)
prUsage();
frameRate = new Integer(args[i]).intValue();
} else if (args[i].equals("-o")) {
i++;
if (i >= args.length)
prUsage();
outputURL = args[i];
} else {
inputFiles.addElement(args[i]);
}
i++;
}
if (outputURL == null || inputFiles.size() == 0)
prUsage();
// Check for output file extension.
if (!outputURL.endsWith(".mov") && !outputURL.endsWith(".MOV")) {
System.err
.println("The output file extension should end with a .mov extension");
prUsage();
}
if (width < 0 || height < 0) {
System.err.println("Please specify the correct image size.");
prUsage();
}
// Check the frame rate.
if (frameRate < 1)
frameRate = 1;
// Generate the output media locators.
MediaLocator oml;
if ((oml = createMediaLocator(outputURL)) == null) {
System.err.println("Cannot build media locator from: " + outputURL);
System.exit(0);
}
JpegImagesToMovie imageToMovie = new JpegImagesToMovie();
imageToMovie.doIt(width, height, frameRate, inputFiles, oml);
System.exit(0);
}*/
static void prUsage() {
System.err
.println("Usage: java JpegImagesToMovie -w <width> -h <height> -f <frame rate> -o <output URL> <input JPEG file 1> <input JPEG file 2> ...");
System.exit(-1);
}
/**
* Create a media locator from the given string.
*/
static MediaLocator createMediaLocator(String url) {
MediaLocator ml;
if (url.indexOf(":") > 0 && (ml = new MediaLocator(url)) != null)
return ml;
if (url.startsWith(File.separator)) {
if ((ml = new MediaLocator("file:" + url)) != null)
return ml;
} else {
String file = "file:" + System.getProperty("user.dir")
+ File.separator + url;
if ((ml = new MediaLocator(file)) != null)
return ml;
}
return null;
}
// /////////////////////////////////////////////
//
// Inner classes.
// /////////////////////////////////////////////
/**
* A DataSource to read from a list of JPEG image files and turn that into a
* stream of JMF buffers. The DataSource is not seekable or positionable.
*/
class ImageDataSource extends PullBufferDataSource {
ImageSourceStream streams[];
ImageDataSource(int width, int height, int frameRate, Vector images) {
streams = new ImageSourceStream[1];
streams[0] = new ImageSourceStream(width, height, frameRate, images);
}
public void setLocator(MediaLocator source) {
}
public MediaLocator getLocator() {
return null;
}
/**
* Content type is of RAW since we are sending buffers of video frames
* without a container format.
*/
public String getContentType() {
return ContentDescriptor.RAW;
}
public void connect() {
}
public void disconnect() {
}
public void start() {
}
public void stop() {
}
/**
* Return the ImageSourceStreams.
*/
public PullBufferStream[] getStreams() {
return streams;
}
/**
* We could have derived the duration from the number of frames and
* frame rate. But for the purpose of this program, it's not necessary.
*/
public Time getDuration() {
return DURATION_UNKNOWN;
}
public Object[] getControls() {
return new Object[0];
}
public Object getControl(String type) {
return null;
}
}
/**
* The source stream to go along with ImageDataSource.
*/
class ImageSourceStream implements PullBufferStream {
Vector images;
int width, height;
VideoFormat format;
int nextImage = 0; // index of the next image to be read.
boolean ended = false;
public ImageSourceStream(int width, int height, int frameRate,
Vector images) {
this.width = width;
this.height = height;
this.images = images;
format = new VideoFormat(VideoFormat.JPEG, new Dimension(width,
height), Format.NOT_SPECIFIED, Format.byteArray,
(float) frameRate);
}
/**
* We should never need to block assuming data are read from files.
*/
public boolean willReadBlock() {
return false;
}
/**
* This is called from the Processor to read a frame worth of video
* data.
*/
public void read(Buffer buf) throws IOException {
// Check if we've finished all the frames.
if (nextImage >= images.size()) {
// We are done. Set EndOfMedia.
//System.err.println("Done reading all images.");
buf.setEOM(true);
buf.setOffset(0);
buf.setLength(0);
ended = true;
return;
}
String imageFile = (String) images.elementAt(nextImage);
nextImage++;
//System.err.println(" - reading image file: " + imageFile);
// Open a random access file for the next image.
RandomAccessFile raFile;
raFile = new RandomAccessFile(imageFile, "r");
byte data[] = null;
// Check the input buffer type & size.
if (buf.getData() instanceof byte[])
data = (byte[]) buf.getData();
// Check to see the given buffer is big enough for the frame.
if (data == null || data.length < raFile.length()) {
data = new byte[(int) raFile.length()];
buf.setData(data);
}
// Read the entire JPEG image from the file.
raFile.readFully(data, 0, (int) raFile.length());
//System.err.println(" read " + raFile.length() + " bytes.");
buf.setOffset(0);
buf.setLength((int) raFile.length());
buf.setFormat(format);
buf.setFlags(buf.getFlags() | buf.FLAG_KEY_FRAME);
// Close the random access file.
raFile.close();
}
/**
* Return the format of each video frame. That will be JPEG.
*/
public Format getFormat() {
return format;
}
public ContentDescriptor getContentDescriptor() {
return new ContentDescriptor(ContentDescriptor.RAW);
}
public long getContentLength() {
return 0;
}
public boolean endOfStream() {
return ended;
}
public Object[] getControls() {
return new Object[0];
}
public Object getControl(String type) {
return null;
}
}
}
Its doIt function can be called from another class having main function:
CreatVideo.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package imagetovideo;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Vector;
import javax.media.MediaLocator;
public class CreateVideo{
public static final File dir = new File("D:\\imagesFolder\\");
public static final String[] extensions = new String[]{"jpg", "png"};
public static final FilenameFilter imageFilter = new FilenameFilter() {
#Override
public boolean accept(final File dir, String name) {
for (final String ext : extensions) {
if (name.endsWith("." + ext)) {
return (true);
}
}
return (false);
}
};
// Main function
public static void main(String[] args) throws IOException {
File file = new File("D:\\a.mp4");
if (!file.exists()) {
file.createNewFile();
}
Vector<String> imgLst = new Vector<>();
if (dir.isDirectory()) {
int counter = 1;
for (final File f : dir.listFiles(imageFilter)) {
imgLst.add(f.getAbsolutePath());
}
}
makeVideo("file:\\" + file.getAbsolutePath(), imgLst);
}
public static void makeVideo(String fileName, Vector imgLst) throws MalformedURLException {
JpegImagesToMovie imageToMovie = new JpegImagesToMovie();
MediaLocator oml;
if ((oml = imageToMovie.createMediaLocator(fileName)) == null) {
System.err.println("Cannot build media locator from: " + fileName);
System.exit(0);
}
int interval = 40;
imageToMovie.doIt(720, 360, (1000 / interval), imgLst, oml);
}
}
Requirements:
Include jmf-2.1.1e.jar in your Library Folder (using this library)
We are aware of the issue with jar softlinker
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6967414
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618
and have used following class (found on web and modified to take care of JAVA 7 as well.)
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A utility class for working around the java webstart jar signing/security bug
* <p/>
* see http://bugs.sun.com/view_bug.do?bug_id=6967414 and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618
*
* #author Scott Chan
*/
public class JarSignersHardLinker {
private static final String JRE_1_DOT = "1.";
private static final String DOT_ZERO_UNDERSCORE = ".0_";
/**
* the 1.6.0 update where this problem first occurred
*/
private static final int PROBLEM_JRE_UPDATE = 19;
private static final int PROBLEM_JRE_MAJOR_VERSION = 6;
public static final List sm_hardRefs = new ArrayList();
protected static void makeHardSignersRef(JarFile jar) throws java.io.IOException {
if (jar != null && jar.getClass().getName().equals("com.sun.deploy.cache.CachedJarFile")) {
Logger.info("Making hard refs for: " + jar.getName());
//lets attempt to get at the each of the soft links.
//first need to call the relevant no-arg method to ensure that the soft ref is populated
//then we access the private member, resolve the softlink and throw it in a static list.
callNoArgMethod("getSigners", jar);
makeHardLink("signersRef", jar);
callNoArgMethod("getSignerMap", jar);
makeHardLink("signerMapRef", jar);
// callNoArgMethod("getCodeSources", jar);
// makeHardLink("codeSourcesRef", jar);
callNoArgMethod("getCodeSourceCache", jar);
makeHardLink("codeSourceCacheRef", jar);
}
}
/**
* if the specified field for the given instance is a Softreference
* That soft reference is resolved and the returned ref is stored in a static list,
* making it a hard link that should never be garbage collected
*
* #param fieldName
* #param instance
*/
private static void makeHardLink(String fieldName, Object instance) {
//System.out.println("attempting hard ref to " + instance.getClass().getName() + "." + fieldName);
try {
Field signersRef = instance.getClass().getDeclaredField(fieldName);
signersRef.setAccessible(true);
Object o = signersRef.get(instance);
if (o instanceof SoftReference) {
SoftReference r = (SoftReference) o;
Object o2 = r.get();
sm_hardRefs.add(o2);
} else {
Logger.warn(fieldName + ": is not an instance of soft reference");
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
return;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* Call the given no-arg method on the given instance
*
* #param methodName
* #param instance
*/
private static void callNoArgMethod(String methodName, Object instance) {
// System.out.println("calling noarg method hard ref to " + instance.getClass().getName() + "." + methodName + "()");
try {
Method m = instance.getClass().getDeclaredMethod(methodName);
m.setAccessible(true);
m.invoke(instance);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* is the preloader enabled. ie: will the preloader run in the current environment
*
* #return
*/
public static boolean isHardLinkerEnabled() {
boolean isHardLinkerDisabled = false; //change this to use whatever mechanism you use to enable or disable the preloader
return !isHardLinkerDisabled && isRunningOnJre1_6_0_19OrHigher() && isRunningOnWebstart();
}
/**
* is the application currently running on webstart
* <p/>
* detect the presence of a JNLPclassloader
*
* #return
*/
public static boolean isRunningOnWebstart() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
while (cl != null) {
if (cl.getClass().getName().equals("com.sun.jnlp.JNLPClassLoader")) {
return true;
}
cl = cl.getParent();
}
return false;
}
/**
* Is the JRE 1.6.0_19 or higher?
* TBFI-5349: Java has a bug, sometimes Jars get garbage collected. To resolve this we are making
* hard references to the Jars.
*
* This method checks for java version. The bug is in 1.6.0_19 and above release hence checking for version 19
* #return
*/
public static boolean isRunningOnJre1_6_0_19OrHigher() {
String javaVersion = System.getProperty("java.version");
String updateStr = null;
String javaMajorVersionStr = null;
boolean isHardReferenceRequired = false;
// Problem persist in JAVA 7 and probable in JAVA 8 as well. So changing the patter.
Pattern pattern = Pattern.compile(JRE_1_DOT + "([6-9]+)" + DOT_ZERO_UNDERSCORE + "([0-9]+)(.*)");
Matcher matcher = pattern.matcher(javaVersion);
while (matcher.find()) {
javaMajorVersionStr = matcher.group(1);
updateStr = matcher.group(2);
break;
}
Logger.info("Java version: " + javaMajorVersionStr + " update string: " + updateStr);
try {
if (javaMajorVersionStr != null) {
int java_version = Integer.parseInt(javaMajorVersionStr);
if (java_version > PROBLEM_JRE_MAJOR_VERSION) {
isHardReferenceRequired = true;
} else if (java_version == PROBLEM_JRE_MAJOR_VERSION && Integer.parseInt(updateStr) >= PROBLEM_JRE_UPDATE) {
isHardReferenceRequired = true;
}
}
return isHardReferenceRequired;
} catch (NumberFormatException e) {
//then unable to determine java Major version or update level
e.printStackTrace();
return isHardReferenceRequired;
}
}
/**
* get all the JarFile objects for all of the jars in the classpath
*
* #return
*/
public static Set<JarFile> getAllJarsFilesInClassPath() {
Set<JarFile> jars = new LinkedHashSet<JarFile>();
for (URL url : getAllJarUrls()) {
try {
jars.add(getJarFile(url));
} catch (IOException e) {
Logger.error("unable to retrieve jar at URL: " + url);
}
}
return jars;
}
/**
* Returns set of URLS for the jars in the classpath.
* URLS will have the protocol of jar eg: jar:http://HOST/PATH/JARNAME.jar!/META-INF/MANIFEST.MF
*/
static Set<URL> getAllJarUrls() {
try {
Set<URL> urls = new LinkedHashSet<URL>();
Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");
while (mfUrls.hasMoreElements()) {
URL jarUrl = mfUrls.nextElement();
// System.out.println(jarUrl);
if (!jarUrl.getProtocol().equals("jar")) {
continue;
}
urls.add(jarUrl);
}
return urls;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* get the jarFile object for the given url
*
* #param jarUrl
* #return
* #throws IOException
*/
public static JarFile getJarFile(URL jarUrl) throws IOException {
URLConnection urlConnnection = jarUrl.openConnection();
if (urlConnnection instanceof JarURLConnection) {
// Using a JarURLConnection will load the JAR from the cache when using Webstart 1.6
// In Webstart 1.5, the URL will point to the cached JAR on the local filesystem
JarURLConnection jcon = (JarURLConnection) urlConnnection;
return jcon.getJarFile();
} else {
throw new AssertionError("Expected JarURLConnection");
}
}
/**
* Spawn a new thread to run through each jar in the classpath and create a hardlink
* to the jars softly referenced signers infomation.
*/
public static void go() {
if (!isHardLinkerEnabled()) {
return;
}
Logger.info("Starting Resource Preloader Hardlinker");
Thread t = new Thread(new Runnable() {
public void run() {
try {
Set<JarFile> jars = getAllJarsFilesInClassPath();
for (JarFile jar : jars) {
makeHardSignersRef(jar);
}
} catch (Exception e) {
Logger.warn("Problem preloading resources", e);
} catch (Error e) {
Logger.error("Error preloading resources", e);
}
}
});
t.start();
}
}
When we launch the application with JRE6 it works fine. But the problem is with JRE7. When the application is launched with JRE7 we get below exception in the log. From the exception we know that the jars are not hard referenced and that the user can have problems if the jars get garbage collected. We have a release next week and need to find a work around for this issue.
java.lang.NoSuchMethodException: com.sun.deploy.cache.CachedJarFile.getSigners()
at java.lang.Class.getDeclaredMethod(Unknown Source)
at com.XXXXXX.ui.main.JarSignersHardLinker.callNoArgMethod(JarSignersHardLinker.java:96)
at com.XXXXXX.ui.main.JarSignersHardLinker.makeHardSignersRef(JarSignersHardLinker.java:45)
at com.XXXXXX.ui.main.JarSignersHardLinker$1.run(JarSignersHardLinker.java:262)
at java.lang.Thread.run(Unknown Source)
java.lang.NoSuchFieldException: signersRef
at java.lang.Class.getDeclaredField(Unknown Source)
at com.XXXXXX.ui.main.JarSignersHardLinker.makeHardLink(JarSignersHardLinker.java:69)
at com.XXXXXX.ui.main.JarSignersHardLinker.makeHardSignersRef(JarSignersHardLinker.java:46)
at com.XXXXXX.ui.main.JarSignersHardLinker$1.run(JarSignersHardLinker.java:262)
at java.lang.Thread.run(Unknown Source)
This exception is repeated 52 times (for all the JAR's).
We have made sure that all the 52 jars/files (except the JNLP itself) are signed properly and that the java cache is cleard before the application is launched.
JAVA version used is JDK 7u40 on windows machine.
Options tried are:
Removing the jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024
from java.securites file.
Checking the jar signer certificate. Signer certificate uses SHA1withRSA as signing algorithm.
Note:
THE SOURCE CODE IS COMPILED IN JAVA 5u11 AND RUN IN JAVA 7u40
We have observed one more difference. With JRE6, when we run the same
piece of code, it first loades JAVAWS.jar, Deploy.jar and plugin .jar from java/jre6/lib path but with JRE7 these jars are not loaded.
This has been tried in both 64 and 32 bits java version with no luck.
Any help here is really appreciated.
#jorge_B: We sign the jars using ant task. But due to a problem in JAVA 6u19 (where the softreferenced jars are sometimes garbage collected) we have decided to hardlink the jars as soon as we hit a java version 6u19 or above. This issue is not with jar signing. The issue is when we try to hard reference the jars. our jars are not getting hard referenced, insted we are getting nosuchmethod and nosuchfield exception in the log.
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A utility class for working around the java webstart jar signing/security bug
* <p/>
* see http://bugs.sun.com/view_bug.do?bug_id=6967414 and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6805618
*
* #author Scott Chan
*/
public class JarSignersHardLinker {
private static final String JRE_VERSION_START = "1.";
private static final int PROBLEM_JRE_VERSION = 6;
private static final String DOT_ZERO = ".0_";
/**
* the 1.6.0 update where this problem first occurred
*/
private static final int PROBLEM_JRE_UPDATE = 19;
private static String majorVersionStr = null;
public static final List sm_hardRefs = new ArrayList();
protected static void makeHardSignersRef(JarFile jar) throws java.io.IOException {
Logger.info("Making hard refs for: " + (jar != null ? jar.getName() : null) + " with Java Version: "+majorVersionStr);
if (jar != null && jar.getClass().getName().equals("com.sun.deploy.cache.CachedJarFile")) {
//lets attempt to get at the each of the soft links.
//first neet to call the relevant no-arg method to ensure that the soft ref is populated
//then we access the private member, resolve the softlink and throw it in a static list.
if (majorVersionStr != null && Integer.parseInt(majorVersionStr) > PROBLEM_JRE_VERSION) {
callNoArgMethod("getSigningData", jar);
makeHardLink("signingDataRef", jar);
} else {
callNoArgMethod("getSigners", jar);
makeHardLink("signersRef", jar);
callNoArgMethod("getSignerMap", jar);
makeHardLink("signerMapRef", jar);
// callNoArgMethod("getCodeSources", jar);
// makeHardLink("codeSourcesRef", jar);
callNoArgMethod("getCodeSourceCache", jar);
makeHardLink("codeSourceCacheRef", jar);
}
}
}
/**
* if the specified field for the given instance is a Softreference
* That soft reference is resolved and the returned ref is stored in a static list,
* making it a hard link that should never be garbage collected
*
* #param fieldName
* #param instance
*/
private static void makeHardLink(String fieldName, Object instance) {
Logger.info("attempting hard ref to " + instance.getClass().getName() + "." + fieldName);
try {
Field signersRef = instance.getClass().getDeclaredField(fieldName);
signersRef.setAccessible(true);
Object o = signersRef.get(instance);
if (o instanceof SoftReference) {
SoftReference r = (SoftReference) o;
Object o2 = r.get();
sm_hardRefs.add(o2);
} else {
Logger.warn(fieldName + ": is not an instance of soft reference");
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
return;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* Call the given no-arg method on the given instance
*
* #param methodName
* #param instance
*/
private static void callNoArgMethod(String methodName, Object instance) {
Logger.info("calling noarg method hard ref to " + instance.getClass().getName() + "." + methodName + "()");
try {
Method m = instance.getClass().getDeclaredMethod(methodName);
m.setAccessible(true);
m.invoke(instance);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (NoSuchMethodException e1) {
e1.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* is the preloader enabled. ie: will the preloader run in the current environment
*
* #return
*/
public static boolean isHardLinkerEnabled() {
boolean isHardLinkerDisabled = false; //change this to use whatever mechanism you use to enable or disable the preloader
return !isHardLinkerDisabled && isRunningOnJre1_6_0_19OrHigher() && isRunningOnWebstart();
}
/**
* is the application currently running on webstart
* <p/>
* detect the presence of a JNLPclassloader
*
* #return
*/
public static boolean isRunningOnWebstart() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
while (cl != null) {
if (cl.getClass().getName().equals("com.sun.jnlp.JNLPClassLoader")) {
return true;
}
cl = cl.getParent();
}
return false;
}
/**
* Is the JRE 1.6.0_19 or higher?
*
* #return
*/
public static boolean isRunningOnJre1_6_0_19OrHigher() {
String javaVersion = System.getProperty("java.version");
// Sometimes java releases version 1.X.0_YY-rev for specific issue and specific user,
// to resolve this we use patter instead of string split.
//ERP-6460: Checking whether JRE is 6 update 19 or higher
String updateStr = null;
majorVersionStr = null;
boolean isHardReferenceRequired = false;
Pattern pattern = Pattern.compile(JRE_VERSION_START + "([6-9]+)" + DOT_ZERO + "([0-9]+)(.*)");
Matcher matcher = pattern.matcher(javaVersion);
while (matcher.find()) {
majorVersionStr = matcher.group(1);
updateStr = matcher.group(2);
break;
}
try {
if (majorVersionStr != null) {
int java_version = Integer.parseInt(majorVersionStr);
if (java_version > PROBLEM_JRE_VERSION) {
isHardReferenceRequired = true;
} else if (java_version == PROBLEM_JRE_VERSION && Integer.parseInt(updateStr) >= PROBLEM_JRE_UPDATE) {
isHardReferenceRequired = true;
}
}
return isHardReferenceRequired;
} catch (NumberFormatException e) {
e.printStackTrace();
return isHardReferenceRequired;
}
}
/**
* get all the JarFile objects for all of the jars in the classpath
*
* #return
*/
public static Set<JarFile> getAllJarsFilesInClassPath() {
Set<JarFile> jars = new LinkedHashSet<JarFile>();
for (URL url : getAllJarUrls()) {
try {
jars.add(getJarFile(url));
} catch (IOException e) {
Logger.error("unable to retrieve jar at URL: " + url);
}
}
return jars;
}
/**
* Returns set of URLS for the jars in the classpath.
* URLS will have the protocol of jar eg: jar:http://HOST/PATH/JARNAME.jar!/META-INF/MANIFEST.MF
*/
static Set<URL> getAllJarUrls() {
try {
Set<URL> urls = new LinkedHashSet<URL>();
Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");
while (mfUrls.hasMoreElements()) {
URL jarUrl = mfUrls.nextElement();
// System.out.println(jarUrl);
if (!jarUrl.getProtocol().equals("jar")) {
continue;
}
urls.add(jarUrl);
}
return urls;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* get the jarFile object for the given url
*
* #param jarUrl
* #return
* #throws IOException
*/
public static JarFile getJarFile(URL jarUrl) throws IOException {
URLConnection urlConnnection = jarUrl.openConnection();
if (urlConnnection instanceof JarURLConnection) {
// Using a JarURLConnection will load the JAR from the cache when using Webstart 1.6
// In Webstart 1.5, the URL will point to the cached JAR on the local filesystem
JarURLConnection jcon = (JarURLConnection) urlConnnection;
return jcon.getJarFile();
} else {
throw new AssertionError("Expected JarURLConnection");
}
}
/**
* Spawn a new thread to run through each jar in the classpath and create a hardlink
* to the jars softly referenced signers infomation.
*/
public static void go() {
if (!isHardLinkerEnabled()) {
return;
}
Logger.info("Starting Resource Preloader Hardlinker");
Thread t = new Thread(new Runnable() {
public void run() {
try {
Set<JarFile> jars = getAllJarsFilesInClassPath();
for (JarFile jar : jars) {
makeHardSignersRef(jar);
}
} catch (Exception e) {
Logger.error("Problem preloading resources", e);
} catch (Error e) {
Logger.error("Error preloading resources", e);
}
}
});
t.start();
}
}
We have a Lotus Notes Plug-In, developed in Java. The current version of Notes we're supporting is 8.5.2.
This plug-in adds a button to the Notes UI. When the user clicks it, we present a window to the user, which allows the user to add the current item to our web-based application using web services. Everything works fine, except when the user tries to add a new email item.
The listener for the "click event" (if you will) needs to know the current document so that it can pass its field data to the web service call. In order to do that, a separate listener has been set up (DocumentContextService) which essentially gets invoked any time the input focus changes within the Notes UI.
DocumentContextService attempts to retrieve the URI of the current document. And that's where things fall apart. I am finding that an unsent email message has no URI. Further, there appears to be no way to get to the document and save it, so that I can obtain one.
Theoretically, this is by design. Oddly, I can see that the new document has a DocumentKey, so I know it exists (as a draft somewhere), but I cannot get to it. So there doesn't appear to be any way to access the document's data until it is actually saved.
Unless I'm wrong (and I very well could be). And there's the question: Is there a way to obtain the underlying document of a new email before it has been saved so that I can access its data (specifically, its fields)?
The code from the document context listener is below. The problem, again, is that the URI property always evaluates to an empty string for new emails.
package com.ibm.lotuslabs.context.service.internal;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import com.ibm.lotuslabs.context.service.document.IDocumentContext;
import com.ibm.rcp.jface.launcher.IURIProvider;
import com.satuit.sys.The;
/**
* Extracts document information about about a selection object. Represents the document within the DocumentSelection.
*/
#SuppressWarnings("deprecation")
public class DocumentContext implements IDocumentContext
{
private IWorkbenchPart part;
private Object obj;
private String label;
private URI uri;
private ImageDescriptor icon;
private Properties properties;
private String id;
/**
* Initializes a new instance of the DocumentContext class.
*
* #param part The current view part.
* #param obj The currently selected object.
*/
public DocumentContext(final IWorkbenchPart part, final Object obj)
{
this.part = part;
this.obj = obj;
// Is this object a URIProvider?
final IURIProvider provider = (IURIProvider)ContextUtil.getAdapterObject(obj, IURIProvider.class);
if (provider != null)
{
this.uri = provider.getURI();
this.label = provider.getTitle();
this.icon = provider.getImageDescriptor();
}
if (this.label == null || this.icon == null)
{
// Is this object a workbench adapter?
final IWorkbenchAdapter wba = (IWorkbenchAdapter)ContextUtil.getAdapterObject(obj, IWorkbenchAdapter.class);
if (wba != null)
{
if (this.label != null)
{
this.label = wba.getLabel(obj);
}
if (this.icon != null)
{
this.icon = wba.getImageDescriptor(obj);
}
}
if (this.icon == null)
{
final Image i = part.getTitleImage();
if (i != null)
{
this.icon = ImageDescriptor.createFromImage(i);
}
}
}
// Is this object a URI?
if (this.uri == null)
{
this.uri = (URI)ContextUtil.getAdapterObject(obj, URI.class);
}
// Is this object a PropertySource?
// (A document that isn't a URI provider may provide a URI in its properties.)
final IPropertySource prop = (IPropertySource)ContextUtil.getAdapterObject(obj, IPropertySource.class);
if (prop != null)
{
this.properties = buildProperties(prop);
}
}
/**
* Gets the ID of this instance.
* #return A string containing the ID.
*/
public final String getId()
{
return this.id;
}
/**
* Gets the workbench part used to initialize this instance.
* #return
*/
public final IWorkbenchPart getPart()
{
return this.part;
}
/* (non-Javadoc)
* #see com.ibm.lotuslabs.context.service.document.IDocumentContext#getImageDescriptor()
*/
public final ImageDescriptor getImageDescriptor()
{
return this.icon;
}
/* (non-Javadoc)
* #see com.ibm.lotuslabs.context.service.document.IDocumentContext#getLabel()
*/
public final String getLabel()
{
if (this.label == null && this.part != null)
{
return this.part.getTitle();
}
return this.label;
}
/* (non-Javadoc)
* #see com.ibm.lotuslabs.context.service.document.IDocumentContext#getObject()
*/
public final Object getObject()
{
return this.obj;
}
/* (non-Javadoc)
* #see com.ibm.lotuslabs.context.service.document.IDocumentContext#getProperties()
*/
public final Properties getProperties()
{
return this.properties;
}
/* (non-Javadoc)
* #see com.ibm.lotuslabs.context.service.document.IDocumentContext#getURI()
*/
public final URI getURI()
{
return this.uri;
}
private Properties buildProperties(final IPropertySource source)
{
if (source == null)
{
return null;
}
final IPropertyDescriptor[] descs = source.getPropertyDescriptors();
if (The.Value(null).Is.NullOrEmpty(descs))
{
return null;
}
final Properties prop = new Properties();
for (int i = 0; i < descs.length; i++)
{
final Object id = descs[i].getId();
final String name = descs[i].getDisplayName();
String value = source.getPropertyValue(descs[i].getId()).toString();
if (The.Value(descs[i].getDescription()).Is.Not.Null())
{
value += "|" + source.getPropertyValue(descs[i].getDescription()).toString();
}
if (this.uri == null)
{
if (The.Value("URI").Is.OneOfIgnoreCase(id.toString(), name) ||
The.Value("URL").Is.OneOfIgnoreCase(id.toString(), name))
{
try
{
this.uri = new URI(value);
continue;
}
catch (URISyntaxException e)
{
}
}
}
prop.setProperty(name, value);
}
return prop;
}
}
Sorry, until the document is saved into the backend database, there is no document to get an URI for, as it does not exists anywhere but in memory. It simply does not exists on disk.
I have a Berkeley-db database where both 'key' and 'value' are of type integer. Is there any way to traverse the database in descending order of 'value'?
I'm using Berkeley-db je-5.0.58 API. The sample code that i'm using from its documentation is shown below.
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2004-2010 Oracle. All rights reserved.
*
*/
package je;
import java.io.File;
import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
/**
* SimpleExample creates a database environment, a database, and a database
* cursor, inserts and retrieves data.
*/
class SimpleExample {
private static final int EXIT_SUCCESS = 0;
private static final int EXIT_FAILURE = 1;
private int numRecords; // num records to insert or retrieve
private int offset; // where we want to start inserting
private boolean doInsert; // if true, insert, else retrieve
private File envDir;
public SimpleExample(int numRecords,
boolean doInsert,
File envDir,
int offset) {
this.numRecords = numRecords;
this.doInsert = doInsert;
this.envDir = envDir;
this.offset = offset;
}
/**
* Usage string
*/
public static void usage() {
System.out.println("usage: java " +
"je.SimpleExample " +
"<dbEnvHomeDirectory> " +
"<insert|retrieve> <numRecords> [offset]");
System.exit(EXIT_FAILURE);
}
/**
* Main
*/
public static void main(String argv[]) {
if (argv.length < 2) {
usage();
return;
}
File envHomeDirectory = new File(argv[0]);
boolean doInsertArg = false;
if (argv[1].equalsIgnoreCase("insert")) {
doInsertArg = true;
} else if (argv[1].equalsIgnoreCase("retrieve")) {
doInsertArg = false;
} else {
usage();
}
int startOffset = 0;
int numRecordsVal = 0;
if (doInsertArg) {
if (argv.length > 2) {
numRecordsVal = Integer.parseInt(argv[2]);
} else {
usage();
return;
}
if (argv.length > 3) {
startOffset = Integer.parseInt(argv[3]);
}
}
try {
SimpleExample app = new SimpleExample(numRecordsVal,
doInsertArg,
envHomeDirectory,
startOffset);
app.run();
} catch (DatabaseException e) {
e.printStackTrace();
System.exit(EXIT_FAILURE);
}
System.exit(EXIT_SUCCESS);
}
/**
* Insert or retrieve data
*/
public void run() throws DatabaseException {
/* Create a new, transactional database environment */
EnvironmentConfig envConfig = new EnvironmentConfig();
envConfig.setTransactional(true);
envConfig.setAllowCreate(true);
Environment exampleEnv = new Environment(envDir, envConfig);
/*
* Make a database within that environment
*
* Notice that we use an explicit transaction to
* perform this database open, and that we
* immediately commit the transaction once the
* database is opened. This is required if we
* want transactional support for the database.
* However, we could have used autocommit to
* perform the same thing by simply passing a
* null txn handle to openDatabase().
*/
Transaction txn = exampleEnv.beginTransaction(null, null);
DatabaseConfig dbConfig = new DatabaseConfig();
dbConfig.setTransactional(true);
dbConfig.setAllowCreate(true);
dbConfig.setSortedDuplicates(true);
Database exampleDb = exampleEnv.openDatabase(txn,
"simpleDb",
dbConfig);
txn.commit();
/*
* Insert or retrieve data. In our example, database records are
* integer pairs.
*/
/* DatabaseEntry represents the key and data of each record */
DatabaseEntry keyEntry = new DatabaseEntry();
DatabaseEntry dataEntry = new DatabaseEntry();
if (doInsert) {
/* put some data in */
for (int i = offset; i < numRecords + offset; i++) {
/*
* Note that autocommit mode, described in the Getting
* Started Guide, is an alternative to explicitly
* creating the transaction object.
*/
txn = exampleEnv.beginTransaction(null, null);
/* Use a binding to convert the int into a DatabaseEntry. */
IntegerBinding.intToEntry(i, keyEntry);
IntegerBinding.intToEntry(i+1, dataEntry);
OperationStatus status =
exampleDb.put(txn, keyEntry, dataEntry);
/*
* Note that put will throw a DatabaseException when
* error conditions are found such as deadlock.
* However, the status return conveys a variety of
* information. For example, the put might succeed,
* or it might not succeed if the record alread exists
* and the database was not configured for duplicate
* records.
*/
if (status != OperationStatus.SUCCESS) {
throw new RuntimeException("Data insertion got status " +
status);
}
txn.commit();
}
} else {
/* retrieve the data */
Cursor cursor = exampleDb.openCursor(null, null);
while (cursor.getNext(keyEntry, dataEntry, LockMode.DEFAULT) ==
OperationStatus.SUCCESS) {
System.out.println("key=" +
IntegerBinding.entryToInt(keyEntry) +
" data=" +
IntegerBinding.entryToInt(dataEntry));
}
cursor.close();
}
exampleDb.close();
exampleEnv.close();
}
}
you can use a custom comparator and use a cursor to traverse the data in descending order.
In java you have to implement a custom Comparator:
EDIT:
import java.util.Comparator;
import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.je.DatabaseEntry;
public class IntegerSorter implements Comparator<byte[]>
{
#Override
public int compare(byte[] o1, byte[] o2)
{
return
IntegerBinding.entryToInt(new DatabaseEntry(o1)) -
IntegerBinding.entryToInt(new DatabaseEntry(o2));
}
}
(...)
dbConfig.setBtreeComparator(IntegerSorter.class);
(...)
I have a couple of questions about a school project I'm working on. The code is as follows.
public class Player
{
private PlayList playList;
private Track track;
private int tracksPlayed;
private int totalTrackTime;
private double averageTrackTime;
/**
* Constructor ...
*/
public Player()
{
playList = new PlayList("audio");
track = playList.getTrack(0);
this.tracksPlayed = tracksPlayed;
this.totalTrackTime = totalTrackTime;
this.averageTrackTime = averageTrackTime;
}
/**
* Return the track collection currently loaded in this player.
*/
public PlayList getPlayList()
{
return playList;
}
/**
*
*/
public void play()
{
track.play();
tracksPlayed++;
int trackDuration = track.getDuration();
totalTrackTime = totalTrackTime + trackDuration;
averageTrackTime = totalTrackTime / tracksPlayed;
}
/**
*
*/
public void stop()
{
track.stop();
}
/**
*
*/
public void setTrack(int trackNumber)
{
int currentTrack = trackNumber;
track = playList.getTrack(currentTrack);
}
/**
*
*/
public String getTrackName()
{
String currentTrack = track.getName();
return currentTrack;
}
/**
*
*/
public String getTrackInfo()
{
String currentTrack = track.getName();
int trackDuration = track.getDuration();
return currentTrack + " " + "(" + trackDuration + ")";
}
/**
*
*/
public int getNumberOfTracksPlayed()
{
return tracksPlayed;
}
/**
*
*/
public int getTotalPlayedTrackLength()
{
return totalTrackTime;
}
/**
*
*/
public double averageTrackLength()
{
return averageTrackTime;
}
}
public class Track
{
private Clip soundClip;
private String name;
/**
* Create a track from an audio file.
*/
public Track(File soundFile)
{
soundClip = loadSound(soundFile);
name = soundFile.getName();
}
/**
* Play this sound track. (The sound will play asynchronously, until
* it is stopped or reaches the end.)
*/
public void play()
{
if(soundClip != null) {
soundClip.start();
}
}
/**
* Stop this track playing. (This method has no effect if the track is not
* currently playing.)
*/
public void stop()
{
if(soundClip != null) {
soundClip.stop();
}
}
/**
* Reset this track to its start.
*/
public void rewind()
{
if(soundClip != null) {
soundClip.setFramePosition(0);
}
}
/**
* Return the name of this track.
*/
public String getName()
{
return name;
}
/**
* Return the duration of this track, in seconds.
*/
public int getDuration()
{
if (soundClip == null) {
return 0;
}
else {
return (int) soundClip.getMicrosecondLength()/1000000;
}
}
/**
* Set the playback volume of the current track.
*
* #param vol Volume level as a percentage (0..100).
*/
public void setVolume(int vol)
{
if(soundClip == null) {
return;
}
if(vol < 0 || vol > 100) {
vol = 100;
}
double val = vol / 100.0;
try {
FloatControl volControl =
(FloatControl) soundClip.getControl(FloatControl.Type.MASTER_GAIN);
float dB = (float)(Math.log(val == 0.0 ? 0.0001 : val) / Math.log(10.0) * 20.0);
volControl.setValue(dB);
} catch (Exception ex) {
System.err.println("Error: could not set volume");
}
}
/**
* Return true if this track has successfully loaded and can be played.
*/
public boolean isValid()
{
return soundClip != null;
}
/**
* Load the sound file supplied by the parameter.
*
* #return The sound clip if successful, null if the file could not be decoded.
*/
private Clip loadSound(File file)
{
Clip newClip;
try {
AudioInputStream stream = AudioSystem.getAudioInputStream(file);
AudioFormat format = stream.getFormat();
// we cannot play ALAW/ULAW, so we convert them to PCM
//
if ((format.getEncoding() == AudioFormat.Encoding.ULAW) ||
(format.getEncoding() == AudioFormat.Encoding.ALAW))
{
AudioFormat tmp = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(),
format.getSampleSizeInBits() * 2,
format.getChannels(),
format.getFrameSize() * 2,
format.getFrameRate(),
true);
stream = AudioSystem.getAudioInputStream(tmp, stream);
format = tmp;
}
DataLine.Info info = new DataLine.Info(Clip.class,
stream.getFormat(),
((int) stream.getFrameLength() *
format.getFrameSize()));
newClip = (Clip) AudioSystem.getLine(info);
newClip.open(stream);
return newClip;
} catch (Exception ex) {
return null;
}
}
}
public class PlayList
{
private List<Track> tracks;
/**
* Constructor for objects of class TrackCollection
*/
public PlayList(String directoryName)
{
tracks = loadTracks(directoryName);
}
/**
* Return a track from this collection.
*/
public Track getTrack(int trackNumber)
{
return tracks.get(trackNumber);
}
/**
* Return the number of tracks in this collection.
*/
public int numberOfTracks()
{
return tracks.size();
}
/**
* Load the file names of all files in the given directory.
* #param dirName Directory (folder) name.
* #param suffix File suffix of interest.
* #return The names of files found.
*/
private List<Track> loadTracks(String dirName)
{
File dir = new File(dirName);
if(dir.isDirectory()) {
File[] allFiles = dir.listFiles();
List<Track> foundTracks = new ArrayList<Track>();
for(File file : allFiles) {
//System.out.println("found: " + file);
Track track = new Track(file);
if(track.isValid()) {
foundTracks.add(track);
}
}
return foundTracks;
}
else {
System.err.println("Error: " + dirName + " must be a directory");
return null;
}
}
/**
* Return this playlist as an array of strings with the track names.
*/
public String[] asStrings()
{
String[] names = new String[tracks.size()];
int i = 0;
for(Track track : tracks) {
names[i++] = track.getName();
}
return names;
}
}
I understand that to call the play methods in the player class, I have to initialize a Track class variable. I also need to initialize it using the PlayList getTrack method. However, how can I initialize it without defining a starting index variable (i.e I don't want it to automatically initialize to a specific song in the index, I want the user to have to select a song first)?
Also, how do I code the play method in the player class to stop a existing song if one is playing before starting a new song and to restart a song if the play method is called again one the same song?
1.
how can I initialize it without defining a starting index variable
public Player (int initTrack){
...
track = playList.getTrack(initTrack);
...
}
2.
You should try with a field storing the track that it is currently playing!