bool VideoDecoder::seek(const Audio::Timestamp &time) { if (!isSeekable()) return false; // Stop all tracks so they can be seeked if (isPlaying()) stopAudio(); // Do the actual seeking if (!seekIntern(time)) return false; // Seek any external track too for (TrackListIterator it = _externalTracks.begin(); it != _externalTracks.end(); it++) if (!(*it)->seek(time)) return false; _lastTimeChange = time; // Now that we've seeked, start all tracks again // Also reset our start time if (isPlaying()) { startAudio(); _startTime = g_system->getMillis() - (time.msecs() / _playbackRate).toInt(); } resetPauseStartTime(); findNextVideoTrack(); _needsUpdate = true; return true; }
const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() { if (!_nextVideoTrack) return 0; const Graphics::Surface *frame = _nextVideoTrack->decodeNextFrame(); if (!_setStartTime) { _startTime = g_system->getMillis(); _setStartTime = true; } _nextVideoTrack = findNextVideoTrack(); _needUpdate = false; // Update audio buffers too // (needs to be done after we find the next track) updateAudioBuffer(); // We have to initialize the scaled surface if (frame && (_scaleFactorX != 1 || _scaleFactorY != 1)) { if (!_scaledSurface) { _scaledSurface = new Graphics::Surface(); _scaledSurface->create(_width, _height, getPixelFormat()); } scaleSurface(frame, _scaledSurface, _scaleFactorX, _scaleFactorY); return _scaledSurface; } return frame; }
void QuickTimeDecoder::init() { Audio::QuickTimeAudioDecoder::init(); // Initialize all the audio tracks for (uint32 i = 0; i < _audioTracks.size(); i++) addTrack(new AudioTrackHandler(this, _audioTracks[i])); // Initialize all the video tracks const Common::Array<Common::QuickTimeParser::Track *> &tracks = Common::QuickTimeParser::_tracks; for (uint32 i = 0; i < tracks.size(); i++) { if (tracks[i]->codecType == CODEC_TYPE_VIDEO) { for (uint32 j = 0; j < tracks[i]->sampleDescs.size(); j++) ((VideoSampleDesc *)tracks[i]->sampleDescs[j])->initCodec(); addTrack(new VideoTrackHandler(this, tracks[i])); } } // Prepare the first video track VideoTrackHandler *nextVideoTrack = (VideoTrackHandler *)findNextVideoTrack(); if (nextVideoTrack) { if (_scaleFactorX != 1 || _scaleFactorY != 1) { // We have to take the scale into consideration when setting width/height _width = (nextVideoTrack->getScaledWidth() / _scaleFactorX).toInt(); _height = (nextVideoTrack->getScaledHeight() / _scaleFactorY).toInt(); } else { _width = nextVideoTrack->getWidth(); _height = nextVideoTrack->getHeight(); } } }
const Graphics::Surface *QuickTimeDecoder::decodeNextFrame() { if (!_nextVideoTrack) return 0; const Graphics::Surface *frame = _nextVideoTrack->decodeNextFrame(); if (!_setStartTime) { _startTime = g_system->getMillis(); _setStartTime = true; } _nextVideoTrack = findNextVideoTrack(); _needUpdate = false; // Update audio buffers too // (needs to be done after we find the next track) updateAudioBuffer(); if (_scaledSurface) { scaleSurface(frame, _scaledSurface, _scaleFactorX, _scaleFactorY); return _scaledSurface; } return frame; }
const Graphics::Surface *AVIDecoder::decodeNextFrame() { AVIVideoTrack *track = nullptr; bool isReversed = false; int frameNum = 0; // Check whether the video is playing in revese for (int idx = _videoTracks.size() - 1; idx >= 0; --idx) { track = static_cast<AVIVideoTrack *>(_videoTracks[idx].track); isReversed |= track->isReversed(); } if (isReversed) { // For reverse mode we need to keep seeking to just before the // desired frame prior to actually decoding a frame frameNum = getCurFrame(); seekIntern(track->getFrameTime(frameNum)); } // Decode the next frame const Graphics::Surface *frame = VideoDecoder::decodeNextFrame(); if (isReversed) { // In reverse mode, set next frame to be the prior frame number for (int idx = _videoTracks.size() - 1; idx >= 0; --idx) { track = static_cast<AVIVideoTrack *>(_videoTracks[idx].track); track->setCurFrame(frameNum - 1); findNextVideoTrack(); } } return frame; }
void QuickTimeDecoder::init() { Audio::QuickTimeAudioDecoder::init(); _startTime = 0; _setStartTime = false; // Initialize all the audio tracks if (!_audioTracks.empty()) { _audioHandles.resize(_audioTracks.size()); for (uint32 i = 0; i < _audioTracks.size(); i++) _handlers.push_back(new AudioTrackHandler(this, _audioTracks[i])); } // Initialize all the video tracks for (uint32 i = 0; i < _tracks.size(); i++) { if (_tracks[i]->codecType == CODEC_TYPE_VIDEO) { for (uint32 j = 0; j < _tracks[i]->sampleDescs.size(); j++) ((VideoSampleDesc *)_tracks[i]->sampleDescs[j])->initCodec(); _handlers.push_back(new VideoTrackHandler(this, _tracks[i])); } } // Prepare the first video track _nextVideoTrack = findNextVideoTrack(); if (_nextVideoTrack) { // Initialize the scaled surface if (_scaleFactorX != 1 || _scaleFactorY != 1) { // We have to initialize the scaled surface _scaledSurface = new Graphics::Surface(); _scaledSurface->create((_nextVideoTrack->getWidth() / _scaleFactorX).toInt(), (_nextVideoTrack->getHeight() / _scaleFactorY).toInt(), getPixelFormat()); _width = _scaledSurface->w; _height = _scaledSurface->h; } else { _width = _nextVideoTrack->getWidth().toInt(); _height = _nextVideoTrack->getHeight().toInt(); } _needUpdate = true; } else { _needUpdate = false; } // Now start any audio if (!_audioTracks.empty()) { startAudio(); _audioStartOffset = Audio::Timestamp(0); } }
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; }
bool VideoDecoder::setReverse(bool reverse) { // Can only reverse video-only videos if (reverse && hasAudio()) return false; // Attempt to make sure all the tracks are in the requested direction for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) { if ((*it)->getTrackType() == Track::kTrackTypeVideo && ((VideoTrack *)*it)->isReversed() != reverse) { if (!((VideoTrack *)*it)->setReverse(reverse)) return false; _needsUpdate = true; // force an update } } findNextVideoTrack(); return true; }
const Graphics::Surface *VideoDecoder::decodeNextFrame() { _needsUpdate = false; readNextPacket(); VideoTrack *track = findNextVideoTrack(); if (!track) return 0; const Graphics::Surface *frame = track->decodeNextFrame(); if (track->hasDirtyPalette()) { _palette = track->getPalette(); _dirtyPalette = true; } return frame; }
void QuickTimeDecoder::seekToTime(const Audio::Timestamp &time) { stopAudio(); _audioStartOffset = time; // Sets all tracks to this time for (uint32 i = 0; i < _handlers.size(); i++) _handlers[i]->seekToTime(time); startAudio(); // Reset our start time _startTime = g_system->getMillis() - time.msecs(); _setStartTime = true; resetPauseStartTime(); // Reset the next video track too _nextVideoTrack = findNextVideoTrack(); _needUpdate = _nextVideoTrack != 0; }
bool VideoDecoder::rewind() { if (!isRewindable()) return false; // Stop all tracks so they can be rewound if (isPlaying()) stopAudio(); for (TrackList::iterator it = _tracks.begin(); it != _tracks.end(); it++) if (!(*it)->rewind()) return false; // Now that we've rewound, start all tracks again if (isPlaying()) startAudio(); _lastTimeChange = 0; _startTime = g_system->getMillis(); resetPauseStartTime(); findNextVideoTrack(); return true; }
const Graphics::Surface *VideoDecoder::decodeNextFrame() { _needsUpdate = false; readNextPacket(); // If we have no next video track at this point, there shouldn't be // any frame available for us to display. if (!_nextVideoTrack) return 0; const Graphics::Surface *frame = _nextVideoTrack->decodeNextFrame(); if (_nextVideoTrack->hasDirtyPalette()) { _palette = _nextVideoTrack->getPalette(); _dirtyPalette = true; } // Look for the next video track here for the next decode. findNextVideoTrack(); return frame; }