[0.1.28] macOS phase 4: videos through FFmpeg 6.0 for macOS, an LGPL build made by build_macos.jai
This commit is contained in:
parent
a66928b223
commit
3e353c77d8
2
.gitignore
vendored
2
.gitignore
vendored
@ -27,5 +27,7 @@ Thumbs.db
|
|||||||
/modules/Labels/models/
|
/modules/Labels/models/
|
||||||
# Segmentation: exported by tools/export_mask2former.py, not committed
|
# Segmentation: exported by tools/export_mask2former.py, not committed
|
||||||
/modules/Segment/models/
|
/modules/Segment/models/
|
||||||
|
# FFmpeg for macOS: the source, build and headers modules/ffmpeg/build_macos.jai makes (its libraries in macos/ are kept)
|
||||||
|
/modules/ffmpeg/macos-build/
|
||||||
# Releases: made by release.jai
|
# Releases: made by release.jai
|
||||||
/release/
|
/release/
|
||||||
|
|||||||
@ -269,7 +269,7 @@ What becomes of each file:
|
|||||||
- **Animated GIFs** are images; their thumbnail is marked **GIF**, and the Capture window says how
|
- **Animated GIFs** are images; their thumbnail is marked **GIF**, and the Capture window says how
|
||||||
long they run and opens them in the default viewer.
|
long they run and opens them in the default viewer.
|
||||||
- **Videos** (MP4, MOV, M4V, 3GP, MKV, WebM, AVI, WMV, MPEG, MTS and M2TS, FLV), read with FFmpeg
|
- **Videos** (MP4, MOV, M4V, 3GP, MKV, WebM, AVI, WMV, MPEG, MTS and M2TS, FLV), read with FFmpeg
|
||||||
(`modules/ffmpeg`, Windows only): an `.mcap` holding the file exactly as it was, of any size (it is
|
(`modules/ffmpeg`; Windows and macOS, not Linux): an `.mcap` holding the file exactly as it was, of any size (it is
|
||||||
copied a few MB at a time, never read whole), and a frame from it a tenth of the way in (at most 3
|
copied a few MB at a time, never read whole), and a frame from it a tenth of the way in (at most 3
|
||||||
seconds), turned the right way up, which is what the grid, the Capture window, OCR and labels see.
|
seconds), turned the right way up, which is what the grid, the Capture window, OCR and labels see.
|
||||||
The date is the phone's (Apple's creation date), else one in its name, else the video's own
|
The date is the phone's (Apple's creation date), else one in its name, else the video's own
|
||||||
|
|||||||
@ -49,7 +49,7 @@ APP_NAME :: "mcap";
|
|||||||
APP_FOLDER_NAME :: "mcap";
|
APP_FOLDER_NAME :: "mcap";
|
||||||
GIT_BRANCH :: "check";
|
GIT_BRANCH :: "check";
|
||||||
GIT_HASH :: "-";
|
GIT_HASH :: "-";
|
||||||
VERSION :: "0.1.27";
|
VERSION :: "0.1.28";
|
||||||
BUILD_DATE :: "-";
|
BUILD_DATE :: "-";
|
||||||
DEBUG :: true;
|
DEBUG :: true;
|
||||||
COMPILE_TESTS :: true;
|
COMPILE_TESTS :: true;
|
||||||
|
|||||||
11
first.jai
11
first.jai
@ -8,7 +8,7 @@ APP_NAME :: "mcap";
|
|||||||
APP_FOLDER_NAME :: "mcap";
|
APP_FOLDER_NAME :: "mcap";
|
||||||
APP_BUNDLE_IDENTIFIER :: "com.example.mcap";
|
APP_BUNDLE_IDENTIFIER :: "com.example.mcap";
|
||||||
|
|
||||||
VERSION :: "0.1.27";
|
VERSION :: "0.1.28";
|
||||||
// Where everything goes: bin/, or bin-headless/ for builds made with no_crash_dialog, so automated
|
// Where everything goes: bin/, or bin-headless/ for builds made with no_crash_dialog, so automated
|
||||||
// builds never write over the ones you run by hand.
|
// builds never write over the ones you run by hand.
|
||||||
build_directory := "bin";
|
build_directory := "bin";
|
||||||
@ -215,7 +215,7 @@ finish_main_build :: (build: Pending_Build) {
|
|||||||
MACOS_BUNDLE_DYLIBS :: string.["libSDL3.0.dylib"];
|
MACOS_BUNDLE_DYLIBS :: string.["libSDL3.0.dylib"];
|
||||||
|
|
||||||
// mcap.app for the release build, mcap-debug.app for the debug one, with an identifier of its own
|
// mcap.app for the release build, mcap-debug.app for the debug one, with an identifier of its own
|
||||||
// so that its permissions are granted apart. Each holds the executable, SDL3 beside it,
|
// so that its permissions are granted apart. Each holds the executable, SDL3 and FFmpeg beside it,
|
||||||
// onnxruntime in Contents/Frameworks, and the icon, Info.plist and models in Contents/Resources.
|
// onnxruntime in Contents/Frameworks, and the icon, Info.plist and models in Contents/Resources.
|
||||||
// The app finds data/, logs/ and images/ in the folder holding the bundle (see
|
// The app finds data/, logs/ and images/ in the folder holding the bundle (see
|
||||||
// app_install_directory), and the models in Contents/Resources (app_resource_directory).
|
// app_install_directory), and the models in Contents/Resources (app_resource_directory).
|
||||||
@ -241,6 +241,8 @@ finish_main_build :: (build: Pending_Build) {
|
|||||||
|
|
||||||
copied := copy_file(tprint("%/%", build_directory, executable_name), tprint("%/%", executable_folder, executable_name));
|
copied := copy_file(tprint("%/%", build_directory, executable_name), tprint("%/%", executable_folder, executable_name));
|
||||||
for MACOS_BUNDLE_DYLIBS copied &&= copy_file(tprint("assets/%", it), tprint("%/%", executable_folder, it));
|
for MACOS_BUNDLE_DYLIBS copied &&= copy_file(tprint("assets/%", it), tprint("%/%", executable_folder, it));
|
||||||
|
// FFmpeg, linked against, so beside the executable as SDL3 is (@loader_path).
|
||||||
|
for file_list("modules/ffmpeg/macos") if ends_with(it, ".dylib") copied &&= copy_file(it, tprint("%/%", executable_folder, path_filename(it)));
|
||||||
if !copied {
|
if !copied {
|
||||||
log_error("ERROR: Couldn't copy the executable and its dylibs into %\n", app);
|
log_error("ERROR: Couldn't copy the executable and its dylibs into %\n", app);
|
||||||
return;
|
return;
|
||||||
@ -368,9 +370,12 @@ copy_assets :: () {
|
|||||||
log("OCR: the models have not been fetched; run jai fetch_models.jai in modules/OCR for OCR.");
|
log("OCR: the models have not been fetched; run jai fetch_models.jai in modules/OCR for OCR.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Videos: FFmpeg's DLLs beside the executable (modules/ffmpeg/windows, in git), the same way.
|
// Videos: FFmpeg's libraries beside the executable (modules/ffmpeg/windows and macos, in git), the
|
||||||
|
// same way. The executable finds the dylibs there through its @loader_path rpath.
|
||||||
#if OS == .WINDOWS {
|
#if OS == .WINDOWS {
|
||||||
for file_list("modules/ffmpeg/windows") if ends_with(it, ".dll") copy_if_changed(it, tprint("%/%", build_directory, path_filename(it)));
|
for file_list("modules/ffmpeg/windows") if ends_with(it, ".dll") copy_if_changed(it, tprint("%/%", build_directory, path_filename(it)));
|
||||||
|
} else #if OS == .MACOS {
|
||||||
|
for file_list("modules/ffmpeg/macos") if ends_with(it, ".dylib") copy_if_changed(it, tprint("%/%", build_directory, path_filename(it)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Labels: its models in bin/label-models, the same way.
|
// Labels: its models in bin/label-models, the same way.
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
// the camera RAW formats that are TIFF inside: image_kind_from_name tells those apart.
|
// the camera RAW formats that are TIFF inside: image_kind_from_name tells those apart.
|
||||||
//
|
//
|
||||||
// Videos (video.jai) are told apart here too, by their first bytes or their extension; video_poster
|
// Videos (video.jai) are told apart here too, by their first bytes or their extension; video_poster
|
||||||
// reads a frame from one with FFmpeg, on Windows, and gif_info counts an animated GIF's frames.
|
// reads a frame from one with FFmpeg, on Windows and macOS, and gif_info counts an animated GIF's frames.
|
||||||
//
|
//
|
||||||
// Thread-safe: every call stands alone, and WIC is set up and released on the calling thread; ImageIO
|
// Thread-safe: every call stands alone, and WIC is set up and released on the calling thread; ImageIO
|
||||||
// needs no setting up.
|
// needs no setting up.
|
||||||
@ -266,7 +266,7 @@ png_size :: (png: [] u8) -> width: s64, height: s64, ok: bool {
|
|||||||
#load "video.jai";
|
#load "video.jai";
|
||||||
#if OS == .WINDOWS #load "wic.jai";
|
#if OS == .WINDOWS #load "wic.jai";
|
||||||
#if OS == .MACOS #load "imageio.jai";
|
#if OS == .MACOS #load "imageio.jai";
|
||||||
#if OS == .WINDOWS #load "video_ffmpeg.jai";
|
#if OS == .WINDOWS || OS == .MACOS #load "video_ffmpeg.jai";
|
||||||
|
|
||||||
#scope_module
|
#scope_module
|
||||||
|
|
||||||
|
|||||||
@ -24,9 +24,9 @@ Video_Info :: struct {
|
|||||||
// start with; the first frame of a clip shorter than a second.
|
// start with; the first frame of a clip shorter than a second.
|
||||||
VIDEO_POSTER_MAX_SECONDS :: 3.0;
|
VIDEO_POSTER_MAX_SECONDS :: 3.0;
|
||||||
|
|
||||||
#if OS != .WINDOWS {
|
#if OS == .LINUX {
|
||||||
video_poster :: (path: string) -> Image, Video_Info, ok: bool, error: string {
|
video_poster :: (path: string) -> Image, Video_Info, ok: bool, error: string {
|
||||||
return .{}, .{}, false, "videos are only read on Windows";
|
return .{}, .{}, false, "videos are only read on Windows and macOS";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// video_poster on Windows, with FFmpeg (modules/ffmpeg). See video.jai.
|
// video_poster on Windows and macOS, with FFmpeg (modules/ffmpeg). See video.jai.
|
||||||
|
|
||||||
video_poster :: (path: string) -> Image, Video_Info, ok: bool, error: string {
|
video_poster :: (path: string) -> Image, Video_Info, ok: bool, error: string {
|
||||||
image: Image;
|
image: Image;
|
||||||
|
|||||||
@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
FFmpeg bindings for jai and some examples decoding and play videos.
|
FFmpeg bindings for jai and some examples decoding and play videos.
|
||||||
|
|
||||||
|
## In mcap
|
||||||
|
|
||||||
|
FFmpeg 6.0 on both systems, so the two sets of bindings match:
|
||||||
|
|
||||||
|
- **Windows:** `windows/` holds the DLLs and import libraries of a GPL "full" build from gyan.dev
|
||||||
|
(`windows/LICENSE-BUILD.txt`), and `windows.jai` the bindings made from its headers (Setup below).
|
||||||
|
- **macOS:** `macos/` holds `libavcodec`, `libavformat`, `libavutil`, `libswresample` and `libswscale`,
|
||||||
|
an LGPL build for Apple silicon made from the release's source by `jai build_macos.jai` (about a
|
||||||
|
minute; `macos/LICENSE-BUILD.txt` has its configure options). It also installs the headers in
|
||||||
|
`macos-build/` (not in git), from which `jai generate.jai` on a Mac makes `macos.jai`. The libraries
|
||||||
|
are linked with `no_dll`, so the compiler does not load them, and copied beside the executable,
|
||||||
|
where its `@loader_path` rpath finds them.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
The FFmpeg libaries and header files are not included in this repo as I didn't want to have to deal with license
|
The FFmpeg libaries and header files are not included in this repo as I didn't want to have to deal with license
|
||||||
|
|||||||
117
modules/ffmpeg/build_macos.jai
Normal file
117
modules/ffmpeg/build_macos.jai
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Builds the FFmpeg 6.0 libraries mcap uses on macOS (avformat, avcodec, avutil, swscale and
|
||||||
|
// swresample) from the release's source, its SHA-256 checked, and puts them in macos/ with the
|
||||||
|
// headers the bindings are made from (generate.jai) in macos-build/install/include. The same version
|
||||||
|
// as the Windows DLLs (windows/), so the two sets of bindings match.
|
||||||
|
//
|
||||||
|
// cd modules/ffmpeg && jai build_macos.jai
|
||||||
|
//
|
||||||
|
// An LGPL build: no GPL parts (the Windows DLLs are a GPL build with libx264), nothing from outside
|
||||||
|
// macOS (--disable-autodetect, pkg-config pointed nowhere, so nothing from Homebrew is linked), and
|
||||||
|
// VideoToolbox and AudioToolbox for the hardware codecs. Needs Apple's command line tools: curl,
|
||||||
|
// tar, make and clang. A few minutes on Apple silicon.
|
||||||
|
|
||||||
|
FFMPEG_VERSION :: "6.0";
|
||||||
|
FFMPEG_ARCHIVE :: "ffmpeg-6.0.tar.xz";
|
||||||
|
FFMPEG_SHA256 :: "57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082";
|
||||||
|
|
||||||
|
BUILD_FOLDER :: "macos-build"; // the source, the build and the installed headers; not in git
|
||||||
|
OUTPUT_FOLDER :: "macos"; // the libraries, in git as windows/ is
|
||||||
|
|
||||||
|
// Each library as its major version names it, which is how they find each other (@rpath/...).
|
||||||
|
LIBRARIES :: string.["libavcodec.60.dylib", "libavformat.60.dylib", "libavutil.58.dylib", "libswresample.4.dylib", "libswscale.7.dylib"];
|
||||||
|
|
||||||
|
CONFIGURE_OPTIONS :: string.[
|
||||||
|
"--install-name-dir=@rpath",
|
||||||
|
"--enable-shared", "--disable-static",
|
||||||
|
"--disable-programs", "--disable-doc",
|
||||||
|
"--disable-avdevice", "--disable-avfilter", "--disable-postproc", "--disable-network",
|
||||||
|
"--disable-autodetect",
|
||||||
|
"--enable-videotoolbox", "--enable-audiotoolbox", "--enable-zlib", "--enable-bzlib",
|
||||||
|
"--extra-cflags=-mmacosx-version-min=14.0", "--extra-ldflags=-mmacosx-version-min=14.0",
|
||||||
|
];
|
||||||
|
|
||||||
|
#run,stallable {
|
||||||
|
set_build_options_dc(.{do_output = false});
|
||||||
|
#if OS != .MACOS {
|
||||||
|
log_error("build_macos.jai builds on a Mac only.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !build() compiler_set_workspace_status(.FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
build :: () -> bool {
|
||||||
|
here := get_working_directory();
|
||||||
|
build_folder := tprint("%/%", here, BUILD_FOLDER);
|
||||||
|
make_directory_if_it_does_not_exist(build_folder);
|
||||||
|
|
||||||
|
archive := tprint("%/%", build_folder, FFMPEG_ARCHIVE);
|
||||||
|
if !file_exists(archive) || sha256_of(archive) != FFMPEG_SHA256 {
|
||||||
|
url := tprint("https://ffmpeg.org/releases/%", FFMPEG_ARCHIVE);
|
||||||
|
log("Downloading %...", url);
|
||||||
|
result := run_command("curl", "-L", "--fail", "--progress-bar", "-o", archive, url);
|
||||||
|
if result.exit_code != 0 { log_error("curl failed (exit code %).", result.exit_code); return false; }
|
||||||
|
hash := sha256_of(archive);
|
||||||
|
if hash != FFMPEG_SHA256 {
|
||||||
|
log_error("% has SHA-256 %, expected %; it was not used.", archive, hash, FFMPEG_SHA256);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
source := tprint("%/ffmpeg-%", build_folder, FFMPEG_VERSION);
|
||||||
|
install := tprint("%/install", build_folder);
|
||||||
|
run_command("rm", "-rf", source, install);
|
||||||
|
result := run_command("tar", "xf", archive, "-C", build_folder);
|
||||||
|
if result.exit_code != 0 { log_error("tar could not unpack %.", archive); return false; }
|
||||||
|
|
||||||
|
log("Configuring...");
|
||||||
|
arguments: [..] string;
|
||||||
|
array_add(*arguments, "env", "PKG_CONFIG_LIBDIR=", "PKG_CONFIG_PATH=", "./configure", tprint("--prefix=%", install));
|
||||||
|
array_add(*arguments, ..CONFIGURE_OPTIONS);
|
||||||
|
result = run_command(..arguments, working_directory = source);
|
||||||
|
if result.exit_code != 0 { log_error("configure failed; see %/ffbuild/config.log.", source); return false; }
|
||||||
|
|
||||||
|
log("Building...");
|
||||||
|
cpus := get_number_of_processors();
|
||||||
|
result = run_command("make", tprint("-j%", cpus), working_directory = source);
|
||||||
|
if result.exit_code != 0 { log_error("make failed."); return false; }
|
||||||
|
result = run_command("make", "install", working_directory = source);
|
||||||
|
if result.exit_code != 0 { log_error("make install failed."); return false; }
|
||||||
|
|
||||||
|
output := tprint("%/%", here, OUTPUT_FOLDER);
|
||||||
|
run_command("rm", "-rf", output);
|
||||||
|
make_directory_if_it_does_not_exist(output);
|
||||||
|
for LIBRARIES {
|
||||||
|
// The major-version name is a link to the full one; the file itself is copied under that name.
|
||||||
|
if !copy_file(tprint("%/lib/%", install, it), tprint("%/%", output, it)) { log_error("Could not copy %.", it); return false; }
|
||||||
|
run_command("strip", "-x", tprint("%/%", output, it));
|
||||||
|
}
|
||||||
|
write_entire_file(tprint("%/LICENSE-BUILD.txt", output), tprint(LICENSE_TEXT, FFMPEG_VERSION, FFMPEG_ARCHIVE, FFMPEG_SHA256, join(..CONFIGURE_OPTIONS, "\n ")));
|
||||||
|
log("Put % libraries in % and the headers in %/include (FFmpeg %, LGPL).", LIBRARIES.count, output, install, FFMPEG_VERSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LICENSE_TEXT :: #string TEXT
|
||||||
|
FFmpeg % shared libraries for macOS on Apple silicon, built by modules/ffmpeg/build_macos.jai.
|
||||||
|
|
||||||
|
Source: https://ffmpeg.org/releases/%
|
||||||
|
SHA-256: %
|
||||||
|
|
||||||
|
License: LGPL version 2.1 or later (no GPL or non-free parts). The source is at the address above;
|
||||||
|
the libraries are built from it unchanged, with these configure options:
|
||||||
|
%
|
||||||
|
TEXT
|
||||||
|
|
||||||
|
// Lowercase hex, or "" when it could not be worked out.
|
||||||
|
sha256_of :: (path: string) -> string {
|
||||||
|
result, output := run_command("shasum", "-a", "256", path, capture_and_return_output = true);
|
||||||
|
if result.exit_code != 0 return "";
|
||||||
|
return to_lower_copy(trim(split(output, " ")[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#import "Basic";
|
||||||
|
#import "Compiler";
|
||||||
|
#import "File";
|
||||||
|
#import "File_Utilities";
|
||||||
|
#import "Process";
|
||||||
|
#import "String";
|
||||||
|
#import "System";
|
||||||
@ -46,10 +46,13 @@ FOOTER :: #string DONE
|
|||||||
|
|
||||||
DONE
|
DONE
|
||||||
|
|
||||||
INCLUDE_PATH :: "src";
|
// Windows: the headers of the downloaded build, copied to src. macOS: those build_macos.jai installs.
|
||||||
|
#if OS == .MACOS INCLUDE_PATH :: "macos-build/install/include";
|
||||||
|
else INCLUDE_PATH :: "src";
|
||||||
|
|
||||||
generate_bindings :: () -> bool {
|
generate_bindings :: () -> bool {
|
||||||
output_filename := "windows.jai";
|
#if OS == .MACOS output_filename := "macos.jai";
|
||||||
|
else output_filename := "windows.jai";
|
||||||
|
|
||||||
opts: Generate_Bindings_Options;
|
opts: Generate_Bindings_Options;
|
||||||
{
|
{
|
||||||
@ -67,9 +70,20 @@ generate_bindings :: () -> bool {
|
|||||||
// doesn't work, just get a load of __UnknownLib dont you :roll:.
|
// doesn't work, just get a load of __UnknownLib dont you :roll:.
|
||||||
// strip_flags &= ~.SYMBOLS_WITH_UNKNOWN_FOREIGN_LIBS;
|
// strip_flags &= ~.SYMBOLS_WITH_UNKNOWN_FOREIGN_LIBS;
|
||||||
|
|
||||||
|
#if OS == .MACOS {
|
||||||
|
// The five libraries build_macos.jai makes, as their major versions name them; with the
|
||||||
|
// extension, since the generator takes a name with a dot in it for a whole file name.
|
||||||
|
array_add(*libpaths, "macos");
|
||||||
|
library_names :: string.[
|
||||||
|
"libavcodec.60.dylib",
|
||||||
|
"libavformat.60.dylib",
|
||||||
|
"libavutil.58.dylib",
|
||||||
|
"libswresample.4.dylib",
|
||||||
|
"libswscale.7.dylib",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
array_add(*libpaths, "windows");
|
array_add(*libpaths, "windows");
|
||||||
|
library_names :: string.[
|
||||||
libraries := string.[
|
|
||||||
"avcodec-60",
|
"avcodec-60",
|
||||||
"avdevice-60",
|
"avdevice-60",
|
||||||
"avfilter-9",
|
"avfilter-9",
|
||||||
@ -79,7 +93,8 @@ generate_bindings :: () -> bool {
|
|||||||
"swresample-4",
|
"swresample-4",
|
||||||
"swscale-7",
|
"swscale-7",
|
||||||
];
|
];
|
||||||
for libraries array_add(*libnames, it);
|
}
|
||||||
|
for library_names array_add(*libnames, it);
|
||||||
|
|
||||||
array_add(*include_paths, INCLUDE_PATH);
|
array_add(*include_paths, INCLUDE_PATH);
|
||||||
|
|
||||||
@ -89,7 +104,7 @@ generate_bindings :: () -> bool {
|
|||||||
// pick the headers I want!
|
// pick the headers I want!
|
||||||
#if false {
|
#if false {
|
||||||
dirs_to_visit: [..] string;
|
dirs_to_visit: [..] string;
|
||||||
for libraries array_add(*dirs_to_visit, tprint("%/lib%", INCLUDE_PATH, it));
|
for library_names array_add(*dirs_to_visit, tprint("%/lib%", INCLUDE_PATH, it));
|
||||||
|
|
||||||
file_visitor :: (info: *File_Visit_Info, source_files : *[..] string) {
|
file_visitor :: (info: *File_Visit_Info, source_files : *[..] string) {
|
||||||
assert(info != null, "info (%) != null", info);
|
assert(info != null, "info (%) != null", info);
|
||||||
@ -121,7 +136,7 @@ generate_bindings :: () -> bool {
|
|||||||
array_add(*source_files, tprint("%/libavformat/avformat.h", INCLUDE_PATH));
|
array_add(*source_files, tprint("%/libavformat/avformat.h", INCLUDE_PATH));
|
||||||
array_add(*source_files, tprint("%/libswscale/swscale.h", INCLUDE_PATH));
|
array_add(*source_files, tprint("%/libswscale/swscale.h", INCLUDE_PATH));
|
||||||
|
|
||||||
array_add(*system_include_paths, GENERATOR_DEFAULT_SYSTEM_INCLUDE_PATH);
|
// system_include_paths left empty: the generator fills in this system's own.
|
||||||
|
|
||||||
builder: String_Builder;
|
builder: String_Builder;
|
||||||
append(*builder, HEADER);
|
append(*builder, HEADER);
|
||||||
@ -134,6 +149,14 @@ generate_bindings :: () -> bool {
|
|||||||
print("Generating ffmpeg bindings...\n");
|
print("Generating ffmpeg bindings...\n");
|
||||||
result := generate_bindings(opts, output_filename);
|
result := generate_bindings(opts, output_filename);
|
||||||
|
|
||||||
|
// The compiler loads each #library to run code at compile time, but there the dylibs cannot find
|
||||||
|
// each other through @rpath; nothing of FFmpeg's is run then, so none is loaded (no_dll).
|
||||||
|
#if OS == .MACOS if result {
|
||||||
|
text, ok := read_entire_file(output_filename);
|
||||||
|
if !ok return false;
|
||||||
|
result = write_entire_file(output_filename, replace(text, " :: #library \"macos/", " :: #library,no_dll \"macos/"));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +266,7 @@ generate_error_codes :: (b: *String_Builder) {
|
|||||||
for info_struct.members longest_name_length = max(longest_name_length, it.name.count);
|
for info_struct.members longest_name_length = max(longest_name_length, it.name.count);
|
||||||
for info_struct.members {
|
for info_struct.members {
|
||||||
slot := cast (*u8) *dummy + it.offset_in_bytes;
|
slot := cast (*u8) *dummy + it.offset_in_bytes;
|
||||||
value := << cast(*s32) slot;
|
value := (cast(*s32) slot).*;
|
||||||
append(b, it.name);
|
append(b, it.name);
|
||||||
num_spaces := longest_name_length - it.name.count;
|
num_spaces := longest_name_length - it.name.count;
|
||||||
for 1..num_spaces append(b, " ");
|
for 1..num_spaces append(b, " ");
|
||||||
|
|||||||
12947
modules/ffmpeg/macos.jai
Normal file
12947
modules/ffmpeg/macos.jai
Normal file
File diff suppressed because it is too large
Load Diff
23
modules/ffmpeg/macos/LICENSE-BUILD.txt
Normal file
23
modules/ffmpeg/macos/LICENSE-BUILD.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
FFmpeg 6.0 shared libraries for macOS on Apple silicon, built by modules/ffmpeg/build_macos.jai.
|
||||||
|
|
||||||
|
Source: https://ffmpeg.org/releases/ffmpeg-6.0.tar.xz
|
||||||
|
SHA-256: 57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082
|
||||||
|
|
||||||
|
License: LGPL version 2.1 or later (no GPL or non-free parts). The source is at the address above;
|
||||||
|
the libraries are built from it unchanged, with these configure options:
|
||||||
|
--install-name-dir=@rpath
|
||||||
|
--enable-shared
|
||||||
|
--disable-static
|
||||||
|
--disable-programs
|
||||||
|
--disable-doc
|
||||||
|
--disable-avdevice
|
||||||
|
--disable-avfilter
|
||||||
|
--disable-postproc
|
||||||
|
--disable-network
|
||||||
|
--disable-autodetect
|
||||||
|
--enable-videotoolbox
|
||||||
|
--enable-audiotoolbox
|
||||||
|
--enable-zlib
|
||||||
|
--enable-bzlib
|
||||||
|
--extra-cflags=-mmacosx-version-min=14.0
|
||||||
|
--extra-ldflags=-mmacosx-version-min=14.0
|
||||||
BIN
modules/ffmpeg/macos/libavcodec.60.dylib
Normal file
BIN
modules/ffmpeg/macos/libavcodec.60.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libavformat.60.dylib
Normal file
BIN
modules/ffmpeg/macos/libavformat.60.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libavutil.58.dylib
Normal file
BIN
modules/ffmpeg/macos/libavutil.58.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libswresample.4.dylib
Normal file
BIN
modules/ffmpeg/macos/libswresample.4.dylib
Normal file
Binary file not shown.
BIN
modules/ffmpeg/macos/libswscale.7.dylib
Normal file
BIN
modules/ffmpeg/macos/libswscale.7.dylib
Normal file
Binary file not shown.
@ -7,7 +7,9 @@ size_t :: u64;
|
|||||||
|
|
||||||
#if OS == .WINDOWS {
|
#if OS == .WINDOWS {
|
||||||
#load "windows.jai";
|
#load "windows.jai";
|
||||||
|
} else #if OS == .MACOS {
|
||||||
|
#load "macos.jai"; // generated from build_macos.jai's headers; its libraries are in macos/
|
||||||
} else {
|
} else {
|
||||||
#assert false, "Only windows has bindings atm, sorry bros!";
|
#assert false, "FFmpeg has bindings for Windows and macOS only.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -376,7 +376,7 @@ import_file :: (path: string) -> Import_Outcome, text: string, new_path: string
|
|||||||
|
|
||||||
// A video: hashed and copied into its .mcap a few MB at a time, so it can be larger than memory.
|
// A video: hashed and copied into its .mcap a few MB at a time, so it can be larger than memory.
|
||||||
import_video_file :: (path: string, name: string, head: [] u8, size: s64, modified: Apollo_Time) -> Import_Outcome, text: string, new_path: string {
|
import_video_file :: (path: string, name: string, head: [] u8, size: s64, modified: Apollo_Time) -> Import_Outcome, text: string, new_path: string {
|
||||||
if OS != .WINDOWS return .SKIPPED, "video (Windows only)", "";
|
if OS == .LINUX return .SKIPPED, "video (Windows and macOS only)", "";
|
||||||
|
|
||||||
hash, hashed := import_hash_file(.{path = path, offset = 0, size = size});
|
hash, hashed := import_hash_file(.{path = path, offset = 0, size = size});
|
||||||
if !hashed return .FAILED, "cannot be read", "";
|
if !hashed return .FAILED, "cannot be read", "";
|
||||||
|
|||||||
@ -254,7 +254,7 @@ open_file_proc :: (thread: *Thread) -> s64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case .VIDEO;
|
case .VIDEO;
|
||||||
#if OS == .WINDOWS {
|
#if OS == .WINDOWS || OS == .MACOS {
|
||||||
image, video, ok, poster_error := video_poster(path);
|
image, video, ok, poster_error := video_poster(path);
|
||||||
if !ok { error = poster_error; }
|
if !ok { error = poster_error; }
|
||||||
else {
|
else {
|
||||||
@ -265,7 +265,7 @@ open_file_proc :: (thread: *Thread) -> s64 {
|
|||||||
}
|
}
|
||||||
to_hash = .{path = path, offset = 0, size = open_file.size};
|
to_hash = .{path = path, offset = 0, size = open_file.size};
|
||||||
} else {
|
} else {
|
||||||
error = "videos are read on Windows only";
|
error = "videos are read on Windows and macOS only";
|
||||||
}
|
}
|
||||||
|
|
||||||
case;
|
case;
|
||||||
@ -492,7 +492,7 @@ open_file_library_ui :: (stage: Open_File_Stage) { using ImGui;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if open_file.kind == .UNKNOWN { TextColored(app_theme.palette.warning, "mcap does not import this kind of file."); return; }
|
if open_file.kind == .UNKNOWN { TextColored(app_theme.palette.warning, "mcap does not import this kind of file."); return; }
|
||||||
if OS != .WINDOWS && open_file.kind == .VIDEO { TextColored(app_theme.palette.warning, "Videos are imported on Windows only."); return; }
|
if OS == .LINUX && open_file.kind == .VIDEO { TextColored(app_theme.palette.warning, "Videos are imported on Windows and macOS only."); return; }
|
||||||
|
|
||||||
if open_file.importing {
|
if open_file.importing {
|
||||||
if importer.phase == .INDEXING Text("Indexing the library (once; this finds duplicates): %", ocr_scan_progress_text(importer.index_done, importer.index_total));
|
if importer.phase == .INDEXING Text("Indexing the library (once; this finds duplicates): %", ocr_scan_progress_text(importer.index_done, importer.index_total));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user