@ -47,6 +47,14 @@ typedef struct DCAParseContext {
# define CORE_MARKER(state) ((state >> 16) & 0xFFFFFFFF)
# define EXSS_MARKER(state) (state & 0xFFFFFFFF)
# define STATE_LE(state) (((state & 0xFF00FF00) >> 8) | ((state & 0x00FF00FF) << 8))
# define STATE_14(state) (((state & 0x3FFF0000) >> 8) | ((state & 0x00003FFF) >> 6))
# define CORE_FRAMESIZE(state) (((state >> 4) & 0x3FFF) + 1)
# define EXSS_FRAMESIZE(state) ((state & 0x2000000000) ? \
( ( state > > 5 ) & 0xFFFFF ) + 1 : \
( ( state > > 13 ) & 0x0FFFF ) + 1 )
/**
* Find the end of the current frame in the bitstream .
* @ return the position of the first byte of the next frame , or - 1
@ -54,12 +62,13 @@ typedef struct DCAParseContext {
static int dca_find_frame_end ( DCAParseContext * pc1 , const uint8_t * buf ,
int buf_size )
{
int start_found , i ;
int start_found , size , i ;
uint64_t state ;
ParseContext * pc = & pc1 - > pc ;
start_found = pc - > frame_start_found ;
state = pc - > state64 ;
size = pc1 - > size ;
i = 0 ;
if ( ! start_found ) {
@ -80,15 +89,75 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
}
}
}
if ( start_found ) {
for ( ; i < buf_size ; i + + ) {
pc1 - > size + + ;
size + + ;
state = ( state < < 8 ) | buf [ i ] ;
if ( start_found = = 1 ) {
switch ( pc1 - > lastmarker ) {
case DCA_SYNCWORD_CORE_BE :
if ( size = = 2 ) {
pc1 - > framesize = CORE_FRAMESIZE ( state ) ;
start_found = 2 ;
}
break ;
case DCA_SYNCWORD_CORE_LE :
if ( size = = 2 ) {
pc1 - > framesize = CORE_FRAMESIZE ( STATE_LE ( state ) ) ;
start_found = 2 ;
}
break ;
case DCA_SYNCWORD_CORE_14B_BE :
if ( size = = 4 ) {
pc1 - > framesize = CORE_FRAMESIZE ( STATE_14 ( state ) ) * 8 / 14 * 2 ;
start_found = 2 ;
}
break ;
case DCA_SYNCWORD_CORE_14B_LE :
if ( size = = 4 ) {
pc1 - > framesize = CORE_FRAMESIZE ( STATE_14 ( STATE_LE ( state ) ) ) * 8 / 14 * 2 ;
start_found = 2 ;
}
break ;
case DCA_SYNCWORD_SUBSTREAM :
if ( size = = 6 ) {
pc1 - > framesize = EXSS_FRAMESIZE ( state ) ;
start_found = 2 ;
}
break ;
default :
av_assert0 ( 0 ) ;
}
continue ;
}
if ( pc1 - > lastmarker = = DCA_SYNCWORD_CORE_BE ) {
if ( pc1 - > framesize > size + 2 )
continue ;
if ( start_found = = 2 & & IS_EXSS_MARKER ( state ) ) {
pc1 - > framesize = size + 2 ;
start_found = 3 ;
continue ;
}
if ( start_found = = 3 ) {
if ( size = = pc1 - > framesize + 4 ) {
pc1 - > framesize + = EXSS_FRAMESIZE ( state ) ;
start_found = 4 ;
}
continue ;
}
}
if ( pc1 - > framesize > size )
continue ;
if ( IS_MARKER ( state ) & &
( pc1 - > lastmarker = = CORE_MARKER ( state ) | |
pc1 - > lastmarker = = DCA_SYNCWORD_SUBSTREAM ) ) {
if ( pc1 - > framesize > pc1 - > size )
continue ;
pc - > frame_start_found = 0 ;
pc - > state64 = - 1 ;
pc1 - > size = 0 ;
@ -96,8 +165,10 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
}
}
}
pc - > frame_start_found = start_found ;
pc - > state64 = state ;
pc1 - > size = size ;
return END_NOT_FOUND ;
}
@ -110,11 +181,11 @@ static av_cold int dca_parse_init(AVCodecParserContext *s)
}
static int dca_parse_params ( const uint8_t * buf , int buf_size , int * duration ,
int * sample_rate , int * framesize )
int * sample_rate )
{
GetBitContext gb ;
uint8_t hdr [ 12 + AV_INPUT_BUFFER_PADDING_SIZE ] = { 0 } ;
int ret , sample_blocks , sr_code ;
int ret , sample_blocks ;
if ( buf_size < 12 )
return AVERROR_INVALIDDATA ;
@ -130,13 +201,8 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration,
return AVERROR_INVALIDDATA ;
* duration = 256 * ( sample_blocks / 8 ) ;
* framesize = get_bits ( & gb , 14 ) + 1 ;
if ( * framesize < 95 )
return AVERROR_INVALIDDATA ;
skip_bits ( & gb , 6 ) ;
sr_code = get_bits ( & gb , 4 ) ;
* sample_rate = avpriv_dca_sample_rates [ sr_code ] ;
skip_bits ( & gb , 20 ) ;
* sample_rate = avpriv_dca_sample_rates [ get_bits ( & gb , 4 ) ] ;
if ( * sample_rate = = 0 )
return AVERROR_INVALIDDATA ;
@ -164,7 +230,7 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx,
}
/* read the duration and sample rate from the frame header */
if ( ! dca_parse_params ( buf , buf_size , & duration , & sample_rate , & pc1 - > framesize ) ) {
if ( ! dca_parse_params ( buf , buf_size , & duration , & sample_rate ) ) {
if ( ! avctx - > sample_rate )
avctx - > sample_rate = sample_rate ;
s - > duration = av_rescale ( duration , avctx - > sample_rate , sample_rate ) ;