1 /* 2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javafx.scene.media; 26 27 import com.sun.javafx.geom.RectBounds; 28 import com.sun.javafx.media.PrismMediaFrameHandler; 29 import com.sun.javafx.sg.prism.MediaFrameTracker; 30 import com.sun.javafx.sg.prism.NGNode; 31 import com.sun.media.jfxmedia.control.VideoDataBuffer; 32 import com.sun.prism.Graphics; 33 import com.sun.prism.Texture; 34 35 /** 36 */ 37 class NGMediaView extends NGNode { 38 39 private boolean smooth = true; 40 private final RectBounds dimension = new RectBounds(); 41 private final RectBounds viewport = new RectBounds(); 42 private PrismMediaFrameHandler handler; 43 private MediaPlayer player; 44 private MediaFrameTracker frameTracker; 45 46 public void renderNextFrame() { 47 visualsChanged(); 48 } 49 50 public boolean isSmooth() { 51 return smooth; 52 } 53 54 public void setSmooth(boolean smooth) { 55 if (smooth != this.smooth) { 56 this.smooth = smooth; 57 visualsChanged(); 58 } 59 } 60 61 public void setX(float x) { 62 if (x != this.dimension.getMinX()) { 63 float width = this.dimension.getWidth(); 64 this.dimension.setMinX(x); 65 this.dimension.setMaxX(x + width); 66 geometryChanged(); 67 } 68 } 69 70 public void setY(float y) { 71 if (y != this.dimension.getMinY()) { 72 float height = this.dimension.getHeight(); 73 this.dimension.setMinY(y); 74 this.dimension.setMaxY(y + height); 75 geometryChanged(); 76 } 77 } 78 79 public void setMediaProvider(Object provider) { 80 if (provider == null) { 81 player = null; 82 handler = null; 83 geometryChanged(); 84 } else if (provider instanceof MediaPlayer) { 85 player = (MediaPlayer)provider; 86 handler = PrismMediaFrameHandler.getHandler(player); 87 geometryChanged(); 88 } 89 } 90 91 public void setViewport(float fitWidth, float fitHeight, 92 float vx, float vy, float vw, float vh, 93 boolean preserveRatio) 94 { 95 float w = 0; 96 float h = 0; 97 float newW = fitWidth; 98 float newH = fitHeight; 99 100 // determine media width/height 101 if (null != player) { 102 Media m = player.getMedia(); 103 w = m.getWidth(); 104 h = m.getHeight(); 105 } 106 107 if (vw > 0 && vh > 0) { 108 viewport.setBounds(vx, vy, vx+vw, vy+vh); 109 w = vw; 110 h = vh; 111 } else { 112 viewport.setBounds(0f, 0f, w, h); 113 } 114 if (fitWidth <= 0f && fitHeight <= 0f) { 115 newW = w; 116 newH = h; 117 } else if (preserveRatio) { 118 // FIXME: we should get the aspect ratio from the Media itself instead of assuming 119 // (RT-26934) 120 if (fitWidth <= 0.0) { 121 newW = h > 0 ? w * (fitHeight / h) : 0.0f; 122 newH = fitHeight; 123 } else if (fitHeight <= 0.0) { 124 newW = fitWidth; 125 newH = w > 0 ? h * (fitWidth / w) : 0.0f; 126 } else { 127 if (w == 0.0f) w = fitWidth; 128 if (h == 0.0f) h = fitHeight; 129 float scale = Math.min(fitWidth / w, fitHeight / h); 130 newW = w * scale; 131 newH = h * scale; 132 } 133 } else if (fitHeight <= 0.0) { 134 newH = h; 135 } else if (fitWidth <= 0.0) { 136 newW = w; 137 } 138 if (newH < 1f) { 139 newH = 1f; 140 } 141 if (newW < 1f) { 142 newW = 1f; 143 } 144 dimension.setMaxX(dimension.getMinX() + newW); 145 dimension.setMaxY(dimension.getMinY() + newH); 146 geometryChanged(); 147 } 148 149 @Override 150 protected void renderContent(Graphics g) { 151 if (null == handler || null == player) { 152 return; // not ready yet... 153 } 154 155 VideoDataBuffer frame = player.getLatestFrame(); 156 if (null == frame) { 157 return; 158 } 159 160 Texture texture = handler.getTexture(g, frame); 161 if (texture != null) { 162 float iw = viewport.getWidth(); 163 float ih = viewport.getHeight(); 164 boolean dimensionsSet = !dimension.isEmpty(); 165 boolean doScale = dimensionsSet && 166 (iw != dimension.getWidth() || ih != dimension.getHeight()); 167 168 g.translate(dimension.getMinX(), dimension.getMinY()); 169 170 if (doScale && iw != 0 && ih != 0) { 171 float scaleW = dimension.getWidth() / iw; 172 float scaleH = dimension.getHeight() / ih; 173 g.scale(scaleW, scaleH); 174 } 175 176 float sx1 = viewport.getMinX(); 177 float sy1 = viewport.getMinY(); 178 float sx2 = sx1 + iw; 179 float sy2 = sy1 + ih; 180 181 g.drawTexture(texture, 182 0f, 0f, iw, ih, 183 sx1, sy1, sx2, sy2); 184 texture.unlock(); 185 186 if (null != frameTracker) { 187 frameTracker.incrementRenderedFrameCount(1); 188 } 189 } 190 frame.releaseFrame(); 191 } 192 193 @Override 194 protected boolean hasOverlappingContents() { 195 return false; 196 } 197 198 public void setFrameTracker(MediaFrameTracker t) { 199 frameTracker = t; 200 } 201 }