VideoSampleBuilderpublic class VideoSampleBuilder extends Object
Fields Summary |
---|
public static final int | VIDEO_TRACK_WIDTH | public static final int | VIDEO_TRACK_HEIGHT | public static final int | VIDEO_TRACK_VOLUME | public static final int | KEY_FRAME_RATE | Properties | userProps | QDRect | startRect | QDRect | endRect |
Constructors Summary |
---|
public VideoSampleBuilder()
/* try to load "videoSampleBuilder.properties" from
current directory. this contains file.location and
start.x/y/width/height and end.x/y/width/height params
*/
try {
userProps.load (new FileInputStream (new File ("videosamplebuilder.properties")));
System.out.println ("Loaded \"videosamplebuilder.properties\"");
} catch (Exception e) {
System.out.println ("Couldn't load \"videosamplebuilder.properties");
}
int CODEC_TYPE = QTUtils.toOSType ("SVQ3");
// int CODEC_TYPE = QTUtils.toOSType("mp4v");
// create a new empty movie
QTFile movFile = new QTFile (new java.io.File("videotrack.mov"));
Movie movie =
Movie.createMovieFile(movFile,
StdQTConstants.kMoviePlayer,
StdQTConstants.createMovieFileDeleteCurFile |
StdQTConstants.createMovieFileDontCreateResFile);
System.out.println ("Created Movie");
// now create an empty video track
int timeScale = 600; // 100 units per second
Track videoTrack = movie.addTrack (VIDEO_TRACK_WIDTH,
VIDEO_TRACK_HEIGHT,
VIDEO_TRACK_VOLUME);
System.out.println ("Added empty Track");
// now we need media for this track
VideoMedia videoMedia = new VideoMedia(videoTrack,
timeScale);
// get image file from props or dialog
QTFile imgFile = getImageFile();
if (imgFile == null)
return;
// get a GraphicsImporter
GraphicsImporter importer = new GraphicsImporter (imgFile);
System.out.println ("Got GraphicsImporter - Bounds are " +
importer.getNaturalBounds());
// Create an offscreen QDGraphics / GWorld that's the
// size of our frames. Importer will draw into this,
// and we'll then hand it to the CSequence
QDGraphics gw =
new QDGraphics (new QDRect (0, 0,
VIDEO_TRACK_WIDTH,
VIDEO_TRACK_HEIGHT));
System.out.println ("Created GWorld, - Bounds are " +
gw.getBounds());
// get start, end rects
getRects (importer);
System.out.println ("startRect = " + startRect);
System.out.println ("endRect = " + endRect);
// set importer's gworld
importer.setGWorld (gw, null);
System.out.println ("Reset importer's GWorld, now: " +
importer.getGWorld());
// get to work
videoMedia.beginEdits();
// figure out per-frame offsets
QDRect gRect = new QDRect (0, 0,
VIDEO_TRACK_WIDTH,
VIDEO_TRACK_HEIGHT);
int frames = 300;
int startX = startRect.getX();
int startY = startRect.getY();
int endX = endRect.getX();
int endY = endRect.getY();
float xOffPerFrame = ((float)(endX - startX) / (float)frames);
float yOffPerFrame = ((float)(endY - startY) / (float)frames);
float widthOffPerFrame = ((float) (endRect.getWidth() -
startRect.getWidth()) /
(float) frames);
float heightOffPerFrame = ((float) (endRect.getHeight() -
startRect.getHeight()) /
(float) frames);
System.out.println ("xOffPerFrame=" + xOffPerFrame +
", yOffPerFrame=" + yOffPerFrame +
", widthOffPerFrame=" + widthOffPerFrame +
", heightOffPerFrame=" + heightOffPerFrame);
// reserve an image with enough space to hold compressed image
// this is needed by the last arg of CSequence.compressFrame
int rawImageSize =
QTImage.getMaxCompressionSize (gw,
gRect,
gw.getPixMap().getPixelSize(),
StdQTConstants.codecNormalQuality,
CODEC_TYPE,
// CodecComponent.anyCodec);
CodecComponent.bestFidelityCodec);
QTHandle imageHandle = new QTHandle (rawImageSize, true);
imageHandle.lock();
RawEncodedImage compressedImage =
RawEncodedImage.fromQTHandle(imageHandle);
// create a CSequence
/* see behavior flags at
http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESI/compresssequencebegin.htm#//apple_ref/c/func/CompressSequenceBegin
*/
CSequence seq = new CSequence (gw,
gRect,
gw.getPixMap().getPixelSize(),
CODEC_TYPE,
CodecComponent.bestFidelityCodec,
StdQTConstants.codecNormalQuality,
StdQTConstants.codecNormalQuality,
KEY_FRAME_RATE,
null,
0);
// remember an ImageDescription from this sequence definition
ImageDescription imgDesc = seq.getDescription();
// loop through the specified number of frames, drawing
// scaled instances into our GWorld and compressing those
// to the CSequence
for (int i=1; i<frames; i++) {
System.out.println ("i==" + i);
// compute a rect for this frame
int x = startX + (int) (xOffPerFrame * i);
int y = startY + (int) (yOffPerFrame * i);
int width = startRect.getWidth() + (int) (widthOffPerFrame * i);
int height = startRect.getHeight() + (int) (heightOffPerFrame * i);
QDRect fromRect = new QDRect (x, y, width, height);
// create a Matrix to represent the move/scale from
// the fromRect to the GWorld and make importer use it
Matrix drawMatrix = new Matrix();
drawMatrix.rect (fromRect, gRect);
System.out.println ("fromRect = " + fromRect);
importer.setMatrix (drawMatrix);
// have importer draw (scaled) into our GWorld
importer.draw();
System.out.println ("Importer drew");
// compress a frame
/* behavior flags at
http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESI/compresssequenceframe.htm#//apple_ref/c/func/CompressSequenceFrame
*/
CompressedFrameInfo cfInfo =
seq.compressFrame (gw,
gRect,
StdQTConstants.codecFlagUpdatePrevious,
compressedImage);
System.out.println ("similarity = " + cfInfo.getSimilarity());
// see http://developer.apple.com/qa/qtmcc/qtmcc20.html
// for explanation of mediaSampleNotSync
boolean syncSample = (cfInfo.getSimilarity() == 0);
int flags = syncSample ? 0 : StdQTConstants.mediaSampleNotSync;
// add compressed frame to the video media
videoMedia.addSample (imageHandle,
0,
cfInfo.getDataSize(),
20, // time per frame, in timescale
imgDesc,
1, // one sample
flags
);
} // for
// done editing
videoMedia.endEdits();
// now insert this media into track
videoTrack.insertMedia (0, // trackStart
0, // mediaTime
videoMedia.getDuration(), // mediaDuration
1); // mediaRate
System.out.println ("inserted media into video track");
// save up
System.out.println ("Saving...");
OpenMovieFile omf = OpenMovieFile.asWrite (movFile);
movie.addResource (omf,
StdQTConstants.movieInDataForkResID,
movFile.getName());
System.out.println ("Done");
|
Methods Summary |
---|
protected QTFile | getImageFile()Gets imageFile from props file, or file-preview if
that doesn't work.
// is it in the props?
QTFile imageFile = null;
if (userProps.containsKey ("file")) {
imageFile = new QTFile (userProps.getProperty("file"));
if (! imageFile.exists())
imageFile = null;
}
// if not, or if that failed, then use a dialog
if (imageFile == null) {
int[] types = {};
imageFile = QTFile.standardGetFilePreview (types);
}
return imageFile;
| protected void | getRects(GraphicsImporter importer)Gets startRect, endRect from userProps, or selects
randomly if that doesn't work
Random rand = new Random();
int rightStop =
importer.getNaturalBounds().getWidth() - VIDEO_TRACK_WIDTH;
int bottomStop =
importer.getNaturalBounds().getHeight() - VIDEO_TRACK_HEIGHT;
// try to get startRect from userProps
try {
int startX = Integer.parseInt (userProps.getProperty("start.x"));
int startY = Integer.parseInt (userProps.getProperty("start.y"));
int startWidth = Integer.parseInt (userProps.getProperty("start.width"));
int startHeight = Integer.parseInt (userProps.getProperty("start.height"));
startRect = new QDRect (startX, startY, startWidth, startHeight);
} catch (Exception e) {
// make random start rect
int startX = Math.abs (rand.nextInt() % rightStop);
int startY = Math.abs (rand.nextInt() % bottomStop);
startRect = new QDRect (startX, startY,
VIDEO_TRACK_WIDTH,
VIDEO_TRACK_HEIGHT);
}
// try to get endRect from userProps
try {
int endX = Integer.parseInt (userProps.getProperty("end.x"));
int endY = Integer.parseInt (userProps.getProperty("end.y"));
int endWidth = Integer.parseInt (userProps.getProperty("end.width"));
int endHeight = Integer.parseInt (userProps.getProperty("end.height"));
endRect = new QDRect (endX, endY, endWidth, endHeight);
} catch (Exception e) {
float zoom = (rand.nextFloat() - 0.5f); // -0.5 <= zoom <= 0.5
System.out.println ("zoom = " + zoom);
int endX = Math.abs (rand.nextInt() % rightStop);
int endY = Math.abs (rand.nextInt() % bottomStop);
endRect = new QDRect (endX, endY,
VIDEO_TRACK_WIDTH * zoom,
VIDEO_TRACK_HEIGHT * zoom);
}
| public static void | main(java.lang.String[] arrrImAPirate)
try {
QTSessionCheck.check();
new VideoSampleBuilder();
} catch (Exception e) {
e.printStackTrace();
}
System.exit(0);
|
|