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