Skip to content

Commit d2b2441

Browse files
authored
Different loose mid side algorithm compatible with multithreading (#675)
1 parent 8d4ccdf commit d2b2441

File tree

1 file changed

+65
-80
lines changed

1 file changed

+65
-80
lines changed

src/libFLAC/stream_encoder.c

+65-80
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@
8383
*/
8484
#undef ENABLE_RICE_PARAMETER_SEARCH
8585

86+
#ifdef local_abs64
87+
#undef local_abs64
88+
#endif
89+
#define local_abs64(x) ((uint64_t)((x)<0? -(x) : (x)))
90+
8691

8792
typedef struct {
8893
FLAC__int32 *data[FLAC__MAX_CHANNELS];
@@ -413,9 +418,6 @@ typedef struct FLAC__StreamEncoderPrivate {
413418
FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
414419
FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
415420
#endif
416-
uint32_t loose_mid_side_stereo_frames; /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
417-
uint32_t loose_mid_side_stereo_frame_count; /* number of frames using the current channel assignment */
418-
FLAC__ChannelAssignment last_channel_assignment;
419421
FLAC__StreamMetadata streaminfo; /* scratchpad for STREAMINFO as it is built */
420422
FLAC__StreamMetadata_SeekTable *seek_table; /* pointer into encoder->protected_->metadata_ where the seek table is */
421423
uint32_t current_sample_number;
@@ -737,9 +739,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_(
737739
else if(!encoder->protected_->do_mid_side_stereo)
738740
encoder->protected_->loose_mid_side_stereo = false;
739741

740-
if(encoder->protected_->loose_mid_side_stereo && encoder->protected_->num_threads > 2)
741-
encoder->protected_->num_threads = 2;
742-
743742
if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__MAX_BITS_PER_SAMPLE)
744743
return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
745744

@@ -921,20 +920,6 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_(
921920
}
922921

923922
encoder->private_->input_capacity = 0;
924-
#ifndef FLAC__INTEGER_ONLY_LIBRARY
925-
encoder->private_->loose_mid_side_stereo_frames = (uint32_t)((double)encoder->protected_->sample_rate * 0.4 / (double)encoder->protected_->blocksize + 0.5);
926-
#else
927-
/* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */
928-
/* sample rate can be up to 1048575 Hz, and thus use 20 bits, so we do the multiply&divide by hand */
929-
FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 1048575);
930-
FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535);
931-
FLAC__ASSERT(encoder->protected_->sample_rate <= 1048575);
932-
FLAC__ASSERT(encoder->protected_->blocksize <= 65535);
933-
encoder->private_->loose_mid_side_stereo_frames = (uint32_t)FLAC__fixedpoint_trunc((((FLAC__uint64)(encoder->protected_->sample_rate) * (FLAC__uint64)(26214)) << 16) / (encoder->protected_->blocksize<<16) + FLAC__FP_ONE_HALF);
934-
#endif
935-
if(encoder->private_->loose_mid_side_stereo_frames == 0)
936-
encoder->private_->loose_mid_side_stereo_frames = 1;
937-
encoder->private_->loose_mid_side_stereo_frame_count = 0;
938923
encoder->private_->current_sample_number = 0;
939924
encoder->private_->current_frame_number = 0;
940925

@@ -3518,42 +3503,35 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_block
35183503
}
35193504
else if(encoder->private_->num_started_threadtasks == encoder->private_->num_threadtasks) {
35203505
/* If the first task in the queue is still running, check whether there is enough work
3521-
* left in the queue. If there is, start on some */
3522-
if(encoder->protected_->loose_mid_side_stereo) {
3523-
pthread_mutex_lock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3524-
if(!encoder->private_->threadtask[encoder->private_->next_thread]->task_done)
3525-
pthread_cond_wait(&encoder->private_->threadtask[encoder->private_->next_thread]->cond_task_done, &encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3526-
}
3527-
else {
3528-
/* First, check whether the mutex for the next due task is locked or free. If it is free (and thus acquired now) and
3529-
* the task is done, proceed to the next bit (writing the bitbuffer). If it is either currently locked or not yet
3530-
* processed, choose between starting on some work (if there is enough work in the queue) or waiting for the task
3531-
* to finish. Either way, release the mutex first, so it doesn't get interlocked with the work queue mutex */
3532-
int mutex_result = pthread_mutex_trylock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3533-
while(mutex_result || !encoder->private_->threadtask[encoder->private_->next_thread]->task_done) {
3534-
if(!mutex_result)
3535-
pthread_mutex_unlock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3536-
3537-
pthread_mutex_lock(&encoder->private_->mutex_work_queue);
3538-
if(encoder->private_->num_available_threadtasks > (encoder->protected_->num_threads - 1)) {
3539-
FLAC__StreamEncoderThreadTask * task = NULL;
3540-
task = encoder->private_->threadtask[encoder->private_->next_threadtask];
3541-
encoder->private_->num_available_threadtasks--;
3542-
encoder->private_->next_threadtask++;
3543-
if(encoder->private_->next_threadtask == encoder->private_->num_threadtasks)
3544-
encoder->private_->next_threadtask = 1;
3545-
pthread_mutex_unlock(&encoder->private_->mutex_work_queue);
3546-
pthread_mutex_lock(&task->mutex_this_task);
3547-
process_frame_thread_inner_(encoder, task);
3548-
mutex_result = pthread_mutex_trylock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3549-
}
3550-
else {
3551-
pthread_mutex_unlock(&encoder->private_->mutex_work_queue);
3552-
pthread_mutex_lock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3553-
while(!encoder->private_->threadtask[encoder->private_->next_thread]->task_done)
3554-
pthread_cond_wait(&encoder->private_->threadtask[encoder->private_->next_thread]->cond_task_done,&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3555-
mutex_result = 0;
3556-
}
3506+
* left in the queue. If there is, start on some
3507+
* First, check whether the mutex for the next due task is locked or free. If it is free (and thus acquired now) and
3508+
* the task is done, proceed to the next bit (writing the bitbuffer). If it is either currently locked or not yet
3509+
* processed, choose between starting on some work (if there is enough work in the queue) or waiting for the task
3510+
* to finish. Either way, release the mutex first, so it doesn't get interlocked with the work queue mutex */
3511+
int mutex_result = pthread_mutex_trylock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3512+
while(mutex_result || !encoder->private_->threadtask[encoder->private_->next_thread]->task_done) {
3513+
if(!mutex_result)
3514+
pthread_mutex_unlock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3515+
3516+
pthread_mutex_lock(&encoder->private_->mutex_work_queue);
3517+
if(encoder->private_->num_available_threadtasks > (encoder->protected_->num_threads - 1)) {
3518+
FLAC__StreamEncoderThreadTask * task = NULL;
3519+
task = encoder->private_->threadtask[encoder->private_->next_threadtask];
3520+
encoder->private_->num_available_threadtasks--;
3521+
encoder->private_->next_threadtask++;
3522+
if(encoder->private_->next_threadtask == encoder->private_->num_threadtasks)
3523+
encoder->private_->next_threadtask = 1;
3524+
pthread_mutex_unlock(&encoder->private_->mutex_work_queue);
3525+
pthread_mutex_lock(&task->mutex_this_task);
3526+
process_frame_thread_inner_(encoder, task);
3527+
mutex_result = pthread_mutex_trylock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3528+
}
3529+
else {
3530+
pthread_mutex_unlock(&encoder->private_->mutex_work_queue);
3531+
pthread_mutex_lock(&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3532+
while(!encoder->private_->threadtask[encoder->private_->next_thread]->task_done)
3533+
pthread_cond_wait(&encoder->private_->threadtask[encoder->private_->next_thread]->cond_task_done,&encoder->private_->threadtask[encoder->private_->next_thread]->mutex_this_task);
3534+
mutex_result = 0;
35573535
}
35583536
}
35593537
/* Task is finished, write bitbuffer */
@@ -3769,14 +3747,33 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
37693747
*/
37703748
if(encoder->protected_->do_mid_side_stereo) {
37713749
if(encoder->protected_->loose_mid_side_stereo) {
3772-
FLAC__ASSERT(encoder->protected_->num_threads < 3);
3773-
if(encoder->private_->loose_mid_side_stereo_frame_count == 0) {
3750+
uint64_t sumAbsLR = 0, sumAbsMS = 0;
3751+
uint32_t i;
3752+
if(encoder->protected_->bits_per_sample < 25) {
3753+
for(i = 1; i < encoder->protected_->blocksize; i++) {
3754+
int32_t predictionLeft = threadtask->integer_signal[0][i] - threadtask->integer_signal[0][i-1];
3755+
int32_t predictionRight = threadtask->integer_signal[1][i] - threadtask->integer_signal[1][i-1];
3756+
sumAbsLR += abs(predictionLeft) + abs(predictionRight);
3757+
sumAbsMS += abs((predictionLeft + predictionRight) >> 1) + abs(predictionLeft - predictionRight);
3758+
}
3759+
}
3760+
else { /* bps 25 or higher */
3761+
for(i = 1; i < encoder->protected_->blocksize; i++) {
3762+
int64_t predictionLeft = (int64_t)threadtask->integer_signal[0][i] - (int64_t)threadtask->integer_signal[0][i-1];
3763+
int64_t predictionRight = (int64_t)threadtask->integer_signal[1][i] - (int64_t)threadtask->integer_signal[1][i-1];
3764+
sumAbsLR += local_abs64(predictionLeft) + local_abs64(predictionRight);
3765+
sumAbsMS += local_abs64((predictionLeft + predictionRight) >> 1) + local_abs64(predictionLeft - predictionRight);
3766+
}
3767+
}
3768+
if(sumAbsLR < sumAbsMS) {
37743769
do_independent = true;
3775-
do_mid_side = true;
3770+
do_mid_side = false;
3771+
frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT;
37763772
}
37773773
else {
3778-
do_independent = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT);
3779-
do_mid_side = !do_independent;
3774+
do_independent = false;
3775+
do_mid_side = true;
3776+
frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_MID_SIDE;
37803777
}
37813778
}
37823779
else {
@@ -3908,17 +3905,14 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
39083905
/*
39093906
* Compose the frame bitbuffer
39103907
*/
3911-
if(do_mid_side) {
3908+
if((do_independent && do_mid_side) || encoder->protected_->loose_mid_side_stereo) {
39123909
uint32_t left_bps = 0, right_bps = 0; /* initialized only to prevent superfluous compiler warning */
39133910
FLAC__Subframe *left_subframe = 0, *right_subframe = 0; /* initialized only to prevent superfluous compiler warning */
39143911
FLAC__ChannelAssignment channel_assignment;
39153912

39163913
FLAC__ASSERT(encoder->protected_->channels == 2);
39173914

3918-
if(encoder->protected_->loose_mid_side_stereo && encoder->private_->loose_mid_side_stereo_frame_count > 0) {
3919-
channel_assignment = (encoder->private_->last_channel_assignment == FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT? FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT : FLAC__CHANNEL_ASSIGNMENT_MID_SIDE);
3920-
}
3921-
else {
3915+
if(!encoder->protected_->loose_mid_side_stereo) {
39223916
uint32_t bits[4]; /* WATCHOUT - indexed by FLAC__ChannelAssignment */
39233917
uint32_t min_bits;
39243918
int ca;
@@ -3927,7 +3921,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
39273921
FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE == 1);
39283922
FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE == 2);
39293923
FLAC__ASSERT(FLAC__CHANNEL_ASSIGNMENT_MID_SIDE == 3);
3930-
FLAC__ASSERT(do_independent && do_mid_side);
39313924

39323925
/* We have to figure out which channel assignent results in the smallest frame */
39333926
bits[FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT] = threadtask->best_subframe_bits [0] + threadtask->best_subframe_bits [1];
@@ -3940,23 +3933,21 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
39403933

39413934
/* When doing loose mid-side stereo, ignore left-side
39423935
* and right-side options */
3943-
ca = encoder->protected_->loose_mid_side_stereo ? 3 : 1;
3944-
for( ; ca <= 3; ca++) {
3936+
for(ca = 1; ca <= 3; ca++) {
39453937
if(bits[ca] < min_bits) {
39463938
min_bits = bits[ca];
39473939
channel_assignment = (FLAC__ChannelAssignment)ca;
39483940
}
39493941
}
3942+
frame_header.channel_assignment = channel_assignment;
39503943
}
39513944

3952-
frame_header.channel_assignment = channel_assignment;
3953-
39543945
if(!FLAC__frame_add_header(&frame_header, threadtask->frame)) {
39553946
encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
39563947
return false;
39573948
}
39583949

3959-
switch(channel_assignment) {
3950+
switch(frame_header.channel_assignment) {
39603951
case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
39613952
left_subframe = &threadtask->subframe_workspace [0][threadtask->best_subframe [0]];
39623953
right_subframe = &threadtask->subframe_workspace [1][threadtask->best_subframe [1]];
@@ -3977,7 +3968,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
39773968
FLAC__ASSERT(0);
39783969
}
39793970

3980-
switch(channel_assignment) {
3971+
switch(frame_header.channel_assignment) {
39813972
case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
39823973
left_bps = threadtask->subframe_bps [0];
39833974
right_bps = threadtask->subframe_bps [1];
@@ -4005,6 +3996,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
40053996
return false;
40063997
}
40073998
else {
3999+
FLAC__ASSERT(do_independent);
40084000
if(!FLAC__frame_add_header(&frame_header, threadtask->frame)) {
40094001
encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
40104002
return false;
@@ -4018,13 +4010,6 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__StreamEncoderT
40184010
}
40194011
}
40204012

4021-
if(encoder->protected_->loose_mid_side_stereo) {
4022-
encoder->private_->loose_mid_side_stereo_frame_count++;
4023-
if(encoder->private_->loose_mid_side_stereo_frame_count >= encoder->private_->loose_mid_side_stereo_frames)
4024-
encoder->private_->loose_mid_side_stereo_frame_count = 0;
4025-
encoder->private_->last_channel_assignment = frame_header.channel_assignment;
4026-
}
4027-
40284013
return true;
40294014
}
40304015

0 commit comments

Comments
 (0)