Created
June 27, 2012 19:43
-
-
Save naftulikay/3006322 to your computer and use it in GitHub Desktop.
Generate a video from scratch with Xuggler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.tkassembled.xuggle; | |
import java.awt.Color; | |
import java.awt.Graphics; | |
import java.awt.image.BufferedImage; | |
import java.io.File; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import com.xuggle.xuggler.ICodec; | |
import com.xuggle.xuggler.IContainer; | |
import com.xuggle.xuggler.IPacket; | |
import com.xuggle.xuggler.IPixelFormat; | |
import com.xuggle.xuggler.IRational; | |
import com.xuggle.xuggler.IStream; | |
import com.xuggle.xuggler.IStreamCoder; | |
import com.xuggle.xuggler.IVideoPicture; | |
import com.xuggle.xuggler.demos.DecodeAndPlayVideo; | |
import com.xuggle.xuggler.video.ConverterFactory; | |
import com.xuggle.xuggler.video.IConverter; | |
public class ManualVideoCompile { | |
private static final Logger logger = LoggerFactory.getLogger(ManualVideoCompile.class); | |
private static final String OUTPUT_FILE = "/home/rfkrocktk/Desktop/out.flv"; | |
private static final Integer OUTPUT_WIDTH = 960; | |
private static final Integer OUTPUT_HEIGHT = 540; | |
public static void main(String[] arguments) { | |
logger.debug("Compiling an empty stream to {}", OUTPUT_FILE); | |
File outputFile = new File(OUTPUT_FILE); | |
if (outputFile.exists()) | |
outputFile.delete(); | |
// open a container | |
IContainer container = IContainer.make(); | |
container.open(OUTPUT_FILE, IContainer.Type.WRITE, null); | |
// create the video stream and get its coder | |
ICodec videoCodec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_H264); | |
IStream videoStream = container.addNewStream(videoCodec); | |
IStreamCoder videoStreamCoder = videoStream.getStreamCoder(); | |
// setup the stream coder | |
IRational frameRate = IRational.make(1, 30); | |
videoStreamCoder.setWidth(OUTPUT_WIDTH); | |
videoStreamCoder.setHeight(OUTPUT_HEIGHT); | |
videoStreamCoder.setFrameRate(frameRate); | |
videoStreamCoder.setTimeBase(IRational.make(frameRate.getDenominator(), | |
frameRate.getNumerator())); | |
videoStreamCoder.setBitRate(350000); | |
videoStreamCoder.setNumPicturesInGroupOfPictures(30); | |
videoStreamCoder.setPixelType(IPixelFormat.Type.YUV420P); | |
videoStreamCoder.setFlag(IStreamCoder.Flags.FLAG_QSCALE, true); | |
videoStreamCoder.setGlobalQuality(0); | |
// open the coder first | |
videoStreamCoder.open(null, null); | |
// write the header | |
container.writeHeader(); | |
// let us begin | |
long positionInMicroseconds = 0; | |
// encode 30 frames, right? | |
for (int i = 0; i < 30 * frameRate.getDouble(); i++) { | |
// create a green box with a 50 pixel border for the frame image | |
BufferedImage outputImage = new BufferedImage(videoStreamCoder.getWidth(), | |
videoStreamCoder.getHeight(), BufferedImage.TYPE_INT_ARGB); | |
Graphics graphics = outputImage.getGraphics(); | |
graphics.setColor(Color.GREEN); | |
graphics.drawRect(50, 50, | |
videoStreamCoder.getWidth() - 100, | |
videoStreamCoder.getHeight() - 100); | |
outputImage = convert(outputImage, BufferedImage.TYPE_3BYTE_BGR); | |
// now, create a packet | |
IPacket packet = IPacket.make(); | |
IConverter converter = ConverterFactory.createConverter(outputImage, | |
videoStreamCoder.getPixelType()); | |
IVideoPicture frame = converter.toPicture(outputImage, positionInMicroseconds); | |
frame.setQuality(0); | |
if (videoStreamCoder.encodeVideo(packet, frame, 0) < 0) { | |
throw new RuntimeException("Unable to encode video."); | |
} | |
if (packet.isComplete()) { | |
if (container.writePacket(packet) < 0) { | |
throw new RuntimeException("Could not write packet to container."); | |
} | |
} | |
// after all this, increase the timestamp by one frame (in microseconds) | |
positionInMicroseconds += (frameRate.getDouble() * Math.pow(1000, 2)); | |
} | |
// done, so now let's wrap this up. | |
container.writeTrailer(); | |
videoStreamCoder.close(); | |
// container.flushPackets(); | |
container.close(); | |
DecodeAndPlayVideo.main(new String[]{OUTPUT_FILE}); | |
} | |
private static BufferedImage convert(BufferedImage value, int type) { | |
if (value.getType() == type) | |
return value; | |
BufferedImage result = new BufferedImage(value.getWidth(), value.getHeight(), | |
type); | |
result.getGraphics().drawImage(value, 0, 0, null); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment