From bb2d290dcaae8d29f56066ac92330c59862012a7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 11 Jul 2016 21:49:11 -0400 Subject: VIDEO: Handle STRN chunks in AVI file streams to set stream name --- video/avi_decoder.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++--------- video/avi_decoder.h | 15 +++++++++++++++ 2 files changed, 57 insertions(+), 9 deletions(-) (limited to 'video') diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp index cb087c72fc..44f8ade933 100644 --- a/video/avi_decoder.cpp +++ b/video/avi_decoder.cpp @@ -101,6 +101,7 @@ void AVIDecoder::initCommon() { _movieListEnd = 0; _fileStream = 0; _videoTrackCounter = _audioTrackCounter = 0; + _lastAddedTrack = nullptr; memset(&_header, 0, sizeof(_header)); } @@ -147,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; @@ -265,8 +268,7 @@ void AVIDecoder::handleStreamHeader(uint32 size) { } } - if (!_selectTrackFn || _selectTrackFn(true, _videoTrackCounter++)) - addTrack(new AVIVideoTrack(_header.totalFrames, sHeader, bmInfo, initialPalette)); + addTrack(new AVIVideoTrack(_header.totalFrames, sHeader, bmInfo, initialPalette)); } else if (sHeader.streamType == ID_AUDS) { PCMWaveFormat wvInfo; wvInfo.tag = _fileStream->readUint16LE(); @@ -281,17 +283,48 @@ void AVIDecoder::handleStreamHeader(uint32 size) { if (wvInfo.channels == 2) sHeader.sampleSize /= 2; - if (!_selectTrackFn || _selectTrackFn(false, _audioTrackCounter++)) { - AVIAudioTrack *track = createAudioTrack(sHeader, wvInfo); - track->createAudioStream(); - addTrack(track); - } + AVIAudioTrack *track = createAudioTrack(sHeader, wvInfo); + track->createAudioStream(); + addTrack(track); } // Ensure that we're at the end of the chunk _fileStream->seek(startPos + strfSize); } +void AVIDecoder::addTrack(Track *track, bool isExternal) { + if (!_selectTrackFn || + (dynamic_cast(track) && _selectTrackFn(true, _videoTrackCounter++)) || + (dynamic_cast(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(_lastAddedTrack); + AVIAudioTrack *audTrack = dynamic_cast(_lastAddedTrack); + if (vidTrack) + vidTrack->getName() = Common::String(buffer); + else if (audTrack) + audTrack->getName() = Common::String(buffer); + } +} + bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) { close(); @@ -301,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) { diff --git a/video/avi_decoder.h b/video/avi_decoder.h index 04e6a1847e..8b9fcbd9a3 100644 --- a/video/avi_decoder.h +++ b/video/avi_decoder.h @@ -83,6 +83,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; @@ -166,6 +176,7 @@ protected: uint32 quality; uint32 sampleSize; Common::Rect frame; + Common::String name; }; class AVIVideoTrack : public FixedRateVideoTrack { @@ -181,6 +192,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; @@ -224,6 +236,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; } @@ -272,6 +285,7 @@ protected: Common::Rational _frameRateOverride; int _videoTrackCounter, _audioTrackCounter; + Track *_lastAddedTrack; SelectTrackFn _selectTrackFn; void initCommon(); @@ -280,6 +294,7 @@ protected: 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(); -- cgit v1.2.3