001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.video; 031 032import org.openimaj.image.Image; 033 034/** 035 * A video from an array of frames 036 * 037 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 038 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 039 * 040 * @param <T> 041 * the image type of the frames 042 */ 043public class ArrayBackedVideo<T extends Image<?, T>> extends Video<T> 044{ 045 private T[] frames; 046 private boolean loop; 047 private double fps = 30d; 048 049 /** 050 * Default constructor for creating array backed videos with no frames for 051 * subclasses. 052 */ 053 protected ArrayBackedVideo() 054 { 055 } 056 057 /** 058 * Construct a video from the provided frames. Assumes a rate of 30 FPS. 059 * 060 * @param frames 061 * the frames 062 */ 063 public ArrayBackedVideo(T[] frames) { 064 this.frames = frames; 065 this.currentFrame = 0; 066 this.fps = 30; 067 this.loop = true; 068 } 069 070 /** 071 * Construct a video from the provided frames. 072 * 073 * @param frames 074 * the frames 075 * @param fps 076 * the frame rate 077 */ 078 public ArrayBackedVideo(T[] frames, double fps) { 079 this.frames = frames; 080 this.currentFrame = 0; 081 this.fps = fps; 082 this.loop = true; 083 } 084 085 /** 086 * Construct a video from the provided frames. 087 * 088 * @param frames 089 * the frames 090 * @param fps 091 * the frame rate 092 * @param loop 093 * loop the video 094 */ 095 public ArrayBackedVideo(T[] frames, double fps, boolean loop) { 096 this.frames = frames; 097 this.currentFrame = 0; 098 this.fps = fps; 099 this.loop = loop; 100 } 101 102 @Override 103 public synchronized T getNextFrame() { 104 final T frame = frames[this.currentFrame % this.frames.length]; 105 this.incrementFrame(); 106 return frame; 107 } 108 109 @Override 110 public synchronized T getCurrentFrame() { 111 return frames[this.currentFrame % this.frames.length]; 112 } 113 114 private void incrementFrame() { 115 if (this.currentFrame + 1 < this.frames.length || loop) { 116 this.currentFrame++; 117 } 118 } 119 120 @Override 121 public synchronized void setCurrentFrameIndex(long newFrame) { 122 if (!loop && newFrame >= this.frames.length - 1) 123 this.currentFrame = this.frames.length - 1; 124 else 125 this.currentFrame = (int) newFrame; 126 } 127 128 @Override 129 public synchronized boolean hasNextFrame() { 130 return loop || this.currentFrame < this.frames.length; 131 } 132 133 /** 134 * {@inheritDoc} 135 * 136 * @see org.openimaj.video.Video#getWidth() 137 */ 138 @Override 139 public int getWidth() 140 { 141 return getCurrentFrame().getWidth(); 142 } 143 144 /** 145 * {@inheritDoc} 146 * 147 * @see org.openimaj.video.Video#getHeight() 148 */ 149 @Override 150 public int getHeight() 151 { 152 return getCurrentFrame().getHeight(); 153 } 154 155 @Override 156 public long countFrames() { 157 return this.frames.length; 158 } 159 160 @Override 161 public void reset() 162 { 163 this.currentFrame = 0; 164 } 165 166 /** 167 * {@inheritDoc} 168 * 169 * @see org.openimaj.video.Video#getTimeStamp() 170 */ 171 @Override 172 public long getTimeStamp() 173 { 174 return (long) (1000 * getCurrentFrameIndex() / this.fps); 175 } 176 177 /** 178 * {@inheritDoc} 179 * 180 * @see org.openimaj.video.Video#getFPS() 181 */ 182 @Override 183 public double getFPS() 184 { 185 return fps; 186 } 187}