aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/avi_decoder.cpp51
-rw-r--r--video/avi_decoder.h26
2 files changed, 68 insertions, 9 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index e07805f489..980ce3a3ea 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -76,12 +76,13 @@ enum {
};
-AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _frameRateOverride(0), _soundType(soundType) {
+AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType, SelectTrackFn trackFn) :
+ _frameRateOverride(0), _soundType(soundType), _selectTrackFn(trackFn) {
initCommon();
}
-AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType)
- : _frameRateOverride(frameRateOverride), _soundType(soundType) {
+AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType,
+ SelectTrackFn trackFn) : _frameRateOverride(frameRateOverride), _soundType(soundType), _selectTrackFn(trackFn) {
initCommon();
}
@@ -99,6 +100,8 @@ void AVIDecoder::initCommon() {
_movieListStart = 0;
_movieListEnd = 0;
_fileStream = 0;
+ _videoTrackCounter = _audioTrackCounter = 0;
+ _lastAddedTrack = nullptr;
memset(&_header, 0, sizeof(_header));
}
@@ -145,10 +148,12 @@ bool AVIDecoder::parseNextChunk() {
case ID_JUNQ: // Same as JUNK, safe to ignore
case ID_ISFT: // Metadata, safe to ignore
case ID_DISP: // Metadata, should be safe to ignore
- case ID_STRN: // Metadata, safe to ignore
case ID_DMLH: // OpenDML extension, contains an extra total frames field, safe to ignore
skipChunk(size);
break;
+ case ID_STRN: // Metadata, safe to ignore
+ readStreamName(size);
+ break;
case ID_IDX1:
readOldIndex(size);
break;
@@ -287,6 +292,39 @@ void AVIDecoder::handleStreamHeader(uint32 size) {
_fileStream->seek(startPos + strfSize);
}
+void AVIDecoder::addTrack(Track *track, bool isExternal) {
+ if (!_selectTrackFn ||
+ (dynamic_cast<AVIVideoTrack *>(track) && _selectTrackFn(true, _videoTrackCounter++)) ||
+ (dynamic_cast<AVIAudioTrack *>(track) && _selectTrackFn(false, _audioTrackCounter++))) {
+ VideoDecoder::addTrack(track, isExternal);
+ _lastAddedTrack = track;
+ } else {
+ _lastAddedTrack = nullptr;
+ }
+}
+
+void AVIDecoder::readStreamName(uint32 size) {
+ if (!_lastAddedTrack) {
+ skipChunk(size);
+ } else {
+ // Get in the name
+ assert(size > 0 && size < 64);
+ char buffer[64];
+ _fileStream->read(buffer, size);
+ if (size & 1)
+ _fileStream->skip(1);
+
+ // Apply it to the most recently read stream
+ assert(_lastAddedTrack);
+ AVIVideoTrack *vidTrack = dynamic_cast<AVIVideoTrack *>(_lastAddedTrack);
+ AVIAudioTrack *audTrack = dynamic_cast<AVIAudioTrack *>(_lastAddedTrack);
+ if (vidTrack)
+ vidTrack->getName() = Common::String(buffer);
+ else if (audTrack)
+ audTrack->getName() = Common::String(buffer);
+ }
+}
+
bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
close();
@@ -296,7 +334,7 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
return false;
}
- /* uint32 fileSize = */ stream->readUint32LE();
+ int32 fileSize = stream->readUint32LE();
uint32 riffType = stream->readUint32BE();
if (riffType != ID_AVI) {
@@ -307,7 +345,7 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
_fileStream = stream;
// Go through all chunks in the file
- while (parseNextChunk())
+ while (_fileStream->pos() < fileSize && parseNextChunk())
;
if (!_decodedHeader) {
@@ -337,7 +375,6 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
}
if (_videoTracks.size() != 1) {
- warning("Unhandled AVI video track count: %d", _videoTracks.size());
close();
return false;
}
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 96d9e821ff..a3733b579c 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -57,12 +57,15 @@ namespace Video {
* - sci
* - sword1
* - sword2
+ * - titanic
* - zvision
*/
class AVIDecoder : public VideoDecoder {
public:
- AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
- AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ typedef bool(*SelectTrackFn)(bool isVideo, int trackNumber);
+ AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType, SelectTrackFn trackFn = nullptr);
+ AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType,
+ SelectTrackFn trackFn = nullptr);
virtual ~AVIDecoder();
bool loadStream(Common::SeekableReadStream *stream);
@@ -81,6 +84,16 @@ protected:
bool supportsAudioTrackSwitching() const { return true; }
AudioTrack *getAudioTrack(int index);
+ /**
+ * Define a track to be used by this class.
+ *
+ * The pointer is then owned by this base class.
+ *
+ * @param track The track to add
+ * @param isExternal Is this an external track not found by loadStream()?
+ */
+ void addTrack(Track *track, bool isExternal = false);
+
struct BitmapInfoHeader {
uint32 size;
uint32 width;
@@ -164,6 +177,7 @@ protected:
uint32 quality;
uint32 sampleSize;
Common::Rect frame;
+ Common::String name;
};
class AVIVideoTrack : public FixedRateVideoTrack {
@@ -179,6 +193,7 @@ protected:
Graphics::PixelFormat getPixelFormat() const;
int getCurFrame() const { return _curFrame; }
int getFrameCount() const { return _frameCount; }
+ Common::String &getName() { return _vidsHeader.name; }
const Graphics::Surface *decodeNextFrame() { return _lastFrame; }
const byte *getPalette() const;
@@ -222,6 +237,7 @@ protected:
void skipAudio(const Audio::Timestamp &time, const Audio::Timestamp &frameTime);
virtual void resetStream();
uint32 getCurChunk() const { return _curChunk; }
+ Common::String &getName() { return _audsHeader.name; }
void setCurChunk(uint32 chunk) { _curChunk = chunk; }
bool isRewindable() const { return true; }
@@ -268,12 +284,18 @@ protected:
Audio::Mixer::SoundType _soundType;
Common::Rational _frameRateOverride;
+
+ int _videoTrackCounter, _audioTrackCounter;
+ Track *_lastAddedTrack;
+ SelectTrackFn _selectTrackFn;
+
void initCommon();
bool parseNextChunk();
void skipChunk(uint32 size);
void handleList(uint32 listSize);
void handleStreamHeader(uint32 size);
+ void readStreamName(uint32 size);
uint16 getStreamType(uint32 tag) const { return tag & 0xFFFF; }
byte getStreamIndex(uint32 tag) const;
void checkTruemotion1();