|  |  | @@ -22,7 +22,7 @@ | 
		
	
		
			
			|  |  |  | * @file | 
		
	
		
			
			|  |  |  | * ADX audio parser | 
		
	
		
			
			|  |  |  | * | 
		
	
		
			
			|  |  |  | * Reads header to extradata and splits packets into individual blocks. | 
		
	
		
			
			|  |  |  | * Splits packets into individual blocks. | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #include "libavutil/intreadwrite.h" | 
		
	
	
		
			
				|  |  | @@ -33,11 +33,9 @@ typedef struct ADXParseContext { | 
		
	
		
			
			|  |  |  | ParseContext pc; | 
		
	
		
			
			|  |  |  | int header_size; | 
		
	
		
			
			|  |  |  | int block_size; | 
		
	
		
			
			|  |  |  | int buf_pos; | 
		
	
		
			
			|  |  |  | int remaining; | 
		
	
		
			
			|  |  |  | } ADXParseContext; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #define MIN_HEADER_SIZE 24 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int adx_parse(AVCodecParserContext *s1, | 
		
	
		
			
			|  |  |  | AVCodecContext *avctx, | 
		
	
		
			
			|  |  |  | const uint8_t **poutbuf, int *poutbuf_size, | 
		
	
	
		
			
				|  |  | @@ -46,45 +44,36 @@ static int adx_parse(AVCodecParserContext *s1, | 
		
	
		
			
			|  |  |  | ADXParseContext *s = s1->priv_data; | 
		
	
		
			
			|  |  |  | ParseContext *pc = &s->pc; | 
		
	
		
			
			|  |  |  | int next = END_NOT_FOUND; | 
		
	
		
			
			|  |  |  | int i; | 
		
	
		
			
			|  |  |  | uint64_t state = pc->state64; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (!avctx->extradata_size) { | 
		
	
		
			
			|  |  |  | int ret; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ff_combine_frame(pc, END_NOT_FOUND, &buf, &buf_size); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (!s->header_size && pc->index >= MIN_HEADER_SIZE) { | 
		
	
		
			
			|  |  |  | if (ret = avpriv_adx_decode_header(avctx, pc->buffer, pc->index, | 
		
	
		
			
			|  |  |  | &s->header_size, NULL)) | 
		
	
		
			
			|  |  |  | return AVERROR_INVALIDDATA; | 
		
	
		
			
			|  |  |  | s->block_size = BLOCK_SIZE * avctx->channels; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (s->header_size && s->header_size <= pc->index) { | 
		
	
		
			
			|  |  |  | avctx->extradata = av_mallocz(s->header_size + FF_INPUT_BUFFER_PADDING_SIZE); | 
		
	
		
			
			|  |  |  | if (!avctx->extradata) | 
		
	
		
			
			|  |  |  | return AVERROR(ENOMEM); | 
		
	
		
			
			|  |  |  | avctx->extradata_size = s->header_size; | 
		
	
		
			
			|  |  |  | memcpy(avctx->extradata, pc->buffer, s->header_size); | 
		
	
		
			
			|  |  |  | memmove(pc->buffer, pc->buffer + s->header_size, s->header_size); | 
		
	
		
			
			|  |  |  | pc->index -= s->header_size; | 
		
	
		
			
			|  |  |  | if (!s->header_size) { | 
		
	
		
			
			|  |  |  | for (i = 0; i < buf_size; i++) { | 
		
	
		
			
			|  |  |  | state = (state << 8) | buf[i]; | 
		
	
		
			
			|  |  |  | /* check for fixed fields in ADX header for possible match */ | 
		
	
		
			
			|  |  |  | if ((state & 0xFFFF0000FFFFFF00) == 0x8000000003120400ULL) { | 
		
	
		
			
			|  |  |  | int channels    = state & 0xFF; | 
		
	
		
			
			|  |  |  | int header_size = ((state >> 32) & 0xFFFF) + 4; | 
		
	
		
			
			|  |  |  | if (channels > 0 && header_size >= 8) { | 
		
	
		
			
			|  |  |  | s->header_size = header_size; | 
		
	
		
			
			|  |  |  | s->block_size  = BLOCK_SIZE * channels; | 
		
	
		
			
			|  |  |  | s->remaining   = i - 7 + s->header_size + s->block_size; | 
		
	
		
			
			|  |  |  | break; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | *poutbuf      = NULL; | 
		
	
		
			
			|  |  |  | *poutbuf_size = 0; | 
		
	
		
			
			|  |  |  | return buf_size; | 
		
	
		
			
			|  |  |  | pc->state64 = state; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (pc->index - s->buf_pos >= s->block_size) { | 
		
	
		
			
			|  |  |  | *poutbuf      = &pc->buffer[s->buf_pos]; | 
		
	
		
			
			|  |  |  | *poutbuf_size = s->block_size; | 
		
	
		
			
			|  |  |  | s->buf_pos   += s->block_size; | 
		
	
		
			
			|  |  |  | return 0; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (pc->index && s->buf_pos) { | 
		
	
		
			
			|  |  |  | memmove(pc->buffer, &pc->buffer[s->buf_pos], pc->index - s->buf_pos); | 
		
	
		
			
			|  |  |  | pc->index -= s->buf_pos; | 
		
	
		
			
			|  |  |  | s->buf_pos = 0; | 
		
	
		
			
			|  |  |  | if (s->header_size) { | 
		
	
		
			
			|  |  |  | if (!s->remaining) | 
		
	
		
			
			|  |  |  | s->remaining = s->block_size; | 
		
	
		
			
			|  |  |  | if (s->remaining <= buf_size) { | 
		
	
		
			
			|  |  |  | next = s->remaining; | 
		
	
		
			
			|  |  |  | s->remaining = 0; | 
		
	
		
			
			|  |  |  | } else | 
		
	
		
			
			|  |  |  | s->remaining -= buf_size; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (buf_size + pc->index >= s->block_size) | 
		
	
		
			
			|  |  |  | next = s->block_size - pc->index; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { | 
		
	
		
			
			|  |  |  | *poutbuf      = NULL; | 
		
	
	
		
			
				|  |  | 
 |