Ticket #9247: theora-sync.diff

File theora-sync.diff, 5.6 KB (added by eriktorbjorn, 13 years ago)

Patch against current SVN

  • engines/sword25/fmv/theora_decoder.cpp

     
    329329        reset();
    330330}
    331331
     332double TheoraDecoder::getTime() {
     333        uint32 now = g_system->getMillis();
     334        uint32 elapsedTime;
     335
     336        if (_audStream) {
     337                elapsedTime = _mixer->getElapsedTime(*_audHandle).msecs();
     338        } else {
     339                // no audio timer to worry about, we can just use the system clock
     340                // only one complication: If the process is suspended, we should
     341                // reset timing to account for the gap in play time. Do it the
     342                // easy/hack way
     343                elapsedTime = now - _startTime;
     344        }
     345
     346        return elapsedTime * .001;
     347}
     348
     349// The Theora example decoder seems to have this fancy adaptive timing
     350// thingamajig, but it also has the advantage of owning the decoder process
     351// completely. We, on the other hand, are at the mercy of the game engine,
     352// which calls this function whenever it feels like it.
     353
     354Graphics::Surface *TheoraDecoder::decode() {
     355        bool endMovie = false;
     356
     357        if (_startTime == 0) {
     358                _startTime = g_system->getMillis();
     359        }
     360
     361        int32 oldFrame = _curFrame;
     362
     363        // Ensure that we always have something to sync against
     364        // TODO: This should probably try to grab as much audio data as possible
     365        // because I believe I'm getting sound underruns...
     366        if (_audStream) {
     367                uint32 oldQueue = _audStream->numQueuedStreams();
     368
     369                while (!endMovie && _audStream->numQueuedStreams() == oldQueue) {
     370                        if (!decodePacket())
     371                                endMovie = true;
     372                }
     373        }
     374
     375        // Advance to the appropriate video frame
     376
     377        while (!endMovie && _videobufTime < getTime()) {
     378                if (!decodePacket())
     379                        endMovie = true;
     380        }
     381
     382        if (_surface && _curFrame != oldFrame) {
     383                th_ycbcr_buffer yuv;
     384
     385                th_decode_ycbcr_out(_theoraDecode, yuv);
     386
     387                // Convert YUV data to RGB data
     388                YUVtoBGRA::translate(yuv, _theoraInfo, (byte *)_surface->getBasePtr(0, 0), _surface->pitch * _surface->h);
     389               
     390                switch (_theoraInfo.pixel_fmt) {
     391                case TH_PF_420:
     392                        break;
     393                case TH_PF_422:
     394                        break;
     395                case TH_PF_444:
     396                        break;
     397                default:
     398                        break;
     399                }
     400        }
     401
     402        return endMovie ? NULL : _surface;
     403}
     404
    332405Graphics::Surface *TheoraDecoder::decodeNextFrame() {
     406        error("TheoraDecoder: Use decode() instead of decodeNextFrame()");
     407        return _surface;
     408}
     409
     410Graphics::Surface *TheoraDecoder::decodePacket() {
    333411        int i, j;
    334412
    335413//      _stateFlag = false; // playback has not begun
     
    394472                                _videobufTime = th_granule_time(_theoraDecode, _videobufGranulePos);
    395473                                _curFrame++;
    396474
     475#if 1
     476                                // is it already too old to be useful? This is only actually
     477                                // useful cosmetically after a SIGSTOP. Note that we have to
     478                                // decode the frame even if we don't show it (for now) due to
     479                                // keyframing. Soon enough libtheora will be able to deal
     480                                // with non-keyframe seeks.
     481
     482                                if (_videobufTime >= getTime())
     483                                        _videobufReady = true;
     484                                else {
     485                                        // If we are too slow, reduce the pp level.
     486                                        _ppInc = (_ppLevel > 0) ? -1 : 0;
     487                                }
     488#else
    397489                                _videobufReady = true;
     490#endif
    398491                        }
    399492                } else
    400493                        break;
     
    425518
    426519        // are we at or past time for this video frame?
    427520        if (_stateFlag && _videobufReady) {
    428                 th_ycbcr_buffer yuv;
    429 
    430                 th_decode_ycbcr_out(_theoraDecode, yuv);
    431 
    432                 // Convert YUV data to RGB data
    433                 YUVtoBGRA::translate(yuv, _theoraInfo, (byte *)_surface->getBasePtr(0, 0), _surface->pitch * _surface->h);
    434                
    435                 switch (_theoraInfo.pixel_fmt) {
    436                 case TH_PF_420:
    437                         break;
    438                 case TH_PF_422:
    439                         break;
    440                 case TH_PF_444:
    441                         break;
    442                 default:
    443                         break;
    444                 }
    445 
    446521                _videobufReady = false;
    447522        }
    448523
     524        // TODO
     525        // If we have lots of extra time, increase the post-processing level
     526
    449527        // if our buffers either don't exist or are ready to go,
    450528        // we can begin playback
    451529        if ((!_theoraPacket || _videobufReady) &&
     
    468546        _videobufReady = false;
    469547        _videobufGranulePos = -1;
    470548        _videobufTime = 0;
     549        _startTime = 0;
    471550
    472551        _audiobufFill = 0;
    473552        _audiobufReady = false;
     
    484563        return !isVideoLoaded();
    485564}
    486565
    487 
    488566uint32 TheoraDecoder::getElapsedTime() const {
    489567        if (_audStream && _mixer)
    490568                return _mixer->getSoundElapsedTime(*_audHandle);
  • engines/sword25/fmv/movieplayer.cpp

     
    124124
    125125void MoviePlayer::update() {
    126126        if (_decoder.isVideoLoaded()) {
    127                 Graphics::Surface *s = _decoder.decodeNextFrame();
     127                Graphics::Surface *s = _decoder.decode();
    128128                if (s) {
    129129                        // Transfer the next frame
    130130                        assert(s->bytesPerPixel == 4);
  • engines/sword25/fmv/theora_decoder.h

     
    6363        void reset();
    6464
    6565        /**
    66          * Decode the next frame and return the frame's surface
     66         * Decode the appropriate amount of data and return the frame's surface
    6767         * @note the return surface should *not* be freed
    6868         * @note this may return 0, in which case the last frame should be kept on screen
    6969         */
     70        Graphics::Surface *decode();
    7071        Graphics::Surface *decodeNextFrame();
    7172
    7273        bool isVideoLoaded() const {
     
    105106        void queuePage(ogg_page *page);
    106107        int bufferData();
    107108        Audio::QueuingAudioStream *createAudioStream();
     109        double getTime();
     110        Graphics::Surface *decodePacket();
    108111
    109112private:
    110113        Common::SeekableReadStream *_fileStream;
     
    139142        int _ppLevel;
    140143        int _ppInc;
    141144
     145        uint32 _startTime;
     146
    142147        // single frame video buffering
    143148        bool _videobufReady;
    144149        ogg_int64_t  _videobufGranulePos;