Add support for WWXD keyframes in qpfile format

This commit is contained in:
Ryan Lucia 2018-05-10 03:28:51 -04:00
parent 747525142a
commit a621072e7d
3 changed files with 41 additions and 10 deletions

View File

@ -19,6 +19,8 @@
#include "libaegisub/keyframe.h"
#include <sstream>
#include "libaegisub/io.h"
#include "libaegisub/line_iterator.h"
@ -35,10 +37,9 @@ std::vector<int> agi_keyframes(std::istream &file) {
return std::vector<int>(agi::line_iterator<int>(file), agi::line_iterator<int>());
}
std::vector<int> other_keyframes(std::istream &file, char (*func)(std::string const&)) {
std::vector<int> enumerated_keyframes(std::istream &file, char (*func)(std::string const&)) {
int count = 0;
std::vector<int> ret;
agi::line_iterator<std::string> end;
for (auto line : agi::line_iterator<std::string>(file)) {
char c = tolower(func(line));
if (c == 'i')
@ -49,6 +50,16 @@ std::vector<int> other_keyframes(std::istream &file, char (*func)(std::string co
return ret;
}
std::vector<int> indexed_keyframes(std::istream &file, int (*func)(std::string const&)) {
std::vector<int> ret;
for (auto line : agi::line_iterator<std::string>(file)) {
int frame_no = func(line);
if (frame_no >= 0)
ret.push_back(frame_no);
}
return ret;
}
char xvid(std::string const& line) {
return line.empty() ? 0 : line[0];
}
@ -68,6 +79,20 @@ char x264(std::string const& line) {
if (pos == line.npos || pos + 5 >= line.size()) return 0;
return line[pos + 5];
}
int wwxd(std::string const& line) {
if (line.empty() || line[0] == '#')
return -1;
std::istringstream ss(line);
int frame_no;
char frame_type;
ss >> frame_no >> frame_type;
if (ss.fail())
throw agi::keyframe::KeyframeFormatParseError("WWXD keyframe file not in qpfile format");
if (frame_type == 'I')
return frame_no;
return -1;
}
}
namespace agi { namespace keyframe {
@ -87,13 +112,14 @@ std::vector<int> Load(agi::fs::path const& filename) {
getline(is, header);
if (header == "# keyframe format v1") return agi_keyframes(is);
if (boost::starts_with(header, "# XviD 2pass stat file")) return other_keyframes(is, xvid);
if (boost::starts_with(header, "# ffmpeg 2-pass log file, using xvid codec")) return other_keyframes(is, xvid);
if (boost::starts_with(header, "# avconv 2-pass log file, using xvid codec")) return other_keyframes(is, xvid);
if (boost::starts_with(header, "##map version")) return other_keyframes(is, divx);
if (boost::starts_with(header, "#options:")) return other_keyframes(is, x264);
if (boost::starts_with(header, "# XviD 2pass stat file")) return enumerated_keyframes(is, xvid);
if (boost::starts_with(header, "# ffmpeg 2-pass log file, using xvid codec")) return enumerated_keyframes(is, xvid);
if (boost::starts_with(header, "# avconv 2-pass log file, using xvid codec")) return enumerated_keyframes(is, xvid);
if (boost::starts_with(header, "##map version")) return enumerated_keyframes(is, divx);
if (boost::starts_with(header, "#options:")) return enumerated_keyframes(is, x264);
if (boost::starts_with(header, "# WWXD log file, using qpfile format")) return indexed_keyframes(is, wwxd);
throw Error("Unknown keyframe format");
throw UnknownKeyframeFormatError("File header does not match any known formats");
}
} }

View File

@ -29,6 +29,7 @@ namespace agi {
/// @param keyframes List of keyframes to save
void Save(agi::fs::path const& filename, std::vector<int> const& keyframes);
DEFINE_EXCEPTION(Error, Exception);
DEFINE_EXCEPTION(KeyframeFormatParseError, agi::InvalidInputException);
DEFINE_EXCEPTION(UnknownKeyframeFormatError, agi::InvalidInputException);
}
}

View File

@ -391,10 +391,14 @@ void Project::LoadKeyframes(agi::fs::path path) {
ShowError(e.GetMessage());
config::mru->Remove("Keyframes", path);
}
catch (agi::keyframe::Error const& e) {
catch (agi::keyframe::KeyframeFormatParseError const& e) {
ShowError("Failed to parse keyframes file: " + e.GetMessage());
config::mru->Remove("Keyframes", path);
}
catch (agi::keyframe::UnknownKeyframeFormatError const& e) {
ShowError("Keyframes file in unknown format: " + e.GetMessage());
config::mru->Remove("Keyframes", path);
}
}
void Project::CloseKeyframes() {