avifenc, avifdec: Allow "-j all" to automatically use all of the cores on the machine
Fixes: #645
diff --git a/apps/avifdec.c b/apps/avifdec.c
index 313439c..81de197 100644
--- a/apps/avifdec.c
+++ b/apps/avifdec.c
@@ -29,7 +29,7 @@
printf("Options:\n");
printf(" -h,--help : Show syntax help\n");
printf(" -V,--version : Show the version number\n");
- printf(" -j,--jobs J : Number of jobs (worker threads, default: 1)\n");
+ printf(" -j,--jobs J : Number of jobs (worker threads, default: 1. Use \"all\" to use all available cores)\n");
printf(" -c,--codec C : AV1 codec to use (choose from versions list below)\n");
printf(" -d,--depth D : Output depth [8,16]. (PNG only; For y4m, depth is retained, and JPEG is always 8bpc)\n");
printf(" -q,--quality Q : Output quality [0-100]. (JPEG only, default: %d)\n", DEFAULT_JPEG_QUALITY);
@@ -74,9 +74,13 @@
return 0;
} else if (!strcmp(arg, "-j") || !strcmp(arg, "--jobs")) {
NEXTARG();
- jobs = atoi(arg);
- if (jobs < 1) {
- jobs = 1;
+ if (!strcmp(arg, "all")) {
+ jobs = avifQueryMaxThreads();
+ } else {
+ jobs = atoi(arg);
+ if (jobs < 1) {
+ jobs = 1;
+ }
}
} else if (!strcmp(arg, "-c") || !strcmp(arg, "--codec")) {
NEXTARG();
diff --git a/apps/avifenc.c b/apps/avifenc.c
index 3e8a3b0..4415bf8 100644
--- a/apps/avifenc.c
+++ b/apps/avifenc.c
@@ -51,7 +51,7 @@
printf("Options:\n");
printf(" -h,--help : Show syntax help\n");
printf(" -V,--version : Show the version number\n");
- printf(" -j,--jobs J : Number of jobs (worker threads, default: 1)\n");
+ printf(" -j,--jobs J : Number of jobs (worker threads, default: 1. Use \"all\" to use all available cores)\n");
printf(" -o,--output FILENAME : Instead of using the last filename given as output, use this filename\n");
printf(" -l,--lossless : Set all defaults to encode losslessly, and emit warnings when settings/input don't allow for it\n");
printf(" -d,--depth D : Output depth [8,10,12]. (JPEG/PNG only; For y4m or stdin, depth is retained)\n");
@@ -487,9 +487,13 @@
goto cleanup;
} else if (!strcmp(arg, "-j") || !strcmp(arg, "--jobs")) {
NEXTARG();
- jobs = atoi(arg);
- if (jobs < 1) {
- jobs = 1;
+ if (!strcmp(arg, "all")) {
+ jobs = avifQueryMaxThreads();
+ } else {
+ jobs = atoi(arg);
+ if (jobs < 1) {
+ jobs = 1;
+ }
}
} else if (!strcmp(arg, "--stdin")) {
input.useStdin = AVIF_TRUE;
diff --git a/apps/shared/avifutil.c b/apps/shared/avifutil.c
index e99d8f0..4ddc406 100644
--- a/apps/shared/avifutil.c
+++ b/apps/shared/avifutil.c
@@ -220,3 +220,74 @@
printf("Diagnostics:\n");
printf(" * %s\n", diag->error);
}
+
+// ---------------------------------------------------------------------------
+// avifQueryMaxThreads (separated into OS implementations)
+
+#if defined(_WIN32)
+
+// Windows
+
+#pragma warning(disable : 5031)
+#pragma warning(disable : 5032)
+#include <windows.h>
+
+int avifQueryMaxThreads(void)
+{
+ int numCPU;
+ SYSTEM_INFO sysinfo;
+ GetSystemInfo(&sysinfo);
+ numCPU = sysinfo.dwNumberOfProcessors;
+ return numCPU;
+}
+
+#elif defined(__APPLE__)
+
+// Apple
+
+#include <sys/sysctl.h>
+
+int avifQueryMaxThreads()
+{
+ int mib[4];
+ int numCPU;
+ size_t len = sizeof(numCPU);
+
+ /* set the mib for hw.ncpu */
+ mib[0] = CTL_HW;
+ mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;
+
+ /* get the number of CPUs from the system */
+ sysctl(mib, 2, &numCPU, &len, NULL, 0);
+
+ if (numCPU < 1) {
+ mib[1] = HW_NCPU;
+ sysctl(mib, 2, &numCPU, &len, NULL, 0);
+ if (numCPU < 1)
+ numCPU = 1;
+ }
+ return numCPU;
+}
+
+#elif defined(__EMSCRIPTEN__)
+
+// Emscripten
+
+int avifQueryMaxThreads()
+{
+ return 1;
+}
+
+#else
+
+// POSIX
+
+#include <unistd.h>
+
+int avifQueryMaxThreads()
+{
+ int numCPU = (int)sysconf(_SC_NPROCESSORS_ONLN);
+ return (numCPU > 0) ? numCPU : 1;
+}
+
+#endif
diff --git a/apps/shared/avifutil.h b/apps/shared/avifutil.h
index cd26b3a..a8fed45 100644
--- a/apps/shared/avifutil.h
+++ b/apps/shared/avifutil.h
@@ -23,6 +23,7 @@
void avifContainerDump(avifDecoder * decoder);
void avifPrintVersions(void);
void avifDumpDiagnostics(const avifDiagnostics * diag);
+int avifQueryMaxThreads(void);
typedef enum avifAppFileFormat
{