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 java.io.Closeable; 033import java.util.Iterator; 034 035import org.openimaj.image.Image; 036 037/** 038 * Abstract base class for videos. 039 * 040 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 041 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 042 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 043 * 044 * @param <T> 045 * the image type of the frames 046 */ 047public abstract class Video<T extends Image<?, T>> implements Iterable<T>, Closeable 048{ 049 /** The number of frames per second */ 050 // protected double fps = -1; 051 052 /** The current frame being displayed */ 053 protected int currentFrame; 054 055 /** 056 * Get the next frame. Increments the frame counter by 1. 057 * 058 * @return the next frame 059 */ 060 public abstract T getNextFrame(); 061 062 /** 063 * Get the current frame 064 * 065 * @return the current frame 066 */ 067 public abstract T getCurrentFrame(); 068 069 /** 070 * Get the width of the video frame 071 * 072 * @return the width of the video frame. 073 */ 074 public abstract int getWidth(); 075 076 /** 077 * Get the height of the video frame. 078 * 079 * @return the height of the video frame. 080 */ 081 public abstract int getHeight(); 082 083 /** 084 * Get the timestamp of the current frame in milliseconds 085 * 086 * @return the time stamp in milliseconds 087 */ 088 public abstract long getTimeStamp(); 089 090 // /** 091 // * Determine how many milliseconds each frame needs 092 // * to be displayed for 093 // * 094 // * @return the time to show each frame in ms 095 // */ 096 // public long getMilliPerFrame() 097 // { 098 // if(this.getFPS() < 0) return 1; 099 // return (long) (1000 * (1.0/this.getFPS())); 100 // } 101 // 102 /** 103 * Get the frame rate 104 * 105 * @return the frame rate 106 */ 107 public abstract double getFPS(); 108 109 // /** 110 // * Set the frame rate 111 // * 112 // * @return the frame rate 113 // */ 114 // public void setFPS(double fps) 115 // { 116 // this.fps = fps; 117 // } 118 119 /** 120 * Get the index of the current frame 121 * 122 * @return the current frame index 123 */ 124 public synchronized int getCurrentFrameIndex() 125 { 126 return currentFrame; 127 } 128 129 /** 130 * Set the current frame index (i.e. skips to a certain frame). If your 131 * video subclass can implement this in a cleverer way, then override this 132 * method, otherwise this method will simply grab frames until it gets to 133 * the given frame index. This method is naive and may take some time as 134 * each frame will be decoded by the video decoder. 135 * 136 * @param newFrame 137 * the new index 138 */ 139 public synchronized void setCurrentFrameIndex(long newFrame) 140 { 141 // We're already at the frame? 142 if (this.currentFrame == newFrame) 143 return; 144 145 // If we're ahread of where we want to be 146 if (this.currentFrame > newFrame) 147 { 148 this.reset(); 149 } 150 151 // Grab frames until we read the new frame counter 152 // (or until the getNextFrame() method returns null) 153 while (this.currentFrame < newFrame && getNextFrame() != null) 154 ; 155 } 156 157 /** 158 * Seek the video to a given timestamp in SECONDS. Many videos (including 159 * cameras etc.) will have no ability to seek so by default this function 160 * does nothing. 161 * 162 * @param timestamp 163 */ 164 public void seek(double timestamp) { 165 166 } 167 168 /** 169 * Returns whether this video has another frame to provide. 170 * 171 * @return Whether the video has another frame available 172 */ 173 public abstract boolean hasNextFrame(); 174 175 /** 176 * Return the number of frames in the whole video. If the video is a live 177 * stream, then this method should return -1. 178 * 179 * @return the number of frames in the whole video or -1 if unknown 180 */ 181 public abstract long countFrames(); 182 183 /** 184 * Reset the video - putting the frame counter back to the start. 185 */ 186 public abstract void reset(); 187 188 @Override 189 public Iterator<T> iterator() { 190 return new VideoIterator<T>(this); 191 } 192 193 /** 194 * Close the video object 195 */ 196 @Override 197 public void close() { 198 199 } 200}