[Scummvm-cvs-logs] SF.net SVN: scummvm:[53894] scummvm/branches/branch-1-2-0/graphics/video/ smk_decoder.cpp

athrxx at users.sourceforge.net athrxx at users.sourceforge.net
Thu Oct 28 00:50:13 CEST 2010


Revision: 53894
          http://scummvm.svn.sourceforge.net/scummvm/?rev=53894&view=rev
Author:   athrxx
Date:     2010-10-27 22:50:13 +0000 (Wed, 27 Oct 2010)

Log Message:
-----------
VIDEO: (backport) fix some evaluation order bugs in smacker decoder

These bugs would cause crashs in MSVC 2008/2010 release builds.

Modified Paths:
--------------
    scummvm/branches/branch-1-2-0/graphics/video/smk_decoder.cpp

Modified: scummvm/branches/branch-1-2-0/graphics/video/smk_decoder.cpp
===================================================================
--- scummvm/branches/branch-1-2-0/graphics/video/smk_decoder.cpp	2010-10-27 22:41:08 UTC (rev 53893)
+++ scummvm/branches/branch-1-2-0/graphics/video/smk_decoder.cpp	2010-10-27 22:50:13 UTC (rev 53894)
@@ -252,9 +252,12 @@
 	_loBytes = new SmallHuffmanTree(_bs);
 	_hiBytes = new SmallHuffmanTree(_bs);
 
-	_markers[0] = _bs.getBits8() | (_bs.getBits8() << 8);
-	_markers[1] = _bs.getBits8() | (_bs.getBits8() << 8);
-	_markers[2] = _bs.getBits8() | (_bs.getBits8() << 8);
+	_markers[0] = _bs.getBits8();
+	_markers[0] |= (_bs.getBits8() << 8);
+	_markers[1] = _bs.getBits8();
+	_markers[1] |= (_bs.getBits8() << 8);
+	_markers[2] = _bs.getBits8();
+	_markers[2] |= (_bs.getBits8() << 8);
 
 	_last[0] = _last[1] = _last[2] = 0xffffffff;
 
@@ -389,12 +392,13 @@
 	_frameCount = _fileStream->readUint32LE();
 	int32 frameRate = _fileStream->readSint32LE();
 
+	// framerate contains 2 digits after the comma, so 1497 is actually 14.97 fps
 	if (frameRate > 0)
 		_frameRate = Common::Rational(1000, frameRate);
 	else if (frameRate < 0)
 		_frameRate = Common::Rational(100000, -frameRate);
 	else
-		_frameRate = 10;
+		_frameRate = 1000;
 
 	// Flags are determined by which bit is set, which can be one of the following:
 	// 0 - set to 1 if file contains a ring frame.
@@ -540,53 +544,18 @@
 		chunkSize = _fileStream->readUint32LE();
 		chunkSize -= 4;    // subtract the first 4 bytes (chunk size)
 
-		if (_header.audioInfo[i].compression != kCompressionNone) {
+		if (_header.audioInfo[i].compression == kCompressionNone) {
+			dataSizeUnpacked = chunkSize;
+		} else {
 			dataSizeUnpacked = _fileStream->readUint32LE();
 			chunkSize -= 4;    // subtract the next 4 bytes (unpacked data size)
-		} else {
-			dataSizeUnpacked = 0;
 		}
 
-		if (_header.audioInfo[i].hasAudio && chunkSize > 0 && i == 0) {
-			// If it's track 0, play the audio data
-			byte *soundBuffer = (byte *)malloc(chunkSize);
-
-			_fileStream->read(soundBuffer, chunkSize);
-
-			if (_header.audioInfo[i].compression == kCompressionRDFT || _header.audioInfo[i].compression == kCompressionDCT) {
-				// TODO: Compressed audio (Bink RDFT/DCT encoded)
-				free(soundBuffer);
-				continue;
-			} else if (_header.audioInfo[i].compression == kCompressionDPCM) {
-				// Compressed audio (Huffman DPCM encoded)
-				queueCompressedBuffer(soundBuffer, chunkSize, dataSizeUnpacked, i);
-				free(soundBuffer);
-			} else {
-				// Uncompressed audio (PCM)
-				byte flags = 0;
-				if (_header.audioInfo[0].is16Bits)
-					flags = flags | Audio::FLAG_16BITS;
-				if (_header.audioInfo[0].isStereo)
-					flags = flags | Audio::FLAG_STEREO;
-
-				_audioStream->queueBuffer(soundBuffer, chunkSize, DisposeAfterUse::YES, flags);
-				// The sound buffer will be deleted by QueuingAudioStream
-			}
-
-			if (!_audioStarted) {
-				_mixer->playStream(_soundType, &_audioHandle, _audioStream, -1, 255);
-				_audioStarted = true;
-			}
-		} else {
-			// Ignore the rest of the audio tracks, if they exist
-			// TODO: Are there any Smacker videos with more than one audio stream?
-			// If yes, we should play the rest of the audio streams as well
-			if (chunkSize > 0)
-				_fileStream->skip(chunkSize);
-		}
+		handleAudioTrack(i, chunkSize, dataSizeUnpacked);
 	}
 
 	uint32 frameSize = _frameSizes[_curFrame] & ~3;
+//	uint32 remainder =  _frameSizes[_curFrame] & 3;
 
 	if (_fileStream->pos() - startPos > frameSize)
 		error("Smacker actual frame size exceeds recorded frame size");
@@ -746,6 +715,46 @@
 	return _surface;
 }
 
+void SmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize) {
+	if (_header.audioInfo[track].hasAudio && chunkSize > 0 && track == 0) {
+		// If it's track 0, play the audio data
+		byte *soundBuffer = (byte *)malloc(chunkSize);
+
+		_fileStream->read(soundBuffer, chunkSize);
+
+		if (_header.audioInfo[track].compression == kCompressionRDFT || _header.audioInfo[track].compression == kCompressionDCT) {
+			// TODO: Compressed audio (Bink RDFT/DCT encoded)
+			free(soundBuffer);
+			return;
+		} else if (_header.audioInfo[track].compression == kCompressionDPCM) {
+			// Compressed audio (Huffman DPCM encoded)
+			queueCompressedBuffer(soundBuffer, chunkSize, unpackedSize, track);
+			free(soundBuffer);
+		} else {
+			// Uncompressed audio (PCM)
+			byte flags = 0;
+			if (_header.audioInfo[track].is16Bits)
+				flags = flags | Audio::FLAG_16BITS;
+			if (_header.audioInfo[track].isStereo)
+				flags = flags | Audio::FLAG_STEREO;
+
+			_audioStream->queueBuffer(soundBuffer, chunkSize, DisposeAfterUse::YES, flags);
+			// The sound buffer will be deleted by QueuingAudioStream
+		}
+
+		if (!_audioStarted) {
+			_mixer->playStream(_soundType, &_audioHandle, _audioStream, -1, 255);
+			_audioStarted = true;
+		}
+	} else {
+		// Ignore the rest of the audio tracks, if they exist
+		// TODO: Are there any Smacker videos with more than one audio stream?
+		// If yes, we should play the rest of the audio streams as well
+		if (chunkSize > 0)
+			_fileStream->skip(chunkSize);
+	}
+}
+
 void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize,
 		uint32 unpackedSize, int streamNum) {
 
@@ -774,14 +783,24 @@
 
 	int32 bases[2];
 
-	if (isStereo)
-		bases[1] = (!is16Bits) ?   audioBS.getBits8() :
-		               ((int16) (((audioBS.getBits8() << 8) | audioBS.getBits8())));
+	if (isStereo) {
+		if (is16Bits) {
+			byte hi = audioBS.getBits8();
+			byte lo = audioBS.getBits8();
+			bases[1] = (int16) ((hi << 8) | lo);
+		} else {
+			bases[1] = audioBS.getBits8();
+		}
+	}
 
-	bases[0] = (!is16Bits) ?   audioBS.getBits8() :
-	               ((int16) (((audioBS.getBits8() << 8) | audioBS.getBits8())));
+	if (is16Bits) {
+		byte hi = audioBS.getBits8();
+		byte lo = audioBS.getBits8();
+		bases[0] = (int16) ((hi << 8) | lo);
+	} else {
+		bases[0] = audioBS.getBits8();
+	}
 
-
 	// The bases are the first samples, too
 	for (int i = 0; i < (isStereo ? 2 : 1); i++, curPointer += (is16Bits ? 2 : 1), curPos += (is16Bits ? 2 : 1)) {
 		if (is16Bits)
@@ -805,10 +824,11 @@
 			}
 		} else {
 			for (int k = 0; k < (isStereo ? 2 : 1); k++) {
-				bases[k] += (int16) (audioTrees[k * 2]->getCode(audioBS) |
-				                    (audioTrees[k * 2 + 1]->getCode(audioBS) << 8));
+				byte lo = audioTrees[k * 2]->getCode(audioBS);
+				byte hi = audioTrees[k * 2 + 1]->getCode(audioBS);
+				bases[k] += (int16) (lo | (hi << 8));
 
-				WRITE_BE_UINT16(curPointer, CLIP<int32>(bases[k], -32768, 32767));
+				WRITE_BE_UINT16(curPointer, bases[k]);
 				curPointer += 2;
 				curPos += 2;
 			}


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