1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-01 18:45:33 +00:00

Merge branch 'videoplayback' of https://github.com/ChrisKCat/openmw into videoplayback

Conflicts:
	apps/openmw/mwrender/videoplayer.cpp
This commit is contained in:
scrawl 2012-12-12 22:24:38 +01:00
commit 7fd9e1d212
7 changed files with 124 additions and 64 deletions

View file

@ -112,6 +112,12 @@ namespace MWBase
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const = 0; virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const = 0;
///< Is the given sound currently playing on the given object? ///< Is the given sound currently playing on the given object?
virtual void pauseAllSounds() = 0;
///< Pauses all currently playing sounds, including music.
virtual void resumeAllSounds() = 0;
///< Resumes all previously paused sounds.
virtual void update(float duration) = 0; virtual void update(float duration) = 0;
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0; virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up) = 0;

View file

@ -3,6 +3,7 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
@ -144,16 +145,12 @@ namespace MWRender
double get_audio_clock(VideoState *is) { double get_audio_clock(VideoState *is) {
double pts; double pts;
int hw_buf_size, bytes_per_sec, n;
pts = is->audio_clock; /* maintained in the audio thread */ pts = is->audio_clock; /* maintained in the audio thread */
hw_buf_size = is->audio_buf_size - is->audio_buf_index;
bytes_per_sec = 0;
n = is->audio_st->codec->channels * 2;
if(is->audio_st) { if(is->audio_st) {
bytes_per_sec = is->audio_st->codec->sample_rate * n; int n = is->audio_st->codec->channels * 2;
} int bytes_per_sec = is->audio_st->codec->sample_rate * n;
if(bytes_per_sec) { int hw_buf_size = is->audio_buf_size - is->audio_buf_index;
pts -= (double)hw_buf_size / bytes_per_sec; pts -= (double)hw_buf_size / bytes_per_sec;
} }
return pts; return pts;
@ -194,8 +191,8 @@ namespace MWRender
diff = get_audio_clock(is) - ref_clock; diff = get_audio_clock(is) - ref_clock;
if(diff < AV_NOSYNC_THRESHOLD) { if(diff < AV_NOSYNC_THRESHOLD) {
// accumulate the diffs // accumulate the diffs
is->audio_diff_cum = diff + is->audio_diff_avg_coef is->audio_diff_cum = diff + is->audio_diff_avg_coef *
* is->audio_diff_cum; is->audio_diff_cum;
if(is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) { if(is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
is->audio_diff_avg_count++; is->audio_diff_avg_count++;
} else { } else {
@ -327,9 +324,9 @@ namespace MWRender
} }
*/ */
void timer_callback (int delay, VideoState* is) void timer_callback (boost::system_time t, VideoState* is)
{ {
boost::this_thread::sleep (boost::posix_time::milliseconds(delay)); boost::this_thread::sleep (t);
is->refresh++; is->refresh++;
} }
@ -338,8 +335,8 @@ namespace MWRender
{ {
//SDL_AddTimer(delay, sdl_refresh_timer_cb, is); //SDL_AddTimer(delay, sdl_refresh_timer_cb, is);
//is->refresh_queue.push_back (delay); //is->refresh_queue.push_back (delay);
boost::system_time t = boost::get_system_time() + boost::posix_time::milliseconds(delay);
boost::thread (boost::bind(&timer_callback, delay, is)); boost::thread (boost::bind(&timer_callback, t, is));
} }
void video_display(VideoState *is) void video_display(VideoState *is)
@ -351,7 +348,8 @@ namespace MWRender
if (is->video_st->codec->width != 0 && is->video_st->codec->height != 0) if (is->video_st->codec->width != 0 && is->video_st->codec->height != 0)
{ {
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton ().getByName("VideoTexture"); Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton ().getByName("VideoTexture");
if (texture.isNull () || static_cast<int>(texture->getWidth()) != is->video_st->codec->width || static_cast<int>(texture->getHeight()) != is->video_st->codec->height) if (texture.isNull () || static_cast<int>(texture->getWidth()) != is->video_st->codec->width
|| static_cast<int>(texture->getHeight()) != is->video_st->codec->height)
{ {
Ogre::TextureManager::getSingleton ().remove ("VideoTexture"); Ogre::TextureManager::getSingleton ().remove ("VideoTexture");
texture = Ogre::TextureManager::getSingleton().createManual( texture = Ogre::TextureManager::getSingleton().createManual(
@ -448,8 +446,7 @@ namespace MWRender
/* wait until we have a new pic */ /* wait until we have a new pic */
{ {
boost::unique_lock<boost::mutex> lock(is->pictq_mutex); boost::unique_lock<boost::mutex> lock(is->pictq_mutex);
while(is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && while(is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !is->quit) {
!is->quit) {
is->pictq_cond.timed_wait(lock, boost::posix_time::milliseconds(1)); is->pictq_cond.timed_wait(lock, boost::posix_time::milliseconds(1));
} }
} }
@ -464,9 +461,9 @@ namespace MWRender
if(is->sws_context == NULL) { if(is->sws_context == NULL) {
int w = is->video_st->codec->width; int w = is->video_st->codec->width;
int h = is->video_st->codec->height; int h = is->video_st->codec->height;
is->sws_context = sws_getContext(w, h, is->sws_context = sws_getContext(w, h, is->video_st->codec->pix_fmt,
is->video_st->codec->pix_fmt, w, h, w, h, PIX_FMT_RGBA, SWS_BICUBIC,
PIX_FMT_RGBA, SWS_BICUBIC, NULL, NULL, NULL); NULL, NULL, NULL);
if(is->sws_context == NULL) if(is->sws_context == NULL)
throw std::runtime_error("Cannot initialize the conversion context!\n"); throw std::runtime_error("Cannot initialize the conversion context!\n");
} }
@ -576,8 +573,6 @@ namespace MWRender
av_free_packet(packet); av_free_packet(packet);
} }
SDL_CloseAudio();
av_free(pFrame); av_free(pFrame);
avpicture_free((AVPicture *)is->rgbaFrame); avpicture_free((AVPicture *)is->rgbaFrame);
@ -852,6 +847,7 @@ namespace MWRender
// Register all formats and codecs // Register all formats and codecs
av_register_all(); av_register_all();
MWBase::Environment::get().getSoundManager()->pauseAllSounds();
if(SDL_Init(SDL_INIT_AUDIO)) { if(SDL_Init(SDL_INIT_AUDIO)) {
throw std::runtime_error("Failed to initialize SDL"); throw std::runtime_error("Failed to initialize SDL");
} }
@ -892,6 +888,9 @@ namespace MWRender
delete mState; delete mState;
mState = NULL; mState = NULL;
SDL_CloseAudio();
MWBase::Environment::get().getSoundManager()->resumeAllSounds();
mRectangle->setVisible (false); mRectangle->setVisible (false);
MWBase::Environment::get().getWindowManager ()->removeGuiMode (MWGui::GM_Video); MWBase::Environment::get().getWindowManager ()->removeGuiMode (MWGui::GM_Video);

View file

@ -254,7 +254,7 @@ bool OpenAL_SoundStream::isPlaying()
alGetSourcei(mSource, AL_SOURCE_STATE, &state); alGetSourcei(mSource, AL_SOURCE_STATE, &state);
throwALerror(); throwALerror();
if(state == AL_PLAYING) if(state == AL_PLAYING || state == AL_PAUSED)
return true; return true;
return !mIsFinished; return !mIsFinished;
} }
@ -393,7 +393,7 @@ bool OpenAL_Sound::isPlaying()
alGetSourcei(mSource, AL_SOURCE_STATE, &state); alGetSourcei(mSource, AL_SOURCE_STATE, &state);
throwALerror(); throwALerror();
return state==AL_PLAYING; return state==AL_PLAYING || state==AL_PAUSED;
} }
void OpenAL_Sound::update() void OpenAL_Sound::update()
@ -504,8 +504,9 @@ void OpenAL_Output::init(const std::string &devname)
ALuint src = 0; ALuint src = 0;
alGenSources(1, &src); alGenSources(1, &src);
throwALerror(); throwALerror();
mFreeSources.push_back(src); mSources.push_back(src);
} }
mFreeSources.insert(mFreeSources.begin(), mSources.begin(), mSources.end());
} }
catch(std::exception &e) catch(std::exception &e)
{ {
@ -521,11 +522,10 @@ void OpenAL_Output::deinit()
{ {
mStreamThread->removeAll(); mStreamThread->removeAll();
while(!mFreeSources.empty()) mFreeSources.clear();
{ if(mSources.size() > 0)
alDeleteSources(1, &mFreeSources.front()); alDeleteSources(mSources.size(), &mSources[0]);
mFreeSources.pop_front(); mSources.clear();
}
mBufferRefs.clear(); mBufferRefs.clear();
mUnusedBuffers.clear(); mUnusedBuffers.clear();
@ -814,6 +814,33 @@ void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3
} }
void OpenAL_Output::pauseAllSounds()
{
IDVec sources = mSources;
IDDq::const_iterator iter = mFreeSources.begin();
while(iter != mFreeSources.end())
{
sources.erase(std::find(sources.begin(), sources.end(), *iter));
iter++;
}
if(sources.size() > 0)
alSourcePausev(sources.size(), &sources[0]);
}
void OpenAL_Output::resumeAllSounds()
{
IDVec sources = mSources;
IDDq::const_iterator iter = mFreeSources.begin();
while(iter != mFreeSources.end())
{
sources.erase(std::find(sources.begin(), sources.end(), *iter));
iter++;
}
if(sources.size() > 0)
alSourcePlayv(sources.size(), &sources[0]);
}
OpenAL_Output::OpenAL_Output(SoundManager &mgr) OpenAL_Output::OpenAL_Output(SoundManager &mgr)
: Sound_Output(mgr), mDevice(0), mContext(0), mBufferCacheMemSize(0), : Sound_Output(mgr), mDevice(0), mContext(0), mBufferCacheMemSize(0),
mLastEnvironment(Env_Normal), mStreamThread(new StreamThread) mLastEnvironment(Env_Normal), mStreamThread(new StreamThread)

View file

@ -21,6 +21,9 @@ namespace MWSound
ALCdevice *mDevice; ALCdevice *mDevice;
ALCcontext *mContext; ALCcontext *mContext;
typedef std::vector<ALuint> IDVec;
IDVec mSources;
typedef std::deque<ALuint> IDDq; typedef std::deque<ALuint> IDDq;
IDDq mFreeSources; IDDq mFreeSources;
IDDq mUnusedBuffers; IDDq mUnusedBuffers;
@ -49,6 +52,9 @@ namespace MWSound
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env); virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env);
virtual void pauseAllSounds();
virtual void resumeAllSounds();
OpenAL_Output& operator=(const OpenAL_Output &rhs); OpenAL_Output& operator=(const OpenAL_Output &rhs);
OpenAL_Output(const OpenAL_Output &rhs); OpenAL_Output(const OpenAL_Output &rhs);

View file

@ -31,6 +31,9 @@ namespace MWSound
virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) = 0; virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) = 0;
virtual void pauseAllSounds() = 0;
virtual void resumeAllSounds() = 0;
Sound_Output& operator=(const Sound_Output &rhs); Sound_Output& operator=(const Sound_Output &rhs);
Sound_Output(const Sound_Output &rhs); Sound_Output(const Sound_Output &rhs);

View file

@ -404,6 +404,19 @@ namespace MWSound
} }
void SoundManager::pauseAllSounds()
{
if(mOutput->isInitialized())
mOutput->pauseAllSounds();
}
void SoundManager::resumeAllSounds()
{
if(mOutput->isInitialized())
mOutput->resumeAllSounds();
}
void SoundManager::updateRegionSound(float duration) void SoundManager::updateRegionSound(float duration)
{ {
MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell(); MWWorld::Ptr::CellStore *current = MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell();

View file

@ -127,6 +127,12 @@ namespace MWSound
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const; virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const;
///< Is the given sound currently playing on the given object? ///< Is the given sound currently playing on the given object?
virtual void pauseAllSounds();
///< Pauses all currently playing sounds, including music.
virtual void resumeAllSounds();
///< Resumes all previously paused sounds.
virtual void update(float duration); virtual void update(float duration);
virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up); virtual void setListenerPosDir(const Ogre::Vector3 &pos, const Ogre::Vector3 &dir, const Ogre::Vector3 &up);