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