[Scummvm-cvs-logs] scummvm master -> 121faeaa94bf3720143c12f025a9b95e4a875442

clone2727 clone2727 at gmail.com
Mon Nov 26 23:49:44 CET 2012


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
121faeaa94 VIDEO: Add preliminary API functions for seeking to a frame


Commit: 121faeaa94bf3720143c12f025a9b95e4a875442
    https://github.com/scummvm/scummvm/commit/121faeaa94bf3720143c12f025a9b95e4a875442
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2012-11-26T14:44:36-08:00

Commit Message:
VIDEO: Add preliminary API functions for seeking to a frame

Changed paths:
    video/video_decoder.cpp
    video/video_decoder.h



diff --git a/video/video_decoder.cpp b/video/video_decoder.cpp
index 6c45cc5..826880b 100644
--- a/video/video_decoder.cpp
+++ b/video/video_decoder.cpp
@@ -324,6 +324,35 @@ bool VideoDecoder::seek(const Audio::Timestamp &time) {
 	return true;
 }
 
+bool VideoDecoder::seekToFrame(uint frame) {
+	VideoTrack *track = 0;
+
+	for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) {
+		if (!(*it)->isSeekable())
+			return false;
+
+		if ((*it)->getTrackType() == Track::kTrackTypeVideo) {
+			// We only allow seeking by frame when one video track
+			// is present
+			if (track)
+				return false;
+
+			track = (VideoTrack *)*it;
+		}
+	}
+
+	// If we didn't find a video track, we can't seek by frame (of course)
+	if (!track)
+		return false;
+
+	Audio::Timestamp time = track->getFrameTime(frame);
+
+	if (time < 0)
+		return false;
+
+	return seek(time);
+}
+
 void VideoDecoder::start() {
 	if (!isPlaying())
 		setRate(1);
@@ -434,21 +463,45 @@ bool VideoDecoder::VideoTrack::endOfTrack() const {
 	return getCurFrame() >= (getFrameCount() - 1);
 }
 
+Audio::Timestamp VideoDecoder::VideoTrack::getFrameTime(uint frame) const {
+	// Default implementation: Return an invalid (negative) number
+	return Audio::Timestamp().addFrames(-1);
+}
+
 uint32 VideoDecoder::FixedRateVideoTrack::getNextFrameStartTime() const {
 	if (endOfTrack() || getCurFrame() < 0)
 		return 0;
 
-	Common::Rational time = (getCurFrame() + 1) * 1000;
-	time /= getFrameRate();
-	return time.toInt();
+	return getFrameTime(getCurFrame() + 1).msecs();
+}
+
+Audio::Timestamp VideoDecoder::FixedRateVideoTrack::getFrameTime(uint frame) const {
+	// Try to get as accurate as possible, considering we have a fractional frame rate
+	// (which Audio::Timestamp doesn't support).
+	Common::Rational frameRate = getFrameRate();
+
+	if (frameRate == frameRate.toInt()) // The nice case (a whole number)
+		return Audio::Timestamp(0, frame, frameRate.toInt());
+
+	// Just convert to milliseconds.
+	Common::Rational time = frame * 1000;
+	time /= frameRate;
+	return Audio::Timestamp(time.toInt(), 1000);
+}
+
+uint VideoDecoder::FixedRateVideoTrack::getFrameAtTime(const Audio::Timestamp &time) const {
+	Common::Rational frameRate = getFrameRate();
+
+	// Easy conversion
+	if (frameRate == time.framerate())
+		return time.totalNumberOfFrames();
+
+	// Default case
+	return (time.totalNumberOfFrames() * frameRate / time.framerate()).toInt();
 }
 
 Audio::Timestamp VideoDecoder::FixedRateVideoTrack::getDuration() const {
-	// Since Audio::Timestamp doesn't support a fractional frame rate, we're currently
-	// just converting to milliseconds.
-	Common::Rational time = getFrameCount() * 1000;
-	time /= getFrameRate();
-	return time.toInt();
+	return getFrameTime(getFrameCount());
 }
 
 bool VideoDecoder::AudioTrack::endOfTrack() const {
diff --git a/video/video_decoder.h b/video/video_decoder.h
index ca88696..e762626 100644
--- a/video/video_decoder.h
+++ b/video/video_decoder.h
@@ -178,6 +178,14 @@ public:
 	virtual bool seek(const Audio::Timestamp &time);
 
 	/**
+	 * Seek to a given frame.
+	 *
+	 * This only works when one video track is present, and that track
+	 * supports getFrameTime(). This calls seek() internally.
+	 */
+	bool seekToFrame(uint frame);
+
+	/**
 	 * Pause or resume the video. This should stop/resume any audio playback
 	 * and other stuff. The initial pause time is kept so that any timing
 	 * variables can be updated appropriately.
@@ -535,6 +543,14 @@ protected:
 		 * Does the palette currently in use by this track need to be updated?
 		 */
 		virtual bool hasDirtyPalette() const { return false; }
+
+		/**
+		 * Get the time the given frame should be shown.
+		 *
+		 * By default, this returns a negative (invalid) value. This function
+		 * should only be used by VideoDecoder::seekToFrame().
+		 */
+		virtual Audio::Timestamp getFrameTime(uint frame) const;
 	};
 
 	/**
@@ -549,12 +565,19 @@ protected:
 
 		uint32 getNextFrameStartTime() const;
 		virtual Audio::Timestamp getDuration() const;
+		Audio::Timestamp getFrameTime(uint frame) const;
 
 	protected:
 		/**
 		 * Get the rate at which this track is played.
 		 */
 		virtual Common::Rational getFrameRate() const = 0;
+
+		/**
+		 * Get the frame that should be displaying at the given time. This is
+		 * helpful for someone implementing seek().
+		 */
+		uint getFrameAtTime(const Audio::Timestamp &time) const;
 	};
 
 	/**






More information about the Scummvm-git-logs mailing list