mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-21 03:31:40 +00:00
VIDEO: Fix QuickTime regression with mediaTime and dithering
Fixes an error when playing a QuickTime video that has a mediaTime set on its first edit. This was caused by mediaTime changes in: ef184a6cef98a1756c0669a03fa9b6fa2386b6e7 Those changes buffered frames during initialization so that the keyframe and other frames don't play instead of the intended start frame that mediaTime specifies. My mistake was that decoding isn't allowed during VideoDecoder::loadStream(); VideoDecoder::setDitheringPalette() requires that no frames have been decoded yet, and at least Director and Mohawk call that. Now the initial mediaTime buffering is delayed until the first decode. Fixes bug #13479 where certain Myst videos error. Fixes the opening movie in the Director game Chop Suey.
This commit is contained in:
parent
f1099a5cf2
commit
69662ee9a4
@ -299,7 +299,8 @@ QuickTimeDecoder::VideoTrackHandler::VideoTrackHandler(QuickTimeDecoder *decoder
|
||||
|
||||
_curEdit = 0;
|
||||
_curFrame = -1;
|
||||
enterNewEditListEntry(true); // might set _curFrame
|
||||
_delayedFrameToBufferTo = -1;
|
||||
enterNewEditListEntry(true, true); // might set _curFrame
|
||||
|
||||
_durationOverride = -1;
|
||||
_scaledSurface = 0;
|
||||
@ -369,6 +370,8 @@ bool QuickTimeDecoder::VideoTrackHandler::endOfTrack() const {
|
||||
}
|
||||
|
||||
bool QuickTimeDecoder::VideoTrackHandler::seek(const Audio::Timestamp &requestedTime) {
|
||||
_delayedFrameToBufferTo = -1; // abort any delayed buffering
|
||||
|
||||
uint32 convertedFrames = requestedTime.convertToFramerate(_decoder->_timeScale).totalNumberOfFrames();
|
||||
for (_curEdit = 0; !atLastEdit(); _curEdit++)
|
||||
if (convertedFrames >= _parent->editList[_curEdit].timeOffset && convertedFrames < _parent->editList[_curEdit].timeOffset + _parent->editList[_curEdit].trackDuration)
|
||||
@ -580,6 +583,8 @@ const byte *QuickTimeDecoder::VideoTrackHandler::getPalette() const {
|
||||
}
|
||||
|
||||
bool QuickTimeDecoder::VideoTrackHandler::setReverse(bool reverse) {
|
||||
_delayedFrameToBufferTo = -1; // abort any delayed buffering
|
||||
|
||||
_reversed = reverse;
|
||||
|
||||
if (_reversed) {
|
||||
@ -721,7 +726,7 @@ bool QuickTimeDecoder::VideoTrackHandler::isEmptyEdit() const {
|
||||
return (_parent->editList[_curEdit].mediaTime == -1);
|
||||
}
|
||||
|
||||
void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrames) {
|
||||
void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrames, bool initializingTrack) {
|
||||
if (atLastEdit())
|
||||
return;
|
||||
|
||||
@ -765,8 +770,15 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrame
|
||||
// Track down the keyframe
|
||||
// Then decode until the frame before target
|
||||
_curFrame = findKeyFrame(frameNum) - 1;
|
||||
while (_curFrame < (int32)frameNum - 1)
|
||||
bufferNextFrame();
|
||||
if (initializingTrack) {
|
||||
// We can't decode frames during track initialization,
|
||||
// so delay buffering until the first decode.
|
||||
_delayedFrameToBufferTo = (int32)frameNum - 1;
|
||||
} else {
|
||||
while (_curFrame < (int32)frameNum - 1) {
|
||||
bufferNextFrame();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Since frameNum is the frame that needs to be displayed
|
||||
// we'll set _curFrame to be the "last frame displayed"
|
||||
@ -777,6 +789,16 @@ void QuickTimeDecoder::VideoTrackHandler::enterNewEditListEntry(bool bufferFrame
|
||||
}
|
||||
|
||||
const Graphics::Surface *QuickTimeDecoder::VideoTrackHandler::bufferNextFrame() {
|
||||
// Buffer any frames that were identified during track initialization
|
||||
// and delayed until decoding.
|
||||
if (_delayedFrameToBufferTo != -1) {
|
||||
int32 frameNum = _delayedFrameToBufferTo;
|
||||
_delayedFrameToBufferTo = -1;
|
||||
while (_curFrame < frameNum) {
|
||||
bufferNextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
_curFrame++;
|
||||
|
||||
// Get the next packet
|
||||
|
@ -155,6 +155,7 @@ private:
|
||||
Common::QuickTimeParser::Track *_parent;
|
||||
uint32 _curEdit;
|
||||
int32 _curFrame;
|
||||
int32 _delayedFrameToBufferTo;
|
||||
uint32 _nextFrameStartTime; // media time
|
||||
Graphics::Surface *_scaledSurface;
|
||||
int32 _durationOverride; // media time
|
||||
@ -172,7 +173,7 @@ private:
|
||||
uint32 getCurFrameDuration(); // media time
|
||||
uint32 findKeyFrame(uint32 frame) const;
|
||||
bool isEmptyEdit() const;
|
||||
void enterNewEditListEntry(bool bufferFrames);
|
||||
void enterNewEditListEntry(bool bufferFrames, bool intializingTrack = false);
|
||||
const Graphics::Surface *bufferNextFrame();
|
||||
uint32 getRateAdjustedFrameTime() const; // media time
|
||||
uint32 getCurEditTimeOffset() const; // media time
|
||||
|
Loading…
x
Reference in New Issue
Block a user