VIDEO: Handle STRN chunks in AVI file streams to set stream name

This commit is contained in:
Paul Gilbert 2016-07-11 21:49:11 -04:00
parent 8a6bba0fec
commit bb2d290dca
2 changed files with 57 additions and 9 deletions

View File

@ -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<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();
@ -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) {

View File

@ -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();