Committing the rest of the VideoDecoder Rewrite from patch #2963496.

svn-id: r49079
This commit is contained in:
Matthew Hoops 2010-05-18 14:17:24 +00:00
parent f3892a506b
commit 11cbdd0318
41 changed files with 1107 additions and 1214 deletions

View file

@ -23,7 +23,6 @@
*
*/
#include "common/archive.h"
#include "common/endian.h"
#include "common/file.h"
#include "common/stream.h"
@ -49,6 +48,7 @@ AviDecoder::AviDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) :
_audStream = NULL;
_fileStream = NULL;
_audHandle = new Audio::SoundHandle();
_dirtyPalette = false;
memset(_palette, 0, sizeof(_palette));
memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT));
memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER));
@ -58,7 +58,7 @@ AviDecoder::AviDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) :
}
AviDecoder::~AviDecoder() {
closeFile();
close();
delete _audHandle;
}
@ -190,7 +190,7 @@ void AviDecoder::handleStreamHeader() {
/*_palette[i * 4 + 3] = */_fileStream->readByte();
}
setPalette(_palette);
_dirtyPalette = true;
}
} else if (sHeader.streamType == ID_AUDS) {
_audsHeader = sHeader;
@ -204,24 +204,16 @@ void AviDecoder::handleStreamHeader() {
}
}
bool AviDecoder::loadFile(const char *fileName) {
closeFile();
_fileStream = SearchMan.createReadStreamForMember(fileName);
if (!_fileStream)
return false;
bool AviDecoder::load(Common::SeekableReadStream &stream) {
close();
_fileStream = &stream;
_decodedHeader = false;
// Seek to the first frame
_videoInfo.currentFrame = -1;
// Read chunks until we have decoded the header
while (!_decodedHeader)
runHandle(_fileStream->readUint32BE());
_videoFrameBuffer = new byte[_header.width * _header.height];
memset(_videoFrameBuffer, 0, _header.width * _header.height);
uint32 nextTag = _fileStream->readUint32BE();
// Throw out any JUNK section
@ -247,34 +239,24 @@ bool AviDecoder::loadFile(const char *fileName) {
_mixer->playStream(_soundType, _audHandle, _audStream);
debug (0, "Frames = %d, Dimensions = %d x %d", _header.totalFrames, _header.width, _header.height);
debug (0, "Frame Rate = %d", getFrameRate());
debug (0, "Frame Rate = %d", _vidsHeader.rate / _vidsHeader.scale);
if ((_audsHeader.scale != 0) && (_header.flags & AVIF_ISINTERLEAVED))
debug (0, "Sound Rate = %d", AUDIO_RATE);
debug (0, "Video Codec = \'%s\'", tag2str(_vidsHeader.streamHandler));
_videoInfo.firstframeOffset = _fileStream->pos();
_videoInfo.width = _header.width;
_videoInfo.height = _header.height;
_videoInfo.frameCount = _header.totalFrames;
// Our frameDelay is calculated in 1/100 ms, so we convert it here
_videoInfo.frameDelay = _header.microSecondsPerFrame / 10;
if (!_videoCodec)
return false;
return true;
}
void AviDecoder::closeFile() {
void AviDecoder::close() {
if (!_fileStream)
return;
delete _fileStream;
_fileStream = 0;
delete[] _videoFrameBuffer;
_videoFrameBuffer = 0;
// Deinitialize sound
_mixer->stopHandle(*_audHandle);
_audStream = 0;
@ -293,14 +275,26 @@ void AviDecoder::closeFile() {
memset(&_vidsHeader, 0, sizeof(AVIStreamHeader));
memset(&_audsHeader, 0, sizeof(AVIStreamHeader));
memset(&_ixInfo, 0, sizeof(AVIOLDINDEX));
reset();
}
Surface *AviDecoder::getNextFrame() {
uint32 AviDecoder::getElapsedTime() const {
if (_audStream)
return _mixer->getSoundElapsedTime(*_audHandle);
return VideoDecoder::getElapsedTime();
}
Surface *AviDecoder::decodeNextFrame() {
uint32 nextTag = _fileStream->readUint32BE();
if (_fileStream->eos())
return NULL;
if (_curFrame == -1)
_startTime = g_system->getMillis();
if (nextTag == ID_LIST) {
// A list of audio/video chunks
uint32 listSize = _fileStream->readUint32LE() - 4;
@ -312,7 +306,7 @@ Surface *AviDecoder::getNextFrame() {
// Decode chunks in the list and see if we get a frame
Surface *frame = NULL;
while (_fileStream->pos() < startPos + (int32)listSize) {
Surface *temp = getNextFrame();
Surface *temp = decodeNextFrame();
if (temp)
frame = temp;
}
@ -335,7 +329,7 @@ Surface *AviDecoder::getNextFrame() {
} else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' ||
getStreamType(nextTag) == 'AM' || getStreamType(nextTag) == '32') {
// Compressed Frame
_videoInfo.currentFrame++;
_curFrame++;
uint32 chunkSize = _fileStream->readUint32LE();
if (chunkSize == 0) // Keep last frame on screen
@ -364,7 +358,7 @@ Surface *AviDecoder::getNextFrame() {
_fileStream->readByte(); // Flags that don't serve us any purpose
}
setPalette(_palette);
_dirtyPalette = true;
// No alignment necessary. It's always even.
} else if (nextTag == ID_JUNK) {
@ -372,56 +366,11 @@ Surface *AviDecoder::getNextFrame() {
} else if (nextTag == ID_IDX1) {
runHandle(ID_IDX1);
} else
error ("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());
error("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());
return NULL;
}
bool AviDecoder::decodeNextFrame() {
Surface *surface = NULL;
int32 curFrame = _videoInfo.currentFrame;
while (!surface && !endOfVideo() && !_fileStream->eos())
surface = getNextFrame();
if (curFrame == _videoInfo.currentFrame) {
warning("No video frame found");
_videoInfo.currentFrame++;
}
if (surface)
memcpy(_videoFrameBuffer, surface->pixels, _header.width * _header.height);
if (_videoInfo.currentFrame == 0)
_videoInfo.startTime = g_system->getMillis();
return !endOfVideo();
}
int32 AviDecoder::getAudioLag() {
if (!_fileStream)
return 0;
int32 frameDelay = getFrameDelay();
int32 videoTime = (_videoInfo.currentFrame + 1) * frameDelay;
int32 audioTime;
if (!_audStream) {
/* No audio.
Calculate the lag by how much time has gone by since the first frame
and how much time *should* have passed.
*/
audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
} else {
const Audio::Timestamp ts = _mixer->getElapsedTime(*_audHandle);
audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();
}
return videoTime - audioTime;
}
Codec *AviDecoder::createCodec() {
switch (_vidsHeader.streamHandler) {
case ID_CRAM:
@ -437,11 +386,14 @@ Codec *AviDecoder::createCodec() {
return NULL;
}
Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
PixelFormat AviDecoder::getPixelFormat() const {
assert(_videoCodec);
return _videoCodec->getPixelFormat();
}
if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) {
Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM)
return Audio::makeQueuingAudioStream(AUDIO_RATE, false);
}
if (_wvInfo.tag != 0) // No sound
warning ("Unsupported AVI audio format %d", _wvInfo.tag);