forked from pixop/video-compare
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
136 lines (116 loc) · 5.32 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#define SDL_MAIN_HANDLED
#include <algorithm>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <string>
#include <vector>
#include "argagg.h"
#include "video_compare.h"
#ifdef _WIN32
#include <Windows.h>
// Credits to Mircea Neacsu, https://github.com/neacsum/utf8
char** get_argv(int* argc, char** argv) {
char** uargv = nullptr;
wchar_t** wargv = CommandLineToArgvW(GetCommandLineW(), argc);
if (wargv) {
uargv = new char*[*argc];
for (int i = 0; i < *argc; i++) {
int nc = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, 0, 0, 0, 0);
uargv[i] = new char[nc + 1];
WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, uargv[i], nc, 0, 0);
}
LocalFree(wargv);
}
return uargv;
}
void free_argv(int argc, char** argv) {
for (int i = 0; i < argc; i++) {
delete argv[i];
}
delete argv;
}
#else
#define UNUSED(x) (void)(x)
char** get_argv(const int* argc, char** argv) {
UNUSED(argc);
return argv;
}
void free_argv(int argc, char** argv) {
UNUSED(argc);
UNUSED(argv);
}
#endif
int main(int argc, char** argv) {
char** argv_decoded = get_argv(&argc, argv);
int exit_code = 0;
try {
argagg::parser argparser{{{"help", {"-h", "--help"}, "show help", 0},
{"high-dpi", {"-d", "--high-dpi"}, "allow high DPI mode for e.g. displaying UHD content on Retina displays", 0},
{"display-mode", {"-m", "--mode"}, "display mode (layout), 'split' for split screen (default), 'vstack' for vertical stack, 'hstack' for horizontal stack", 1},
{"window-size", {"-w", "--window-size"}, "override window size, specified as [width]x[height] (e.g. 800x600, 1280x or x480)", 1},
{"time-shift", {"-t", "--time-shift"}, "shift the time stamps of the right video by a user-specified number of seconds (e.g. 0.150, -0.1 or 1)", 1},
{"left-filters", {"-l", "--left-filters"}, "specify a comma-separated list of FFmpeg filters to be applied to the left video (e.g. format=gray,crop=iw:ih-240)", 1},
{"right-filters", {"-r", "--right-filters"}, "specify a comma-separated list of FFmpeg filters to be applied to the right video (e.g. yadif,hqdn3d,pad=iw+320:ih:160:0)", 1}}};
argagg::parser_results args;
args = argparser.parse(argc, argv_decoded);
std::tuple<int, int> window_size(-1, -1);
double time_shift_ms = 0;
Display::Mode display_mode = Display::Mode::split;
std::string left_video_filters, right_video_filters;
if (args["help"] || args.count() == 0) {
std::ostringstream usage;
usage << "video-compare 20230223-github Copyright (c) 2018-2023 Jon Frydensbjerg, the video-compare community" << std::endl << std::endl;
usage << "Usage: " << argv[0] << " [OPTIONS]... FILE1 FILE2" << std::endl << std::endl;
argagg::fmt_ostream fmt(std::cerr);
fmt << usage.str() << argparser;
} else {
if (args.pos.size() != 2) {
throw std::logic_error{"Two FFmpeg compatible video files must be supplied"};
}
if (args["display-mode"]) {
const std::string display_mode_arg = args["display-mode"];
if (display_mode_arg == "split") {
display_mode = Display::Mode::split;
} else if (display_mode_arg == "vstack") {
display_mode = Display::Mode::vstack;
} else if (display_mode_arg == "hstack") {
display_mode = Display::Mode::hstack;
} else {
throw std::logic_error{"Cannot parse display mode argument (valid options: split, vstack, hstack)"};
}
}
if (args["window-size"]) {
const std::string window_size_arg = args["window-size"];
const std::regex window_size_re("(\\d*)x(\\d*)");
if (!std::regex_match(window_size_arg, window_size_re)) {
throw std::logic_error{"Cannot parse window size argument (required format: [width]x[height], e.g. 800x600, 1280x or x480)"};
}
const std::regex delimiter_re("x");
auto const token_vec = std::vector<std::string>(std::sregex_token_iterator{begin(window_size_arg), end(window_size_arg), delimiter_re, -1}, std::sregex_token_iterator{});
window_size = std::make_tuple(!token_vec[0].empty() ? std::stoi(token_vec[0]) : -1, token_vec.size() == 2 ? std::stoi(token_vec[1]) : -1);
}
if (args["time-shift"]) {
const std::string time_shift_arg = args["time-shift"];
const std::regex time_shift_re("^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$");
if (!std::regex_match(time_shift_arg, time_shift_re)) {
throw std::logic_error{"Cannot parse time shift argument; must be a valid number in seconds, e.g. 1 or -0.333"};
}
time_shift_ms = std::stod(time_shift_arg) * 1000.0;
}
if (args["left-filters"]) {
left_video_filters = static_cast<const std::string&>(args["left-filters"]);
}
if (args["right-filters"]) {
right_video_filters = static_cast<const std::string&>(args["right-filters"]);
}
VideoCompare compare{display_mode, args["high-dpi"], window_size, time_shift_ms, args.pos[0], left_video_filters, args.pos[1], right_video_filters};
compare();
}
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
exit_code = -1;
}
free_argv(argc, argv_decoded);
return exit_code;
}