Commit 76f83888 authored by Stefan Westerfeld's avatar Stefan Westerfeld

DOCS: add build instructions for Windows/Cygwin (from Andreas Strohmeier)

See #45.
Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent b26ef9a7
......@@ -4,7 +4,8 @@ doc_DATA = audiowmark.pdf audiowmark.html
GRAPHVIZ_PY = graphviz.py
EXTRA_DIST = audiowmark.md $(GRAPHVIZ_PY) example-spectrum.dat example-spectrum.gp
EXTRA_DIST = audiowmark.md $(GRAPHVIZ_PY) example-spectrum.dat example-spectrum.gp \
videowmark-win.cc win-x64-build-guide.txt
audiowmark.pdf: audiowmark.md $(GRAPHVIZ_PY) example-spectrum.png
pandoc -F $(GRAPHVIZ_PY) -V papersize:a4 -V geometry:margin=2cm $< -o $@
......
/*
* Copyright (C) Andreas Strohmeier
*
* This program is a port of the Linux bash script videowmark,
* which is part of the audiowmark program by Stefan Westerfeld,
* into the C++ programming language.
* To keep it simple, there is only this single CPP file without a
* header file.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <iostream>
#include <string>
#include <cstdio>
#include <windows.h>
#include <algorithm>
#include <filesystem>
using namespace std;
string g_sFFMPEG_VERBOSE = "-v error";
string g_sFFProbe = "ffprobe.exe";
string g_sFFMpeg = "ffmpeg.exe";
string g_sAudiowmark = "audiowmark.exe";
int g_iQuiet = 0;
#define STRING_LENGTH 4096
//---------------------------------------------------------------------------
//show message and exit
int die(string sErrorMsg)
{
printf("videowmark: error: %s\n", sErrorMsg.c_str());
exit(1);
}
//---------------------------------------------------------------------------
//Fix me
//Maybe there is es better solution
//
//The result of getenv is not correct in cygwin environment.
//
//Example: getenv("TEMP");
//
//Result : /cygdrive/c/path/to/temp
//But should be: c:\path\to\temp
//
//This is a workaround to repair the path
string repair_cygwin_path(string sPath)
{
int i = 0;
string sResult = "";
if(int(sPath.find("/cygdrive/")) == 0 )
{
sPath.erase(0, 10);
for(i = 0; i < sPath.length(); i++)
{
if(sPath[i] == '/')
{
sPath[i] = '\\';
}
}
if(sPath[1] != ':')
{
sPath.insert(1, ":");
}
}
sResult = sPath;
return sResult;
}
//---------------------------------------------------------------------------
//Fix me
//Maybe there is es better solution
string get_unix_path(string sPath)
{
int i = 0;
string sResult = "";
for(i = 0; i < sPath.length(); i++)
{
if(sPath[i] == '\\')
{
sPath[i] = '/';
}
}
sResult = sPath;
return sResult;
}
//---------------------------------------------------------------------------
// Create the temp file
string create_temp_file(string sFilename)
{
string sTempPath = "";
string sFilenameWoPath = "";
string sTempUnixFilename = "";
string sTempFilename = "";
//Fix me:
//The result of getenv is not correct in cygwin environment.
//
//Example: getenv("TEMP");
//
//Result : /cygdrive/c/path/to/temp
//But should be: c:\path\to\temp
//
//Get environment variable TEMP
sTempPath = getenv("TEMP");
//Repair the path if needed
sTempPath = repair_cygwin_path(sTempPath);
//Fix me:
//filesystem::path in Cygwin only works with /
sTempUnixFilename = get_unix_path(sFilename);
filesystem::path p(sTempUnixFilename);
sFilenameWoPath = p.filename();
sTempFilename = sTempPath + "\\" + sFilenameWoPath;
if(CopyFile(sFilename.c_str(), sTempFilename.c_str(), false) == false)
{
die("Could not create temp file");
}
return sTempFilename;
}
//---------------------------------------------------------------------------
// Delete file
bool delete_temp_file(string sFilename)
{
return DeleteFile(sFilename.c_str());
}
//---------------------------------------------------------------------------
// Execute a command and get the results.
string ExecCmd(string sCMD /* [in] command to execute */ )
{
int i = 0;
string strResult = "";
char cmd[STRING_LENGTH] = {};
HANDLE hPipeRead = 0;
HANDLE hPipeWrite = 0;
strcpy(cmd, sCMD.c_str());
SECURITY_ATTRIBUTES saAttr = {sizeof(SECURITY_ATTRIBUTES)};
saAttr.bInheritHandle = TRUE; // Pipe handles are inherited by child process.
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe to get results from child's stdout.
if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
return strResult;
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdOutput = hPipeWrite;
si.hStdError = hPipeWrite;
si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing.
// Requires STARTF_USESHOWWINDOW in dwFlags.
PROCESS_INFORMATION pi = { 0 };
BOOL fSuccess = CreateProcessA(NULL, (LPSTR)cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (! fSuccess)
{
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
return strResult;
}
bool bProcessEnded = false;
for (; !bProcessEnded ;)
{
// Give some timeslice (50 ms), so we won't waste 100% CPU.
bProcessEnded = WaitForSingleObject( pi.hProcess, 50) == WAIT_OBJECT_0;
// Even if process exited - we continue reading, if
// there is some data available over pipe.
char buf[STRING_LENGTH] = {};
DWORD dwRead = 0;
DWORD dwAvail = 0;
for (;;)
{
if (!PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
break;
if (!dwAvail) // No data available, return
break;
if (!ReadFile(hPipeRead, buf, min( sizeof(buf) - 1, (long unsigned int )dwAvail ), &dwRead, NULL) || !dwRead)
// Error, the child process might ended
break;
//Get results
strResult += buf;
//Clean up entire buffer to remove trash
for(i = 0; i < STRING_LENGTH; i++){buf[i] = 0;}
}
}
CloseHandle(hPipeWrite);
CloseHandle(hPipeRead);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return strResult;
}
//---------------------------------------------------------------------------
//auto detect codec and bitrate from input stream, generate ffmpeg options for audio encoder
string audio_encode_options(string sFilename)
{
string sParam = "";
string sCMD = "";
string sResult = "";
string sValue = "";
string sCodecName = "";
string sProbeResult = "";
string sTempResult = "";
string sBitRate = "";
string sData = "";
char cResult[STRING_LENGTH] = {};
int i = 0;
int iPos = 0;
//ffprobe -v error -print_format compact -show_streams "$1"
sParam = "-print_format compact -show_streams \"" + sFilename + "\"";
sCMD = g_sFFProbe + " " + g_sFFMPEG_VERBOSE + " " + sParam;
//Execute and get results
sProbeResult = ExecCmd(sCMD);
//Parse to find the audio line
for(i = 0; i < sProbeResult.length(); i++)
{
if(sProbeResult[i] != 0x0d && sProbeResult[i] != 0x0a)
{
sTempResult += sProbeResult[i];
}
if(sProbeResult[i] == 0x0d)
{
if(int(sTempResult.find("codec_type=audio")) > 0)
{
sResult = sTempResult;
break;
}
else
{
sTempResult = "";
}
}
}
//Parse to find codec_name and bit_rate
if(sResult.length() > 0)
{
sValue = "codec_name=";
iPos = sResult.find(sValue);
if(iPos > 0)
{
iPos += sValue.length();
while(sResult[iPos] != '|')
{
sCodecName += sResult[iPos];
iPos++;
}
}
sValue = "bit_rate=";
iPos = sResult.find(sValue);
if(iPos > 0)
{
iPos += sValue.length();
while(sResult[iPos] != '|')
{
sBitRate += sResult[iPos];
iPos++;
}
}
// opus encoder is experimental, ffmpeg recommends libopus for encoding
if (sCodecName == "opus")
{
sCodecName = "libopus";
}
sResult = "-c:a " + sCodecName;
if (sBitRate != "N/A")
{
sResult += " -ab " + sBitRate;
}
}
return sResult;
}
//---------------------------------------------------------------------------
// count number of audio and video streams, typical output: "audio=1:video=1"
string audio_video_stream_count(string sFilename)
{
string sParam = "";
string sCMD = "";
string sResult = "";
char cResult[STRING_LENGTH] = {};
int iVideoCodec = 0;
int iAudioCodec = 0;
//ffprobe -v error -print_format compact -show_streams "$1"
sParam = "-print_format compact -show_streams \"" + sFilename + "\"";
sCMD = g_sFFProbe + " " + g_sFFMPEG_VERBOSE + " " + sParam;
//Execute and get results
sResult = ExecCmd(sCMD);
if(sResult.length() > 0)
{
if(int(sResult.find("codec_type=audio")) > 0)
{
iAudioCodec = 1;
}
if(int(sResult.find("codec_type=video")) > 0)
{
iVideoCodec = 1;
}
sprintf(cResult, "audio=%d:video=%d", iAudioCodec, iVideoCodec);
sResult = cResult;
}
return sResult;
}
//---------------------------------------------------------------------------
// get file extension
string extension(string sFilename)
{
string sResult = "";
string sTempUnixFilename = "";
//Fix me:
//filesystem::path in Cygwin only works with /
sTempUnixFilename = get_unix_path(sFilename);
filesystem::path p(sTempUnixFilename);
sResult = p.extension();
return sResult;
}
//---------------------------------------------------------------------------
// add watermark to file
void add_watermark(string sInFile, string sOutFile, string sHash, string sARGS)
{
string sCMD = "";
string sParam = "";
string sExtIn = "";
string sExtOut = "";
string sResult = "";
string sStreamCount = "";
string sEncodeOptions = "";
string sTempFilenameVideo = "";
string sTempFilenameAudio = "";
string sTempFilenameAudioWM = "";
// check file extensions
sExtIn = extension(sInFile);
sExtOut = extension(sOutFile);
if(sExtIn != sExtOut)
{
die("input/output extension must match ('" + sExtIn + "' vs. '" + sExtOut + "')");
}
// check audio/video stream count
sStreamCount = audio_video_stream_count(sInFile);
if(sStreamCount != "audio=1:video=1")
{
printf("videowmark: detected input file stream count: %s\n", sStreamCount.c_str());
die ("input file must have one audio stream and one video stream");
}
// create tmpfiles
sTempFilenameVideo = create_temp_file(sInFile);
// create audio tmpfilename ( just the name, not the file )
sTempFilenameAudio = sTempFilenameVideo + ".wav";
// create wm_audio tmpfilename ( just the name, not the file )
sTempFilenameAudioWM = sTempFilenameVideo + "_wm.wav";
// get audio as wav
//ffmpeg $FFMPEG_VERBOSE -y -i "$in_file" -f wav -rf64 always "$wav"
sParam = "-y -i \"" + sTempFilenameVideo + "\" -f wav -rf64 always \"" + sTempFilenameAudio + "\"";
sCMD = g_sFFMpeg + " " + g_sFFMPEG_VERBOSE + " " + sParam;
//Execute and get results
sResult = ExecCmd(sCMD);
//Show detailed FFMpeg results
if(g_sFFMPEG_VERBOSE == "-v info"){printf("%s\n", sResult.c_str());}
if(sResult.length() > 0)
{
if(int(sResult.find("Error")) > 0)
{
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
delete_temp_file(sTempFilenameAudioWM);
die("extracting audio from video failed (ffmpeg)");
}
}
// add watermark
// audiowmark add "${AUDIOWMARK_ARGS[@]}" "$orig_wav" "$wm_wav" "$bits" --set-input-label "$in_file" --set-output-label "$out_file" --output-format rf64"
sEncodeOptions = audio_encode_options(sInFile);
if(g_iQuiet == 0){printf("Audio Codec: %s\n", sEncodeOptions.c_str());}
sParam = "add " + sARGS + " \"" + sTempFilenameAudio + "\" \"" + sTempFilenameAudioWM + "\" " + sHash + " --set-input-label \"" + sInFile + "\" --set-output-label \"" + sOutFile + "\" --output-format rf64";
sCMD = g_sAudiowmark + " " + sParam;
//Execute and get results
sResult = ExecCmd(sCMD);
if(sResult.length() > 0)
{
if(int(sResult.find("Error")) > 0)
{
//Show detailed cause of error
if(g_sFFMPEG_VERBOSE == "-v info"){printf("%s\n", sResult.c_str());}
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
delete_temp_file(sTempFilenameAudioWM);
die("watermark generation failed (audiowmark)");
}
}
//Show Audiowmark results
if(g_iQuiet == 0)
{
printf("%s\n", sResult.c_str());
}
// rejoin
// ffmpeg $FFMPEG_VERBOSE -y -i "$in_file" -i "$wm_wav" -c:v copy $(audio_encode_options "$in_file") -map 0:v:0 -map 1:a:0 "$out_file"
sParam = "-y -i \"" + sTempFilenameVideo + "\" -i \"" + sTempFilenameAudioWM + "\" -c:v copy " + sEncodeOptions + " -map 0:v:0 -map 1:a:0 \"" + sOutFile + "\"";
sCMD = g_sFFMpeg + " " + g_sFFMPEG_VERBOSE + " " + sParam;
//Execute and get results
sResult = ExecCmd(sCMD);
//Show detailed FFMpeg results
if(g_sFFMPEG_VERBOSE == "-v info"){printf("%s\n", sResult.c_str());}
if(sResult.length() > 0)
{
if(int(sResult.find("Error")) > 0)
{
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
delete_temp_file(sTempFilenameAudioWM);
die("merging video and watermarked audio failed (ffmpeg)");
}
}
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
delete_temp_file(sTempFilenameAudioWM);
}
//---------------------------------------------------------------------------
// get watermark from file
void get_watermark(string sFilename, string sARGS)
{
string sParam = "";
string sCMD = "";
string sTempPath = "";
string sResult = "";
string sTempFilenameVideo = "";
string sTempFilenameAudio = "";
char cResult[STRING_LENGTH] = {};
// check audio/video stream count
sResult = audio_video_stream_count(sFilename);
if(sResult.length() > 0)
{
if(sResult != "audio=1:video=1" )
{
printf("videowmark: detected input file stream count: %s\n", sResult.c_str());
die("input file must have one audio stream and one video stream");
}
}
// create video tmpfile
sTempFilenameVideo = create_temp_file(sFilename);
// create audio tmpfilename ( just the name, not the file )
sTempFilenameAudio = sTempFilenameVideo + ".wav";
// get audio as wav
//ffmpeg $FFMPEG_VERBOSE -y -i "$in_file" -f wav -rf64 always "$wav" || die "extracting audio from video failed (ffmpeg)"
sParam = "-y -i \"" + sTempFilenameVideo + "\" -f wav -rf64 always \"" + sTempFilenameAudio + "\"";
sCMD = g_sFFMpeg + " " + g_sFFMPEG_VERBOSE + " " + sParam;
//Execute and get results
sResult = ExecCmd(sCMD);
//Show detailed FFMpeg results
if(g_sFFMPEG_VERBOSE == "-v info"){printf("%s\n", sResult.c_str());}
if(sResult.length() > 0)
{
if(int(sResult.find("Error")) > 0)
{
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
die("extracting audio from video failed (ffmpeg)");
}
}
// get watermark
//audiowmark get "${AUDIOWMARK_ARGS[@]}" "$wav" || die "retrieving watermark from audio failed (audiowmark)"
sParam = "get " + sARGS + " \"" + sTempFilenameAudio + "\"";
sCMD = g_sAudiowmark + " " + sParam;
//Execute and get results
sResult = ExecCmd(sCMD);
if(sResult.length() > 0)
{
if(int(sResult.find("Error")) > 0)
{
//Show detailed cause of error
if(g_sFFMPEG_VERBOSE == "-v info"){printf("%s\n", sResult.c_str());}
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
die("retrieving watermark from audio failed (audiowmark)");
}
}
//Show Audiowmark results
printf("%s\n", sResult.c_str());
//Clean up
delete_temp_file(sTempFilenameVideo);
delete_temp_file(sTempFilenameAudio);
}
//---------------------------------------------------------------------------
void show_help_and_exit()
{
printf(
"usage: videowmark <command> [ <args>... ]\n"
"\n"
"Commands:\n"
" * create a watermarked video file with a message\n"
" videowmark add <input_video> <watermarked_video> <message_hex>\n"
"\n"
" * retrieve message\n"
" videowmark get <watermarked_video>\n"
"\n"
"Global options:\n"
" --strength <s> set watermark strength\n"
" --key <file> load watermarking key from file\n"
" -q, --quiet disable information messages\n"
" -v, --verbose enable ffmpeg verbose output\n"
);
exit(0);
}
//---------------------------------------------------------------------------
int main(int argc , char *argv[])
{
string sResult = "";
string sAction = "";
string sKeyfile = "";
string sFilename = "";
string sInFile = "";
string sOutFile = "";
string sHash = "";
int i = 0;
string sARGS = "";
if(argc > 1)
{
//Get all args
for(i = 1; i < argc; i++)
{
if(string(argv[i]) == "-v" || string(argv[i]) == "--verbose")
{
g_sFFMPEG_VERBOSE = "-v info";
}
else if(string(argv[i]) == "-q" || string(argv[i]) == "--quiet")
{
sARGS += " -q";
g_iQuiet = 1;
}
else if(string(argv[i]) == "--detect-speed")
{
sARGS += " " + string(argv[i]);
}
else if(string(argv[i]) == "-h" || string(argv[i]) == "--help")
{
show_help_and_exit();
}
else if(string(argv[i]) == "--key")
{
if(argc >= i+1 )
{
sARGS += " " + string(argv[i]) + " " + string(argv[i+1]);
i++;
}
else
{
die("videowmark: error parsing command line arguments (use videowmark -h)");
}
}
else if(string(argv[i]) == "--strength")
{
if(argc >= i+1 )
{
sARGS += " " + string(argv[i]) + " " + string(argv[i+1]);
i++;
}
else
{
die("videowmark: error parsing command line arguments (use videowmark -h)");
}
}
else if(string(argv[i]) == "add" || string(argv[i]) == "get" || string(argv[i]) == "probe")
{
sAction = string(argv[i]);
}
else if(sInFile.length() == 0 && string(argv[i]).length() > 0)
{
sInFile = string(argv[i]);
}
else if(sOutFile.length() == 0 && string(argv[i]).length() > 0)
{
sOutFile = string(argv[i]);
}
else if(sHash.length() == 0 && string(argv[i]).length() > 0)
{
sHash = string(argv[i]);
}
else
{
//
}
}
//Get and execute action
if(sAction == "add" && sInFile.length() > 0 && sOutFile.length() > 0 && sHash.length() > 0)
{
add_watermark(sInFile, sOutFile, sHash, sARGS);
}
else if(sAction == "get" && sInFile.length() > 0)
{
get_watermark(sInFile, sARGS);
}
else if(sAction == "probe" && sInFile.length() > 0)
{
printf("%s %s\n", sInFile.c_str(),audio_encode_options(sInFile).c_str());
}
else
{
printf("videowmark: error parsing command line arguments (use videowmark -h)\n");
}
}
else
{
show_help_and_exit();
}
return 0;
}
//---------------------------------------------------------------------------
In this step-by-step guide I show how to build Audiowmark
to run it on Windows x64.
I won't explain every single tool, just the creation process.
That's enough work.
Following these instructions exactly should lead to success.
Prerequisites (programs / source codes / libraries):
- Download source code from Audiowmark
DL: https://github.com/swesterfeld/audiowmark/releases
I chose this one : audiowmark-0.6.2.tar.zst
- Download source code from zita-resampler
DL: https://github.com/digital-stage/zita-resampler/
- Download 7zip ( newest beta version to extract .zst files )
DL: https://www.7-zip.org/
- Download Notepad++
DL: https://notepad-plus-plus.org/
- Download Cygwin
DL: https://cygwin.com/
- Download CMAKE
DL: https://cmake.org/download/
- Download MinGW-w64
DL: https://github.com/niXman/mingw-builds-binaries/releases
I chose this one : x86_64-13.2.0-release-posix-seh-msvcrt-rt_v11-rev0.7z
- Download FFmpeg
DL: https://github.com/BtbN/FFmpeg-Builds/releases
I chose this one : ffmpeg-master-latest-win64-gpl-shared.zip
Prepare everything:
- Install Cygwin ( do a clean install )
We need to add the following libraries to Cygwin ( choose always the latest stable release )
- gcc-core
- gcc-debuginfo
- gcc-g++
- mingw64-x86_64-gcc-core
- mingw64-x86_64-gcc-g++
- make
- make-debuginfo
- libfftw3-devel
- libsndfile-devel
- libgcrypt-devel
- libmpg123-devel
- libzita-resampler ( Not included in Cygwin. We have to compile and copy it later manually )
- FFmpeg ( It is available in Cygwin, but i had some problems with it. So we add it later manually )
- Install CMAKE
- Install Notepad++
- Install 7zip ( newest beta version to extract .zst files )
- Extract zita-resempler-main.zip to c:\zita-resempler-main
- Extract audiowmark-0.6.2.zip to c:\audiowmark-0.6.2
Edit "c:\audiowmark-0.6.2\src\utils.cc" and insert the following line directly below the comment section ( needed for vasprintf )
#define _GNU_SOURCE
- Extract ffmpeg-master-latest-win64-gpl-shared.zip to c:\ffmpeg-master-latest-win64-gpl-shared
- Extract x86_64-13.2.0-release-posix-seh-msvcrt-rt_v11-rev0.7z\mingw64 to c:\mingw64
- Add "C:\mingw64\bin" to the system path variable and place it at the top most position
- Important : Restart Windows !
- After restart windows edit the file c:\zita-resempler-main\CMakeLists.txt with Notepad++.
Find the line below # make ( should be line 22 ) and insert the parameter SHARED.
# make
before:
add_library(zita-resampler ${SOURCES} ${HEADER_LIST})
after:
add_library(zita-resampler SHARED ${SOURCES} ${HEADER_LIST})
- Start CMAKE
Select the source dir c:\zita-resempler-main
Select / create the build dir ( f.e.: c:\zita-resampler-main\build64 )
Press "Configure"
Choose "MinGW Makefiles as generator"
Choose "Use default native compilers"
Press "Finish" to complete the configuration
We should see : Configuring done ( ignore the red values in the list above )
After successfull configuration press "Generate"
We should see : Gernerating done
Close CMAKE
- Open the command prompt ( cmd.exe ) and go to the directory "c:\zita-resampler-main\build64".
Type in:
mingw32-make
We should see : [100%] Built target zita-resampler
Now we should have the following two new files:
"c:\zita-resampler-main\build64\libzita-resampler.dll"
"c:\zita-resampler-main\build64\libzita-resampler.dll.a"
Close CMD
- Install zita-resampler
- Copy the file "c:\zita-resampler-main\build64\libzita-resampler.dll" to "C:\cygwin64\usr\x86_64-pc-cygwin\bin"
- Copy the file "c:\zita-resampler-main\build64\libzita-resampler.dll.a" to "C:\cygwin64\usr\x86_64-pc-cygwin\lib"
- Copy the whole directory "C:\zita-resampler-main\source\zita-resampler" to "C:\audiowmark-0.6.2\src\zita-resampler"
- Install FFmpeg
- Copy ALL files from "C:\ffmpeg-master-latest-win64-gpl-shared\bin\*.*" to "C:\cygwin64\usr\x86_64-w64-mingw32\sys-root\mingw\bin"
- Copy ALL files ( except dir "pkgconfig" ) from "C:\ffmpeg-master-latest-win64-gpl-shared\lib\*.*" to "C:\cygwin64\usr\x86_64-w64-mingw32\sys-root\mingw\lib"
- Copy ALL .pc-files from "C:\ffmpeg-master-latest-win64-gpl-shared\lib\pkgconfig\*.pc" to "C:\cygwin64\lib\pkgconfig"
- Copy ALL sub directories from "C:\ffmpeg-master-latest-win64-gpl-shared\include\*" to "C:\audiowmark-0.6.2\src\*"
Now we should be ready to build the audiowmark source code:
- Start Cygwin64-Terminal with admin rights
Change the current directory to: /cygdrive/c/audiowmark-0.6.2
- Type in:
./configure --host=x86_64-pc-cygwin
- Type in:
make.exe
All created EXE-files will be saved to "C:\audiowmark-0.6.2\src\.libs"
Note : There is another, significantly smaller version of each EXE file in "C:\audiowmark-0.6.2\src\". Don't use these. They don't work.
The last part to do is to build the videowmark.exe.
The file "C:\audiowmark-0.6.2\src\videowmark" is a linux bash script and can not executed on windows.
So I ported it to C++.
To keep it simple, I made only this single CPP file without a header file.
- Copy the file "C:\audiowmark-0.6.2\docs\videowmark-win.cc" to "C:\audiowmark-0.6.2\src\"
- Open Cygwin and and go to the directory "/cygdrive/c/audiowmark-0.6.2/src/"
- Type in :
g++ -o videowmark.exe videowmark.cc
Okay, we are almost finished.
In order to deliver audiowmark.exe and videowmark.exe all corresponding DLL- and EXE-files must also be delivered.
And that's a lot.
Every single DLL- and EXE-file we will find somewhere in "C:\cygwin64"
Each file must be copied into the SAME directory where the EXE file is located.
Location: C:\audiowmark-0.6.2\src\.libs\
audiowmark.exe
C:\audiowmark-0.6.2\src\
videowmark.exe
Location: /usr/x86_64-w64-mingw32/sys-root/mingw/bin/
ffmpeg.exe
ffplay.exe
ffprobe.exe
avcodec-60.dll
avdevice-60.dll
avfilter-9.dll
avformat-60.dll
avutil-58.dll
libatomic-1.dll
libgcc_s_seh-1.dll
libgomp-1.dll
libquadmath-0.dll
libssp-0.dll
libstdc++-6.dll
libwinpthread-1.dll
postproc-57.dll
swresample-4.dll
swscale-7.dll
Location: /usr/bin/
cygiconv-2.dll
cygintl-8.dll
cyggpg-error-0.dll
cygvorbis-0.dll
cygvorbisenc-2.dll
cygogg-0.dll
cygFLAC-8.dll
cygopus-0.dll
cygmp3lame-0.dll
cyggcrypt-20.dll
cygsndfile-1.dll
cygmpg123-0.dll
cygstdc++-6.dll
cygwin1.dll
cyggcc_s-seh-1.dll
cygfftw3f-3.dll
Location: /usr/x86_64-pc-cygwin/bin/
libzita-resampler.dll
That's it. We're done.
That was easy, wasn't it?
BR
Andreas
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment