[Scummvm-cvs-logs] scummvm master -> e6452518ddb13294c2b3264e9dc754c8ad6ff3ef

clone2727 clone2727 at gmail.com
Sun May 15 08:24:52 CEST 2011


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:
e6452518dd SWORD25: Begin fixing the TheoraDecoder implementation


Commit: e6452518ddb13294c2b3264e9dc754c8ad6ff3ef
    https://github.com/scummvm/scummvm/commit/e6452518ddb13294c2b3264e9dc754c8ad6ff3ef
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-05-14T23:20:49-07:00

Commit Message:
SWORD25: Begin fixing the TheoraDecoder implementation

getFrameRate() and endOfVideo() have been fixed so it can be used as a standalone decoder. a/v sync still needs to be fixed

Changed paths:
    engines/sword25/fmv/movieplayer.cpp
    engines/sword25/fmv/theora_decoder.cpp
    engines/sword25/fmv/theora_decoder.h



diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index 2a55f6d..c60f5d4 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -46,7 +46,7 @@ namespace Sword25 {
 #define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */
 
 #ifdef USE_THEORADEC
-MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel), _decoder(g_system->getMixer()) {
+MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel), _decoder() {
 	if (!registerScriptBindings())
 		error("Script bindings could not be registered.");
 	else
diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp
index 15e81af..f7e5e7a 100644
--- a/engines/sword25/fmv/theora_decoder.cpp
+++ b/engines/sword25/fmv/theora_decoder.cpp
@@ -51,7 +51,7 @@ static double rint(double v) {
 	return floor(v + 0.5);
 }
 
-TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : _mixer(mixer) {
+TheoraDecoder::TheoraDecoder(Audio::Mixer::SoundType soundType) {
 	_fileStream = 0;
 	_surface = 0;
 
@@ -59,7 +59,6 @@ TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT
 	_vorbisPacket = 0;
 	_theoraDecode = 0;
 	_theoraSetup = 0;
-	_stateFlag = false;
 
 	_soundType = soundType;
 	_audStream = 0;
@@ -67,7 +66,7 @@ TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT
 
 	ogg_sync_init(&_oggSync);
 
-	_curFrame = 0;
+	_curFrame = -1;
 	_audiobuf = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t));
 
 	reset();
@@ -115,7 +114,8 @@ bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
 
 	// Ogg file open; parse the headers
 	// Only interested in Vorbis/Theora streams
-	while (!_stateFlag) {
+	bool foundHeader = false;
+	while (!foundHeader) {
 		int ret = bufferData();
 
 		if (ret == 0)
@@ -128,7 +128,7 @@ bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
 			if (!ogg_page_bos(&_oggPage)) {
 				// don't leak the page; get it into the appropriate stream
 				queuePage(&_oggPage);
-				_stateFlag = true;
+				foundHeader = true;
 				break;
 			}
 
@@ -280,15 +280,17 @@ bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
 
 	// open audio
 	if (_vorbisPacket) {
-		_audStream = createAudioStream();
-		if (_audStream && _mixer)
-			_mixer->playStream(_soundType, _audHandle, _audStream);
+		_audStream = Audio::makeQueuingAudioStream(_vorbisInfo.rate, _vorbisInfo.channels);
+		if (_audStream)
+			g_system->getMixer()->playStream(_soundType, _audHandle, _audStream);
 	}
 
 	_surface = new Graphics::Surface();
-
 	_surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, g_system->getScreenFormat());
 
+	// Set the frame rate
+	_frameRate = Common::Rational(_theoraInfo.fps_numerator, _theoraInfo.fps_denominator);
+
 	return true;
 }
 
@@ -300,8 +302,8 @@ void TheoraDecoder::close() {
 		vorbis_comment_clear(&_vorbisComment);
 		vorbis_info_clear(&_vorbisInfo);
 
-		if (_mixer)
-			_mixer->stopHandle(*_audHandle);
+		g_system->getMixer()->stopHandle(*_audHandle);
+
 		_audStream = 0;
 		_vorbisPacket = false;
 	}
@@ -372,7 +374,7 @@ const Graphics::Surface *TheoraDecoder::decodeNextFrame() {
 		}
 	}
 
-	while (_theoraPacket && !_videobufReady) {
+	while (_theoraPacket && !_theoraOut.e_o_s) {
 		// theora is one in, one out...
 		if (ogg_stream_packetout(&_theoraOut, &_oggPacket) > 0) {
 
@@ -399,26 +401,28 @@ const Graphics::Surface *TheoraDecoder::decodeNextFrame() {
 			if (th_decode_packetin(_theoraDecode, &_oggPacket, NULL) == 0) {
 #endif
 				_curFrame++;
-				_videobufReady = true;
-			}
-		} else
-			break;
-	}
 
-	if (!_videobufReady && !_audiobufReady && _fileStream->eos()) {
-		return NULL;
-	}
+				// Convert YUV data to RGB data
+				th_ycbcr_buffer yuv;
+				th_decode_ycbcr_out(_theoraDecode, yuv);
+				translateYUVtoRGBA(yuv);
 
-	if (!_videobufReady || !_audiobufReady) {
-		// no data yet for somebody.  Grab another page
-		bufferData();
-		while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
-			queuePage(&_oggPage);
+				if (_curFrame == 0)
+					_startTime = g_system->getMillis();
+
+				// break out
+				break;
+			}
+		} else {
+			// Queue more data
+			bufferData();
+			while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
+				queuePage(&_oggPage);
 		}
 	}
 
 	// If playback has begun, top audio buffer off immediately.
-	if (_stateFlag && _audiobufReady) {
+	if (_audiobufReady) {
 		_audStream->queueBuffer((byte *)_audiobuf, AUDIOFD_FRAGSIZE, DisposeAfterUse::NO, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO);
 
 		// The audio mixer is now responsible for the old audio buffer.
@@ -428,39 +432,17 @@ const Graphics::Surface *TheoraDecoder::decodeNextFrame() {
 		_audiobufReady = false;
 	}
 
-	// are we at or past time for this video frame?
-	if (_stateFlag && _videobufReady) {
-		th_ycbcr_buffer yuv;
-
-		th_decode_ycbcr_out(_theoraDecode, yuv);
-
-		// Convert YUV data to RGB data
-		translateYUVtoRGBA(yuv, (byte *)_surface->getBasePtr(0, 0));
-		
-		_videobufReady = false;
-	}
-
-	// if our buffers either don't exist or are ready to go,
-	// we can begin playback
-	if ((!_theoraPacket || _videobufReady) &&
-	        (!_vorbisPacket || _audiobufReady))
-		_stateFlag = true;
-
-	// same if we've run out of input
-	if (_fileStream->eos())
-		_stateFlag = true;
-
 	return _surface;
 }
 
 void TheoraDecoder::reset() {
 	FixedRateVideoDecoder::reset();
 
+	// FIXME: This does a rewind() instead of a reset()!
+
 	if (_fileStream)
 		_fileStream->seek(0);
 
-	_videobufReady = false;
-
 #if ENABLE_THEORA_SEEKING
 	_videobufGranulePos = -1;
 	_audiobufGranulePos = 0;
@@ -470,36 +452,31 @@ void TheoraDecoder::reset() {
 	_audiobufFill = 0;
 	_audiobufReady = false;
 
-	_curFrame = 0;
+	_curFrame = -1;
 
 	_theoraPacket = 0;
 	_vorbisPacket = 0;
-	_stateFlag = false;
 }
 
 bool TheoraDecoder::endOfVideo() const {
-	return !isVideoLoaded();
+	return !isVideoLoaded() || _theoraOut.e_o_s;
 }
 
-
 uint32 TheoraDecoder::getElapsedTime() const {
-	if (_audStream && _mixer)
-		return _mixer->getSoundElapsedTime(*_audHandle);
+	if (_audStream)
+		return g_system->getMixer()->getSoundElapsedTime(*_audHandle);
 
 	return FixedRateVideoDecoder::getElapsedTime();
 }
 
-Audio::QueuingAudioStream *TheoraDecoder::createAudioStream() {
-	return Audio::makeQueuingAudioStream(_vorbisInfo.rate, _vorbisInfo.channels);
-}
-
-static void convertYUVtoBGRA(int y, int u, int v, byte *dst) {
+static void convertYUVtoBGRA(int y, int u, int v, byte *dst, Graphics::PixelFormat format) {
 	byte r, g, b;
 	Graphics::YUV2RGB(y, u, v, r, g, b);
-	*(dst + 0) = b;
-	*(dst + 1) = g;
-	*(dst + 2) = r;
-	*(dst + 3) = 0xFF;
+
+	if (format.bytesPerPixel == 2)
+		*((uint16 *)dst) = format.RGBToColor(r, g, b);
+	else
+		*((uint32 *)dst) = format.RGBToColor(r, g, b);
 }
 
 enum TheoraYUVBuffers {
@@ -508,7 +485,7 @@ enum TheoraYUVBuffers {
 	kBufferV = 2
 };
 
-void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, byte *pixelData) {
+void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer) {
 	// Width and height of all buffers have to be divisible by 2.
 	assert((YUVBuffer[kBufferY].width & 1)   == 0);
 	assert((YUVBuffer[kBufferY].height & 1)  == 0);
@@ -524,10 +501,10 @@ void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, byte *pixelDa
 	const byte *ySrc = YUVBuffer[kBufferY].data;
 	const byte *uSrc = YUVBuffer[kBufferU].data;
 	const byte *vSrc = YUVBuffer[kBufferV].data;
-	byte *dst  = pixelData;
+	byte *dst  = (byte *)_surface->pixels;
 	int u = 0, v = 0;
 
-	const int blockSize = YUVBuffer[kBufferY].width << 2;
+	const int blockSize = YUVBuffer[kBufferY].width * getPixelFormat().bytesPerPixel;
 	const int halfHeight = YUVBuffer[kBufferY].height >> 1;
 	const int halfWidth = YUVBuffer[kBufferY].width >> 1;
 	const int yStep = (YUVBuffer[kBufferY].stride << 1) - YUVBuffer[kBufferY].width;
@@ -543,8 +520,8 @@ void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, byte *pixelDa
 			v = *vSrc++;
 
 			for (int i = 0; i <= 1; i++) {
-				convertYUVtoBGRA(*ySrc, u, v, dst);
-				convertYUVtoBGRA(*(ySrc + stride), u, v, dst + blockSize);
+				convertYUVtoBGRA(*ySrc, u, v, dst, getPixelFormat());
+				convertYUVtoBGRA(*(ySrc + stride), u, v, dst + blockSize, getPixelFormat());
 				ySrc++;
 				dst += 4;	// BGRA
 			}
diff --git a/engines/sword25/fmv/theora_decoder.h b/engines/sword25/fmv/theora_decoder.h
index d8da024..a1ce3ae 100644
--- a/engines/sword25/fmv/theora_decoder.h
+++ b/engines/sword25/fmv/theora_decoder.h
@@ -53,7 +53,7 @@ namespace Sword25 {
  */
 class TheoraDecoder : public Video::FixedRateVideoDecoder {
 public:
-	TheoraDecoder(Audio::Mixer *mixer = 0, Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
+	TheoraDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
 	virtual ~TheoraDecoder();
 
 	/**
@@ -71,43 +71,30 @@ public:
 	 */
 	const Graphics::Surface *decodeNextFrame();
 
-	bool isVideoLoaded() const {
-		return _fileStream != 0;
-	}
-	bool isPaused() const {
-		return (FixedRateVideoDecoder::isPaused() || !isVideoLoaded());
-	}
+	bool isVideoLoaded() const { return _fileStream != 0; }
+	uint16 getWidth() const { return _surface->w; }
+	uint16 getHeight() const { return _surface->h; }
 
-	uint16 getWidth() const {
-		return _surface->w;
-	}
-	uint16 getHeight() const {
-		return _surface->h;
-	}
 	uint32 getFrameCount() const {
 		// It is not possible to get frame count easily
 		// I.e. seeking is required
 		assert(0);
 		return 0;
 	}
-	Graphics::PixelFormat getPixelFormat() const {
-		return Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
-	}
+
+	Graphics::PixelFormat getPixelFormat() const { return _surface->format; }
 
 	uint32 getElapsedTime() const;
 
 	bool endOfVideo() const;
 
 protected:
-	Common::Rational getFrameRate() const {
-		return _frameRate;
-	}
+	Common::Rational getFrameRate() const {	return _frameRate; }
 
 private:
 	void queuePage(ogg_page *page);
 	int bufferData();
-	Audio::QueuingAudioStream *createAudioStream();
-	void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, byte *pixelData);
+	void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer);
 
 private:
 	Common::SeekableReadStream *_fileStream;
@@ -115,7 +102,6 @@ private:
 	Common::Rational _frameRate;
 	uint32 _frameCount;
 
-	Audio::Mixer *_mixer;
 	Audio::Mixer::SoundType _soundType;
 	Audio::SoundHandle *_audHandle;
 	Audio::QueuingAudioStream *_audStream;
@@ -136,15 +122,11 @@ private:
 
 	int _theoraPacket;
 	int _vorbisPacket;
-	bool _stateFlag;
 
 	int _ppLevelMax;
 	int _ppLevel;
 	int _ppInc;
 
-	// single frame video buffering
-	bool _videobufReady;
-
 	// single audio fragment audio buffering
 	int _audiobufFill;
 	bool _audiobufReady;






More information about the Scummvm-git-logs mailing list