void MoviePlayer::handleNextFrame() { if (!isVideoLoaded()) return; VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen]; if (_flags & 2) { uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum); assert(dstPtr); uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0); assert(dst); copyFrameToBuffer(dst, kDstResource, 0, 0, _vm->_screenWidth * _vm->_bytesPerPixel); } else if (_flags & 1) { copyFrameToBuffer(pvs->getBackPixels(0, 0), kDstScreen, 0, 0, pvs->pitch); Common::Rect imageRect(getWidth(), getHeight()); _vm->restoreBackgroundHE(imageRect); } else { copyFrameToBuffer(pvs->getPixels(0, 0), kDstScreen, 0, 0, pvs->pitch); Common::Rect imageRect(getWidth(), getHeight()); _vm->markRectAsDirty(kMainVirtScreen, imageRect); } if (endOfVideo()) close(); }
void MoviePlayerSMK::nextFrame() { if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) rewind(); if (!endOfVideo()) { decodeNextFrame(); if (_vm->_interactiveVideo == TYPE_OMNITV) { copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); } else if (_vm->_interactiveVideo == TYPE_LOOPING) { copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); } } else if (_vm->_interactiveVideo == TYPE_OMNITV) { close(); _vm->_interactiveVideo = 0; _vm->_variableArray[254] = 6747; } }
void MoviePlayerDXA::playVideo() { // Most of the videos included in the Amiga version, reduced the // resoluton to 384 x 280, so require the screen to be cleared, // before starting playing those videos. if (getWidth() == 384 && getHeight() == 280) { _vm->clearSurfaces(); } while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit()) handleNextFrame(); }
void RivenVideo::playBlocking(int32 endTime) { _vm->_cursor->hideCursor(); if (!_playing) { play(); } // Sanity check if (isLooping()) error("Called playBlocking() on a looping video"); bool playTillEnd; if (endTime == -1) { playTillEnd = true; } else { playTillEnd = false; _video->setEndTime(Audio::Timestamp(0, endTime, 600)); } if (playTillEnd) { enable(); } bool continuePlaying = true; while (!endOfVideo() && !_vm->hasGameEnded() && continuePlaying) { // Draw a frame _vm->doFrame(); // Handle skipping if (playTillEnd && _vm->getStack()->keyGetAction() == kKeyActionSkip) { continuePlaying = false; // Seek to the last frame _video->seek(_video->getDuration().addMsecs(-1)); _vm->getStack()->mouseForceUp(); _vm->getStack()->keyResetAction(); } } if (playTillEnd) { disable(); stop(); } // Execute the stored opcode uint16 storedOpcodeMovieSlot = _vm->_scriptMan->getStoredMovieOpcodeSlot(); uint32 storedOpcodeTime = _vm->_scriptMan->getStoredMovieOpcodeTime(); if (_slot == storedOpcodeMovieSlot && getTime() >= storedOpcodeTime) { // CHECKME: Suspicious use of time units _vm->_scriptMan->runStoredMovieOpcode(); } _vm->_cursor->showCursor(); }
uint32 QuickTimeDecoder::getTimeToNextFrame() const { if (endOfVideo() || _curFrame < 0) return 0; // Convert from the QuickTime rate base to 1000 uint32 nextFrameStartTime = _nextFrameStartTime * 1000 / _streams[_videoStreamIndex]->time_scale; uint32 elapsedTime = getElapsedTime(); if (nextFrameStartTime <= elapsedTime) return 0; return nextFrameStartTime - elapsedTime; }
void MoviePlayerDXA::nextFrame() { if (_bgSoundStream && _vm->_mixer->isSoundHandleActive(_bgSound) && needsUpdate()) { copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); return; } if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) { rewind(); startSound(); } if (!endOfVideo()) { if (_vm->_interactiveVideo == TYPE_OMNITV) { copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); } else if (_vm->_interactiveVideo == TYPE_LOOPING) { copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); } } else if (_vm->_interactiveVideo == TYPE_OMNITV) { close(); _vm->_interactiveVideo = 0; _vm->_variableArray[254] = 6747; } }
uint32 FixedRateVideoDecoder::getTimeToNextFrame() const { if (endOfVideo() || _curFrame < 0) return 0; uint32 elapsedTime = getTime(); uint32 nextFrameStartTime = getFrameBeginTime(_curFrame + 1); // If the time that the next frame should be shown has past // the frame should be shown ASAP. if (nextFrameStartTime <= elapsedTime) return 0; return nextFrameStartTime - elapsedTime; }
uint32 VideoDecoder::getTimeToNextFrame() const { if (endOfVideo() || _needsUpdate) return 0; const VideoTrack *track = findNextVideoTrack(); if (!track) return 0; uint32 elapsedTime = getTime(); uint32 nextFrameStartTime = track->getNextFrameStartTime(); if (nextFrameStartTime <= elapsedTime) return 0; return nextFrameStartTime - elapsedTime; }
void SeekableBinkDecoder::skipNextFrame() { if (endOfVideo()) return; VideoFrame &frame = _frames[_curFrame + 1]; if (!_bink->seek(frame.offset)) error("Bad bink seek"); uint32 frameSize = frame.size; for (uint32 i = 0; i < _audioTracks.size(); i++) { uint32 audioPacketLength = _bink->readUint32LE(); frameSize -= 4; if (frameSize < audioPacketLength) error("Audio packet too big for the frame"); if (audioPacketLength >= 4) { // Skip audio data _bink->seek(audioPacketLength, SEEK_CUR); frameSize -= audioPacketLength; } } uint32 videoPacketStart = _bink->pos(); uint32 videoPacketEnd = _bink->pos() + frameSize; frame.bits = new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, videoPacketStart, videoPacketEnd), true); videoPacket(frame); delete frame.bits; frame.bits = 0; _curFrame++; if (_curFrame == 0) _startTime = g_system->getMillis(); }
uint32 VideoDecoder::getTimeToNextFrame() const { if (endOfVideo() || _needsUpdate || !_nextVideoTrack) return 0; uint32 currentTime = getTime(); uint32 nextFrameStartTime = _nextVideoTrack->getNextFrameStartTime(); if (_nextVideoTrack->isReversed()) { // For reversed videos, we need to handle the time difference the opposite way. if (nextFrameStartTime >= currentTime) return 0; return currentTime - nextFrameStartTime; } // Otherwise, handle it normally. if (nextFrameStartTime <= currentTime) return 0; return nextFrameStartTime - currentTime; }
void MoviePlayerSMK::playVideo() { while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit()) handleNextFrame(); }
const Graphics::Surface *BinkDecoder::decodeNextFrame() { if (endOfVideo()) return 0; VideoFrame &frame = _frames[_curFrame + 1]; if (!_bink->seek(frame.offset)) error("Bad bink seek"); uint32 frameSize = frame.size; for (uint32 i = 0; i < _audioTracks.size(); i++) { AudioTrack &audio = _audioTracks[i]; uint32 audioPacketLength = _bink->readUint32LE(); frameSize -= 4; if (frameSize < audioPacketLength) error("Audio packet too big for the frame"); if (audioPacketLength >= 4) { uint32 audioPacketStart = _bink->pos(); uint32 audioPacketEnd = _bink->pos() + audioPacketLength; if (i == _audioTrack) { // Only play one audio track // Number of samples in bytes audio.sampleCount = _bink->readUint32LE() / (2 * audio.channels); audio.bits = new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, audioPacketStart + 4, audioPacketEnd), true); audioPacket(audio); delete audio.bits; audio.bits = 0; } _bink->seek(audioPacketEnd); frameSize -= audioPacketLength; } } uint32 videoPacketStart = _bink->pos(); uint32 videoPacketEnd = _bink->pos() + frameSize; frame.bits = new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink, videoPacketStart, videoPacketEnd), true); videoPacket(frame); delete frame.bits; frame.bits = 0; _curFrame++; if (_curFrame == 0) _startTime = g_system->getMillis(); return &_surface; }
const Graphics::Surface *BinkDecoder::decodeNextFrame() { if (endOfVideo()) return 0; VideoFrame &frame = _frames[_curFrame + 1]; if (!_bink->seek(frame.offset)) error("Bad bink seek"); uint32 frameSize = frame.size; for (uint32 i = 0; i < _audioTracks.size(); i++) { AudioTrack &audio = _audioTracks[i]; uint32 audioPacketLength = _bink->readUint32LE(); frameSize -= 4; if (frameSize < audioPacketLength) error("Audio packet too big for the frame"); if (audioPacketLength >= 4) { if (i == _audioTrack) { // Only play one audio track // Number of samples in bytes audio.sampleCount = _bink->readUint32LE() / (2 * audio.channels); audio.bits = new Common::BitStream32LE(*_bink, (audioPacketLength - 4) * 8); audioPacket(audio); delete audio.bits; audio.bits = 0; } else // Skip the rest _bink->skip(audioPacketLength); frameSize -= audioPacketLength; } } frame.bits = new Common::BitStream32LE(*_bink, frameSize * 8); videoPacket(frame); delete frame.bits; frame.bits = 0; _curFrame++; if (_curFrame == 0) _startTime = g_system->getMillis(); if (!_audioStarted && _audioStream) { _audioStarted = true; g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audioHandle, _audioStream); } return &_surface; }
bool VideoDecoder::needsUpdate() const { return !endOfVideo() && getTimeToNextFrame() == 0; }
void SmushDecoder::handleFrame() { uint32 tag; int32 size; int pos = 0; if (_videoLooping && _curFrame == _nbframes - 1) { _file->seek(_startPos, SEEK_SET); _curFrame = -1; } if (_curFrame == -1) _startTime = g_system->getMillis(); if (_videoPause) return; if (endOfVideo()) { // Looping is handled outside, by rewinding the video. _videoPause = true; return; } tag = _file->readUint32BE(); if (tag == MKTAG('A','N','N','O')) { char *anno; byte *data; size = _file->readUint32BE(); data = new byte[size]; _file->read(data, size); anno = (char *)data; if (strncmp(anno, ANNO_HEADER, sizeof(ANNO_HEADER) - 1) == 0) { //char *annoData = anno + sizeof(ANNO_HEADER); // Examples: // Water streaming around boat from Manny's balcony // MakeAnim animation type 'Bl16' parameters: 10000;12000;100;1;0;0;0;0;25;0; // Water in front of the Blue Casket // MakeAnim animation type 'Bl16' parameters: 20000;25000;100;1;0;0;0;0;25;0; // Scrimshaw exterior: // MakeAnim animation type 'Bl16' parameters: 6000;8000;100;0;0;0;0;0;2;0; // Lola engine room (loops a limited number of times?): // MakeAnim animation type 'Bl16' parameters: 6000;8000;90;1;0;0;0;0;2;0; Debug::debug(Debug::Movie, "Announcement data: %s\n", anno); // It looks like the announcement data is actually for setting some of the // header parameters, not for any looping purpose } else { Debug::debug(Debug::Movie, "Announcement header not understood: %s\n", anno); } delete[] anno; tag = _file->readUint32BE(); } assert(tag == MKTAG('F','R','M','E')); size = _file->readUint32BE(); byte *frame = new byte[size]; _file->read(frame, size); do { if (READ_BE_UINT32(frame + pos) == MKTAG('B','l','1','6')) { _blocky16->decode((byte *)_surface.pixels, frame + pos + 8); pos += READ_BE_UINT32(frame + pos + 4) + 8; } else if (READ_BE_UINT32(frame + pos) == MKTAG('W','a','v','e')) { int decompressed_size = READ_BE_UINT32(frame + pos + 8); if (decompressed_size < 0) handleWave(frame + pos + 8 + 4 + 8, READ_BE_UINT32(frame + pos + 8 + 8)); else handleWave(frame + pos + 8 + 4, decompressed_size); pos += READ_BE_UINT32(frame + pos + 4) + 8; } else { Debug::error(Debug::Movie, "SmushDecoder::handleFrame() unknown tag"); } } while (pos < size); delete[] frame; ++_curFrame; }