static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,

                              const AVFrame *frame, int *got_packet_ptr)

{

    int n, i, ch, st, pkt_size, ret;

    const int16_t *samples;

    int16_t **samples_p;

    uint8_t *dst;

    ADPCMEncodeContext *c = avctx->priv_data;

    uint8_t *buf;



    samples = (const int16_t *)frame->data[0];

    samples_p = (int16_t **)frame->extended_data;

    st = avctx->channels == 2;



    if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF)

        pkt_size = (2 + avctx->channels * (22 + 4 * (frame->nb_samples - 1)) + 7) / 8;

    else

        pkt_size = avctx->block_align;

    if ((ret = ff_alloc_packet2(avctx, avpkt, pkt_size)))

        return ret;

    dst = avpkt->data;



    switch(avctx->codec->id) {

    case AV_CODEC_ID_ADPCM_IMA_WAV:

    {

        int blocks, j;



        blocks = (frame->nb_samples - 1) / 8;



        for (ch = 0; ch < avctx->channels; ch++) {

            ADPCMChannelStatus *status = &c->status[ch];

            status->prev_sample = samples_p[ch][0];

            /* status->step_index = 0;

               XXX: not sure how to init the state machine */

            bytestream_put_le16(&dst, status->prev_sample);

            *dst++ = status->step_index;

            *dst++ = 0; /* unknown */

        }



        /* stereo: 4 bytes (8 samples) for left, 4 bytes for right */

        if (avctx->trellis > 0) {

            FF_ALLOC_OR_GOTO(avctx, buf, avctx->channels * blocks * 8, error);

            for (ch = 0; ch < avctx->channels; ch++) {

                adpcm_compress_trellis(avctx, &samples_p[ch][1],

                                       buf + ch * blocks * 8, &c->status[ch],

                                       blocks * 8, 1);

            }

            for (i = 0; i < blocks; i++) {

                for (ch = 0; ch < avctx->channels; ch++) {

                    uint8_t *buf1 = buf + ch * blocks * 8 + i * 8;

                    for (j = 0; j < 8; j += 2)

                        *dst++ = buf1[j] | (buf1[j + 1] << 4);

                }

            }

            av_free(buf);

        } else {

            for (i = 0; i < blocks; i++) {

                for (ch = 0; ch < avctx->channels; ch++) {

                    ADPCMChannelStatus *status = &c->status[ch];

                    const int16_t *smp = &samples_p[ch][1 + i * 8];

                    for (j = 0; j < 8; j += 2) {

                        uint8_t v = adpcm_ima_compress_sample(status, smp[j    ]);

                        v        |= adpcm_ima_compress_sample(status, smp[j + 1]) << 4;

                        *dst++ = v;

                    }

                }

            }

        }

        break;

    }

    case AV_CODEC_ID_ADPCM_IMA_QT:

    {

        PutBitContext pb;

        init_put_bits(&pb, dst, pkt_size * 8);



        for (ch = 0; ch < avctx->channels; ch++) {

            ADPCMChannelStatus *status = &c->status[ch];

            put_bits(&pb, 9, (status->prev_sample & 0xFFFF) >> 7);

            put_bits(&pb, 7,  status->step_index);

            if (avctx->trellis > 0) {

                uint8_t buf[64];

                adpcm_compress_trellis(avctx, &samples_p[ch][1], buf, status,

                                       64, 1);

                for (i = 0; i < 64; i++)

                    put_bits(&pb, 4, buf[i ^ 1]);

            } else {

                for (i = 0; i < 64; i += 2) {

                    int t1, t2;

                    t1 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i    ]);

                    t2 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i + 1]);

                    put_bits(&pb, 4, t2);

                    put_bits(&pb, 4, t1);

                }

            }

        }



        flush_put_bits(&pb);

        break;

    }

    case AV_CODEC_ID_ADPCM_SWF:

    {

        PutBitContext pb;

        init_put_bits(&pb, dst, pkt_size * 8);



        n = frame->nb_samples - 1;



        // store AdpcmCodeSize

        put_bits(&pb, 2, 2);    // set 4-bit flash adpcm format



        // init the encoder state

        for (i = 0; i < avctx->channels; i++) {

            // clip step so it fits 6 bits

            c->status[i].step_index = av_clip(c->status[i].step_index, 0, 63);

            put_sbits(&pb, 16, samples[i]);

            put_bits(&pb, 6, c->status[i].step_index);

            c->status[i].prev_sample = samples[i];

        }



        if (avctx->trellis > 0) {

            FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);

            adpcm_compress_trellis(avctx, samples + avctx->channels, buf,

                                   &c->status[0], n, avctx->channels);

            if (avctx->channels == 2)

                adpcm_compress_trellis(avctx, samples + avctx->channels + 1,

                                       buf + n, &c->status[1], n,

                                       avctx->channels);

            for (i = 0; i < n; i++) {

                put_bits(&pb, 4, buf[i]);

                if (avctx->channels == 2)

                    put_bits(&pb, 4, buf[n + i]);

            }

            av_free(buf);

        } else {

            for (i = 1; i < frame->nb_samples; i++) {

                put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0],

                         samples[avctx->channels * i]));

                if (avctx->channels == 2)

                    put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[1],

                             samples[2 * i + 1]));

            }

        }

        flush_put_bits(&pb);

        break;

    }

    case AV_CODEC_ID_ADPCM_MS:

        for (i = 0; i < avctx->channels; i++) {

            int predictor = 0;

            *dst++ = predictor;

            c->status[i].coeff1 = ff_adpcm_AdaptCoeff1[predictor];

            c->status[i].coeff2 = ff_adpcm_AdaptCoeff2[predictor];

        }

        for (i = 0; i < avctx->channels; i++) {

            if (c->status[i].idelta < 16)

                c->status[i].idelta = 16;

            bytestream_put_le16(&dst, c->status[i].idelta);

        }

        for (i = 0; i < avctx->channels; i++)

            c->status[i].sample2= *samples++;

        for (i = 0; i < avctx->channels; i++) {

            c->status[i].sample1 = *samples++;

            bytestream_put_le16(&dst, c->status[i].sample1);

        }

        for (i = 0; i < avctx->channels; i++)

            bytestream_put_le16(&dst, c->status[i].sample2);



        if (avctx->trellis > 0) {

            n = avctx->block_align - 7 * avctx->channels;

            FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);

            if (avctx->channels == 1) {

                adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,

                                       avctx->channels);

                for (i = 0; i < n; i += 2)

                    *dst++ = (buf[i] << 4) | buf[i + 1];

            } else {

                adpcm_compress_trellis(avctx, samples,     buf,

                                       &c->status[0], n, avctx->channels);

                adpcm_compress_trellis(avctx, samples + 1, buf + n,

                                       &c->status[1], n, avctx->channels);

                for (i = 0; i < n; i++)

                    *dst++ = (buf[i] << 4) | buf[n + i];

            }

            av_free(buf);

        } else {

            for (i = 7 * avctx->channels; i < avctx->block_align; i++) {

                int nibble;

                nibble  = adpcm_ms_compress_sample(&c->status[ 0], *samples++) << 4;

                nibble |= adpcm_ms_compress_sample(&c->status[st], *samples++);

                *dst++  = nibble;

            }

        }

        break;

    case AV_CODEC_ID_ADPCM_YAMAHA:

        n = frame->nb_samples / 2;

        if (avctx->trellis > 0) {

            FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error);

            n *= 2;

            if (avctx->channels == 1) {

                adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,

                                       avctx->channels);

                for (i = 0; i < n; i += 2)

                    *dst++ = buf[i] | (buf[i + 1] << 4);

            } else {

                adpcm_compress_trellis(avctx, samples,     buf,

                                       &c->status[0], n, avctx->channels);

                adpcm_compress_trellis(avctx, samples + 1, buf + n,

                                       &c->status[1], n, avctx->channels);

                for (i = 0; i < n; i++)

                    *dst++ = buf[i] | (buf[n + i] << 4);

            }

            av_free(buf);

        } else

            for (n *= avctx->channels; n > 0; n--) {

                int nibble;

                nibble  = adpcm_yamaha_compress_sample(&c->status[ 0], *samples++);

                nibble |= adpcm_yamaha_compress_sample(&c->status[st], *samples++) << 4;

                *dst++  = nibble;

            }

        break;

    default:

        return AVERROR(EINVAL);

    }



    avpkt->size = pkt_size;

    *got_packet_ptr = 1;

    return 0;

error:

    return AVERROR(ENOMEM);

}
