From f06db87a0ee0323ceb5a1e946fa9ed1f8576abca Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 31 Aug 2010 18:37:59 +0000 Subject: SWORD25: Implement playback. Blitting is TODO. svn-id: r53298 --- engines/sword25/fmv/movieplayer.cpp | 20 +++++++++--- engines/sword25/fmv/theora_decoder.cpp | 58 ++++++++++++++++++++++++++++++++-- engines/sword25/fmv/theora_decoder.h | 12 +++++-- 3 files changed, 81 insertions(+), 9 deletions(-) diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp index 3114d68bdc..e4b417adc5 100644 --- a/engines/sword25/fmv/movieplayer.cpp +++ b/engines/sword25/fmv/movieplayer.cpp @@ -54,7 +54,7 @@ MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel) { _decoder = new TheoraDecoder(); } -bool MoviePlayer::LoadMovie(const Common::String &filename, unsigned int Z) { +bool MoviePlayer::LoadMovie(const Common::String &filename, unsigned int z) { Common::SeekableReadStream *in = Kernel::GetInstance()->GetPackage()->GetStream(filename); if (!in) { @@ -62,11 +62,15 @@ bool MoviePlayer::LoadMovie(const Common::String &filename, unsigned int Z) { return false; } + debug(2, "LoadMovie(%s, %d)", filename.c_str(), z); + if (!_decoder->load(in)) { BS_LOG_ERRORLN("Could not load movie file \"%s\".", filename.c_str()); return false; } + warning("STUB: MoviePlayer::LoadMovie(). Z is not handled"); + return true; } @@ -77,22 +81,30 @@ bool MoviePlayer::UnloadMovie() { } bool MoviePlayer::Play() { + _decoder->pauseVideo(false); + return true; } bool MoviePlayer::Pause() { + _decoder->pauseVideo(true); + return true; } void MoviePlayer::Update() { + if (!_decoder->isVideoLoaded()) + return; + + Graphics::Surface *surface = _decoder->decodeNextFrame(); } bool MoviePlayer::IsMovieLoaded() { - return true; + return _decoder->isVideoLoaded(); } bool MoviePlayer::IsPaused() { - return true; + return _decoder->isPaused(); } float MoviePlayer::GetScaleFactor() { @@ -103,7 +115,7 @@ void MoviePlayer::SetScaleFactor(float ScaleFactor) { } double MoviePlayer::GetTime() { - return 1.0; + return (double)_decoder->getElapsedTime() / 1000.0; } diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp index 31458a2deb..bcd77ca880 100644 --- a/engines/sword25/fmv/theora_decoder.cpp +++ b/engines/sword25/fmv/theora_decoder.cpp @@ -60,11 +60,21 @@ TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT _soundType = soundType; _audStream = 0; _audHandle = new Audio::SoundHandle(); + + _theoraDecode = 0; + _theoraSetup = 0; + + _curFrame = 0; + + _audiobuf = (ogg_int16_t *)calloc(AUDIOFD_FRAGSIZE, sizeof(ogg_int16_t)); + + reset(); } TheoraDecoder::~TheoraDecoder() { close(); delete _audHandle; + free(_audiobuf); } void TheoraDecoder::queuePage(ogg_page *page) { @@ -81,7 +91,7 @@ int TheoraDecoder::bufferData() { ogg_sync_wrote(&_oggSync, bytes); - return(bytes); + return bytes; } bool TheoraDecoder::load(Common::SeekableReadStream *stream) { @@ -209,6 +219,36 @@ bool TheoraDecoder::load(Common::SeekableReadStream *stream) { debug(1, " Frame content is %dx%d with offset (%d,%d).", _theoraInfo.frame_width, _theoraInfo.frame_height, _theoraInfo.pic_x, _theoraInfo.pic_y); + switch (_theoraInfo.colorspace){ + case TH_CS_UNSPECIFIED: + /* nothing to report */ + break;; + case TH_CS_ITU_REC_470M: + debug(1, " encoder specified ITU Rec 470M (NTSC) color."); + break; + case TH_CS_ITU_REC_470BG: + debug(1, " encoder specified ITU Rec 470BG (PAL) color."); + break; + default: + debug(1, "warning: encoder specified unknown colorspace (%d).", _theoraInfo.colorspace); + break; + } + + debug(1, "Encoded by %s", _theoraComment.vendor); + if (_theoraComment.comments) { + debug(1, "theora comment header:"); + for (int i = 0; i < _theoraComment.comments; i++) { + if (_theoraComment.user_comments[i]) { + int len = _theoraComment.comment_lengths[i]; + char *value = (char *)malloc(len + 1); + memcpy(value, _theoraComment.user_comments[i], len); + value[len] = '\0'; + debug(1, "\t%s", value); + free(value); + } + } + } + th_decode_ctl(_theoraDecode, TH_DECCTL_GET_PPLEVEL_MAX, &_ppLevelMax, sizeof(_ppLevelMax)); _ppLevel = _ppLevelMax; th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &_ppLevel, sizeof(_ppLevel)); @@ -220,7 +260,9 @@ bool TheoraDecoder::load(Common::SeekableReadStream *stream) { th_comment_clear(&_theoraComment); } + th_setup_free(_theoraSetup); + _theoraSetup = 0; if (_vorbisPacket) { vorbis_synthesis_init(&_vorbisDSP, &_vorbisInfo); @@ -241,8 +283,7 @@ bool TheoraDecoder::load(Common::SeekableReadStream *stream) { } _surface = new Graphics::Surface(); - - _surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, 3); + _surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, 4); return true; } @@ -258,12 +299,15 @@ void TheoraDecoder::close() { if (_mixer) _mixer->stopHandle(*_audHandle); _audStream = 0; + _vorbisPacket = 0; } if (_theoraPacket) { ogg_stream_clear(&_theoraOut); th_decode_free(_theoraDecode); th_comment_clear(&_theoraComment); th_info_clear(&_theoraInfo); + _theoraDecode = 0; + _theoraPacket = 0; } if (!_fileStream) @@ -406,6 +450,7 @@ Graphics::Surface *TheoraDecoder::decodeNextFrame() { void TheoraDecoder::reset() { VideoDecoder::reset(); + if (_fileStream) _fileStream->seek(0); @@ -416,8 +461,15 @@ void TheoraDecoder::reset() { _audiobufFill = 0; _audiobufReady = false; _audiobufGranulePos = 0; + + _curFrame = 0; } +bool TheoraDecoder::endOfVideo() const { + return !isVideoLoaded(); +} + + uint32 TheoraDecoder::getElapsedTime() const { if (_audStream && _mixer) return _mixer->getSoundElapsedTime(*_audHandle); diff --git a/engines/sword25/fmv/theora_decoder.h b/engines/sword25/fmv/theora_decoder.h index 7faadfd9dc..3ce53e0900 100644 --- a/engines/sword25/fmv/theora_decoder.h +++ b/engines/sword25/fmv/theora_decoder.h @@ -68,6 +68,10 @@ public: bool isVideoLoaded() const { return _fileStream != 0; } + bool isPaused() const { + return (VideoDecoder::isPaused() || !isVideoLoaded()); + } + uint16 getWidth() const { return _surface->w; } @@ -75,14 +79,18 @@ public: return _surface->h; } uint32 getFrameCount() const { - return _frameCount; + // It is not possible to get frame count easily + // I.e. seeking is required + assert(0); } Graphics::PixelFormat getPixelFormat() const { - return Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 0, 0, 0); + return Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); } uint32 getElapsedTime() const; + bool endOfVideo() const; + protected: Common::Rational getFrameRate() const { return _frameRate; -- cgit v1.2.3