From: Andreas Beeker Date: Sat, 6 Feb 2016 22:23:47 +0000 (+0000) Subject: Add example for adding videos X-Git-Tag: REL_3_14_FINAL~47 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b2d6b7c51a55829086be3775ff5b68d6a1bb9d36;p=poi.git Add example for adding videos git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1728888 13f79535-47bb-0310-9956-ffa450edef68 --- 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; + } + } + } + +}