Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 79 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,78 @@ pacman -S hdf5
pacman -S jsoncpp
```

#### Compile & Build
##### Windows MinGW

```shell
# - MinGW build require tool MSYS2, you sould download and install it first, then use pacman in MSYS2 Enviroment
#
# - Assume you're building to mingw64, if you'd like to build to mingw32, replace `mingw-w64-x86_64` with `mingw-w64-i686`
#
# - Some packages are updated and not compatible, so some of the steps are using `pacman -U` to install specific version
# packages with USTC Mirrors, you can change `https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/` to other sources.

# Build deps
pacman -S libintl mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-make

# Boost
# - It seems that when using Boost 1.66+ will cause build fail
pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz

# OpenCV
pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/mingw-w64-x86_64-opencv-3.4.3-2-any.pkg.tar.xz
pacman -S mingw-w64-x86_64-hdf5

# Jsoncpp
# - JSONCPP comes with cmake, so if you've install cmake manually, you're not needed to install JSONCPP again
pacman -S mingw-w64-x86_64-jsoncpp jsoncpp-devel

# FFmpeg
# - Some dll files are missing in MSYS2 MinGW64 FFmpeg package, so you should download it from other builds
# - You can also download it later, as it's not build dependency (but runtime dependency)
# pacman -U https://mirrors.ustc.edu.cn/msys2/mingw/x86_64/mingw-w64-x86_64-ffmpeg-3.4.2-1-any.pkg.tar.xz
wget https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-3.4.2-win64-static.zip
unzip -p ffmpeg-3.4.2-win64-static.zip ffmpeg-3.4.2-win64-static/bin/ffmpeg.exe > /mingw64/bin/ffmpeg.exe
```

##### Windows via Microsoft Visual Studio

- Download and install [Microsoft Visual Studio](https://visualstudio.microsoft.com/)

> Will uses Visual Studio 2015 Enterprise (VC14) as example for below.

- Download [CMake-GUI](https://cmake.org/download/)

- Download [Boost prebuilt library](https://sourceforge.net/projects/boost/files/boost-binaries/) for VC14

> You may need a older version (< 1.66.0) in case of some unknown bug.

- Download [OpenCV prebuilt library](https://opencv.org/releases/) for Windows

> OpenCV should be 3.2+ but not 4.x

- Download [HDF5 prebuilt library](https://www.hdfgroup.org/downloads/hdf5) for VC14
> You may need an account to download the file, you can register for free or build your own.
> If you don't want to install the msi package, run `msiexec /a drive:\path\to\file.msi /qb TARGETDIR=drive:\path\to\extract`

- Download [JSONCPP prebuilt library](http://access.osvr.com/binary/deps/jsoncpp) for VC14

> You should grab a FFmpeg 3.x binary from https://ffmpeg.zeranoe.com/ to make it works.

> You should download OpenH264 1.7.0+ library file from https://github.com/cisco/openh264/releases manually.

> 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.

> You may also need Visual C++ 2015 Redistributable.

#### Compile & Build

##### Xcode

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

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

##### CMake
##### CMake (*nix)

``` Shell
cd animeloop-cli
Expand All @@ -109,6 +172,15 @@ cmake ..
make animeloop-cli
```

##### MSYS2 + MinGW + CMake (Windows)

``` Shell
cd animeloop-cli
mkdir build && cd build
cmake -G "MinGw Makefiles" ..
mingw32-make.exe animeloop-cli
```

## Usage

```Shell
Expand All @@ -135,6 +207,11 @@ Usage:
# Example
./animeloop-cli -i ~/your-video-file --max-duration 4 --min-duration 1.0 --cover -o ~/Downloads/
```

## Special Thanks

* [@ccloli](https://github.com/ccloli) for Windows build support

## License

This project is available under the MIT License. See the LICENSE file for more info.
66 changes: 59 additions & 7 deletions animeloop-cli/child_process.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,71 @@
//
// Created by shin on 12/2/17.
//
#include <iostream>
#include "child_process.hpp"

#ifdef _WIN32
#include <windows.h>
#else
#include <sys/wait.h>
#include <unistd.h>
#endif

#include "child_process.hpp"
#include <iostream>

using namespace std;

void child_process(function<void()> functor) {
void child_process(string cli) {
#ifdef _WIN32

STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD exit_code = 0;
LPSTR exec = const_cast<char *>(cli.c_str());

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

// Start the child process.
if (!CreateProcess(
NULL, // No module name (use command line)
exec, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi // Pointer to PROCESS_INFORMATION structure
)) {
printf("CreateProcess failed (%d)\n", GetLastError());
return;
}

// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);

// Get exit code
GetExitCodeProcess(pi.hProcess, &exit_code);
if (exit_code) {
cerr << "The child was killed or segfaulted or something." << endl;
}

// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

#else

int pid = fork();

if(pid == -1) {
/* Failed to fork */
cerr << "Fork failed" << endl;
throw;
} else if(pid == 0) {
functor();
int status = system(cli.c_str());
if (status) {
cerr << "The child was killed or segfaulted or something." << endl;
}
exit(100);
}

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

status = WEXITSTATUS(status);

#endif


}
4 changes: 2 additions & 2 deletions animeloop-cli/child_process.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#ifndef ANIMELOOP_CLI_CHILD_PROCESS_H
#define ANIMELOOP_CLI_CHILD_PROCESS_H

#include <functional>
#include <string>

void child_process(std::function<void()> functor);
void child_process(std::string cli);

#endif //ANIMELOOP_CLI_CHILD_PROCESS_H
9 changes: 4 additions & 5 deletions animeloop-cli/loop_video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,10 @@ void al::LoopVideo::generate(const LoopDurations durations) {

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

Expand Down
4 changes: 3 additions & 1 deletion animeloop-cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "cxxopts.hpp"
#include "loop_video.hpp"
#include "utils.hpp"

using namespace std;
using namespace boost::filesystem;
Expand Down Expand Up @@ -54,7 +55,8 @@ int main(int argc, char * argv[]) {
cout << "Animeloop (´・ω・`)" << endl;
cout << endl;
cout << ":: detecting external program..." << endl;
if (system("which ffmpeg &> /dev/null") == 0) {

if (detect_ffmpeg()) {
cout << "[o] detected ffmpeg." << endl;
} else {
cout << "[x] not detect ffmpeg." << endl;
Expand Down
23 changes: 16 additions & 7 deletions animeloop-cli/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,14 @@ void al::resize_video(path input_filepath, path output_filepath, Size size) {

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

execlp("ffmpeg", "ffmpeg", "-loglevel", "panic", "-i", i, "-s", s, "-an", o, NULL);
});
const string cli = "ffmpeg -loglevel panic -stats -i \"" + i + "\" -s " + s + " -an \"" + o + "\"";
child_process(cli);
cout << "done." << endl;
} else {
// Calculate hash string per frame.
Expand Down Expand Up @@ -309,4 +308,14 @@ std::string al::time_string(double seconds) {
auto ms = boost::posix_time::milliseconds(seconds * 1000);
auto time = boost::posix_time::time_duration(ms);
return boost::posix_time::to_simple_string(time);
}

bool detect_ffmpeg() {
#ifdef _WIN32
string find_ffmpeg_command = "where /q ffmpeg";
#else
string find_ffmpeg_command = "which ffmpeg &> /dev/null";
#endif

return system(find_ffmpeg_command.c_str()) == 0;
}
2 changes: 2 additions & 0 deletions animeloop-cli/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,6 @@ namespace al {
std::string time_string(double seconds);
}

bool detect_ffmpeg();

#endif /* utils_hpp */