diff options
author | Martijn van Beurden <mvanb1@gmail.com> | 2023-07-18 16:33:34 +0200 |
---|---|---|
committer | Martijn van Beurden <mvanb1@gmail.com> | 2023-09-22 21:10:15 +0200 |
commit | 9abbcd41844d5e05c6b534440f7ac43e0383be4f (patch) | |
tree | b88defd7f3b32b17d996ea9290bd169642128cf4 | |
parent | df5dc22cbfd5dddef6493c04538da85128a33a26 (diff) | |
download | flac-9abbcd41844d5e05c6b534440f7ac43e0383be4f.tar.gz |
Enable main thread to code frame instead of idle
-rw-r--r-- | src/libFLAC/include/private/stream_encoder.h | 2 | ||||
-rw-r--r-- | src/libFLAC/stream_encoder.c | 115 |
2 files changed, 68 insertions, 49 deletions
diff --git a/src/libFLAC/include/private/stream_encoder.h b/src/libFLAC/include/private/stream_encoder.h index b358906b..310fd448 100644 --- a/src/libFLAC/include/private/stream_encoder.h +++ b/src/libFLAC/include/private/stream_encoder.h @@ -43,7 +43,7 @@ */ #define FLAC__MAX_EXTRA_RESIDUAL_BPS 4 #define FLAC__STREAM_ENCODER_MAX_THREADS 16 -#define FLAC__STREAM_ENCODER_MAX_THREADTASKS 32 +#define FLAC__STREAM_ENCODER_MAX_THREADTASKS 34 #if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN #include "private/cpu.h" diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c index bd81047c..e651362c 100644 --- a/src/libFLAC/stream_encoder.c +++ b/src/libFLAC/stream_encoder.c @@ -224,7 +224,8 @@ static void update_metadata_(const FLAC__StreamEncoder *encoder); static void update_ogg_metadata_(FLAC__StreamEncoder *encoder); #endif static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block); -void * process_frame_thread_(void * threadtask); +void * process_frame_thread_(void * encoder); +FLAC__bool process_frame_thread_inner_(FLAC__StreamEncoder * encoder); static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderThreadTask *threadtask); static FLAC__bool process_subframe_( @@ -1150,7 +1151,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( if(encoder->protected_->num_threads > 1) { #ifdef HAVE_PTHREAD - encoder->private_->num_threadtasks = encoder->protected_->num_threads * 2; /* First threadtask is reserved for main thread */ + encoder->private_->num_threadtasks = encoder->protected_->num_threads * 2 + 2; /* First threadtask is reserved for main thread */ if(sem_init(&encoder->private_->sem_work_available, 0, 0)) { encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; @@ -1174,7 +1175,7 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR; } if(encoder->protected_->do_md5) { - encoder->private_->md5_fifo.size = (encoder->protected_->blocksize+OVERREAD_) * encoder->private_->num_threadtasks; + encoder->private_->md5_fifo.size = (encoder->protected_->blocksize+OVERREAD_) * (encoder->private_->num_threadtasks + 2); for(i = 0; i < encoder->protected_->channels; i++) { if(0 == (encoder->private_->md5_fifo.data[i] = safe_malloc_mul_2op_p(sizeof(FLAC__int32), /*times*/encoder->private_->md5_fifo.size))) { sem_destroy(&encoder->private_->sem_work_available); @@ -3429,8 +3430,18 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block encoder->private_->num_created_threads++; } else if(encoder->private_->num_started_threadtasks == encoder->private_->num_threadtasks) { + /* If the first task in the queue is still running, there is probably plenty + * of work left in the queue. When that is the case, do some work instead of + * waiting */ + while(sem_trywait(&encoder->private_->threadtask[encoder->private_->next_thread]->sem_work_done)) { + if(sem_trywait(&encoder->private_->sem_work_available) == 0) + process_frame_thread_inner_(encoder); + else { + sem_wait(&encoder->private_->threadtask[encoder->private_->next_thread]->sem_work_done); + break; + } + } /* Wait for thread to finish, then write bitbuffer */ - sem_wait(&encoder->private_->threadtask[encoder->private_->next_thread]->sem_work_done); if(!encoder->private_->threadtask[encoder->private_->next_thread]->returnvalue) return false; if(!write_bitbuffer_(encoder, encoder->private_->threadtask[encoder->private_->next_thread], encoder->protected_->blocksize, is_last_block)) { @@ -3481,12 +3492,9 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block #ifdef HAVE_PTHREAD void * process_frame_thread_(void * args) { FLAC__StreamEncoder * encoder = args; - FLAC__StreamEncoderThreadTask * task; - FLAC__uint16 crc; - uint32_t t, channel; + uint32_t channel; while(1) { - FLAC__bool ok = true; /* First check whether non MD5 work is available. If it isn't, try to * check whether a thread is already waiting for MD5 work. If that isn't * the case either, wait for non-MD5 work */ @@ -3515,53 +3523,64 @@ void * process_frame_thread_(void * args) { #ifdef __APPLE__ pthread_testcancel(); #endif - - task = NULL; - for(t = 1; t < encoder->private_->num_threadtasks; t++) { - if(sem_trywait(&encoder->private_->threadtask[t]->sem_work_available) == 0) { - task = encoder->private_->threadtask[t]; - break; - } - } - if(task == NULL) { - encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; - FLAC__ASSERT(0); + if(!process_frame_thread_inner_(encoder)){ return NULL; } + } +} - /* - * Process the frame header and subframes into the frame bitbuffer - */ - if(ok && !process_subframes_(encoder, task)) { - /* the above function sets the state for us in case of an error */ - ok = false; - } +FLAC__bool process_frame_thread_inner_(FLAC__StreamEncoder * encoder) { + FLAC__bool ok = true; + FLAC__StreamEncoderThreadTask * task; + FLAC__uint16 crc; + uint32_t t; - /* - * Zero-pad the frame to a byte_boundary - */ - if(ok && !FLAC__bitwriter_zero_pad_to_byte_boundary(task->frame)) { - encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; - ok = false; + task = NULL; + for(t = 1; t < encoder->private_->num_threadtasks; t++) { + if(sem_trywait(&encoder->private_->threadtask[t]->sem_work_available) == 0) { + task = encoder->private_->threadtask[t]; + break; } + } + if(task == NULL) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + FLAC__ASSERT(0); + return false; + } - /* - * CRC-16 the whole thing - */ - FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(task->frame)); - if( - ok && - ( - !FLAC__bitwriter_get_write_crc16(task->frame, &crc) || - !FLAC__bitwriter_write_raw_uint32(task->frame, crc, FLAC__FRAME_FOOTER_CRC_LEN) - ) - ) { - encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; - ok = false; - } - task->returnvalue = ok; - sem_post(&task->sem_work_done); + /* + * Process the frame header and subframes into the frame bitbuffer + */ + if(ok && !process_subframes_(encoder, task)) { + /* the above function sets the state for us in case of an error */ + ok = false; + } + + /* + * Zero-pad the frame to a byte_boundary + */ + if(ok && !FLAC__bitwriter_zero_pad_to_byte_boundary(task->frame)) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + ok = false; } + + /* + * CRC-16 the whole thing + */ + FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(task->frame)); + if( + ok && + ( + !FLAC__bitwriter_get_write_crc16(task->frame, &crc) || + !FLAC__bitwriter_write_raw_uint32(task->frame, crc, FLAC__FRAME_FOOTER_CRC_LEN) + ) + ) { + encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + ok = false; + } + task->returnvalue = ok; + sem_post(&task->sem_work_done); + return true; } #endif |