Add support for WWXD keyframes in qpfile format
This commit is contained in:
parent
747525142a
commit
a621072e7d
3 changed files with 41 additions and 10 deletions
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "libaegisub/keyframe.h"
|
#include "libaegisub/keyframe.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "libaegisub/io.h"
|
#include "libaegisub/io.h"
|
||||||
#include "libaegisub/line_iterator.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>());
|
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;
|
int count = 0;
|
||||||
std::vector<int> ret;
|
std::vector<int> ret;
|
||||||
agi::line_iterator<std::string> end;
|
|
||||||
for (auto line : agi::line_iterator<std::string>(file)) {
|
for (auto line : agi::line_iterator<std::string>(file)) {
|
||||||
char c = tolower(func(line));
|
char c = tolower(func(line));
|
||||||
if (c == 'i')
|
if (c == 'i')
|
||||||
|
@ -49,6 +50,16 @@ std::vector<int> other_keyframes(std::istream &file, char (*func)(std::string co
|
||||||
return ret;
|
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) {
|
char xvid(std::string const& line) {
|
||||||
return line.empty() ? 0 : line[0];
|
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;
|
if (pos == line.npos || pos + 5 >= line.size()) return 0;
|
||||||
return line[pos + 5];
|
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 {
|
namespace agi { namespace keyframe {
|
||||||
|
@ -87,13 +112,14 @@ std::vector<int> Load(agi::fs::path const& filename) {
|
||||||
getline(is, header);
|
getline(is, header);
|
||||||
|
|
||||||
if (header == "# keyframe format v1") return agi_keyframes(is);
|
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, "# XviD 2pass stat file")) return enumerated_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, "# 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 other_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 other_keyframes(is, divx);
|
if (boost::starts_with(header, "##map version")) return enumerated_keyframes(is, divx);
|
||||||
if (boost::starts_with(header, "#options:")) return other_keyframes(is, x264);
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace agi {
|
||||||
/// @param keyframes List of keyframes to save
|
/// @param keyframes List of keyframes to save
|
||||||
void Save(agi::fs::path const& filename, std::vector<int> const& keyframes);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -391,10 +391,14 @@ void Project::LoadKeyframes(agi::fs::path path) {
|
||||||
ShowError(e.GetMessage());
|
ShowError(e.GetMessage());
|
||||||
config::mru->Remove("Keyframes", path);
|
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());
|
ShowError("Failed to parse keyframes file: " + e.GetMessage());
|
||||||
config::mru->Remove("Keyframes", path);
|
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() {
|
void Project::CloseKeyframes() {
|
||||||
|
|
Loading…
Reference in a new issue