@ -161,8 +161,24 @@ typedef struct APEContext {
const uint8_t * ptr ; ///< current position in frame data
int error ;
void ( * entropy_decode_mono ) ( struct APEContext * ctx , int blockstodecode ) ;
void ( * entropy_decode_stereo ) ( struct APEContext * ctx , int blockstodecode ) ;
void ( * predictor_decode_mono ) ( struct APEContext * ctx , int count ) ;
void ( * predictor_decode_stereo ) ( struct APEContext * ctx , int count ) ;
} APEContext ;
static void ape_apply_filters ( APEContext * ctx , int32_t * decoded0 ,
int32_t * decoded1 , int count ) ;
static void entropy_decode_mono_3900 ( APEContext * ctx , int blockstodecode ) ;
static void entropy_decode_stereo_3900 ( APEContext * ctx , int blockstodecode ) ;
static void entropy_decode_mono_3990 ( APEContext * ctx , int blockstodecode ) ;
static void entropy_decode_stereo_3990 ( APEContext * ctx , int blockstodecode ) ;
static void predictor_decode_mono_3950 ( APEContext * ctx , int count ) ;
static void predictor_decode_stereo_3950 ( APEContext * ctx , int count ) ;
// TODO: dsputilize
static av_cold int ape_decode_close ( AVCodecContext * avctx )
@ -231,6 +247,17 @@ static av_cold int ape_decode_init(AVCodecContext *avctx)
filter_alloc_fail ) ;
}
if ( s - > fileversion < 3990 ) {
s - > entropy_decode_mono = entropy_decode_mono_3900 ;
s - > entropy_decode_stereo = entropy_decode_stereo_3900 ;
} else {
s - > entropy_decode_mono = entropy_decode_mono_3990 ;
s - > entropy_decode_stereo = entropy_decode_stereo_3990 ;
}
s - > predictor_decode_mono = predictor_decode_mono_3950 ;
s - > predictor_decode_stereo = predictor_decode_stereo_3950 ;
ff_dsputil_init ( & s - > dsp , avctx ) ;
avctx - > channel_layout = ( avctx - > channels = = 2 ) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO ;
@ -401,11 +428,9 @@ static inline void update_rice(APERice *rice, unsigned int x)
rice - > k + + ;
}
static inline int ape_decode_value ( APEContext * ctx , APERice * rice )
static inline int ape_decode_value_3900 ( APEContext * ctx , APERice * rice )
{
unsigned int x , overflow ;
if ( ctx - > fileversion < 3990 ) {
int tmpk ;
overflow = range_get_symbol ( ctx , counts_3970 , counts_diff_3970 ) ;
@ -426,7 +451,19 @@ static inline int ape_decode_value(APEContext *ctx, APERice *rice)
return AVERROR_INVALIDDATA ;
}
x + = overflow < < tmpk ;
} else {
update_rice ( rice , x ) ;
/* Convert to signed */
if ( x & 1 )
return ( x > > 1 ) + 1 ;
else
return - ( x > > 1 ) ;
}
static inline int ape_decode_value_3990 ( APEContext * ctx , APERice * rice )
{
unsigned int x , overflow ;
int base , pivot ;
pivot = rice - > ksum > > 5 ;
@ -460,7 +497,6 @@ static inline int ape_decode_value(APEContext *ctx, APERice *rice)
}
x = base + overflow * pivot ;
}
update_rice ( rice , x ) ;
@ -471,15 +507,41 @@ static inline int ape_decode_value(APEContext *ctx, APERice *rice)
return - ( x > > 1 ) ;
}
static void entropy_decode ( APEContext * ctx , int blockstodecode , int stereo )
static void entropy_decode_mono_3900 ( APEContext * ctx , int blockstodecode )
{
int32_t * decoded0 = ctx - > decoded [ 0 ] ;
while ( blockstodecode - - )
* decoded0 + + = ape_decode_value_3900 ( ctx , & ctx - > riceY ) ;
}
static void entropy_decode_stereo_3900 ( APEContext * ctx , int blockstodecode )
{
int32_t * decoded0 = ctx - > decoded [ 0 ] ;
int32_t * decoded1 = ctx - > decoded [ 1 ] ;
while ( blockstodecode - - ) {
* decoded0 + + = ape_decode_value ( ctx , & ctx - > riceY ) ;
if ( stereo )
* decoded1 + + = ape_decode_value ( ctx , & ctx - > riceX ) ;
* decoded0 + + = ape_decode_value_3900 ( ctx , & ctx - > riceY ) ;
* decoded1 + + = ape_decode_value_3900 ( ctx , & ctx - > riceX ) ;
}
}
static void entropy_decode_mono_3990 ( APEContext * ctx , int blockstodecode )
{
int32_t * decoded0 = ctx - > decoded [ 0 ] ;
while ( blockstodecode - - )
* decoded0 + + = ape_decode_value_3990 ( ctx , & ctx - > riceY ) ;
}
static void entropy_decode_stereo_3990 ( APEContext * ctx , int blockstodecode )
{
int32_t * decoded0 = ctx - > decoded [ 0 ] ;
int32_t * decoded1 = ctx - > decoded [ 1 ] ;
while ( blockstodecode - - ) {
* decoded0 + + = ape_decode_value_3990 ( ctx , & ctx - > riceY ) ;
* decoded1 + + = ape_decode_value_3990 ( ctx , & ctx - > riceX ) ;
}
}
@ -588,12 +650,14 @@ static av_always_inline int predictor_update_filter(APEPredictor *p,
return p - > filterA [ filter ] ;
}
static void predictor_decode_stereo ( APEContext * ctx , int count )
static void predictor_decode_stereo_3950 ( APEContext * ctx , int count )
{
APEPredictor * p = & ctx - > predictor ;
int32_t * decoded0 = ctx - > decoded [ 0 ] ;
int32_t * decoded1 = ctx - > decoded [ 1 ] ;
ape_apply_filters ( ctx , ctx - > decoded [ 0 ] , ctx - > decoded [ 1 ] , count ) ;
while ( count - - ) {
/* Predictor Y */
* decoded0 = predictor_update_filter ( p , * decoded0 , 0 , YDELAYA , YDELAYB ,
@ -615,12 +679,14 @@ static void predictor_decode_stereo(APEContext *ctx, int count)
}
}
static void predictor_decode_mono ( APEContext * ctx , int count )
static void predictor_decode_mono_3950 ( APEContext * ctx , int count )
{
APEPredictor * p = & ctx - > predictor ;
int32_t * decoded0 = ctx - > decoded [ 0 ] ;
int32_t predictionA , currentA , A , sign ;
ape_apply_filters ( ctx , ctx - > decoded [ 0 ] , NULL , count ) ;
currentA = p - > lastA [ 0 ] ;
while ( count - - ) {
@ -779,11 +845,10 @@ static void ape_unpack_mono(APEContext *ctx, int count)
return ;
}
entropy_decode ( ctx , count , 0 ) ;
ape_apply_filters ( ctx , ctx - > decoded [ 0 ] , NULL , count ) ;
ctx - > entropy_decode_mono ( ctx , count ) ;
/* Now apply the predictor decoding */
predictor_decode_mono ( ctx , count ) ;
ctx - > predictor_decode_mono ( ctx , count ) ;
/* Pseudo-stereo - just copy left channel to right channel */
if ( ctx - > channels = = 2 ) {
@ -803,11 +868,10 @@ static void ape_unpack_stereo(APEContext *ctx, int count)
return ;
}
entropy_decode ( ctx , count , 1 ) ;
ape_apply_filters ( ctx , decoded0 , decoded1 , count ) ;
ctx - > entropy_decode_stereo ( ctx , count ) ;
/* Now apply the predictor decoding */
predictor_decode_stereo ( ctx , count ) ;
ctx - > predictor_decode_stereo ( ctx , count ) ;
/* Decorrelate and scale to output depth */
while ( count - - ) {