Esempio n. 1
0
static av_cold void opus_decode_flush(AVCodecContext *ctx)
{
    OpusContext *c = ctx->priv_data;
    int i;

    for (i = 0; i < c->nb_streams; i++) {
        OpusStreamContext *s = &c->streams[i];

        memset(&s->packet, 0, sizeof(s->packet));
        s->delayed_samples = 0;

        if (s->celt_delay)
            av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay));
#if CONFIG_SWRESAMPLE
        swr_close(s->swr);
#elif CONFIG_AVRESAMPLE
        avresample_close(s->avr);
#endif

        av_audio_fifo_drain(c->sync_buffers[i], av_audio_fifo_size(c->sync_buffers[i]));

        ff_silk_flush(s->silk);
        ff_celt_flush(s->celt);
    }
}
Esempio n. 2
0
static int afilter_frame(AVFilterLink *inlink, AVFrame *frame)
{
    AVFilterContext *ctx = inlink->dst;
    AVFilterLink *outlink = ctx->outputs[0];
    LoopContext *s = ctx->priv;
    int ret = 0;

    if (s->ignored_samples + frame->nb_samples > s->start && s->size > 0 && s->loop != 0) {
        if (s->nb_samples < s->size) {
            int written = FFMIN(frame->nb_samples, s->size - s->nb_samples);
            int drain = 0;

            ret = av_audio_fifo_write(s->fifo, (void **)frame->extended_data, written);
            if (ret < 0)
                return ret;
            if (!s->nb_samples) {
                drain = FFMAX(0, s->start - s->ignored_samples);
                s->pts = frame->pts;
                av_audio_fifo_drain(s->fifo, drain);
                s->pts += s->start - s->ignored_samples;
            }
            s->nb_samples += ret - drain;
            drain = frame->nb_samples - written;
            if (s->nb_samples == s->size && drain > 0) {
                int ret2;

                ret2 = av_audio_fifo_write(s->left, (void **)frame->extended_data, frame->nb_samples);
                if (ret2 < 0)
                   return ret2;
                av_audio_fifo_drain(s->left, drain);
            }
            frame->nb_samples = ret;
            s->pts += ret;
            ret = ff_filter_frame(outlink, frame);
        } else {
            int nb_samples = frame->nb_samples;

            av_frame_free(&frame);
            ret = push_samples(ctx, nb_samples);
        }
    } else {
        s->ignored_samples += frame->nb_samples;
        frame->pts = s->pts;
        s->pts += frame->nb_samples;
        ret = ff_filter_frame(outlink, frame);
    }

    return ret;
}
Esempio n. 3
0
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{
    AVFilterContext *ctx = inlink->dst;
    ShowFreqsContext *s = ctx->priv;
    AVFrame *fin = NULL;
    int ret = 0;

    av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples);
    while (av_audio_fifo_size(s->fifo) >= s->win_size) {
        fin = ff_get_audio_buffer(inlink, s->win_size);
        if (!fin) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }

        fin->pts = s->pts;
        s->pts += s->skip_samples;
        ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size);
        if (ret < 0)
            goto fail;

        ret = plot_freqs(inlink, fin);
        av_frame_free(&fin);
        av_audio_fifo_drain(s->fifo, s->skip_samples);
        if (ret < 0)
            goto fail;
    }

fail:
    av_frame_free(&fin);
    av_frame_free(&in);
    return ret;
}
Esempio n. 4
0
static av_cold void opus_decode_flush(AVCodecContext *ctx)
{
    OpusContext *c = ctx->priv_data;
    int i;

    for (i = 0; i < c->nb_streams; i++) {
        OpusStreamContext *s = &c->streams[i];

        memset(&s->packet, 0, sizeof(s->packet));
        s->delayed_samples = 0;

        if (s->celt_delay)
            av_audio_fifo_drain(s->celt_delay, av_audio_fifo_size(s->celt_delay));
        swr_close(s->swr);

        ff_silk_flush(s->silk);
        ff_celt_flush(s->celt);
    }
}
Esempio n. 5
0
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{
    AVFilterContext *ctx = inlink->dst;
    AVFilterLink *outlink = ctx->outputs[0];
    AudioSurroundContext *s = ctx->priv;

    av_audio_fifo_write(s->fifo, (void **)in->extended_data,
                        in->nb_samples);

    if (s->pts == AV_NOPTS_VALUE)
        s->pts = in->pts;

    av_frame_free(&in);

    while (av_audio_fifo_size(s->fifo) >= s->buf_size) {
        AVFrame *out;
        int ret;

        ret = av_audio_fifo_peek(s->fifo, (void **)s->input->extended_data, s->buf_size);
        if (ret < 0)
            return ret;

        ctx->internal->execute(ctx, fft_channel, NULL, NULL, inlink->channels);

        s->filter(ctx);

        out = ff_get_audio_buffer(outlink, s->hop_size);
        if (!out)
            return AVERROR(ENOMEM);

        ctx->internal->execute(ctx, ifft_channel, out, NULL, outlink->channels);

        out->pts = s->pts;
        if (s->pts != AV_NOPTS_VALUE)
            s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
        av_audio_fifo_drain(s->fifo, s->hop_size);
        ret = ff_filter_frame(outlink, out);
        if (ret < 0)
            return ret;
    }

    return 0;
}
Esempio n. 6
0
int avresample_read(AVAudioResampleContext *avr, void **output, int nb_samples)
{
    if (!output)
        return av_audio_fifo_drain(avr->out_fifo, nb_samples);
    return av_audio_fifo_read(avr->out_fifo, output, nb_samples);
}
Esempio n. 7
0
static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size)
{
    int samples    = s->packet.frame_duration;
    int redundancy = 0;
    int redundancy_size, redundancy_pos;
    int ret, i, consumed;
    int delayed_samples = s->delayed_samples;

    ret = opus_rc_init(&s->rc, data, size);
    if (ret < 0)
        return ret;

    /* decode the silk frame */
    if (s->packet.mode == OPUS_MODE_SILK || s->packet.mode == OPUS_MODE_HYBRID) {
        if (!swr_is_initialized(s->swr)) {
            ret = opus_init_resample(s);
            if (ret < 0)
                return ret;
        }

        samples = ff_silk_decode_superframe(s->silk, &s->rc, s->silk_output,
                                            FFMIN(s->packet.bandwidth, OPUS_BANDWIDTH_WIDEBAND),
                                            s->packet.stereo + 1,
                                            silk_frame_duration_ms[s->packet.config]);
        if (samples < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Error decoding a SILK frame.\n");
            return samples;
        }
        samples = swr_convert(s->swr,
                              (uint8_t**)s->out, s->packet.frame_duration,
                              (const uint8_t**)s->silk_output, samples);
        if (samples < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Error resampling SILK data.\n");
            return samples;
        }
        av_assert2((samples & 7) == 0);
        s->delayed_samples += s->packet.frame_duration - samples;
    } else
        ff_silk_flush(s->silk);

    // decode redundancy information
    consumed = opus_rc_tell(&s->rc);
    if (s->packet.mode == OPUS_MODE_HYBRID && consumed + 37 <= size * 8)
        redundancy = opus_rc_p2model(&s->rc, 12);
    else if (s->packet.mode == OPUS_MODE_SILK && consumed + 17 <= size * 8)
        redundancy = 1;

    if (redundancy) {
        redundancy_pos = opus_rc_p2model(&s->rc, 1);

        if (s->packet.mode == OPUS_MODE_HYBRID)
            redundancy_size = opus_rc_unimodel(&s->rc, 256) + 2;
        else
            redundancy_size = size - (consumed + 7) / 8;
        size -= redundancy_size;
        if (size < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Invalid redundancy frame size.\n");
            return AVERROR_INVALIDDATA;
        }

        if (redundancy_pos) {
            ret = opus_decode_redundancy(s, data + size, redundancy_size);
            if (ret < 0)
                return ret;
            ff_celt_flush(s->celt);
        }
    }

    /* decode the CELT frame */
    if (s->packet.mode == OPUS_MODE_CELT || s->packet.mode == OPUS_MODE_HYBRID) {
        float *out_tmp[2] = { s->out[0], s->out[1] };
        float **dst = (s->packet.mode == OPUS_MODE_CELT) ?
                      out_tmp : s->celt_output;
        int celt_output_samples = samples;
        int delay_samples = av_audio_fifo_size(s->celt_delay);

        if (delay_samples) {
            if (s->packet.mode == OPUS_MODE_HYBRID) {
                av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, delay_samples);

                for (i = 0; i < s->output_channels; i++) {
                    s->fdsp->vector_fmac_scalar(out_tmp[i], s->celt_output[i], 1.0,
                                                delay_samples);
                    out_tmp[i] += delay_samples;
                }
                celt_output_samples -= delay_samples;
            } else {
                av_log(s->avctx, AV_LOG_WARNING,
                       "Spurious CELT delay samples present.\n");
                av_audio_fifo_drain(s->celt_delay, delay_samples);
                if (s->avctx->err_recognition & AV_EF_EXPLODE)
                    return AVERROR_BUG;
            }
        }

        opus_raw_init(&s->rc, data + size, size);

        ret = ff_celt_decode_frame(s->celt, &s->rc, dst,
                                   s->packet.stereo + 1,
                                   s->packet.frame_duration,
                                   (s->packet.mode == OPUS_MODE_HYBRID) ? 17 : 0,
                                   celt_band_end[s->packet.bandwidth]);
        if (ret < 0)
            return ret;

        if (s->packet.mode == OPUS_MODE_HYBRID) {
            int celt_delay = s->packet.frame_duration - celt_output_samples;
            void *delaybuf[2] = { s->celt_output[0] + celt_output_samples,
                                  s->celt_output[1] + celt_output_samples
                                };

            for (i = 0; i < s->output_channels; i++) {
                s->fdsp->vector_fmac_scalar(out_tmp[i],
                                            s->celt_output[i], 1.0,
                                            celt_output_samples);
            }

            ret = av_audio_fifo_write(s->celt_delay, delaybuf, celt_delay);
            if (ret < 0)
                return ret;
        }
    } else
        ff_celt_flush(s->celt);

    if (s->redundancy_idx) {
        for (i = 0; i < s->output_channels; i++)
            opus_fade(s->out[i], s->out[i],
                      s->redundancy_output[i] + 120 + s->redundancy_idx,
                      ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx);
        s->redundancy_idx = 0;
    }
    if (redundancy) {
        if (!redundancy_pos) {
            ff_celt_flush(s->celt);
            ret = opus_decode_redundancy(s, data + size, redundancy_size);
            if (ret < 0)
                return ret;

            for (i = 0; i < s->output_channels; i++) {
                opus_fade(s->out[i] + samples - 120 + delayed_samples,
                          s->out[i] + samples - 120 + delayed_samples,
                          s->redundancy_output[i] + 120,
                          ff_celt_window2, 120 - delayed_samples);
                if (delayed_samples)
                    s->redundancy_idx = 120 - delayed_samples;
            }
        } else {
            for (i = 0; i < s->output_channels; i++) {
                memcpy(s->out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float));
                opus_fade(s->out[i] + 120 + delayed_samples,
                          s->redundancy_output[i] + 120,
                          s->out[i] + 120 + delayed_samples,
                          ff_celt_window2, 120);
            }
        }
    }

    return samples;
}
Esempio n. 8
0
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
{
    AVFilterContext *ctx = inlink->dst;
    AVFilterLink *outlink = ctx->outputs[0];
    AFFTFiltContext *s = ctx->priv;
    const int window_size = s->window_size;
    const float f = 1. / s->win_scale;
    double values[VAR_VARS_NB];
    AVFrame *out, *in = NULL;
    int ch, n, ret, i, j, k;
    int start = s->start, end = s->end;

    av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples);
    av_frame_free(&frame);

    while (av_audio_fifo_size(s->fifo) >= window_size) {
        if (!in) {
            in = ff_get_audio_buffer(outlink, window_size);
            if (!in)
                return AVERROR(ENOMEM);
        }

        ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, window_size);
        if (ret < 0)
            break;

        for (ch = 0; ch < inlink->channels; ch++) {
            const float *src = (float *)in->extended_data[ch];
            FFTComplex *fft_data = s->fft_data[ch];

            for (n = 0; n < in->nb_samples; n++) {
                fft_data[n].re = src[n] * s->window_func_lut[n];
                fft_data[n].im = 0;
            }

            for (; n < window_size; n++) {
                fft_data[n].re = 0;
                fft_data[n].im = 0;
            }
        }

        values[VAR_PTS]         = s->pts;
        values[VAR_SAMPLE_RATE] = inlink->sample_rate;
        values[VAR_NBBINS]      = window_size / 2;
        values[VAR_CHANNELS]    = inlink->channels;

        for (ch = 0; ch < inlink->channels; ch++) {
            FFTComplex *fft_data = s->fft_data[ch];
            float *buf = (float *)s->buffer->extended_data[ch];
            int x;

            values[VAR_CHANNEL] = ch;

            av_fft_permute(s->fft, fft_data);
            av_fft_calc(s->fft, fft_data);

            for (n = 0; n < window_size / 2; n++) {
                float fr, fi;

                values[VAR_BIN] = n;

                fr = av_expr_eval(s->real[ch], values, s);
                fi = av_expr_eval(s->imag[ch], values, s);

                fft_data[n].re *= fr;
                fft_data[n].im *= fi;
            }

            for (n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) {
                fft_data[n].re =  fft_data[x].re;
                fft_data[n].im = -fft_data[x].im;
            }

            av_fft_permute(s->ifft, fft_data);
            av_fft_calc(s->ifft, fft_data);

            start = s->start;
            end = s->end;
            k = end;
            for (i = 0, j = start; j < k && i < window_size; i++, j++) {
                buf[j] += s->fft_data[ch][i].re * f;
            }

            for (; i < window_size; i++, j++) {
                buf[j] = s->fft_data[ch][i].re * f;
            }

            start += s->hop_size;
            end = j;
        }

        s->start = start;
        s->end = end;

        if (start >= window_size) {
            float *dst, *buf;

            start -= window_size;
            end   -= window_size;

            s->start = start;
            s->end = end;

            out = ff_get_audio_buffer(outlink, window_size);
            if (!out) {
                ret = AVERROR(ENOMEM);
                break;
            }

            out->pts = s->pts;
            s->pts += window_size;

            for (ch = 0; ch < inlink->channels; ch++) {
                dst = (float *)out->extended_data[ch];
                buf = (float *)s->buffer->extended_data[ch];

                for (n = 0; n < window_size; n++) {
                    dst[n] = buf[n] * (1 - s->overlap);
                }
                memmove(buf, buf + window_size, window_size * 4);
            }

            ret = ff_filter_frame(outlink, out);
            if (ret < 0)
                break;
        }

        av_audio_fifo_drain(s->fifo, s->hop_size);
    }

    av_frame_free(&in);
    return ret;
}
Esempio n. 9
0
static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size)
{
    int samples    = s->packet.frame_duration;
    int redundancy = 0;
    int redundancy_size, redundancy_pos;
    int ret, i, consumed;
    int delayed_samples = s->delayed_samples;

    ret = ff_opus_rc_dec_init(&s->rc, data, size);
    if (ret < 0)
        return ret;

    /* decode the silk frame */
    if (s->packet.mode == OPUS_MODE_SILK || s->packet.mode == OPUS_MODE_HYBRID) {
#if CONFIG_SWRESAMPLE
        if (!swr_is_initialized(s->swr)) {
#elif CONFIG_AVRESAMPLE
        if (!avresample_is_open(s->avr)) {
#endif
            ret = opus_init_resample(s);
            if (ret < 0)
                return ret;
        }

        samples = ff_silk_decode_superframe(s->silk, &s->rc, s->silk_output,
                                            FFMIN(s->packet.bandwidth, OPUS_BANDWIDTH_WIDEBAND),
                                            s->packet.stereo + 1,
                                            silk_frame_duration_ms[s->packet.config]);
        if (samples < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Error decoding a SILK frame.\n");
            return samples;
        }
#if CONFIG_SWRESAMPLE
        samples = swr_convert(s->swr,
                              (uint8_t**)s->out, s->packet.frame_duration,
                              (const uint8_t**)s->silk_output, samples);
#elif CONFIG_AVRESAMPLE
        samples = avresample_convert(s->avr, (uint8_t**)s->out, s->out_size,
                                     s->packet.frame_duration,
                                     (uint8_t**)s->silk_output,
                                     sizeof(s->silk_buf[0]),
                                     samples);
#endif
        if (samples < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Error resampling SILK data.\n");
            return samples;
        }
        av_assert2((samples & 7) == 0);
        s->delayed_samples += s->packet.frame_duration - samples;
    } else
        ff_silk_flush(s->silk);

    // decode redundancy information
    consumed = opus_rc_tell(&s->rc);
    if (s->packet.mode == OPUS_MODE_HYBRID && consumed + 37 <= size * 8)
        redundancy = ff_opus_rc_dec_log(&s->rc, 12);
    else if (s->packet.mode == OPUS_MODE_SILK && consumed + 17 <= size * 8)
        redundancy = 1;

    if (redundancy) {
        redundancy_pos = ff_opus_rc_dec_log(&s->rc, 1);

        if (s->packet.mode == OPUS_MODE_HYBRID)
            redundancy_size = ff_opus_rc_dec_uint(&s->rc, 256) + 2;
        else
            redundancy_size = size - (consumed + 7) / 8;
        size -= redundancy_size;
        if (size < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Invalid redundancy frame size.\n");
            return AVERROR_INVALIDDATA;
        }

        if (redundancy_pos) {
            ret = opus_decode_redundancy(s, data + size, redundancy_size);
            if (ret < 0)
                return ret;
            ff_celt_flush(s->celt);
        }
    }

    /* decode the CELT frame */
    if (s->packet.mode == OPUS_MODE_CELT || s->packet.mode == OPUS_MODE_HYBRID) {
        float *out_tmp[2] = { s->out[0], s->out[1] };
        float **dst = (s->packet.mode == OPUS_MODE_CELT) ?
                      out_tmp : s->celt_output;
        int celt_output_samples = samples;
        int delay_samples = av_audio_fifo_size(s->celt_delay);

        if (delay_samples) {
            if (s->packet.mode == OPUS_MODE_HYBRID) {
                av_audio_fifo_read(s->celt_delay, (void**)s->celt_output, delay_samples);

                for (i = 0; i < s->output_channels; i++) {
                    s->fdsp->vector_fmac_scalar(out_tmp[i], s->celt_output[i], 1.0,
                                                delay_samples);
                    out_tmp[i] += delay_samples;
                }
                celt_output_samples -= delay_samples;
            } else {
                av_log(s->avctx, AV_LOG_WARNING,
                       "Spurious CELT delay samples present.\n");
                av_audio_fifo_drain(s->celt_delay, delay_samples);
                if (s->avctx->err_recognition & AV_EF_EXPLODE)
                    return AVERROR_BUG;
            }
        }

        ff_opus_rc_dec_raw_init(&s->rc, data + size, size);

        ret = ff_celt_decode_frame(s->celt, &s->rc, dst,
                                   s->packet.stereo + 1,
                                   s->packet.frame_duration,
                                   (s->packet.mode == OPUS_MODE_HYBRID) ? 17 : 0,
                                   ff_celt_band_end[s->packet.bandwidth]);
        if (ret < 0)
            return ret;

        if (s->packet.mode == OPUS_MODE_HYBRID) {
            int celt_delay = s->packet.frame_duration - celt_output_samples;
            void *delaybuf[2] = { s->celt_output[0] + celt_output_samples,
                                  s->celt_output[1] + celt_output_samples };

            for (i = 0; i < s->output_channels; i++) {
                s->fdsp->vector_fmac_scalar(out_tmp[i],
                                            s->celt_output[i], 1.0,
                                            celt_output_samples);
            }

            ret = av_audio_fifo_write(s->celt_delay, delaybuf, celt_delay);
            if (ret < 0)
                return ret;
        }
    } else
        ff_celt_flush(s->celt);

    if (s->redundancy_idx) {
        for (i = 0; i < s->output_channels; i++)
            opus_fade(s->out[i], s->out[i],
                      s->redundancy_output[i] + 120 + s->redundancy_idx,
                      ff_celt_window2 + s->redundancy_idx, 120 - s->redundancy_idx);
        s->redundancy_idx = 0;
    }
    if (redundancy) {
        if (!redundancy_pos) {
            ff_celt_flush(s->celt);
            ret = opus_decode_redundancy(s, data + size, redundancy_size);
            if (ret < 0)
                return ret;

            for (i = 0; i < s->output_channels; i++) {
                opus_fade(s->out[i] + samples - 120 + delayed_samples,
                          s->out[i] + samples - 120 + delayed_samples,
                          s->redundancy_output[i] + 120,
                          ff_celt_window2, 120 - delayed_samples);
                if (delayed_samples)
                    s->redundancy_idx = 120 - delayed_samples;
            }
        } else {
            for (i = 0; i < s->output_channels; i++) {
                memcpy(s->out[i] + delayed_samples, s->redundancy_output[i], 120 * sizeof(float));
                opus_fade(s->out[i] + 120 + delayed_samples,
                          s->redundancy_output[i] + 120,
                          s->out[i] + 120 + delayed_samples,
                          ff_celt_window2, 120);
            }
        }
    }

    return samples;
}

static int opus_decode_subpacket(OpusStreamContext *s,
                                 const uint8_t *buf, int buf_size,
                                 float **out, int out_size,
                                 int nb_samples)
{
    int output_samples = 0;
    int flush_needed   = 0;
    int i, j, ret;

    s->out[0]   = out[0];
    s->out[1]   = out[1];
    s->out_size = out_size;

    /* check if we need to flush the resampler */
#if CONFIG_SWRESAMPLE
    if (swr_is_initialized(s->swr)) {
        if (buf) {
            int64_t cur_samplerate;
            av_opt_get_int(s->swr, "in_sample_rate", 0, &cur_samplerate);
            flush_needed = (s->packet.mode == OPUS_MODE_CELT) || (cur_samplerate != s->silk_samplerate);
        } else {
            flush_needed = !!s->delayed_samples;
        }
    }
#elif CONFIG_AVRESAMPLE
    if (avresample_is_open(s->avr)) {
        if (buf) {
            int64_t cur_samplerate;
            av_opt_get_int(s->avr, "in_sample_rate", 0, &cur_samplerate);
            flush_needed = (s->packet.mode == OPUS_MODE_CELT) || (cur_samplerate != s->silk_samplerate);
        } else {
            flush_needed = !!s->delayed_samples;
        }
    }
#endif

    if (!buf && !flush_needed)
        return 0;

    /* use dummy output buffers if the channel is not mapped to anything */
    if (!s->out[0] ||
        (s->output_channels == 2 && !s->out[1])) {
        av_fast_malloc(&s->out_dummy, &s->out_dummy_allocated_size, s->out_size);
        if (!s->out_dummy)
            return AVERROR(ENOMEM);
        if (!s->out[0])
            s->out[0] = s->out_dummy;
        if (!s->out[1])
            s->out[1] = s->out_dummy;
    }

    /* flush the resampler if necessary */
    if (flush_needed) {
        ret = opus_flush_resample(s, s->delayed_samples);
        if (ret < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Error flushing the resampler.\n");
            return ret;
        }
#if CONFIG_SWRESAMPLE
        swr_close(s->swr);
#elif CONFIG_AVRESAMPLE
        avresample_close(s->avr);
#endif
        output_samples += s->delayed_samples;
        s->delayed_samples = 0;

        if (!buf)
            goto finish;
    }

    /* decode all the frames in the packet */
    for (i = 0; i < s->packet.frame_count; i++) {
        int size = s->packet.frame_size[i];
        int samples = opus_decode_frame(s, buf + s->packet.frame_offset[i], size);

        if (samples < 0) {
            av_log(s->avctx, AV_LOG_ERROR, "Error decoding an Opus frame.\n");
            if (s->avctx->err_recognition & AV_EF_EXPLODE)
                return samples;

            for (j = 0; j < s->output_channels; j++)
                memset(s->out[j], 0, s->packet.frame_duration * sizeof(float));
            samples = s->packet.frame_duration;
        }
        output_samples += samples;

        for (j = 0; j < s->output_channels; j++)
            s->out[j] += samples;
        s->out_size -= samples * sizeof(float);
    }

finish:
    s->out[0] = s->out[1] = NULL;
    s->out_size = 0;

    return output_samples;
}