|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-05 17:44:00
|
Module: performous
Branch: master
Commit: d71590998afdb63e9f93148316f649ed94e5208e
Author: Lasse Karkkainen <tro...@tr...>
Date: Sun Jul 5 20:41:05 2009 +0300
Make jukebox mode reload the song at end of song even if the next song is the same as the current one (if there is only one song or if the next song uses the same MP3).
Fix video latency compensation in song selector by changing the interface so that videogap is passed to Video constructor.
Adjust video seeking parameters to better workaround ffmpeg seeking issues.
Make video use AnimValue for its alpha blending (smoother and more reliable now).
---
game/audio.cc | 11 +++++++++--
game/audio.hh | 2 ++
game/screen_sing.cc | 4 ++--
game/screen_songs.cc | 12 +++++++++---
game/video.cc | 18 +++++++++---------
game/video.hh | 11 +++++------
6 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/game/audio.cc b/game/audio.cc
index 42f0b05..09aa93f 100644
--- a/game/audio.cc
+++ b/game/audio.cc
@@ -118,11 +118,18 @@ void Audio::playSample(std::string filename) {
}
}
-void Audio::seek(double seek_dist) {
+void Audio::seek(double offset) {
boost::recursive_mutex::scoped_lock l(m_mutex);
if (m_streams.empty()) return;
Stream& s = m_streams.back();
- int position = clamp(s.mpeg.position() + seek_dist, 0.0, s.mpeg.duration() - 1.0);
+ seekPos(s.mpeg.position() + offset);
+}
+
+void Audio::seekPos(double pos) {
+ boost::recursive_mutex::scoped_lock l(m_mutex);
+ if (m_streams.empty()) return;
+ Stream& s = m_streams.back();
+ int position = clamp(pos, 0.0, s.mpeg.duration() - 1.0);
s.mpeg.seek(position);
s.prebuffering = true;
m_paused = false;
diff --git a/game/audio.hh b/game/audio.hh
index b63d2a8..ba3d2af 100644
--- a/game/audio.hh
+++ b/game/audio.hh
@@ -139,6 +139,8 @@ class Audio {
* @param seek_dist number of seconds to seek from current position
*/
void seek(double seek_dist);
+ /** Seek to specific time **/
+ void seekPos(double pos);
/** Is the music playing (loaded and not at EOF yet, pause doesn't matter) **/
bool isPlaying() const;
/** Get the current position. If not known or nothing is playing, NaN is returned. **/
diff --git a/game/screen_sing.cc b/game/screen_sing.cc
index 936a3ba..c2a6b01 100644
--- a/game/screen_sing.cc
+++ b/game/screen_sing.cc
@@ -25,7 +25,7 @@ void ScreenSing::enter() {
std::cerr << e.what() << std::endl;
}
}
- if (!song.video.empty() && config["graphic/video"].b()) m_video.reset(new Video(song.path + song.video));
+ if (!song.video.empty() && config["graphic/video"].b()) m_video.reset(new Video(song.path + song.video, song.videoGap));
m_pause_icon.reset(new Surface(getThemePath("sing_pause.svg")));
m_score_text[0].reset(new SvgTxtThemeSimple(getThemePath("sing_score_text.svg"), config["graphic/text_lod"].f()));
m_score_text[1].reset(new SvgTxtThemeSimple(getThemePath("sing_score_text.svg"), config["graphic/text_lod"].f()));
@@ -131,7 +131,7 @@ void ScreenSing::draw() {
if (ar > arMax || (m_video && ar > arMin)) fillBG(); // Fill white background to avoid black borders
m_background->draw();
} else fillBG();
- if (m_video) { m_video->render(time + song.videoGap); double tmp = m_video->dimensions().ar(); if (tmp > 0.0) ar = tmp; }
+ if (m_video) { m_video->render(time); double tmp = m_video->dimensions().ar(); if (tmp > 0.0) ar = tmp; }
ar = clamp(ar, arMin, arMax);
double offset = 0.5 / ar + 0.2;
theme->bg_bottom.dimensions.fixedWidth(1.0).bottom(offset);
diff --git a/game/screen_songs.cc b/game/screen_songs.cc
index 0800ccb..aac50e1 100644
--- a/game/screen_songs.cc
+++ b/game/screen_songs.cc
@@ -101,6 +101,7 @@ void ScreenSongs::draw() {
if (m_video.get()) m_video->render(time);
if (!m_jukebox) theme->bg.draw();
std::string music, songbg, video;
+ double videoGap = 0.0;
std::ostringstream oss_song, oss_order;
// Test if there are no songs
if (m_songs.empty()) {
@@ -143,7 +144,7 @@ void ScreenSongs::draw() {
}
if (!song.mp3.empty()) music = song.path + song.mp3;
if (!song.background.empty()) songbg = song.path + song.background;
- if (!song.video.empty()) video = song.path + song.video;
+ if (!song.video.empty()) { video = song.path + song.video; videoGap = song.videoGap; }
}
if (m_jukebox) drawJukebox();
else {
@@ -158,11 +159,16 @@ void ScreenSongs::draw() {
m_songbg.reset(); m_video.reset();
if (music.empty()) m_audio.fadeout(); else m_audio.playPreview(music, m_jukebox ? 0.0 : 30.0);
if (!songbg.empty()) try { m_songbg.reset(new Surface(songbg)); } catch (std::exception const&) {}
- if (!video.empty() && config["graphic/video"].b()) m_video.reset(new Video(video));
+ if (!video.empty() && config["graphic/video"].b()) m_video.reset(new Video(video, videoGap));
m_playing = music;
}
if (m_jukebox) {
- if (!m_audio.isPlaying() || m_audio.getPosition() + 1.4 > m_audio.getLength()) m_songs.advance(1); // Switch if at song end
+ // Switch if at song end
+ if (!m_audio.isPlaying() || m_audio.getPosition() + 1.4 > m_audio.getLength()) {
+ m_songs.advance(1);
+ // Force reload of data
+ m_playing.clear();
+ }
} else if (!m_audio.isPaused() && m_playTimer.get() > IDLE_TIMEOUT) { // Switch if song hasn't changed for IDLE_TIMEOUT seconds
if (!m_search.text.empty()) { m_search.text.clear(); m_songs.setFilter(m_search.text); }
m_songs.random();
diff --git a/game/video.cc b/game/video.cc
index 44570aa..afe848e 100644
--- a/game/video.cc
+++ b/game/video.cc
@@ -2,9 +2,10 @@
#include "configuration.hh"
#include <cmath>
-Video::Video(std::string const& _videoFile): m_mpeg(true, false, _videoFile), m_surfaceTime(), m_lastTime(), m_alpha() {}
+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) {
+ time += m_videoGap;
VideoFrame& fr = m_videoFrame;
// Time to switch frame?
if (!fr.data.empty() && time >= fr.timestamp) {
@@ -13,19 +14,18 @@ void Video::render(double time) {
m_surfaceTime = fr.timestamp;
}
double tdist = std::abs(m_surfaceTime - time);
- m_alpha += (tdist < 0.4 ? 0.02f : -0.02f);
- if (m_alpha <= 0.0f) m_alpha = 0.0f;
- else {
- if (m_alpha > 1.2f) m_alpha = 1.2f;
- if (m_alpha < 1.0f) glColor4f(1.0f, 1.0f, 1.0f, m_alpha);
+ m_alpha.setTarget(tdist < 0.4 ? 1.2f : -0.5f);
+ float alpha = clamp(m_alpha.get());
+ if (alpha > 0.0f) {
+ if (alpha < 1.0f) glColor4f(1.0f, 1.0f, 1.0f, alpha);
m_surface.draw();
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ if (alpha < 1.0f) glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
// 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 - 0.4 || (!fr.data.empty() && time > fr.timestamp + 2.0)) {
- m_mpeg.seek(time - 0.3);
+ if (time < m_lastTime - 1.0 || (!fr.data.empty() && time > fr.timestamp + 7.0)) {
+ m_mpeg.seek(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 828ba99..c1ed3ea 100644
--- a/game/video.hh
+++ b/game/video.hh
@@ -1,6 +1,6 @@
-#ifndef PERFORMOUS_VIDEO_HH
-#define PERFORMOUS_VIDEO_HH
+#pragma once
+#include "animvalue.hh"
#include "surface.hh"
#include "ffmpeg.hh"
#include <string>
@@ -9,7 +9,7 @@
class Video {
public:
/// opens given video file
- Video(std::string const& videoFile);
+ Video(std::string const& videoFile, double videoGap = 0.0);
/// renders video
void render(double time);
/// returns Dimensions of video clip
@@ -19,12 +19,11 @@ class Video {
private:
FFmpeg m_mpeg;
+ double m_videoGap;
VideoFrame m_videoFrame;
Surface m_surface;
double m_surfaceTime;
double m_lastTime;
- float m_alpha;
+ AnimValue m_alpha;
};
-#endif
-
|