]> source.dussan.org Git - poi.git/commitdiff
Add example for adding videos
authorAndreas Beeker <kiwiwings@apache.org>
Sat, 6 Feb 2016 22:23:47 +0000 (22:23 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sat, 6 Feb 2016 22:23:47 +0000 (22:23 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1728888 13f79535-47bb-0310-9956-ffa450edef68

src/examples/src/org/apache/poi/xslf/usermodel/AddVideoToPptx.java.txt [new file with mode: 0644]

diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/AddVideoToPptx.java.txt b/src/examples/src/org/apache/poi/xslf/usermodel/AddVideoToPptx.java.txt
new file mode 100644 (file)
index 0000000..2d32c4d
--- /dev/null
@@ -0,0 +1,251 @@
+/*\r
+ *  ====================================================================\r
+ *    Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ * ==================================================================== \r
+ */\r
+\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import java.awt.Rectangle;\r
+import java.awt.image.BufferedImage;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.net.URL;\r
+import java.text.DecimalFormat;\r
+\r
+import javax.imageio.ImageIO;\r
+import javax.xml.namespace.QName;\r
+\r
+import org.apache.poi.openxml4j.opc.PackagePart;\r
+import org.apache.poi.openxml4j.opc.PackagePartName;\r
+import org.apache.poi.openxml4j.opc.PackageRelationship;\r
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
+import org.apache.poi.sl.usermodel.PictureData.PictureType;\r
+import org.apache.xmlbeans.XmlCursor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;\r
+import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTExtension;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonMediaNodeData;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonTimeNodeData;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.CTTimeNodeList;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeIndefinite;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeFillType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeRestartType;\r
+import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeType;\r
+\r
+import com.xuggle.mediatool.IMediaReader;\r
+import com.xuggle.mediatool.MediaListenerAdapter;\r
+import com.xuggle.mediatool.ToolFactory;\r
+import com.xuggle.mediatool.event.IVideoPictureEvent;\r
+import com.xuggle.xuggler.Global;\r
+import com.xuggle.xuggler.IContainer;\r
+import com.xuggle.xuggler.io.InputOutputStreamHandler;\r
+\r
+/**\r
+ * Adding multiple videos to a slide\r
+ * \r
+ * need the Xuggler 5.4 jars:\r
+ *  &lt;repositories&gt;\r
+ *  &lt;repository&gt;\r
+ *  &lt;id&gt;xuggle repo&lt;/id&gt;\r
+ *  &lt;url&gt;http://xuggle.googlecode.com/svn/trunk/repo/share/java/&lt;/url&gt;\r
+ *  &lt;/repository&gt;\r
+ *  &lt;/repositories&gt;\r
+ *  ...\r
+ *  &lt;dependency&gt;\r
+ *  &lt;groupId&gt;xuggle&lt;/groupId&gt;\r
+ *  &lt;artifactId&gt;xuggle-xuggler&lt;/artifactId&gt;\r
+ *  &lt;version&gt;5.4&lt;/version&gt;\r
+ *  &lt;/dependency&gt;\r
+ * \r
+ * @see <a href="http://stackoverflow.com/questions/15197300/apache-poi-xslf-adding-movie-to-the-slide">Apache POI XSLF Adding movie to the slide</a>\r
+ * @see <a href="http://apache-poi.1045710.n5.nabble.com/Question-about-embedded-video-in-PPTX-files-tt5718461.html">Question about embedded video in PPTX files</a>\r
+ */\r
+public class AddVideoToPptx {\r
+    static DecimalFormat df_time = new DecimalFormat("0.####");\r
+\r
+    public static void main(String[] args) throws Exception {\r
+        URL video = new URL("http://archive.org/download/test-mpeg/test-mpeg.mpg");\r
+        // URL video = new URL("file:test-mpeg.mpg");\r
+\r
+        XMLSlideShow pptx = new XMLSlideShow();\r
+\r
+        // add video file\r
+        String videoFileName = video.getPath().substring(video.getPath().lastIndexOf('/')+1);\r
+        PackagePartName partName = PackagingURIHelper.createPartName("/ppt/media/"+videoFileName);\r
+        PackagePart part = pptx.getPackage().createPart(partName, "video/mpeg");\r
+        OutputStream partOs = part.getOutputStream();\r
+        InputStream fis = video.openStream();\r
+        byte buf[] = new byte[1024];\r
+        for (int readBytes; (readBytes = fis.read(buf)) != -1; partOs.write(buf, 0, readBytes));\r
+        fis.close();\r
+        partOs.close();\r
+\r
+        XSLFSlide slide1 = pptx.createSlide();\r
+        XSLFPictureShape pv1 = addPreview(pptx, slide1, part, 5, 50, 50);\r
+        addVideo(pptx, slide1, part, pv1, 5);\r
+        addTimingInfo(slide1, pv1);\r
+        XSLFPictureShape pv2 = addPreview(pptx, slide1, part, 9, 50, 250);\r
+        addVideo(pptx, slide1, part, pv2, 9);\r
+        addTimingInfo(slide1, pv2);\r
+\r
+        FileOutputStream fos = new FileOutputStream("pptx-with-video.pptx");\r
+        pptx.write(fos);\r
+        fos.close();\r
+        \r
+        pptx.close();\r
+    }\r
+\r
+    static XSLFPictureShape addPreview(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, double seconds, int x, int y) throws IOException {\r
+        // get preview after 5 sec.\r
+        IContainer ic = IContainer.make();\r
+        InputOutputStreamHandler iosh = new InputOutputStreamHandler(videoPart.getInputStream());\r
+        if (ic.open(iosh, IContainer.Type.READ, null) < 0) return null;\r
+\r
+        IMediaReader mediaReader = ToolFactory.makeReader(ic);\r
+\r
+        // stipulate that we want BufferedImages created in BGR 24bit color space\r
+        mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);\r
+\r
+        ImageSnapListener isl = new ImageSnapListener(seconds);\r
+        mediaReader.addListener(isl);\r
+\r
+        // read out the contents of the media file and\r
+        // dispatch events to the attached listener\r
+        while (!isl.hasFired && mediaReader.readPacket() == null) ;\r
+\r
+        mediaReader.close();\r
+        ic.close();\r
+\r
+        // add snapshot\r
+        BufferedImage image1 = isl.image;\r
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
+        ImageIO.write(image1, "jpeg", bos);\r
+        XSLFPictureData snap = pptx.addPicture(bos.toByteArray(), PictureType.JPEG);\r
+        XSLFPictureShape pic1 = slide1.createPicture(snap);\r
+        pic1.setAnchor(new Rectangle(x, y, image1.getWidth(), image1.getHeight()));\r
+        return pic1;\r
+    }\r
+\r
+    static void addVideo(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, XSLFPictureShape pic1, double seconds) throws IOException {\r
+\r
+        // add video shape\r
+        PackagePartName partName = videoPart.getPartName();\r
+        PackageRelationship prsEmbed1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.microsoft.com/office/2007/relationships/media");\r
+        PackageRelationship prsExec1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/video");\r
+        CTPicture xpic1 = (CTPicture)pic1.getXmlObject();\r
+        CTHyperlink link1 = xpic1.getNvPicPr().getCNvPr().addNewHlinkClick();\r
+        link1.setId("");\r
+        link1.setAction("ppaction://media");\r
+\r
+        // add video relation\r
+        CTApplicationNonVisualDrawingProps nvPr = xpic1.getNvPicPr().getNvPr();\r
+        nvPr.addNewVideoFile().setLink(prsExec1.getId());\r
+        CTExtension ext = nvPr.addNewExtLst().addNewExt();\r
+        // see http://msdn.microsoft.com/en-us/library/dd950140(v=office.12).aspx\r
+        ext.setUri("{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}");\r
+        String p14Ns = "http://schemas.microsoft.com/office/powerpoint/2010/main";\r
+        XmlCursor cur = ext.newCursor();\r
+        cur.toEndToken();\r
+        cur.beginElement(new QName(p14Ns, "media", "p14"));\r
+        cur.insertNamespace("p14", p14Ns);\r
+        cur.insertAttributeWithValue(new QName(STRelationshipId.type.getName().getNamespaceURI(), "embed"), prsEmbed1.getId());\r
+        cur.beginElement(new QName(p14Ns, "trim", "p14"));\r
+        cur.insertAttributeWithValue("st", df_time.format(seconds*1000.0));\r
+        cur.dispose();\r
+\r
+    }\r
+\r
+    static void addTimingInfo(XSLFSlide slide1, XSLFPictureShape pic1) {\r
+        // add slide timing information, so video can be controlled\r
+        CTSlide xslide = slide1.getXmlObject();\r
+        CTTimeNodeList ctnl;\r
+        if (!xslide.isSetTiming()) {\r
+            CTTLCommonTimeNodeData ctn = xslide.addNewTiming().addNewTnLst().addNewPar().addNewCTn();\r
+            ctn.setDur(STTLTimeIndefinite.INDEFINITE);\r
+            ctn.setRestart(STTLTimeNodeRestartType.NEVER);\r
+            ctn.setNodeType(STTLTimeNodeType.TM_ROOT);\r
+            ctnl = ctn.addNewChildTnLst();\r
+        } else {\r
+            ctnl = xslide.getTiming().getTnLst().getParArray(0).getCTn().getChildTnLst();\r
+        }\r
+\r
+        CTTLCommonMediaNodeData cmedia = ctnl.addNewVideo().addNewCMediaNode();\r
+        cmedia.setVol(80000);\r
+        CTTLCommonTimeNodeData ctn = cmedia.addNewCTn();\r
+        ctn.setFill(STTLTimeNodeFillType.HOLD);\r
+        ctn.setDisplay(false);\r
+        ctn.addNewStCondLst().addNewCond().setDelay(STTLTimeIndefinite.INDEFINITE);\r
+        cmedia.addNewTgtEl().addNewSpTgt().setSpid(""+pic1.getShapeId());\r
+    }\r
+\r
+\r
+    static class ImageSnapListener extends MediaListenerAdapter {\r
+        final double SECONDS_BETWEEN_FRAMES;\r
+        final long MICRO_SECONDS_BETWEEN_FRAMES;\r
+        boolean hasFired = false;\r
+        BufferedImage image = null;\r
+\r
+        // The video stream index, used to ensure we display frames from one and\r
+        // only one video stream from the media container.\r
+        int mVideoStreamIndex = -1;\r
+\r
+        // Time of last frame write\r
+        long mLastPtsWrite = Global.NO_PTS;\r
+\r
+        public ImageSnapListener(double seconds) {\r
+            SECONDS_BETWEEN_FRAMES = seconds;\r
+            MICRO_SECONDS_BETWEEN_FRAMES =\r
+                    (long)(Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES);\r
+        }\r
+\r
+\r
+        @Override\r
+        public void onVideoPicture(IVideoPictureEvent event) {\r
+\r
+            if (event.getStreamIndex() != mVideoStreamIndex) {\r
+                // if the selected video stream id is not yet set, go ahead an\r
+                // select this lucky video stream\r
+                if (mVideoStreamIndex != -1) return;\r
+                mVideoStreamIndex = event.getStreamIndex();\r
+            }\r
+\r
+            long evtTS = event.getTimeStamp();\r
+\r
+            // if uninitialized, back date mLastPtsWrite to get the very first frame\r
+            if (mLastPtsWrite == Global.NO_PTS)\r
+                mLastPtsWrite = Math.max(0, evtTS - MICRO_SECONDS_BETWEEN_FRAMES);\r
+\r
+            // if it's time to write the next frame\r
+            if (evtTS - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES) {\r
+                if (!hasFired) {\r
+                    image = event.getImage();\r
+                    hasFired = true;\r
+                }\r
+                // update last write time\r
+                mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES;\r
+            }\r
+        }\r
+    }\r
+\r
+}\r