|
From: Lasse Kärkkäi. <tr...@us...> - 2012-03-26 01:20:29
|
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Mar 26 04:19:06 2012 +0300
Add a separate pass for preparing a screen, for slow operations that we don't want to do in draw(), and use that for loading the next video frame.
---
game/main.cc | 1 +
game/screen.hh | 4 ++++
game/screen_sing.cc | 7 ++++++-
game/screen_sing.hh | 1 +
game/screenmanager.cc | 4 ++++
game/video.cc | 22 ++++++++++++----------
game/video.hh | 4 ++--
7 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/game/main.cc b/game/main.cc
index a0bcc10..45f3a08 100644
--- a/game/main.cc
+++ b/game/main.cc
@@ -185,6 +185,7 @@ void mainLoop(std::string const& songlist) {
glFinish();
prof("swap");
updateSurfaces();
+ sm.prepareScreen();
glFinish();
prof("surfaces");
if (config["graphic/fps"].b()) {
diff --git a/game/screen.hh b/game/screen.hh
index 64d3e29..5c3e27a 100644
--- a/game/screen.hh
+++ b/game/screen.hh
@@ -19,6 +19,8 @@ class Screen {
virtual ~Screen() {}
/// eventhandler
virtual void manageEvent(SDL_Event event) = 0;
+ /// prepare screen for drawing
+ virtual void prepare() {}
/// draws screen
virtual void draw() = 0;
/// enters screen
@@ -49,6 +51,8 @@ class ScreenManager: public Singleton <ScreenManager> {
void activateScreen(std::string const& name);
/// Does actual switching of screens (if necessary)
void updateScreen();
+ /// Prepare (slow loading operations) of the current screen for rendering
+ void prepareScreen();
/// Draws the current screen and possible transition effects
void drawScreen();
/// Reload OpenGL resources (after fullscreen toggle etc)
diff --git a/game/screen_sing.cc b/game/screen_sing.cc
index 7b16fb4..2a6bbd3 100644
--- a/game/screen_sing.cc
+++ b/game/screen_sing.cc
@@ -399,6 +399,11 @@ namespace {
}
+void ScreenSing::prepare() {
+ double time = m_audio.getPosition();
+ if (m_video) m_video->prepare(time);
+}
+
void ScreenSing::draw() {
// Get the time in the song
double length = m_audio.getLength();
@@ -432,7 +437,7 @@ void ScreenSing::draw() {
// Webcam
if (m_cam && config["graphic/webcam"].b()) m_cam->render();
// Video
- if (m_video /* && (!m_cam || !m_cam->is_good()) */) {
+ if (m_video) {
m_video->render(time); double tmp = m_video->dimensions().ar(); if (tmp > 0.0) ar = tmp;
}
// Top/bottom borders
diff --git a/game/screen_sing.hh b/game/screen_sing.hh
index a5a5a74..9d7438d 100644
--- a/game/screen_sing.hh
+++ b/game/screen_sing.hh
@@ -55,6 +55,7 @@ class ScreenSing: public Screen {
void exit();
void reloadGL();
void manageEvent(SDL_Event event);
+ void prepare();
void draw();
void setSong (boost::shared_ptr<Song> song_)
diff --git a/game/screenmanager.cc b/game/screenmanager.cc
index f3b30f7..5e1bb15 100644
--- a/game/screenmanager.cc
+++ b/game/screenmanager.cc
@@ -43,6 +43,10 @@ Screen* ScreenManager::getScreen(std::string const& name) {
}
}
+void ScreenManager::prepareScreen() {
+ getCurrentScreen()->prepare();
+}
+
void ScreenManager::drawScreen() {
getCurrentScreen()->draw();
drawLogo();
diff --git a/game/video.cc b/game/video.cc
index 09c104f..7adca6a 100644
--- a/game/video.cc
+++ b/game/video.cc
@@ -1,12 +1,11 @@
#include "video.hh"
#include "util.hh"
-
#include <cmath>
Video::Video(std::string const& _videoFile, double videoGap): m_mpeg(true, false, _videoFile), m_videoGap(videoGap), m_surfaceTime(), m_lastTime(), m_alpha(-0.5, 1.5) {}
-void Video::render(double time) {
+void Video::prepare(double time) {
time += m_videoGap;
VideoFrame& fr = m_videoFrame;
// Time to switch frame?
@@ -18,6 +17,17 @@ void Video::render(double time) {
m_surface.load(bitmap);
m_surfaceTime = fr.timestamp;
}
+ // Preload the next future frame
+ if (fr.data.empty()) while (m_mpeg.videoQueue.tryPop(fr) && fr.timestamp < time) {};
+ // Do a seek before next render, if required
+ if (time < m_lastTime - 1.0 || (!fr.data.empty() && time > fr.timestamp + 7.0)) {
+ m_mpeg.seek(std::max(0.0, time - 5.0)); // -5 to workaround ffmpeg inaccurate seeking
+ fr.data.clear();
+ }
+ m_lastTime = time;
+}
+
+void Video::render(double time) {
double tdist = std::abs(m_surfaceTime - time);
m_alpha.setTarget(tdist < 0.4 ? 1.2f : -0.5f);
float alpha = clamp(m_alpha.get());
@@ -33,13 +43,5 @@ void Video::render(double time) {
m_surface.draw();
}
}
- // Preload the next future frame
- if (fr.data.empty()) while (m_mpeg.videoQueue.tryPop(fr) && fr.timestamp < time) {};
- // Do a seek before next render, if required
- if (time < m_lastTime - 1.0 || (!fr.data.empty() && time > fr.timestamp + 7.0)) {
- m_mpeg.seek(std::max(0.0, time - 5.0)); // -5 to workaround ffmpeg inaccurate seeking
- fr.data.clear();
- }
- m_lastTime = time;
}
diff --git a/game/video.hh b/game/video.hh
index c1ed3ea..2390991 100644
--- a/game/video.hh
+++ b/game/video.hh
@@ -10,8 +10,8 @@ class Video {
public:
/// opens given video file
Video(std::string const& videoFile, double videoGap = 0.0);
- /// renders video
- void render(double time);
+ void prepare(double time); ///< Load the current video frame into a texture
+ void render(double time); ///< Render the prepared video frame
/// returns Dimensions of video clip
Dimensions& dimensions() { return m_surface.dimensions; }
/// returns Dimensions of video clip
|