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}