static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_count,

                                                      AudioData *in , int  in_count){

    AudioData *postin, *midbuf, *preout;

    int ret/*, in_max*/;

    AudioData preout_tmp, midbuf_tmp;



    if(s->full_convert){

        av_assert0(!s->resample);

        swri_audio_convert(s->full_convert, out, in, in_count);

        return out_count;

    }



//     in_max= out_count*(int64_t)s->in_sample_rate / s->out_sample_rate + resample_filter_taps;

//     in_count= FFMIN(in_count, in_in + 2 - s->hist_buffer_count);



    if((ret=swri_realloc_audio(&s->postin, in_count))<0)

        return ret;

    if(s->resample_first){

        av_assert0(s->midbuf.ch_count == s->used_ch_count);

        if((ret=swri_realloc_audio(&s->midbuf, out_count))<0)

            return ret;

    }else{

        av_assert0(s->midbuf.ch_count ==  s->out.ch_count);

        if((ret=swri_realloc_audio(&s->midbuf,  in_count))<0)

            return ret;

    }

    if((ret=swri_realloc_audio(&s->preout, out_count))<0)

        return ret;



    postin= &s->postin;



    midbuf_tmp= s->midbuf;

    midbuf= &midbuf_tmp;

    preout_tmp= s->preout;

    preout= &preout_tmp;



    if(s->int_sample_fmt == s-> in_sample_fmt && s->in.planar && !s->channel_map)

        postin= in;



    if(s->resample_first ? !s->resample : !s->rematrix)

        midbuf= postin;



    if(s->resample_first ? !s->rematrix : !s->resample)

        preout= midbuf;



    if(s->int_sample_fmt == s->out_sample_fmt && s->out.planar

       && !(s->out_sample_fmt==AV_SAMPLE_FMT_S32P && (s->dither.output_sample_bits&31))){

        if(preout==in){

            out_count= FFMIN(out_count, in_count); //TODO check at the end if this is needed or redundant

            av_assert0(s->in.planar); //we only support planar internally so it has to be, we support copying non planar though

            copy(out, in, out_count);

            return out_count;

        }

        else if(preout==postin) preout= midbuf= postin= out;

        else if(preout==midbuf) preout= midbuf= out;

        else                    preout= out;

    }



    if(in != postin){

        swri_audio_convert(s->in_convert, postin, in, in_count);

    }



    if(s->resample_first){

        if(postin != midbuf)

            out_count= resample(s, midbuf, out_count, postin, in_count);

        if(midbuf != preout)

            swri_rematrix(s, preout, midbuf, out_count, preout==out);

    }else{

        if(postin != midbuf)

            swri_rematrix(s, midbuf, postin, in_count, midbuf==out);

        if(midbuf != preout)

            out_count= resample(s, preout, out_count, midbuf, in_count);

    }



    if(preout != out && out_count){

        AudioData *conv_src = preout;

        if(s->dither.method){

            int ch;

            int dither_count= FFMAX(out_count, 1<<16);



            if (preout == in) {

                conv_src = &s->dither.temp;

                if((ret=swri_realloc_audio(&s->dither.temp, dither_count))<0)

                    return ret;

            }



            if((ret=swri_realloc_audio(&s->dither.noise, dither_count))<0)

                return ret;

            if(ret)

                for(ch=0; ch<s->dither.noise.ch_count; ch++)

                    swri_get_dither(s, s->dither.noise.ch[ch], s->dither.noise.count, 12345678913579<<ch, s->dither.noise.fmt);

            av_assert0(s->dither.noise.ch_count == preout->ch_count);



            if(s->dither.noise_pos + out_count > s->dither.noise.count)

                s->dither.noise_pos = 0;



            if (s->dither.method < SWR_DITHER_NS){

                if (s->mix_2_1_simd) {

                    int len1= out_count&~15;

                    int off = len1 * preout->bps;



                    if(len1)

                        for(ch=0; ch<preout->ch_count; ch++)

                            s->mix_2_1_simd(conv_src->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_simd_one, 0, 0, len1);

                    if(out_count != len1)

                        for(ch=0; ch<preout->ch_count; ch++)

                            s->mix_2_1_f(conv_src->ch[ch] + off, preout->ch[ch] + off, s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos + off + len1, s->native_one, 0, 0, out_count - len1);

                } else {

                    for(ch=0; ch<preout->ch_count; ch++)

                        s->mix_2_1_f(conv_src->ch[ch], preout->ch[ch], s->dither.noise.ch[ch] + s->dither.noise.bps * s->dither.noise_pos, s->native_one, 0, 0, out_count);

                }

            } else {

                switch(s->int_sample_fmt) {

                case AV_SAMPLE_FMT_S16P :swri_noise_shaping_int16(s, conv_src, preout, &s->dither.noise, out_count); break;

                case AV_SAMPLE_FMT_S32P :swri_noise_shaping_int32(s, conv_src, preout, &s->dither.noise, out_count); break;

                case AV_SAMPLE_FMT_FLTP :swri_noise_shaping_float(s, conv_src, preout, &s->dither.noise, out_count); break;

                case AV_SAMPLE_FMT_DBLP :swri_noise_shaping_double(s,conv_src, preout, &s->dither.noise, out_count); break;

                }

            }

            s->dither.noise_pos += out_count;

        }

//FIXME packed doesn't need more than 1 chan here!

        swri_audio_convert(s->out_convert, out, conv_src, out_count);

    }

    return out_count;

}
