Ticket #9247: theora-sync.diff
File theora-sync.diff, 5.6 KB (added by , 13 years ago) |
---|
-
engines/sword25/fmv/theora_decoder.cpp
329 329 reset(); 330 330 } 331 331 332 double 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 354 Graphics::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 332 405 Graphics::Surface *TheoraDecoder::decodeNextFrame() { 406 error("TheoraDecoder: Use decode() instead of decodeNextFrame()"); 407 return _surface; 408 } 409 410 Graphics::Surface *TheoraDecoder::decodePacket() { 333 411 int i, j; 334 412 335 413 // _stateFlag = false; // playback has not begun … … 394 472 _videobufTime = th_granule_time(_theoraDecode, _videobufGranulePos); 395 473 _curFrame++; 396 474 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 397 489 _videobufReady = true; 490 #endif 398 491 } 399 492 } else 400 493 break; … … 425 518 426 519 // are we at or past time for this video frame? 427 520 if (_stateFlag && _videobufReady) { 428 th_ycbcr_buffer yuv;429 430 th_decode_ycbcr_out(_theoraDecode, yuv);431 432 // Convert YUV data to RGB data433 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 446 521 _videobufReady = false; 447 522 } 448 523 524 // TODO 525 // If we have lots of extra time, increase the post-processing level 526 449 527 // if our buffers either don't exist or are ready to go, 450 528 // we can begin playback 451 529 if ((!_theoraPacket || _videobufReady) && … … 468 546 _videobufReady = false; 469 547 _videobufGranulePos = -1; 470 548 _videobufTime = 0; 549 _startTime = 0; 471 550 472 551 _audiobufFill = 0; 473 552 _audiobufReady = false; … … 484 563 return !isVideoLoaded(); 485 564 } 486 565 487 488 566 uint32 TheoraDecoder::getElapsedTime() const { 489 567 if (_audStream && _mixer) 490 568 return _mixer->getSoundElapsedTime(*_audHandle); -
engines/sword25/fmv/movieplayer.cpp
124 124 125 125 void MoviePlayer::update() { 126 126 if (_decoder.isVideoLoaded()) { 127 Graphics::Surface *s = _decoder.decode NextFrame();127 Graphics::Surface *s = _decoder.decode(); 128 128 if (s) { 129 129 // Transfer the next frame 130 130 assert(s->bytesPerPixel == 4); -
engines/sword25/fmv/theora_decoder.h
63 63 void reset(); 64 64 65 65 /** 66 * Decode the next frameand return the frame's surface66 * Decode the appropriate amount of data and return the frame's surface 67 67 * @note the return surface should *not* be freed 68 68 * @note this may return 0, in which case the last frame should be kept on screen 69 69 */ 70 Graphics::Surface *decode(); 70 71 Graphics::Surface *decodeNextFrame(); 71 72 72 73 bool isVideoLoaded() const { … … 105 106 void queuePage(ogg_page *page); 106 107 int bufferData(); 107 108 Audio::QueuingAudioStream *createAudioStream(); 109 double getTime(); 110 Graphics::Surface *decodePacket(); 108 111 109 112 private: 110 113 Common::SeekableReadStream *_fileStream; … … 139 142 int _ppLevel; 140 143 int _ppInc; 141 144 145 uint32 _startTime; 146 142 147 // single frame video buffering 143 148 bool _videobufReady; 144 149 ogg_int64_t _videobufGranulePos;