- 老实说,不要在JMF上浪费时间,您可以认为这已经死了。这是使用h.264对rtmp流进行屏幕截图的方法(此示例感谢tyreus@gmail.com)。如果代码未显示,请单击此处的pastebin:http
- //pastebin.com/sJHwj0nW
import com.xuggle.xuggler.Configuration; import com.xuggle.xuggler.ICodec; import com.xuggle.xuggler.IContainer; import com.xuggle.xuggler.IContainerFormat; 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.video.ConverterFactory; import com.xuggle.xuggler.video.IConverter; import java.awt.AWTException; import java.awt.Rectangle; import java.awt.Robot; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class XugglerRtmpReferenceImpl { private static String url = "rtmp://your.test.server/screen/"; private static String fileName = "test/teststream"; private static int framesToEnpre = 60; private static int x = 0; private static int y = 0; private static int height = 480; private static int width = 640; public static void main(String[] args) {IContainer container = IContainer.make();IContainerFormat containerFormat_live = IContainerFormat.make();containerFormat_live.setOutputFormat("flv", url + fileName, null);container.setInputBufferLength(0);int retVal = container.open(url + fileName, IContainer.Type.WRITE, containerFormat_live);if (retVal < 0) { System.err.println("Could not open output container for live stream"); System.exit(1);}IStream stream = container.addNewStream(0);IStreamCoder prer = stream.getStreamCoder();ICodec prec = ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_H264);prer.setNumPicturesInGroupOfPictures(5);prer.setCodec(prec);prer.setBitRate(200000);prer.setPixelType(IPixelFormat.Type.YUV420P);prer.setHeight(height);prer.setWidth(width);System.out.println("[ENCODER] video size is " + width + "x" + height);prer.setFlag(IStreamCoder.Flags.FLAG_QSCALE, true);prer.setGlobalQuality(0);IRational frameRate = IRational.make(5, 1);prer.setframeRate(frameRate);prer.setTimebase(IRational.make(frameRate.getDenominator(), frameRate.getNumerator()));Properties props = new Properties();InputStream is = XugglerRtmpReferenceImpl.class.getResourceAsStream("/libx264-normal.ffpreset");try { props.load(is);} catch (IOException e) { System.err.println("You need the libx264-normal.ffpreset file from the Xuggle distribution in your classpath."); System.exit(1);}Configuration.configure(props, prer);prer.open();container.writeHeader();long firstTimeStamp = System.currentTimeMillis();long lastTimeStamp = -1;int i = 0;try { Robot robot = new Robot(); while (i < framesToEnpre) { //long iterationStartTime = System.currentTimeMillis(); long now = System.currentTimeMillis(); //grab the screenshot BufferedImage image = robot.createScreenCapture(new Rectangle(x, y, width, height)); //convert it for Xuggler BufferedImage currentScreenshot = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); currentScreenshot.getGraphics().drawImage(image, 0, 0, null); //start the encoding process IPacket packet = IPacket.make(); IConverter converter = ConverterFactory.createConverter(currentScreenshot, IPixelFormat.Type.YUV420P); long timeStamp = (now - firstTimeStamp) * 1000; IVideoPicture outframe = converter.toPicture(currentScreenshot, timeStamp); if (i == 0) { //make first frame keyframe outframe.setKeyframe(true); } outframe.setQuality(0); prer.enpreVideo(packet, outframe, 0); outframe.delete(); if (packet.isComplete()) { container.writePacket(packet); System.out.println("[ENCODER] writing packet of size " + packet.getSize() + " for elapsed time " + ((timeStamp - lastTimeStamp) / 1000)); lastTimeStamp = timeStamp; } System.out.println("[ENCODER] enpred image " + i + " in " + (System.currentTimeMillis() - now)); i++; try { Thread.sleep(Math.max((long) (1000 / frameRate.getDouble()) - (System.currentTimeMillis() - now), 0)); } catch (InterruptedException e) { e.printStackTrace(); } }} catch (AWTException e) { e.printStackTrace();}container.writeTrailer(); } }