Skip to content

Commit

Permalink
Block usage of frames with only constant subframes
Browse files Browse the repository at this point in the history
Quite a lot of decoders have trouble streaming or seeking in a
file with frames that only consist of constant subframes because
of the large difference between the largest and smallest subframe.
To remedy this, this commit makes disables the use of constant
subframes for the last subframe in case all others are constant
  • Loading branch information
ktmf01 committed Dec 1, 2021
1 parent b358381 commit f6055fc
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 17 deletions.
9 changes: 5 additions & 4 deletions src/libFLAC/fixed.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,14 @@ uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t d
error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save;
}

if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
/* prefer lower order */
if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
order = 0;
else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4))
else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4))
order = 1;
else if(total_error_2 < flac_min(total_error_3, total_error_4))
else if(total_error_2 <= flac_min(total_error_3, total_error_4))
order = 2;
else if(total_error_3 < total_error_4)
else if(total_error_3 <= total_error_4)
order = 3;
else
order = 4;
Expand Down
10 changes: 5 additions & 5 deletions src/libFLAC/fixed_intrin_sse2.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ uint32_t FLAC__fixed_compute_best_predictor_intrin_sse2(const FLAC__int32 data[]
total_error_3 = _mm_cvtsi128_si32(total_err2);
total_error_1 = _mm_cvtsi128_si32(total_err1);

/* prefer higher order */
if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
/* prefer lower order */
if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
order = 0;
else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4))
else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4))
order = 1;
else if(total_error_2 < flac_min(total_error_3, total_error_4))
else if(total_error_2 <= flac_min(total_error_3, total_error_4))
order = 2;
else if(total_error_3 < total_error_4)
else if(total_error_3 <= total_error_4)
order = 3;
else
order = 4;
Expand Down
10 changes: 5 additions & 5 deletions src/libFLAC/fixed_intrin_ssse3.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,14 @@ uint32_t FLAC__fixed_compute_best_predictor_intrin_ssse3(const FLAC__int32 data[
total_error_3 = _mm_cvtsi128_si32(total_err2);
total_error_1 = _mm_cvtsi128_si32(total_err1);

/* prefer higher order */
if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
/* prefer lower order */
if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
order = 0;
else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4))
else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4))
order = 1;
else if(total_error_2 < flac_min(total_error_3, total_error_4))
else if(total_error_2 <= flac_min(total_error_3, total_error_4))
order = 2;
else if(total_error_3 < total_error_4)
else if(total_error_3 <= total_error_4)
order = 3;
else
order = 4;
Expand Down
13 changes: 12 additions & 1 deletion src/libFLAC/stream_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -3140,7 +3140,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti
{
FLAC__FrameHeader frame_header;
uint32_t channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order;
FLAC__bool do_independent, do_mid_side;
FLAC__bool do_independent, do_mid_side, backup_disable_constant_subframes = encoder->private_->disable_constant_subframes, all_subframes_constant = true;

/*
* Calculate the min,max Rice partition orders
Expand Down Expand Up @@ -3221,6 +3221,14 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti
*/
if(do_independent) {
for(channel = 0; channel < encoder->protected_->channels; channel++) {
if((channel + 1) == encoder->protected_->channels && all_subframes_constant){
/* This frame contains only constant subframes at this point. If the last subframe
* is also constant, this will result in a very small frame. Quite a lot of decoders
* have trouble streaming or seeking in a file which such small frames because of the
* large difference between the largest and smallest subframe. To remedy this
* further use of constant subframes in this frame will be disabled */
encoder->private_->disable_constant_subframes = true;
}
if(!
process_subframe_(
encoder,
Expand All @@ -3237,6 +3245,8 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti
)
)
return false;
if(&encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]].type != FLAC__SUBFRAME_TYPE_CONSTANT)
all_subframes_constant = false;
}
}

Expand Down Expand Up @@ -3382,6 +3392,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fracti
}

encoder->private_->last_channel_assignment = frame_header.channel_assignment;
encoder->private_->disable_constant_subframes = backup_disable_constant_subframes;

return true;
}
Expand Down
4 changes: 2 additions & 2 deletions test/metaflac-test-files/case01-expect.meta
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
a042237c5493fdb9656b94a83608d11a
1152
1152
10
10
139
155
8000
1
8
Expand Down

0 comments on commit f6055fc

Please sign in to comment.