[Scummvm-cvs-logs] scummvm master -> 043bd1b9f91719e2d80f17cbecb9b2e11ce49ba4

clone2727 clone2727 at gmail.com
Tue Aug 6 05:30:41 CEST 2013


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:
043bd1b9f9 VIDEO: Clean up the AVI decoder


Commit: 043bd1b9f91719e2d80f17cbecb9b2e11ce49ba4
    https://github.com/scummvm/scummvm/commit/043bd1b9f91719e2d80f17cbecb9b2e11ce49ba4
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2013-08-05T20:29:22-07:00

Commit Message:
VIDEO: Clean up the AVI decoder

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



diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index ff728a8..92a60fc 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -67,6 +67,7 @@ namespace Video {
 #define ID_STRD MKTAG('s','t','r','d')
 //#define ID_INFO MKTAG('I','N','F','O')
 #define ID_ISFT MKTAG('I','S','F','T')
+#define ID_DISP MKTAG('D','I','S','P')
 
 // Codec tags
 #define ID_RLE  MKTAG('R','L','E',' ')
@@ -78,18 +79,6 @@ namespace Video {
 #define ID_DUCK MKTAG('D','U','C','K')
 #define ID_MPG2 MKTAG('m','p','g','2')
 
-static byte char2num(char c) {
-	c = tolower((byte)c);
-	return (c >= 'a' && c <= 'f') ? c - 'a' + 10 : c - '0';
-}
-
-static byte getStreamIndex(uint32 tag) {
-	return char2num((tag >> 24) & 0xFF) << 4 | char2num((tag >> 16) & 0xFF);
-}
-
-static uint16 getStreamType(uint32 tag) {
-	return tag & 0xffff;
-}
 
 AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _frameRateOverride(0), _soundType(soundType) {
 	initCommon();
@@ -107,29 +96,26 @@ AVIDecoder::~AVIDecoder() {
 void AVIDecoder::initCommon() {
 	_decodedHeader = false;
 	_foundMovieList = false;
+	_movieListStart = 0;
 	_fileStream = 0;
-	memset(&_ixInfo, 0, sizeof(_ixInfo));
 	memset(&_header, 0, sizeof(_header));
 }
 
-void AVIDecoder::runHandle(uint32 tag) {
-	assert(_fileStream);
+bool AVIDecoder::parseNextChunk() {
+	uint32 tag = _fileStream->readUint32BE();
+	uint32 size = _fileStream->readUint32LE();
+
 	if (_fileStream->eos())
-		return;
+		return false;
 
 	debug(3, "Decoding tag %s", tag2str(tag));
 
 	switch (tag) {
-	case ID_RIFF:
-		/*_filesize = */_fileStream->readUint32LE();
-		if (_fileStream->readUint32BE() != ID_AVI)
-			error("RIFF file is not an AVI video");
-		break;
 	case ID_LIST:
-		handleList();
+		handleList(size);
 		break;
 	case ID_AVIH:
-		_header.size = _fileStream->readUint32LE();
+		_header.size = size;
 		_header.microSecondsPerFrame = _fileStream->readUint32LE();
 		_header.maxBytesPerSecond = _fileStream->readUint32LE();
 		_header.padding = _fileStream->readUint32LE();
@@ -144,58 +130,64 @@ void AVIDecoder::runHandle(uint32 tag) {
 		_fileStream->skip(16);
 		break;
 	case ID_STRH:
-		handleStreamHeader();
+		handleStreamHeader(size);
 		break;
 	case ID_STRD: // Extra stream info, safe to ignore
 	case ID_VEDT: // Unknown, safe to ignore
 	case ID_JUNK: // Alignment bytes, should be ignored
 	case ID_ISFT: // Metadata, safe to ignore
-		{
-		uint32 junkSize = _fileStream->readUint32LE();
-		_fileStream->skip(junkSize + (junkSize & 1)); // Alignment
-		} break;
+	case ID_DISP: // Metadata, should be safe to ignore
+		skipChunk(size);
+		break;
 	case ID_IDX1:
-		_ixInfo.size = _fileStream->readUint32LE();
-		_ixInfo.indices = new OldIndex::Index[_ixInfo.size / 16];
-		debug(0, "%d Indices", (_ixInfo.size / 16));
-		for (uint32 i = 0; i < (_ixInfo.size / 16); i++) {
-			_ixInfo.indices[i].id = _fileStream->readUint32BE();
-			_ixInfo.indices[i].flags = _fileStream->readUint32LE();
-			_ixInfo.indices[i].offset = _fileStream->readUint32LE();
-			_ixInfo.indices[i].size = _fileStream->readUint32LE();
-			debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size);
+		debug(0, "%d Indices", size / 16);
+		for (uint32 i = 0; i < size / 16; i++) {
+			OldIndex indexEntry;
+			indexEntry.id = _fileStream->readUint32BE();
+			indexEntry.flags = _fileStream->readUint32LE();
+			indexEntry.offset = _fileStream->readUint32LE();
+			indexEntry.size = _fileStream->readUint32LE();
+			_indexEntries.push_back(indexEntry);
+			debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size);
 		}
 		break;
 	default:
 		error("Unknown tag \'%s\' found", tag2str(tag));
 	}
+
+	return true;
 }
 
-void AVIDecoder::handleList() {
-	uint32 listSize = _fileStream->readUint32LE() - 4; // Subtract away listType's 4 bytes
+void AVIDecoder::skipChunk(uint32 size) {
+	// Make sure we're aligned on a word boundary
+	_fileStream->skip(size + (size & 1));
+}
+
+void AVIDecoder::handleList(uint32 listSize) {
 	uint32 listType = _fileStream->readUint32BE();
+	listSize -= 4; // Subtract away listType's 4 bytes
 	uint32 curPos = _fileStream->pos();
 
 	debug(0, "Found LIST of type %s", tag2str(listType));
 
 	if (listType == ID_MOVI) {
-		// Found the 'movi' list
-		// We're done parsing everything
+		// If we found the movie block
 		_foundMovieList = true;
+		_movieListStart = curPos;
+		_fileStream->skip(listSize);
 		return;
+	} else if (listType == ID_HDRL) {
+		// Mark the header as decoded
+		_decodedHeader = true;
 	}
 
 	while ((_fileStream->pos() - curPos) < listSize)
-		runHandle(_fileStream->readUint32BE());
-
-	// We now have all the header data
-	if (listType == ID_HDRL)
-		_decodedHeader = true;
+		parseNextChunk();
 }
 
-void AVIDecoder::handleStreamHeader() {
+void AVIDecoder::handleStreamHeader(uint32 size) {
 	AVIStreamHeader sHeader;
-	sHeader.size = _fileStream->readUint32LE();
+	sHeader.size = size;
 	sHeader.streamType = _fileStream->readUint32BE();
 
 	if (sHeader.streamType == ID_MIDS || sHeader.streamType == ID_TXTS)
@@ -286,28 +278,41 @@ void AVIDecoder::handleStreamHeader() {
 bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
 	close();
 
-	_fileStream = stream;
-	_decodedHeader = false;
-	_foundMovieList = false;
+	uint32 riffTag = stream->readUint32BE();
+	if (riffTag != ID_RIFF) {
+		warning("Failed to find RIFF header");
+		return false;
+	}
 
-	// Read chunks until we have decoded the header
-	while (!_decodedHeader && _fileStream->pos() < _fileStream->size())
-		runHandle(_fileStream->readUint32BE());
+	/* uint32 fileSize = */ stream->readUint32LE();
+	uint32 riffType = stream->readUint32BE();
 
-	if (_fileStream->pos() >= _fileStream->size()) {
-		warning("Failed to find AVI header");
+	if (riffType != ID_AVI) {
+		warning("RIFF not an AVI file");
 		return false;
 	}
 
-	// Then read until we find the movie list
-	while (!_foundMovieList && _fileStream->pos() < _fileStream->size())
-		runHandle(_fileStream->readUint32BE());
+	_fileStream = stream;
+
+	// Go through all chunks in the file
+	while (parseNextChunk())
+		;
 
-	if (_fileStream->pos() >= _fileStream->size()) {
-		warning("Failed to find AVI 'movi' LIST");
+	if (!_decodedHeader) {
+		warning("Failed to parse AVI header");
+		close();
 		return false;
 	}
 
+	if (!_foundMovieList) {
+		warning("Failed to find 'MOVI' list");
+		close();
+		return false;
+	}
+
+	// Seek back to the start of the MOVI list
+	_fileStream->seek(_movieListStart);
+
 	return true;
 }
 
@@ -318,33 +323,35 @@ void AVIDecoder::close() {
 	_fileStream = 0;
 	_decodedHeader = false;
 	_foundMovieList = false;
+	_movieListStart = 0;
 
-	delete[] _ixInfo.indices;
-	memset(&_ixInfo, 0, sizeof(_ixInfo));
+	_indexEntries.clear();
 	memset(&_header, 0, sizeof(_header));
 }
 
 void AVIDecoder::readNextPacket() {
 	uint32 nextTag = _fileStream->readUint32BE();
+	uint32 size = _fileStream->readUint32LE();
 
 	if (_fileStream->eos())
 		return;
 
 	if (nextTag == ID_LIST) {
 		// A list of audio/video chunks
-		uint32 listSize = _fileStream->readUint32LE() - 4;
 		int32 startPos = _fileStream->pos();
 
 		if (_fileStream->readUint32BE() != ID_REC)
 			error("Expected 'rec ' LIST");
 
+		size -= 4; // subtract list type
+
 		// Decode chunks in the list
-		while (_fileStream->pos() < startPos + (int32)listSize)
+		while (_fileStream->pos() < startPos + (int32)size)
 			readNextPacket();
 
 		return;
 	} else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
-		runHandle(nextTag);
+		skipChunk(size);
 		return;
 	}
 
@@ -353,12 +360,11 @@ void AVIDecoder::readNextPacket() {
 	if (!track)
 		error("Cannot get track from tag '%s'", tag2str(nextTag));
 
-	uint32 chunkSize = _fileStream->readUint32LE();
 	Common::SeekableReadStream *chunk = 0;
 
-	if (chunkSize != 0) {
-		chunk = _fileStream->readStream(chunkSize);
-		_fileStream->skip(chunkSize & 1);
+	if (size != 0) {
+		chunk = _fileStream->readStream(size);
+		_fileStream->skip(size & 1);
 	}
 
 	if (track->getTrackType() == Track::kTrackTypeAudio) {
@@ -403,6 +409,13 @@ void AVIDecoder::readNextPacket() {
 	}
 }
 
+byte AVIDecoder::getStreamIndex(uint32 tag) const {
+	char string[3];
+	WRITE_BE_UINT16(string, tag >> 16);
+	string[2] = 0;
+	return strtol(string, 0, 16);
+}
+
 AVIDecoder::AVIVideoTrack::AVIVideoTrack(int frameCount, const AVIStreamHeader &streamHeader, const BitmapInfoHeader &bitmapInfoHeader)
 		: _frameCount(frameCount), _vidsHeader(streamHeader), _bmInfo(bitmapInfoHeader) {
 	memset(_palette, 0, sizeof(_palette));
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 6082232..5d52c7c 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -20,10 +20,10 @@
  *
  */
 
-#ifndef VIDEO_AVI_PLAYER_H
-#define VIDEO_AVI_PLAYER_H
+#ifndef VIDEO_AVI_DECODER_H
+#define VIDEO_AVI_DECODER_H
 
-#include "common/endian.h"
+#include "common/array.h"
 #include "common/rational.h"
 #include "common/rect.h"
 #include "common/str.h"
@@ -102,13 +102,10 @@ private:
 	};
 
 	struct OldIndex {
+		uint32 id;
+		uint32 flags;
+		uint32 offset;
 		uint32 size;
-		struct Index {
-			uint32 id;
-			uint32 flags;
-			uint32 offset;
-			uint32 size;
-		} *indices;
 	};
 
 	// Index Flags
@@ -218,19 +215,24 @@ private:
 		Audio::QueuingAudioStream *createAudioStream();
 	};
 
-	OldIndex _ixInfo;
+	Common::Array<OldIndex> _indexEntries;
 	AVIHeader _header;
 
 	Common::SeekableReadStream *_fileStream;
-	bool _decodedHeader, _foundMovieList;
+	bool _decodedHeader;
+	bool _foundMovieList;
+	uint32 _movieListStart;
 
 	Audio::Mixer::SoundType _soundType;
 	Common::Rational _frameRateOverride;
 	void initCommon();
 
-	void runHandle(uint32 tag);
-	void handleList();
-	void handleStreamHeader();
+	bool parseNextChunk();
+	void skipChunk(uint32 size);
+	void handleList(uint32 listSize);
+	void handleStreamHeader(uint32 size);
+	uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; }
+	byte getStreamIndex(uint32 tag) const;
 };
 
 } // End of namespace Video






More information about the Scummvm-git-logs mailing list