Don't load the FPS from Aegisub keyframes. The format breaks vfr and setting the fps should be done with timecode files.

Originally committed to SVN as r5900.
This commit is contained in:
Thomas Goyne 2011-11-20 17:35:00 +00:00
parent 2f85e5b398
commit 893ec95841
4 changed files with 28 additions and 47 deletions

View file

@ -32,21 +32,19 @@
#include "libaegisub/keyframe.h"
#include "libaegisub/vfr.h"
static std::pair<std::vector<int>, double> agi_keyframes(std::istream &file) {
namespace {
std::vector<int> agi_keyframes(std::istream &file) {
double fps;
std::string fps_str;
file >> fps_str;
file >> fps;
if (!file.good() || fps_str != "fps")
throw agi::keyframe::Error("FPS not found");
std::vector<int> ret;
std::copy(std::istream_iterator<int>(file), std::istream_iterator<int>(), std::back_inserter(ret));
return make_pair(ret, fps);
copy(std::istream_iterator<int>(file), std::istream_iterator<int>(), back_inserter(ret));
return ret;
}
static std::pair<std::vector<int>, double> other_keyframes(std::istream &file, char (*func)(std::string const&)) {
std::vector<int> other_keyframes(std::istream &file, char (*func)(std::string const&)) {
int count = 0;
std::vector<int> ret;
agi::line_iterator<std::string> end;
@ -59,7 +57,7 @@ static std::pair<std::vector<int>, double> other_keyframes(std::istream &file, c
++count;
}
}
return std::make_pair(ret, 0);
return ret;
}
char xvid(std::string const& line) {
@ -83,23 +81,22 @@ char x264(std::string const& line) {
}
template<int N>
static bool starts_with(std::string const& str, const char (&test)[N]) {
bool starts_with(std::string const& str, const char (&test)[N]) {
if (str.size() < N) return false;
return std::mismatch(str.begin(), str.begin() + N - 1, test).first == str.begin() + N - 1;
}
}
namespace agi { namespace keyframe {
void Save(std::string const& filename, std::vector<int> const& keyframes, vfr::Framerate const& fps) {
void Save(std::string const& filename, std::vector<int> const& keyframes) {
io::Save file(filename);
std::ofstream& of = file.Get();
of << "# keyframe format v1" << std::endl;
of << "fps " << fps.FPS() << std::endl;
std::copy(keyframes.begin(), keyframes.end(), std::ostream_iterator<int>(of, "\n"));
of << "fps " << 0 << std::endl;
copy(keyframes.begin(), keyframes.end(), std::ostream_iterator<int>(of, "\n"));
}
std::pair<std::vector<int>, double> Load(std::string const& filename) {
std::vector<int> Load(std::string const& filename) {
std::auto_ptr<std::ifstream> file(io::Open(filename));
std::istream &is(*file.get());

View file

@ -30,13 +30,12 @@ namespace agi {
namespace keyframe {
/// @brief Load a keyframe file
/// @param filename File to load
/// @return Pair of frame numbers which are keyframes and fps
std::pair<std::vector<int>, double> Load(std::string const& filename);
/// @return List of frame numbers which are keyframes
std::vector<int> Load(std::string const& filename);
/// @brief Save keyframes to a file
/// @param filename File to save to
/// @param keyframes List of keyframes to save
/// @param fps Current fps that goes with the keyframes
void Save(std::string const& filename, std::vector<int> const& keyframes, vfr::Framerate const& fps);
void Save(std::string const& filename, std::vector<int> const& keyframes);
DEFINE_SIMPLE_EXCEPTION_NOINNER(Error, Exception, "keyframe/error")
}

View file

@ -482,16 +482,9 @@ void VideoContext::SetAspectRatio(int type, double value) {
void VideoContext::LoadKeyframes(wxString filename) {
if (filename == keyFramesFilename || filename.empty()) return;
try {
std::pair<std::vector<int>, double> kf = agi::keyframe::Load(STD_STR(filename));
keyFrames = kf.first;
keyFrames = agi::keyframe::Load(STD_STR(filename));
keyFramesFilename = filename;
KeyframesOpen(keyFrames);
if (kf.second != 0.) {
ovrFPS = agi::vfr::Framerate(kf.second);
ovrTimecodeFile.clear();
OnSubtitlesCommit();
TimecodesOpen(ovrFPS);
}
config::mru->Add("Keyframes", STD_STR(filename));
}
catch (agi::keyframe::Error const& err) {
@ -505,18 +498,16 @@ void VideoContext::LoadKeyframes(wxString filename) {
}
void VideoContext::SaveKeyframes(wxString filename) {
agi::keyframe::Save(STD_STR(filename), GetKeyFrames(), FPS());
agi::keyframe::Save(STD_STR(filename), GetKeyFrames());
config::mru->Add("Keyframes", STD_STR(filename));
}
void VideoContext::CloseKeyframes() {
keyFramesFilename.clear();
if (videoProvider.get()) {
if (videoProvider)
keyFrames = videoProvider->GetKeyFrames();
}
else {
else
keyFrames.clear();
}
KeyframesOpen(keyFrames);
}

View file

@ -20,7 +20,6 @@
#include <libaegisub/access.h>
#include <libaegisub/keyframe.h>
#include <libaegisub/vfr.h>
#include <fstream>
#include <iterator>
@ -33,15 +32,13 @@ using namespace util;
TEST(lagi_keyframe, save) {
std::vector<int> kf = make_vector<int>(5, 0, 5, 70, 180, 300);
agi::vfr::Framerate fps(80.);
ASSERT_NO_THROW(Save("data/keyframe/out.txt", kf, fps));
ASSERT_NO_THROW(Save("data/keyframe/out.txt", kf));
std::pair<std::vector<int>, double> res;
std::vector<int> res;
ASSERT_NO_THROW(res = Load("data/keyframe/out.txt"));
EXPECT_TRUE(kf == res.first);
EXPECT_EQ(80., res.second);
EXPECT_TRUE(kf == res);
}
TEST(lagi_keyframe, bad_files) {
@ -118,11 +115,10 @@ TEST(lagi_keyframe, xvid) {
33880, 33923, 33969, 33982, 33991, 34010, 34025, 34043, 34055, 34065,
34082, 34102, 34112, 34122, 34142, 34158, 34170, 34187, 34211);
std::pair<std::vector<int>, double> res;
std::vector<int> res;
ASSERT_NO_THROW(res = Load("data/keyframe/xvid.txt"));
EXPECT_TRUE(expected == res.first);
EXPECT_EQ(0., res.second);
EXPECT_TRUE(expected == res);
}
@ -130,20 +126,18 @@ TEST(lagi_keyframe, x264) {
std::vector<int> expected(41);
for (size_t i = 0; i < 41; ++i) expected[i] = i * 250;
std::pair<std::vector<int>, double> res;
std::vector<int> res;
ASSERT_NO_THROW(res = Load("data/keyframe/x264.log"));
EXPECT_TRUE(expected == res.first);
EXPECT_EQ(0., res.second);
EXPECT_TRUE(expected == res);
}
TEST(lagi_keyframe, aegi) {
std::vector<int> expected(135);
for (size_t i = 0; i < 135; ++i) expected[i] = i * 250;
std::pair<std::vector<int>, double> res;
std::vector<int> res;
ASSERT_NO_THROW(res = Load("data/keyframe/aegi.txt"));
EXPECT_TRUE(expected == res.first);
EXPECT_EQ(25., res.second);
EXPECT_TRUE(expected == res);
}