static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,

                                 int *got_frame_ptr, 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, audio_chunks;

    int ret;

    uint8_t *output_samples_u8;

    int16_t *output_samples_s16;



    if (buf_size < 16) {

        av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");

        *got_frame_ptr = 0;

        return buf_size;

    }



    block_type = buf[6];

    if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {

        av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);

        return AVERROR(EINVAL);

    }

    buf      += 16;

    buf_size -= 16;



    /* get number of silent chunks */

    silent_chunks = 0;

    if (block_type == BLOCK_TYPE_INITIAL) {

        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) {

        silent_chunks = 1;

        buf_size = 0; // should already be zero but set it just to be sure

    }



    /* ensure output buffer is large enough */

    audio_chunks = buf_size / s->chunk_size;



    /* get output buffer */

    s->frame.nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels;

    if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {

        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");

        return ret;

    }

    output_samples_u8  = s->frame.data[0];

    output_samples_s16 = (int16_t *)s->frame.data[0];



    /* 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;

        }

    }



    *got_frame_ptr   = 1;

    *(AVFrame *)data = s->frame;



    return avpkt->size;

}

static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data,

                                 int *got_frame_ptr, 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, audio_chunks;

    int ret;

    uint8_t *output_samples_u8;

    int16_t *output_samples_s16;



    if (buf_size < 16) {

        av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n");

        *got_frame_ptr = 0;

        return buf_size;

    }



    block_type = buf[6];

    if (block_type < BLOCK_TYPE_AUDIO || block_type > BLOCK_TYPE_SILENCE) {

        av_log(avctx, AV_LOG_ERROR, "unknown block type: %d\n", block_type);

        return AVERROR(EINVAL);

    }

    buf      += 16;

    buf_size -= 16;



    

    silent_chunks = 0;

    if (block_type == BLOCK_TYPE_INITIAL) {

        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) {

        silent_chunks = 1;

        buf_size = 0; 

    }



    

    audio_chunks = buf_size / s->chunk_size;



    

    s->frame.nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels;

    if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {

        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");

        return ret;

    }

    output_samples_u8  = s->frame.data[0];

    output_samples_s16 = (int16_t *)s->frame.data[0];



    

    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;

        }

    }



    

    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;

        }

    }



    *got_frame_ptr   = 1;

    *(AVFrame *)data = s->frame;



    return avpkt->size;

}

static int FUNC_0(AVCodecContext *VAR_0, void *VAR_1,

                                 int *VAR_2, AVPacket *VAR_3)

{

    const uint8_t *VAR_4 = VAR_3->VAR_1;

    const uint8_t *VAR_5;

    int VAR_6 = VAR_3->size;

    VmdAudioContext *s = VAR_0->priv_data;

    int VAR_7, VAR_8, VAR_9;

    int VAR_10;

    uint8_t *output_samples_u8;

    int16_t *output_samples_s16;



    if (VAR_6 < 16) {

        av_log(VAR_0, AV_LOG_WARNING, "skipping small junk packet\n");

        *VAR_2 = 0;

        return VAR_6;

    }



    VAR_7 = VAR_4[6];

    if (VAR_7 < BLOCK_TYPE_AUDIO || VAR_7 > BLOCK_TYPE_SILENCE) {

        av_log(VAR_0, AV_LOG_ERROR, "unknown block type: %d\n", VAR_7);

        return AVERROR(EINVAL);

    }

    VAR_4      += 16;

    VAR_6 -= 16;



    

    VAR_8 = 0;

    if (VAR_7 == BLOCK_TYPE_INITIAL) {

        uint32_t flags;

        if (VAR_6 < 4) {

            av_log(VAR_0, AV_LOG_ERROR, "packet is too small\n");

            return AVERROR(EINVAL);

        }

        flags         = AV_RB32(VAR_4);

        VAR_8 = av_popcount(flags);

        VAR_4      += 4;

        VAR_6 -= 4;

    } else if (VAR_7 == BLOCK_TYPE_SILENCE) {

        VAR_8 = 1;

        VAR_6 = 0; 

    }



    

    VAR_9 = VAR_6 / s->chunk_size;



    

    s->frame.nb_samples = ((VAR_8 + VAR_9) * VAR_0->block_align) / VAR_0->channels;

    if ((VAR_10 = VAR_0->get_buffer(VAR_0, &s->frame)) < 0) {

        av_log(VAR_0, AV_LOG_ERROR, "get_buffer() failed\n");

        return VAR_10;

    }

    output_samples_u8  = s->frame.VAR_1[0];

    output_samples_s16 = (int16_t *)s->frame.VAR_1[0];



    

    if (VAR_8 > 0) {

        int VAR_11 = VAR_0->block_align * VAR_8;

        if (s->out_bps == 2) {

            memset(output_samples_s16, 0x00, VAR_11 * 2);

            output_samples_s16 += VAR_11;

        } else {

            memset(output_samples_u8,  0x80, VAR_11);

            output_samples_u8 += VAR_11;

        }

    }



    

    if (VAR_9 > 0) {

        VAR_5 = VAR_4 + VAR_6;

        while (VAR_4 < VAR_5) {

            if (s->out_bps == 2) {

                decode_audio_s16(output_samples_s16, VAR_4, s->chunk_size,

                                 VAR_0->channels);

                output_samples_s16 += VAR_0->block_align;

            } else {

                memcpy(output_samples_u8, VAR_4, s->chunk_size);

                output_samples_u8  += VAR_0->block_align;

            }

            VAR_4 += s->chunk_size;

        }

    }



    *VAR_2   = 1;

    *(AVFrame *)VAR_1 = s->frame;



    return VAR_3->size;

}

static int FUNC_0(AVCodecContext *VAR_0, void *VAR_1,
int *VAR_2, AVPacket *VAR_3)
{ const uint8_t *VAR_4 = VAR_3->VAR_1; const uint8_t *VAR_5; int VAR_6 = VAR_3->size; VmdAudioContext *s = VAR_0->priv_data; int VAR_7, VAR_8, VAR_9; int VAR_10; uint8_t *output_samples_u8; int16_t *output_samples_s16; if (VAR_6 < 16) { av_log(VAR_0, AV_LOG_WARNING, "skipping small junk packet\n"); *VAR_2 = 0; return VAR_6; } VAR_7 = VAR_4[6]; if (VAR_7 < BLOCK_TYPE_AUDIO || VAR_7 > BLOCK_TYPE_SILENCE) { av_log(VAR_0, AV_LOG_ERROR, "unknown block type: %d\n", VAR_7); return AVERROR(EINVAL); } VAR_4      += 16; VAR_6 -= 16; VAR_8 = 0; if (VAR_7 == BLOCK_TYPE_INITIAL) { uint32_t flags; if (VAR_6 < 4) { av_log(VAR_0, AV_LOG_ERROR, "packet is too small\n"); return AVERROR(EINVAL); } flags         = AV_RB32(VAR_4); VAR_8 = av_popcount(flags); VAR_4      += 4; VAR_6 -= 4; } else if (VAR_7 == BLOCK_TYPE_SILENCE) { VAR_8 = 1; VAR_6 = 0; } VAR_9 = VAR_6 / s->chunk_size; s->frame.nb_samples = ((VAR_8 + VAR_9) * VAR_0->block_align) / VAR_0->channels; if ((VAR_10 = VAR_0->get_buffer(VAR_0, &s->frame)) < 0) { av_log(VAR_0, AV_LOG_ERROR, "get_buffer() failed\n"); return VAR_10; } output_samples_u8  = s->frame.VAR_1[0]; output_samples_s16 = (int16_t *)s->frame.VAR_1[0]; if (VAR_8 > 0) { int VAR_11 = VAR_0->block_align * VAR_8; if (s->out_bps == 2) { memset(output_samples_s16, 0x00, VAR_11 * 2); output_samples_s16 += VAR_11; } else { memset(output_samples_u8,  0x80, VAR_11); output_samples_u8 += VAR_11; } } if (VAR_9 > 0) { VAR_5 = VAR_4 + VAR_6; while (VAR_4 < VAR_5) { if (s->out_bps == 2) { decode_audio_s16(output_samples_s16, VAR_4, s->chunk_size,
VAR_0->channels); output_samples_s16 += VAR_0->block_align; } else { memcpy(output_samples_u8, VAR_4, s->chunk_size); output_samples_u8  += VAR_0->block_align; } VAR_4 += s->chunk_size; } } *VAR_2   = 1; *(AVFrame *)VAR_1 = s->frame; return VAR_3->size; }