Skip to content

Commit 25c0216

Browse files
authored
Merge pull request #3 from moeoverflow/feature/windows-build
Feature/windows build
2 parents d9299f1 + df6c839 commit 25c0216

File tree

7 files changed

+165
-24
lines changed

7 files changed

+165
-24
lines changed

README.md

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,78 @@ pacman -S hdf5
9292
pacman -S jsoncpp
9393
```
9494

95-
#### Compile & Build
95+
##### Windows MinGW
96+
97+
```shell
98+
# - MinGW build require tool MSYS2, you sould download and install it first, then use pacman in MSYS2 Enviroment
99+
#
100+
# - Assume you're building to mingw64, if you'd like to build to mingw32, replace `mingw-w64-x86_64` with `mingw-w64-i686`
101+
#
102+
# - Some packages are updated and not compatible, so some of the steps are using `pacman -U` to install specific version
103+
# packages with USTC Mirrors, you can change `https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/` to other sources.
104+
105+
# Build deps
106+
pacman -S libintl mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-make
107+
108+
# Boost
109+
# - It seems that when using Boost 1.66+ will cause build fail
110+
pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz
111+
112+
# OpenCV
113+
pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/mingw-w64-x86_64-opencv-3.4.3-2-any.pkg.tar.xz
114+
pacman -S mingw-w64-x86_64-hdf5
115+
116+
# Jsoncpp
117+
# - JSONCPP comes with cmake, so if you've install cmake manually, you're not needed to install JSONCPP again
118+
pacman -S mingw-w64-x86_64-jsoncpp jsoncpp-devel
119+
120+
# FFmpeg
121+
# - Some dll files are missing in MSYS2 MinGW64 FFmpeg package, so you should download it from other builds
122+
# - You can also download it later, as it's not build dependency (but runtime dependency)
123+
# pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/mingw-w64-x86_64-ffmpeg-3.4.2-1-any.pkg.tar.xz
124+
wget https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-3.4.2-win64-static.zip
125+
unzip -p ffmpeg-3.4.2-win64-static.zip ffmpeg-3.4.2-win64-static/bin/ffmpeg.exe > /mingw64/bin/ffmpeg.exe
126+
```
127+
128+
##### Windows via Microsoft Visual Studio
129+
130+
- Download and install [Microsoft Visual Studio](https://visualstudio.microsoft.com/)
131+
132+
> Will uses Visual Studio 2015 Enterprise (VC14) as example for below.
133+
134+
- Download [CMake-GUI](https://cmake.org/download/)
135+
136+
- Download [Boost prebuilt library](https://sourceforge.net/projects/boost/files/boost-binaries/) for VC14
137+
138+
> You may need a older version (< 1.66.0) in case of some unknown bug.
139+
140+
- Download [OpenCV prebuilt library](https://opencv.org/releases/) for Windows
141+
142+
> OpenCV should be 3.2+ but not 4.x
143+
144+
- Download [HDF5 prebuilt library](https://www.hdfgroup.org/downloads/hdf5) for VC14
145+
> You may need an account to download the file, you can register for free or build your own.
146+
> If you don't want to install the msi package, run `msiexec /a drive:\path\to\file.msi /qb TARGETDIR=drive:\path\to\extract`
147+
148+
- Download [JSONCPP prebuilt library](http://access.osvr.com/binary/deps/jsoncpp) for VC14
149+
150+
> You should grab a FFmpeg 3.x binary from https://ffmpeg.zeranoe.com/ to make it works.
151+
152+
> You should download OpenH264 1.7.0+ library file from https://github.com/cisco/openh264/releases manually.
153+
154+
> If you want to use it on Windows, always use backslash to set file path like `D:\path\to\video.mp4`, even under MSYS2 or Cygwin, or boost cannot find the specific path.
155+
156+
> You may also need Visual C++ 2015 Redistributable.
157+
158+
#### Compile & Build
96159

97160
##### Xcode
98161

99162
Open `animeloop-cli.xcodeproj` and run it.
100163

101164
(if you compile opencv source code by yourself, you maybe need edit `Linked Frameworks and Libraries` settings in Xcode project.)
102165

103-
##### CMake
166+
##### CMake (*nix)
104167

105168
``` Shell
106169
cd animeloop-cli
@@ -109,6 +172,15 @@ cmake ..
109172
make animeloop-cli
110173
```
111174

175+
##### MSYS2 + MinGW + CMake (Windows)
176+
177+
``` Shell
178+
cd animeloop-cli
179+
mkdir build && cd build
180+
cmake -G "MinGw Makefiles" ..
181+
mingw32-make.exe animeloop-cli
182+
```
183+
112184
## Usage
113185

114186
```Shell
@@ -135,6 +207,11 @@ Usage:
135207
# Example
136208
./animeloop-cli -i ~/your-video-file --max-duration 4 --min-duration 1.0 --cover -o ~/Downloads/
137209
```
210+
211+
## Special Thanks
212+
213+
* [@ccloli](https://github.com/ccloli) for Windows build support
214+
138215
## License
139216

140217
This project is available under the MIT License. See the LICENSE file for more info.

animeloop-cli/child_process.cpp

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,71 @@
1-
//
2-
// Created by shin on 12/2/17.
3-
//
4-
#include <iostream>
1+
#include "child_process.hpp"
2+
3+
#ifdef _WIN32
4+
#include <windows.h>
5+
#else
56
#include <sys/wait.h>
67
#include <unistd.h>
8+
#endif
79

8-
#include "child_process.hpp"
10+
#include <iostream>
911

1012
using namespace std;
1113

12-
void child_process(function<void()> functor) {
14+
void child_process(string cli) {
15+
#ifdef _WIN32
16+
17+
STARTUPINFO si;
18+
PROCESS_INFORMATION pi;
19+
DWORD exit_code = 0;
20+
LPSTR exec = const_cast<char *>(cli.c_str());
21+
22+
ZeroMemory(&si, sizeof(si));
23+
si.cb = sizeof(si);
24+
ZeroMemory(&pi, sizeof(pi));
25+
26+
// Start the child process.
27+
if (!CreateProcess(
28+
NULL, // No module name (use command line)
29+
exec, // Command line
30+
NULL, // Process handle not inheritable
31+
NULL, // Thread handle not inheritable
32+
FALSE, // Set handle inheritance to FALSE
33+
0, // No creation flags
34+
NULL, // Use parent's environment block
35+
NULL, // Use parent's starting directory
36+
&si, // Pointer to STARTUPINFO structure
37+
&pi // Pointer to PROCESS_INFORMATION structure
38+
)) {
39+
printf("CreateProcess failed (%d)\n", GetLastError());
40+
return;
41+
}
42+
43+
// Wait until child process exits.
44+
WaitForSingleObject(pi.hProcess, INFINITE);
45+
46+
// Get exit code
47+
GetExitCodeProcess(pi.hProcess, &exit_code);
48+
if (exit_code) {
49+
cerr << "The child was killed or segfaulted or something." << endl;
50+
}
51+
52+
// Close process and thread handles.
53+
CloseHandle(pi.hProcess);
54+
CloseHandle(pi.hThread);
55+
56+
#else
57+
1358
int pid = fork();
1459

1560
if(pid == -1) {
1661
/* Failed to fork */
1762
cerr << "Fork failed" << endl;
1863
throw;
1964
} else if(pid == 0) {
20-
functor();
65+
int status = system(cli.c_str());
66+
if (status) {
67+
cerr << "The child was killed or segfaulted or something." << endl;
68+
}
2169
exit(100);
2270
}
2371

@@ -30,4 +78,8 @@ void child_process(function<void()> functor) {
3078
}
3179

3280
status = WEXITSTATUS(status);
81+
82+
#endif
83+
84+
3385
}

animeloop-cli/child_process.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
#ifndef ANIMELOOP_CLI_CHILD_PROCESS_H
66
#define ANIMELOOP_CLI_CHILD_PROCESS_H
77

8-
#include <functional>
8+
#include <string>
99

10-
void child_process(std::function<void()> functor);
10+
void child_process(std::string cli);
1111

1212
#endif //ANIMELOOP_CLI_CHILD_PROCESS_H

animeloop-cli/loop_video.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,10 @@ void al::LoopVideo::generate(const LoopDurations durations) {
180180

181181
if (cover_enabled && !exists(cover_filepath)) {
182182
futures.push_back(pool.enqueue([=]() -> void {
183-
child_process([&]() {
184-
const char * i = video_filepath.c_str();
185-
const char * o = cover_filepath.c_str();
186-
execlp("ffmpeg", "ffmpeg", "-loglevel", "panic", "-i", i, "-vframes", "1", "-f", "image2", o, NULL);
187-
});
183+
const string i = video_filepath;
184+
const string o = cover_filepath;
185+
const string cli = "ffmpeg -loglevel panic -i \"" + i + "\" -vframes 1 -f image2 \"" + o + "\"";
186+
child_process(cli);
188187
}));
189188
}
190189

animeloop-cli/main.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "cxxopts.hpp"
1515
#include "loop_video.hpp"
16+
#include "utils.hpp"
1617

1718
using namespace std;
1819
using namespace boost::filesystem;
@@ -54,7 +55,8 @@ int main(int argc, char * argv[]) {
5455
cout << "Animeloop (´・ω・`)" << endl;
5556
cout << endl;
5657
cout << ":: detecting external program..." << endl;
57-
if (system("which ffmpeg &> /dev/null") == 0) {
58+
59+
if (detect_ffmpeg()) {
5860
cout << "[o] detected ffmpeg." << endl;
5961
} else {
6062
cout << "[x] not detect ffmpeg." << endl;

animeloop-cli/utils.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,14 @@ void al::resize_video(path input_filepath, path output_filepath, Size size) {
5252

5353
auto if_exists = exists(output_filepath);
5454
if (!if_exists) {
55-
if (system("which ffmpeg &> /dev/null") == 0) {
55+
if (detect_ffmpeg()) {
5656
cout << ":: resizing video..." << endl;
57-
child_process([&]() {
58-
const char * i = input_filepath.string().c_str();
59-
const char * s = (to_string(size.width) + "x" + to_string(size.height)).c_str();
60-
const char * o = temp_filename.string().c_str();
57+
const string i = input_filepath.string();
58+
const string s = (to_string(size.width) + "x" + to_string(size.height));
59+
const string o = temp_filename.string();
6160

62-
execlp("ffmpeg", "ffmpeg", "-loglevel", "panic", "-i", i, "-s", s, "-an", o, NULL);
63-
});
61+
const string cli = "ffmpeg -loglevel panic -stats -i \"" + i + "\" -s " + s + " -an \"" + o + "\"";
62+
child_process(cli);
6463
cout << "done." << endl;
6564
} else {
6665
// Calculate hash string per frame.
@@ -309,4 +308,14 @@ std::string al::time_string(double seconds) {
309308
auto ms = boost::posix_time::milliseconds(seconds * 1000);
310309
auto time = boost::posix_time::time_duration(ms);
311310
return boost::posix_time::to_simple_string(time);
311+
}
312+
313+
bool detect_ffmpeg() {
314+
#ifdef _WIN32
315+
string find_ffmpeg_command = "where /q ffmpeg";
316+
#else
317+
string find_ffmpeg_command = "which ffmpeg &> /dev/null";
318+
#endif
319+
320+
return system(find_ffmpeg_command.c_str()) == 0;
312321
}

animeloop-cli/utils.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@ namespace al {
5757
std::string time_string(double seconds);
5858
}
5959

60+
bool detect_ffmpeg();
61+
6062
#endif /* utils_hpp */

0 commit comments

Comments
 (0)