@ -964,6 +964,8 @@ typedef struct HDCDContext {
int cdt_ms ; /**< code detect timer period in ms */
int disable_autoconvert ; /**< disable any format conversion or resampling in the filter graph */
int bits_per_sample ; /**< bits per sample 16, 20, or 24 */
/* end AVOption members */
/** config_input() and config_output() scan links for any resampling
@ -997,6 +999,11 @@ static const AVOption hdcd_options[] = {
{ " pe " , HDCD_ANA_PE_DESC , 0 , AV_OPT_TYPE_CONST , { . i64 = HDCD_ANA_PE } , 0 , 0 , A , " analyze_mode " } ,
{ " cdt " , HDCD_ANA_CDT_DESC , 0 , AV_OPT_TYPE_CONST , { . i64 = HDCD_ANA_CDT } , 0 , 0 , A , " analyze_mode " } ,
{ " tgm " , HDCD_ANA_TGM_DESC , 0 , AV_OPT_TYPE_CONST , { . i64 = HDCD_ANA_TGM } , 0 , 0 , A , " analyze_mode " } ,
{ " bits_per_sample " , " Valid bits per sample (location of the true LSB). " ,
OFFSET ( bits_per_sample ) , AV_OPT_TYPE_INT , { . i64 = 16 } , 16 , 24 , A , " bits_per_sample " } ,
{ " 16 " , " 16-bit (in s32 or s16) " , 0 , AV_OPT_TYPE_CONST , { . i64 = 16 } , 0 , 0 , A , " bits_per_sample " } ,
{ " 20 " , " 20-bit (in s32) " , 0 , AV_OPT_TYPE_CONST , { . i64 = 20 } , 0 , 0 , A , " bits_per_sample " } ,
{ " 24 " , " 24-bit (in s32) " , 0 , AV_OPT_TYPE_CONST , { . i64 = 24 } , 0 , 0 , A , " bits_per_sample " } ,
{ NULL }
} ;
@ -1253,29 +1260,34 @@ static int hdcd_analyze(int32_t *samples, int count, int stride, int gain, int t
}
/** apply HDCD decoding parameters to a series of samples */
static int hdcd_envelope ( int32_t * samples , int count , int stride , int gain , int target_gain , int extend )
static int hdcd_envelope ( int32_t * samples , int count , int stride , int vbits , int gain , int target_gain , int extend )
{
static const int max_asample = sizeof ( peaktab ) / sizeof ( peaktab [ 0 ] ) - 1 ;
int32_t * samples_end = samples + stride * count ;
int i ;
int pe_level = PEAK_EXT_LEVEL , shft = 15 ;
if ( vbits ! = 16 ) {
pe_level = ( 1 < < ( vbits - 1 ) ) - ( 0x8000 - PEAK_EXT_LEVEL ) ;
shft = 32 - vbits - 1 ;
}
av_assert0 ( PEAK_EXT_LEVEL + max_asample = = 0x8000 ) ;
if ( extend ) {
for ( i = 0 ; i < count ; i + + ) {
int32_t sample = samples [ i * stride ] ;
int32_t asample = abs ( sample ) - PEAK_EXT_LEVEL ;
int32_t asample = abs ( sample ) - pe_level ;
if ( asample > = 0 ) {
av_assert0 ( asample < = max_asample ) ;
sample = sample > = 0 ? peaktab [ asample ] : - peaktab [ asample ] ;
} else
sample < < = 15 ;
sample < < = shft ;
samples [ i * stride ] = sample ;
}
} else {
for ( i = 0 ; i < count ; i + + )
samples [ i * stride ] < < = 15 ;
samples [ i * stride ] < < = shft ;
}
if ( gain < = target_gain ) {
@ -1370,7 +1382,7 @@ static void hdcd_process(HDCDContext *ctx, hdcd_state *state, int32_t *samples,
if ( ctx - > analyze_mode )
gain = hdcd_analyze ( samples , envelope_run , stride , gain , target_gain , peak_extend , ctx - > analyze_mode , state - > sustain , - 1 ) ;
else
gain = hdcd_envelope ( samples , envelope_run , stride , gain , target_gain , peak_extend ) ;
gain = hdcd_envelope ( samples , envelope_run , stride , ctx - > bits_per_sample , gain , target_gain , peak_extend ) ;
samples + = envelope_run * stride ;
count - = envelope_run ;
@ -1382,7 +1394,7 @@ static void hdcd_process(HDCDContext *ctx, hdcd_state *state, int32_t *samples,
if ( ctx - > analyze_mode )
gain = hdcd_analyze ( samples , lead , stride , gain , target_gain , peak_extend , ctx - > analyze_mode , state - > sustain , - 1 ) ;
else
gain = hdcd_envelope ( samples , lead , stride , gain , target_gain , peak_extend ) ;
gain = hdcd_envelope ( samples , lead , stride , ctx - > bits_per_sample , gain , target_gain , peak_extend ) ;
}
state - > running_gain = gain ;
@ -1422,8 +1434,8 @@ static void hdcd_process_stereo(HDCDContext *ctx, int32_t *samples, int count)
ctx - > state [ 1 ] . sustain ,
( ctlret = = HDCD_TG_MISMATCH ) ) ;
} else {
gain [ 0 ] = hdcd_envelope ( samples , envelope_run , stride , gain [ 0 ] , ctx - > val_target_gain , peak_extend [ 0 ] ) ;
gain [ 1 ] = hdcd_envelope ( samples + 1 , envelope_run , stride , gain [ 1 ] , ctx - > val_target_gain , peak_extend [ 1 ] ) ;
gain [ 0 ] = hdcd_envelope ( samples , envelope_run , stride , ctx - > bits_per_sample , gain [ 0 ] , ctx - > val_target_gain , peak_extend [ 0 ] ) ;
gain [ 1 ] = hdcd_envelope ( samples + 1 , envelope_run , stride , ctx - > bits_per_sample , gain [ 1 ] , ctx - > val_target_gain , peak_extend [ 1 ] ) ;
}
samples + = envelope_run * stride ;
@ -1444,8 +1456,8 @@ static void hdcd_process_stereo(HDCDContext *ctx, int32_t *samples, int count)
ctx - > state [ 1 ] . sustain ,
( ctlret = = HDCD_TG_MISMATCH ) ) ;
} else {
gain [ 0 ] = hdcd_envelope ( samples , lead , stride , gain [ 0 ] , ctx - > val_target_gain , peak_extend [ 0 ] ) ;
gain [ 1 ] = hdcd_envelope ( samples + 1 , lead , stride , gain [ 1 ] , ctx - > val_target_gain , peak_extend [ 1 ] ) ;
gain [ 0 ] = hdcd_envelope ( samples , lead , stride , ctx - > bits_per_sample , gain [ 0 ] , ctx - > val_target_gain , peak_extend [ 0 ] ) ;
gain [ 1 ] = hdcd_envelope ( samples + 1 , lead , stride , ctx - > bits_per_sample , gain [ 1 ] , ctx - > val_target_gain , peak_extend [ 1 ] ) ;
}
}
@ -1516,8 +1528,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
AVFilterLink * outlink = ctx - > outputs [ 0 ] ;
AVFrame * out ;
const int16_t * in_data ;
const int32_t * in_data32 ;
int32_t * out_data ;
int n , c , result ;
int a = 32 - s - > bits_per_sample ;
out = ff_get_audio_buffer ( outlink , in - > nb_samples ) ;
if ( ! out ) {
@ -1533,16 +1547,32 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
out - > format = outlink - > format ; // is this needed?
out_data = ( int32_t * ) out - > data [ 0 ] ;
if ( inlink - > format = = AV_SAMPLE_FMT_S16P ) {
for ( n = 0 ; n < in - > nb_samples ; n + + )
for ( c = 0 ; c < in - > channels ; c + + ) {
in_data = ( int16_t * ) in - > extended_data [ c ] ;
out_data [ ( n * in - > channels ) + c ] = in_data [ n ] ;
}
} else {
in_data = ( int16_t * ) in - > data [ 0 ] ;
for ( n = 0 ; n < in - > nb_samples * in - > channels ; n + + )
out_data [ n ] = in_data [ n ] ;
switch ( inlink - > format ) {
case AV_SAMPLE_FMT_S16P :
for ( n = 0 ; n < in - > nb_samples ; n + + )
for ( c = 0 ; c < in - > channels ; c + + ) {
in_data = ( int16_t * ) in - > extended_data [ c ] ;
out_data [ ( n * in - > channels ) + c ] = in_data [ n ] ;
}
break ;
case AV_SAMPLE_FMT_S16 :
in_data = ( int16_t * ) in - > data [ 0 ] ;
for ( n = 0 ; n < in - > nb_samples * in - > channels ; n + + )
out_data [ n ] = in_data [ n ] ;
break ;
case AV_SAMPLE_FMT_S32P :
for ( n = 0 ; n < in - > nb_samples ; n + + )
for ( c = 0 ; c < in - > channels ; c + + ) {
in_data32 = ( int32_t * ) in - > extended_data [ c ] ;
out_data [ ( n * in - > channels ) + c ] = in_data32 [ n ] > > a ;
}
break ;
case AV_SAMPLE_FMT_S32 :
in_data32 = ( int32_t * ) in - > data [ 0 ] ;
for ( n = 0 ; n < in - > nb_samples * in - > channels ; n + + )
out_data [ n ] = in_data32 [ n ] > > a ;
break ;
}
if ( s - > process_stereo ) {
@ -1583,6 +1613,8 @@ static int query_formats(AVFilterContext *ctx)
static const enum AVSampleFormat sample_fmts_in [ ] = {
AV_SAMPLE_FMT_S16 ,
AV_SAMPLE_FMT_S16P ,
AV_SAMPLE_FMT_S32 ,
AV_SAMPLE_FMT_S32P ,
AV_SAMPLE_FMT_NONE
} ;
static const enum AVSampleFormat sample_fmts_out [ ] = {
@ -1684,6 +1716,22 @@ static int config_input(AVFilterLink *inlink) {
av_log ( ctx , AV_LOG_VERBOSE , " Auto-convert: %s \n " ,
( ctx - > graph - > disable_auto_convert ) ? " disabled " : " enabled " ) ;
if ( ( inlink - > format = = AV_SAMPLE_FMT_S16 | |
inlink - > format = = AV_SAMPLE_FMT_S16P ) & &
s - > bits_per_sample ! = 16 ) {
av_log ( ctx , AV_LOG_WARNING , " bits_per_sample %d does not fit into sample format %s, falling back to 16 \n " ,
s - > bits_per_sample , av_get_sample_fmt_name ( inlink - > format ) ) ;
s - > bits_per_sample = 16 ;
} else {
av_log ( ctx , AV_LOG_VERBOSE , " Looking for %d-bit HDCD in sample format %s \n " ,
s - > bits_per_sample , av_get_sample_fmt_name ( inlink - > format ) ) ;
}
if ( s - > bits_per_sample ! = 16 )
av_log ( ctx , AV_LOG_WARNING , " 20 and 24-bit HDCD decoding is experimental \n " ) ;
if ( inlink - > sample_rate ! = 44100 )
av_log ( ctx , AV_LOG_WARNING , " HDCD decoding for sample rates other than 44100 is experimental \n " ) ;
hdcd_detect_reset ( & s - > detect ) ;
for ( c = 0 ; c < HDCD_MAX_CHANNELS ; c + + ) {
hdcd_reset ( & s - > state [ c ] , inlink - > sample_rate , s - > cdt_ms ) ;