mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-03 09:23:37 +00:00
SWORD25: Start of plugging audio to Theora decoder
svn-id: r53207
This commit is contained in:
parent
9b3e26e7a2
commit
1e3b3af5c0
@ -41,17 +41,22 @@
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
TheoraDecoder::TheoraDecoder() {
|
||||
TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : _mixer(mixer) {
|
||||
_fileStream = 0;
|
||||
_surface = 0;
|
||||
|
||||
_theoraPacket = 0;
|
||||
_vorbisPacket = 0;
|
||||
_stateFlag = 0;
|
||||
_stateFlag = false;
|
||||
|
||||
_soundType = soundType;
|
||||
_audStream = 0;
|
||||
_audHandle = new Audio::SoundHandle();
|
||||
}
|
||||
|
||||
TheoraDecoder::~TheoraDecoder() {
|
||||
close();
|
||||
delete _audHandle;
|
||||
}
|
||||
|
||||
void TheoraDecoder::queuePage(ogg_page *page) {
|
||||
@ -102,7 +107,7 @@ bool TheoraDecoder::load(Common::SeekableReadStream &stream) {
|
||||
if (!ogg_page_bos(&_oggPage)) {
|
||||
// don't leak the page; get it into the appropriate stream
|
||||
queuePage(&_oggPage);
|
||||
_stateFlag = 1;
|
||||
_stateFlag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -220,8 +225,11 @@ bool TheoraDecoder::load(Common::SeekableReadStream &stream) {
|
||||
}
|
||||
|
||||
// open audio
|
||||
if (_vorbisPacket)
|
||||
open_audio();
|
||||
if (_vorbisPacket) {
|
||||
_audStream = createAudioStream();
|
||||
if (_audStream)
|
||||
_mixer->playStream(_soundType, _audHandle, _audStream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -233,6 +241,9 @@ void TheoraDecoder::close() {
|
||||
vorbis_dsp_clear(&_vorbisDSP);
|
||||
vorbis_comment_clear(&_vorbisComment);
|
||||
vorbis_info_clear(&_vorbisInfo);
|
||||
|
||||
_mixer->stopHandle(*_audHandle);
|
||||
_audStream = 0;
|
||||
}
|
||||
if (_theoraPacket) {
|
||||
ogg_stream_clear(&_theoraOut);
|
||||
@ -258,7 +269,7 @@ void TheoraDecoder::close() {
|
||||
Graphics::Surface *TheoraDecoder::decodeNextFrame() {
|
||||
int i, j;
|
||||
|
||||
_stateFlag = 0; // playback has not begun
|
||||
_stateFlag = false; // playback has not begun
|
||||
|
||||
// we want a video and audio frame ready to go at all times. If
|
||||
// we have to buffer incoming, buffer the compressed data (ie, let
|
||||
@ -281,7 +292,7 @@ Graphics::Surface *TheoraDecoder::decodeNextFrame() {
|
||||
_audiobufFill += i * _vorbisInfo.channels * 2;
|
||||
|
||||
if (_audiobufFill == audiofd_fragsize)
|
||||
_audiobufReady = 1;
|
||||
_audiobufReady = true;
|
||||
|
||||
if (_vorbisDSP.granulepos >= 0)
|
||||
_audiobufGranulePos = _vorbisDSP.granulepos - ret + i;
|
||||
@ -327,7 +338,7 @@ Graphics::Surface *TheoraDecoder::decodeNextFrame() {
|
||||
// with non-keyframe seeks.
|
||||
|
||||
if (_videobufTime >= get_time())
|
||||
_videobufReady = 1;
|
||||
_videobufReady = true;
|
||||
else {
|
||||
// If we are too slow, reduce the pp level.
|
||||
_ppInc = _ppLevel > 0 ? -1 : 0;
|
||||
@ -350,12 +361,13 @@ Graphics::Surface *TheoraDecoder::decodeNextFrame() {
|
||||
}
|
||||
|
||||
// If playback has begun, top audio buffer off immediately.
|
||||
if (_stateFlag) audio_write_nonblocking();
|
||||
if (_stateFlag)
|
||||
audio_write_nonblocking();
|
||||
|
||||
// are we at or past time for this video frame?
|
||||
if (_stateFlag && _videobufReady && _videobufTime <= get_time()) {
|
||||
video_write();
|
||||
_videobufReady = 0;
|
||||
_videobufReady = false;
|
||||
}
|
||||
|
||||
if (_stateFlag &&
|
||||
@ -410,11 +422,11 @@ Graphics::Surface *TheoraDecoder::decodeNextFrame() {
|
||||
// we can begin playback
|
||||
if ((!_theoraPacket || _videobufReady) &&
|
||||
(!_vorbisPacket || _audiobufReady))
|
||||
_stateFlag = 1;
|
||||
_stateFlag = true;
|
||||
|
||||
// same if we've run out of input
|
||||
if (_fileStream->eos())
|
||||
_stateFlag = 1;
|
||||
_stateFlag = true;
|
||||
}
|
||||
|
||||
void TheoraDecoder::reset() {
|
||||
@ -422,13 +434,24 @@ void TheoraDecoder::reset() {
|
||||
if (_fileStream)
|
||||
_fileStream->seek(0);
|
||||
|
||||
_videobufReady = 0;
|
||||
_videobufReady = false;
|
||||
_videobufGranulePos = -1;
|
||||
_videobufTime = 0;
|
||||
|
||||
_audiobufFill = 0;
|
||||
_audiobufReady = 0;
|
||||
_audiobufReady = false;
|
||||
_audiobufGranulePos = 0;
|
||||
}
|
||||
|
||||
uint32 TheoraDecoder::getElapsedTime() const {
|
||||
if (_audStream)
|
||||
return _mixer->getSoundElapsedTime(*_audHandle);
|
||||
|
||||
return VideoDecoder::getElapsedTime();
|
||||
}
|
||||
|
||||
Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
|
||||
return Audio::makeQueuingAudioStream(_vorbisInfo.rate, _vorbisInfo.channels);
|
||||
}
|
||||
|
||||
} // End of namespace Sword25
|
||||
|
@ -27,6 +27,8 @@
|
||||
#define SWORD25_THEORADECODER_H
|
||||
|
||||
#include "graphics/video/video_decoder.h"
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include <theora/theoradec.h>
|
||||
#include <vorbis/codec.h>
|
||||
@ -45,7 +47,7 @@ namespace Sword25 {
|
||||
*/
|
||||
class TheoraDecoder : public Graphics::FixedRateVideoDecoder {
|
||||
public:
|
||||
TheoraDecoder();
|
||||
TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType);
|
||||
virtual ~TheoraDecoder();
|
||||
|
||||
/**
|
||||
@ -68,6 +70,8 @@ public:
|
||||
uint32 getFrameCount() const { return _frameCount; }
|
||||
Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 0, 0, 0); }
|
||||
|
||||
uint32 getElapsedTime() const;
|
||||
|
||||
protected:
|
||||
Common::Rational getFrameRate() const { return _frameRate; }
|
||||
|
||||
@ -81,6 +85,12 @@ private:
|
||||
Common::Rational _frameRate;
|
||||
uint32 _frameCount;
|
||||
|
||||
Audio::Mixer *_mixer;
|
||||
Audio::Mixer::SoundType _soundType;
|
||||
Audio::SoundHandle *_audHandle;
|
||||
Audio::QueuingAudioStream *_audStream;
|
||||
Audio::QueuingAudioStream *createAudioStream();
|
||||
|
||||
ogg_sync_state _oggSync;
|
||||
ogg_page _oggPage;
|
||||
ogg_packet _oggPacket;
|
||||
@ -97,20 +107,20 @@ private:
|
||||
|
||||
int _theoraPacket;
|
||||
int _vorbisPacket;
|
||||
int _stateFlag;
|
||||
bool _stateFlag;
|
||||
|
||||
int _ppLevelMax;
|
||||
int _ppLevel;
|
||||
int _ppInc;
|
||||
|
||||
// single frame video buffering
|
||||
int _videobufReady;
|
||||
bool _videobufReady;
|
||||
ogg_int64_t _videobufGranulePos;
|
||||
double _videobufTime;
|
||||
|
||||
// single audio fragment audio buffering
|
||||
int _audiobufFill;
|
||||
int _audiobufReady;
|
||||
bool _audiobufReady;
|
||||
ogg_int16_t *_audiobuf;
|
||||
ogg_int64_t _audiobufGranulePos; // time position of last sample
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user