| 
				
				
					
				
				
				 | 
			
			 | 
			@@ -417,9 +417,8 @@ static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			#define BLOCK_TYPE_SILENCE  3 | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			typedef struct VmdAudioContext { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    AVCodecContext *avctx; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int out_bps; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int predictors[2]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int chunk_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} VmdAudioContext; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static const uint16_t vmdaudio_table[128] = { | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -442,13 +441,23 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    VmdAudioContext *s = avctx->priv_data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    s->avctx = avctx; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (avctx->channels < 1 || avctx->channels > 2) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        return AVERROR(EINVAL); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (avctx->block_align < 1) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        return AVERROR(EINVAL); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (avctx->bits_per_coded_sample == 16) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        avctx->sample_fmt = AV_SAMPLE_FMT_S16; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    else | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        avctx->sample_fmt = AV_SAMPLE_FMT_U8; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			           "block align = %d, sample rate = %d\n", | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			           avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -457,41 +466,33 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return 0; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    const uint8_t *buf, int buf_size, int stereo) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                             int channels) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int i; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int chan = 0; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int16_t *out = (int16_t*)data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    for(i = 0; i < buf_size; i++) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if(buf[i] & 0x80) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        else | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            s->predictors[chan] += vmdaudio_table[buf[i]]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        s->predictors[chan] = av_clip_int16(s->predictors[chan]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        out[i] = s->predictors[chan]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        chan ^= stereo; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int ch; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    const uint8_t *buf_end = buf + buf_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int predictor[2]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int st = channels - 1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    /* decode initial raw sample */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    for (ch = 0; ch < channels; ch++) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        predictor[ch] = (int16_t)AV_RL16(buf); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        buf += 2; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        *out++ = predictor[ch]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    const uint8_t *buf, int silent_chunks, int data_size) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int silent_size = s->avctx->block_align * silent_chunks * s->out_bps; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (silent_chunks) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        data += silent_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (s->avctx->bits_per_coded_sample == 16) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        /* just copy the data */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        memcpy(data, buf, data_size); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    /* decode DPCM samples */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    ch = 0; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    while (buf < buf_end) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        uint8_t b = *buf++; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if (b & 0x80) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            predictor[ch] -= vmdaudio_table[b & 0x7F]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        else | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            predictor[ch] += vmdaudio_table[b]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        predictor[ch] = av_clip_int16(predictor[ch]); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        *out++ = predictor[ch]; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        ch ^= st; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return silent_size + data_size * s->out_bps; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			static int vmdaudio_decode_frame(AVCodecContext *avctx, | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -499,10 +500,13 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                                 AVPacket *avpkt) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			{ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    const uint8_t *buf = avpkt->data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    const uint8_t *buf_end; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int buf_size = avpkt->size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    VmdAudioContext *s = avctx->priv_data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int block_type, silent_chunks; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    unsigned char *output_samples = (unsigned char *)data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int block_type, silent_chunks, audio_chunks; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int nb_samples, out_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    uint8_t *output_samples_u8  = data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    int16_t *output_samples_s16 = data; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (buf_size < 16) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -518,10 +522,16 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    buf      += 16; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    buf_size -= 16; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    /* get number of silent chunks */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    silent_chunks = 0; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (block_type == BLOCK_TYPE_INITIAL) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        uint32_t flags = AV_RB32(buf); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        silent_chunks  = av_popcount(flags); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        uint32_t flags; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if (buf_size < 4) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            return AVERROR(EINVAL); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        flags         = AV_RB32(buf); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        silent_chunks = av_popcount(flags); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        buf      += 4; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        buf_size -= 4; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } else if (block_type == BLOCK_TYPE_SILENCE) { | 
		
		
	
	
		
			
				| 
				
				
				
					
				
				 | 
			
			 | 
			@@ -530,11 +540,41 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    /* ensure output buffer is large enough */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    audio_chunks = buf_size / s->chunk_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    nb_samples   = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    out_size     = nb_samples * avctx->channels * s->out_bps; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (*data_size < out_size) | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        return -1; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    /* decode silent chunks */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (silent_chunks > 0) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        int silent_size = avctx->block_align * silent_chunks; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        if (s->out_bps == 2) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            memset(output_samples_s16, 0x00, silent_size * 2); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            output_samples_s16 += silent_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            memset(output_samples_u8,  0x80, silent_size); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            output_samples_u8 += silent_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    /* decode audio chunks */ | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    if (audio_chunks > 0) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        buf_end = buf + buf_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        while (buf < buf_end) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            if (s->out_bps == 2) { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                decode_audio_s16(output_samples_s16, buf, s->chunk_size, | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                                 avctx->channels); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                output_samples_s16 += avctx->block_align; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            } else { | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                memcpy(output_samples_u8, buf, s->chunk_size); | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			                output_samples_u8  += avctx->block_align; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			            buf += s->chunk_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			        } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    } | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    *data_size = out_size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			    return avpkt->size; | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			} | 
		
		
	
		
			
			 | 
			 | 
			
			 | 
			
  | 
		
		
	
	
		
			
				| 
				
					
				
				
				
				 | 
			
			 | 
			
  |