Skip to content

Commit 1e71c03

Browse files
committed
flac 1.5 multithreading support
1 parent a851ec0 commit 1e71c03

File tree

1 file changed

+99
-2
lines changed

1 file changed

+99
-2
lines changed

misrc_tools/misrc_capture.c

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
*/
2323

24+
#if defined(__linux__)
25+
#define _GNU_SOURCE
26+
#include <sched.h>
27+
#elif defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
28+
#include <sys/types.h>
29+
#include <sys/sysctl.h>
30+
#endif
31+
2432
#include <errno.h>
2533
#include <signal.h>
2634
#include <string.h>
@@ -59,7 +67,17 @@
5967
#if LIBFLAC_ENABLED == 1
6068
#include "FLAC/metadata.h"
6169
#include "FLAC/stream_encoder.h"
62-
#define GETOPT_STRING "d:a:b:fl:vx:r:ph"
70+
# if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 14
71+
# define GETOPT_STRING "d:a:b:c:fl:vx:r:ph"
72+
static const char* const _FLAC_StreamEncoderSetNumThreadsStatusString[] = {
73+
"FLAC__STREAM_ENCODER_SET_NUM_THREADS_OK",
74+
"FLAC__STREAM_ENCODER_SET_NUM_THREADS_NOT_COMPILED_WITH_MULTITHREADING_ENABLED",
75+
"FLAC__STREAM_ENCODER_SET_NUM_THREADS_ALREADY_INITIALIZED",
76+
"FLAC__STREAM_ENCODER_SET_NUM_THREADS_TOO_MANY_THREADS"
77+
};
78+
# else
79+
# define GETOPT_STRING "d:a:b:fl:vx:r:ph"
80+
# endif
6381
#else
6482
#define GETOPT_STRING "d:a:b:x:r:ph"
6583
#endif
@@ -87,6 +105,7 @@ typedef struct {
87105
#if LIBFLAC_ENABLED == 1
88106
uint32_t flac_level;
89107
bool flac_verify;
108+
uint32_t flac_threads;
90109
#endif
91110
} filewriter_ctx_t;
92111

@@ -111,6 +130,9 @@ void usage(void)
111130
"\t[-f compress ADC output as FLAC]\n"
112131
"\t[-l LEVEL set flac compression level (default: 1)]\n"
113132
"\t[-v enable verification of flac encoder output]\n"
133+
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 14
134+
"\t[-c number of encoding threads per file (default: auto)]\n"
135+
#endif
114136
#endif
115137
);
116138
exit(1);
@@ -189,6 +211,7 @@ int flac_file_writer(void *ctx)
189211
filewriter_ctx_t *file_ctx = ctx;
190212
size_t len = BUFFER_READ_SIZE;
191213
void *buf;
214+
uint32_t ret;
192215
FLAC__bool ok = true;
193216
FLAC__StreamEncoder *encoder = NULL;
194217
FLAC__StreamEncoderInitStatus init_status;
@@ -211,7 +234,12 @@ int flac_file_writer(void *ctx)
211234
do_exit = 1;
212235
return 0;
213236
}
214-
237+
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 14
238+
ret = FLAC__stream_encoder_set_num_threads(encoder, file_ctx->flac_threads);
239+
if (ret != FLAC__STREAM_ENCODER_SET_NUM_THREADS_OK) {
240+
fprintf(stderr, "ERROR: failed to set FLAC threads: %s\n", _FLAC_StreamEncoderSetNumThreadsStatusString[ret]);
241+
}
242+
#endif
215243
if((seektable = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE)) == NULL
216244
|| FLAC__metadata_object_seektable_template_append_spaced_points(seektable, 1<<18, (uint64_t)1<<41) != true
217245
|| FLAC__stream_encoder_set_metadata(encoder, &seektable, 1) != true) {
@@ -252,10 +280,12 @@ int flac_file_writer(void *ctx)
252280
}
253281
FLAC__metadata_object_seektable_template_sort(seektable, false);
254282
/* bug in libflac, fix seektable manually */
283+
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT < 14
255284
for(int i = seektable->data.seek_table.num_points-1; i>=0; i--) {
256285
if (seektable->data.seek_table.points[i].stream_offset != 0) break;
257286
seektable->data.seek_table.points[i].sample_number = 0xFFFFFFFFFFFFFFFF;
258287
}
288+
#endif
259289
ok = FLAC__stream_encoder_finish(encoder);
260290
if(!ok) {
261291
fprintf(stderr, "ERROR: FLAC encoder did not finish correctly: %s\n", FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder)]);
@@ -274,6 +304,55 @@ void print_hsdaoh_message(int msg_type, int msg, void *additional, void *ctx)
274304
new_line = 1;
275305
}
276306

307+
#if LIBFLAC_ENABLED == 1 && defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 14
308+
uint32_t get_num_cores() {
309+
uint32_t numberOfCores = 0;
310+
#if defined(_WIN32) || defined(_WIN64)
311+
DWORD_PTR processAffinityMask;
312+
DWORD_PTR systemAffinityMask;
313+
if (GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask)) {
314+
while (processAffinityMask) {
315+
numberOfCores += processAffinityMask & 1;
316+
processAffinityMask >>= 1;
317+
}
318+
return numberOfCores;
319+
} else {
320+
// Handle error
321+
SYSTEM_INFO sysInfo;
322+
fprintf(stderr, "GetProcessAffinityMask failed with error to get number of cores: %lu, fallback to GetSystemInfo\n", GetLastError());
323+
GetSystemInfo(&sysInfo);
324+
return sysInfo.dwNumberOfProcessors;
325+
}
326+
#elif defined(__linux__)
327+
cpu_set_t mask;
328+
if (sched_getaffinity(0, sizeof(cpu_set_t), &mask) == 0) {
329+
return CPU_COUNT(&mask);
330+
} else {
331+
// Handle error
332+
fprintf(stderr, "sched_getaffinity failed to get number of cores, fallback to sysconf\n");
333+
// cores in deep-sleep are not counted with _SC_NPROCESSORS_ONLN, therefore using _CONF instead
334+
return sysconf(_SC_NPROCESSORS_CONF);
335+
}
336+
#elif defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
337+
size_t size = sizeof(numberOfCores);
338+
#if defined(__APPLE__) || defined(__MACH__)
339+
if (sysctlbyname("hw.logicalcpu", &numberOfCores, &size, NULL, 0) == 0) {
340+
#else
341+
if (sysctlbyname("hw.ncpu", &numberOfCores, &size, NULL, 0) == 0) {
342+
#endif
343+
return numberOfCores;
344+
} else {
345+
// Handle error
346+
fprintf(stderr, "failed to get number of cores\n");
347+
return 0;
348+
}
349+
#else
350+
#warning "No code to get number of cores on this platform!"
351+
return 0;
352+
#endif
353+
}
354+
#endif
355+
277356
int main(int argc, char **argv)
278357
{
279358
//set pipe mode to binary in windows
@@ -288,6 +367,7 @@ int main(int argc, char **argv)
288367
#if LIBFLAC_ENABLED == 1
289368
int flac_level = 1;
290369
bool flac_verify = false;
370+
uint32_t flac_threads = 0;
291371
#endif
292372
thrd_start_t output_thread_func = raw_file_writer;
293373
capture_ctx_t cap_ctx;
@@ -342,6 +422,11 @@ int main(int argc, char **argv)
342422
output_names[1] = optarg;
343423
break;
344424
#if LIBFLAC_ENABLED == 1
425+
#if defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 14
426+
case 'c':
427+
flac_threads = (uint32_t)atoi(optarg);
428+
break;
429+
#endif
345430
case 'f':
346431
output_thread_func = flac_file_writer;
347432
out_size = 4;
@@ -374,6 +459,17 @@ int main(int argc, char **argv)
374459
usage();
375460
}
376461

462+
#if LIBFLAC_ENABLED == 1 && defined(FLAC_API_VERSION_CURRENT) && FLAC_API_VERSION_CURRENT >= 14
463+
if (flac_threads == 0) {
464+
int out_cnt = ((output_names[0] == NULL) ? 0 : 1) + ((output_names[1] == NULL) ? 0 : 1);
465+
flac_threads = get_num_cores();
466+
fprintf(stderr,"Detected %d cores in the system available to the process\n",flac_threads);
467+
flac_threads = (flac_threads - 2 - out_cnt) / out_cnt;
468+
if (flac_threads == 0) flac_threads = 1;
469+
if (flac_threads > 128) flac_threads = 128;
470+
}
471+
#endif
472+
377473
#ifndef _WIN32
378474
sigact.sa_handler = sighandler;
379475
sigemptyset(&sigact.sa_mask);
@@ -408,6 +504,7 @@ int main(int argc, char **argv)
408504
#if LIBFLAC_ENABLED == 1
409505
thread_out_ctx[i].flac_level = flac_level;
410506
thread_out_ctx[i].flac_verify = flac_verify;
507+
thread_out_ctx[i].flac_threads = flac_threads;
411508
#endif
412509
outbuffer_name[3] = (char)(i+48);
413510
rb_init(&thread_out_ctx[i].rb, outbuffer_name, BUFFER_TOTAL_SIZE);

0 commit comments

Comments
 (0)