[Scummvm-cvs-logs] SF.net SVN: scummvm:[55666] scummvm/trunk/engines/sword25/fmv
thebluegr at users.sourceforge.net
thebluegr at users.sourceforge.net
Sun Jan 30 21:39:03 CET 2011
Revision: 55666
http://scummvm.svn.sourceforge.net/scummvm/?rev=55666&view=rev
Author: thebluegr
Date: 2011-01-30 20:39:02 +0000 (Sun, 30 Jan 2011)
Log Message:
-----------
SWORD25: Some optimizations to the Theora decoder
- Optimized and cleaned up translateYUVtoRGBA()
- Disabled a lot of seeking-related functionality
- Replaced some calloc() calls, used for audio buffer creation with malloc()
Modified Paths:
--------------
scummvm/trunk/engines/sword25/fmv/theora_decoder.cpp
scummvm/trunk/engines/sword25/fmv/theora_decoder.h
Modified: scummvm/trunk/engines/sword25/fmv/theora_decoder.cpp
===================================================================
--- scummvm/trunk/engines/sword25/fmv/theora_decoder.cpp 2011-01-30 20:37:59 UTC (rev 55665)
+++ scummvm/trunk/engines/sword25/fmv/theora_decoder.cpp 2011-01-30 20:39:02 UTC (rev 55666)
@@ -24,7 +24,8 @@
*/
/*
- * Source is based on the player example from libvorbis package
+ * Source is based on the player example from libvorbis package,
+ * available at: http://svn.xiph.org/trunk/theora/examples/player_example.c
*
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS
@@ -69,7 +70,7 @@
ogg_sync_init(&_oggSync);
_curFrame = 0;
- _audiobuf = (ogg_int16_t *)calloc(AUDIOFD_FRAGSIZE, sizeof(ogg_int16_t));
+ _audiobuf = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t));
reset();
}
@@ -333,8 +334,6 @@
const Graphics::Surface *TheoraDecoder::decodeNextFrame() {
int i, j;
-// _stateFlag = false; // playback has not begun
-
// we want a video and audio frame ready to go at all times. If
// we have to buffer incoming, buffer the compressed data (ie, let
// ogg do the buffering)
@@ -358,10 +357,12 @@
if (_audiobufFill == AUDIOFD_FRAGSIZE)
_audiobufReady = true;
+#if ENABLE_THEORA_SEEKING
if (_vorbisDSP.granulepos >= 0)
_audiobufGranulePos = _vorbisDSP.granulepos - ret + i;
else
_audiobufGranulePos += i;
+#endif
} else {
// no pending audio; is there a pending packet to decode?
@@ -382,6 +383,8 @@
th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &_ppLevel, sizeof(_ppLevel));
_ppInc = 0;
}
+
+#if ENABLE_THEORA_SEEKING
// HACK: This should be set after a seek or a gap, but we might not have
// a granulepos for the first packet (we only have them for the last
// packet on a page), so we just set it as often as we get it.
@@ -391,10 +394,13 @@
if (_oggPacket.granulepos >= 0) {
th_decode_ctl(_theoraDecode, TH_DECCTL_SET_GRANPOS, &_oggPacket.granulepos, sizeof(_oggPacket.granulepos));
}
+
if (th_decode_packetin(_theoraDecode, &_oggPacket, &_videobufGranulePos) == 0) {
_videobufTime = th_granule_time(_theoraDecode, _videobufGranulePos);
+#else
+ if (th_decode_packetin(_theoraDecode, &_oggPacket, NULL) == 0) {
+#endif
_curFrame++;
-
_videobufReady = true;
}
} else
@@ -419,7 +425,7 @@
// The audio mixer is now responsible for the old audio buffer.
// We need to create a new one.
- _audiobuf = (ogg_int16_t *)calloc(AUDIOFD_FRAGSIZE, sizeof(ogg_int16_t));
+ _audiobuf = (ogg_int16_t *)malloc(AUDIOFD_FRAGSIZE * sizeof(ogg_int16_t));
_audiobufFill = 0;
_audiobufReady = false;
}
@@ -431,7 +437,7 @@
th_decode_ycbcr_out(_theoraDecode, yuv);
// Convert YUV data to RGB data
- translateYUVtoRGBA(yuv, _theoraInfo, (byte *)_surface->getBasePtr(0, 0), _surface->pitch * _surface->h);
+ translateYUVtoRGBA(yuv, (byte *)_surface->getBasePtr(0, 0));
_videobufReady = false;
}
@@ -456,12 +462,15 @@
_fileStream->seek(0);
_videobufReady = false;
+
+#if ENABLE_THEORA_SEEKING
_videobufGranulePos = -1;
+ _audiobufGranulePos = 0;
_videobufTime = 0;
+#endif
_audiobufFill = 0;
_audiobufReady = false;
- _audiobufGranulePos = 0;
_curFrame = 0;
@@ -486,57 +495,67 @@
return Audio::makeQueuingAudioStream(_vorbisInfo.rate, _vorbisInfo.channels);
}
- void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, const th_info &theoraInfo, byte *pixelData, int pixelsSize) {
+static void convertYUVtoBGRA(int y, int u, int v, byte *dst) {
+ byte r, g, b;
+ Graphics::YUV2RGB(y, u, v, r, g, b);
+ *(dst + 0) = b;
+ *(dst + 1) = g;
+ *(dst + 2) = r;
+ *(dst + 3) = 0xFF;
+}
+enum TheoraYUVBuffers {
+ kBufferY = 0,
+ kBufferU = 1,
+ kBufferV = 2
+};
+
+void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, byte *pixelData) {
// Width and height of all buffers have to be divisible by 2.
- assert((YUVBuffer[0].width & 1) == 0);
- assert((YUVBuffer[0].height & 1) == 0);
- assert((YUVBuffer[1].width & 1) == 0);
- assert((YUVBuffer[2].width & 1) == 0);
+ assert((YUVBuffer[kBufferY].width & 1) == 0);
+ assert((YUVBuffer[kBufferY].height & 1) == 0);
+ assert((YUVBuffer[kBufferU].width & 1) == 0);
+ assert((YUVBuffer[kBufferV].width & 1) == 0);
// UV images have to have a quarter of the Y image resolution
- assert(YUVBuffer[1].width == YUVBuffer[0].width >> 1);
- assert(YUVBuffer[2].width == YUVBuffer[0].width >> 1);
- assert(YUVBuffer[1].height == YUVBuffer[0].height >> 1);
- assert(YUVBuffer[2].height == YUVBuffer[0].height >> 1);
+ assert(YUVBuffer[kBufferU].width == YUVBuffer[kBufferY].width >> 1);
+ assert(YUVBuffer[kBufferV].width == YUVBuffer[kBufferY].width >> 1);
+ assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1);
+ assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1);
- const byte *ySrc0 = YUVBuffer[0].data;
- const byte *ySrc1 = YUVBuffer[0].data + YUVBuffer[0].stride;
- const byte *uSrc = YUVBuffer[1].data;
- const byte *vSrc = YUVBuffer[2].data;
- byte *dst0 = &pixelData[0];
- byte *dst1 = &pixelData[0] + (YUVBuffer[0].width << 2);
+ const byte *ySrc = YUVBuffer[kBufferY].data;
+ const byte *uSrc = YUVBuffer[kBufferU].data;
+ const byte *vSrc = YUVBuffer[kBufferV].data;
+ byte *dst = pixelData;
+ int u = 0, v = 0;
- for (int h = 0; h < YUVBuffer[0].height / 2; ++h) {
- for (int w = 0; w < YUVBuffer[0].width / 2; ++w) {
- byte r, g, b;
- int u = *uSrc++;
- int v = *vSrc++;
- int y;
+ const int blockSize = YUVBuffer[kBufferY].width << 2;
+ const int halfHeight = YUVBuffer[kBufferY].height >> 1;
+ const int halfWidth = YUVBuffer[kBufferY].width >> 1;
+ const int yStep = (YUVBuffer[kBufferY].stride << 1) - YUVBuffer[kBufferY].width;
+ // The UV step is usually 0, since in most cases stride == width.
+ // The asserts at the top ensure that the U and V steps are equal
+ // (and they must always be equal)
+ const int uvStep = YUVBuffer[kBufferU].stride - YUVBuffer[kBufferU].width;
+ const int stride = YUVBuffer[kBufferY].stride;
- for (int i = 0; i < 2; i++) {
- y = *ySrc0++;
- Graphics::YUV2RGB(y, u, v, r, g, b);
- *dst0++ = b;
- *dst0++ = g;
- *dst0++ = r;
- *dst0++ = 255;
+ for (int h = 0; h < halfHeight; ++h) {
+ for (int w = 0; w < halfWidth; ++w) {
+ u = *uSrc++;
+ v = *vSrc++;
- y = *ySrc1++;
- Graphics::YUV2RGB(y, u, v, r, g, b);
- *dst1++ = b;
- *dst1++ = g;
- *dst1++ = r;
- *dst1++ = 255;
+ for (int i = 0; i <= 1; i++) {
+ convertYUVtoBGRA(*ySrc, u, v, dst);
+ convertYUVtoBGRA(*(ySrc + stride), u, v, dst + blockSize);
+ ySrc++;
+ dst += 4; // BGRA
}
}
- dst0 += YUVBuffer[0].width << 2;
- dst1 += YUVBuffer[0].width << 2;
- ySrc0 += (YUVBuffer[0].stride << 1) - YUVBuffer[0].width;
- ySrc1 += (YUVBuffer[0].stride << 1) - YUVBuffer[0].width;
- uSrc += YUVBuffer[1].stride - YUVBuffer[1].width;
- vSrc += YUVBuffer[2].stride - YUVBuffer[2].width;
+ dst += blockSize;
+ ySrc += yStep;
+ uSrc += uvStep;
+ vSrc += uvStep;
}
}
Modified: scummvm/trunk/engines/sword25/fmv/theora_decoder.h
===================================================================
--- scummvm/trunk/engines/sword25/fmv/theora_decoder.h 2011-01-30 20:37:59 UTC (rev 55665)
+++ scummvm/trunk/engines/sword25/fmv/theora_decoder.h 2011-01-30 20:39:02 UTC (rev 55666)
@@ -41,6 +41,8 @@
class SeekableReadStream;
}
+//#define ENABLE_THEORA_SEEKING // enables the extra calculations used for video seeking
+
namespace Sword25 {
/**
@@ -105,7 +107,7 @@
void queuePage(ogg_page *page);
int bufferData();
Audio::QueuingAudioStream *createAudioStream();
- void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, const th_info &theoraInfo, byte *pixelData, int pixelsSize);
+ void translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer, byte *pixelData);
private:
Common::SeekableReadStream *_fileStream;
@@ -142,14 +144,17 @@
// single frame video buffering
bool _videobufReady;
- ogg_int64_t _videobufGranulePos;
- double _videobufTime;
// single audio fragment audio buffering
int _audiobufFill;
bool _audiobufReady;
ogg_int16_t *_audiobuf;
+
+#if ENABLE_THEORA_SEEKING
+ double _videobufTime;
+ ogg_int64_t _videobufGranulePos;
ogg_int64_t _audiobufGranulePos; // time position of last sample
+#endif
};
} // End of namespace Sword25
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list