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); } }
void AudioSource::init(void) { position = 0; samples_frac = 0; queue_index = 0; #if defined(LIBTAS_ENABLE_AVDUMPING) || defined(LIBTAS_ENABLE_SOUNDPLAYBACK) if (swr_is_initialized(swr)) swr_close(swr); #endif }
static int control(struct af_instance *af, int cmd, void *arg) { struct af_resample *s = af->priv; switch (cmd) { case AF_CONTROL_REINIT: { struct mp_audio *in = arg; struct mp_audio *out = af->data; struct mp_audio orig_in = *in; if (((out->rate == in->rate) || (out->rate == 0)) && (out->format == in->format) && (mp_chmap_equals(&out->channels, &in->channels) || out->nch == 0) && s->allow_detach && s->playback_speed == 1.0) return AF_DETACH; if (out->rate == 0) out->rate = in->rate; if (mp_chmap_is_empty(&out->channels)) mp_audio_set_channels(out, &in->channels); if (af_to_avformat(in->format) == AV_SAMPLE_FMT_NONE) mp_audio_set_format(in, AF_FORMAT_FLOAT); if (check_output_conversion(out->format) == AV_SAMPLE_FMT_NONE) mp_audio_set_format(out, in->format); int r = ((in->format == orig_in.format) && mp_chmap_equals(&in->channels, &orig_in.channels)) ? AF_OK : AF_FALSE; if (r == AF_OK) r = configure_lavrr(af, in, out, true); return r; } case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: { s->playback_speed = *(double *)arg; return AF_OK; } case AF_CONTROL_RESET: if (s->avrctx) { #if HAVE_LIBSWRESAMPLE swr_close(s->avrctx); if (swr_init(s->avrctx) < 0) { close_lavrr(af); return AF_ERROR; } #else while (avresample_read(s->avrctx, NULL, 1000) > 0) {} #endif } return AF_OK; } return AF_UNKNOWN; }
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); } }
av_cold int swr_init(struct SwrContext *s){ int ret; char l1[1024], l2[1024]; clear_context(s); if(s-> in_sample_fmt >= AV_SAMPLE_FMT_NB){ av_log(s, AV_LOG_ERROR, "Requested input sample format %d is invalid\n", s->in_sample_fmt); return AVERROR(EINVAL); } if(s->out_sample_fmt >= AV_SAMPLE_FMT_NB){ av_log(s, AV_LOG_ERROR, "Requested output sample format %d is invalid\n", s->out_sample_fmt); return AVERROR(EINVAL); } s->out.ch_count = s-> user_out_ch_count; s-> in.ch_count = s-> user_in_ch_count; s->used_ch_count = s->user_used_ch_count; s-> in_ch_layout = s-> user_in_ch_layout; s->out_ch_layout = s->user_out_ch_layout; s->int_sample_fmt= s->user_int_sample_fmt; if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) { av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout); s->in_ch_layout = 0; } if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) { av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout); s->out_ch_layout = 0; } switch(s->engine){ #if CONFIG_LIBSOXR extern struct Resampler const soxr_resampler; case SWR_ENGINE_SOXR: s->resampler = &soxr_resampler; break; #endif case SWR_ENGINE_SWR : s->resampler = &swri_resampler; break; default: av_log(s, AV_LOG_ERROR, "Requested resampling engine is unavailable\n"); return AVERROR(EINVAL); } if(!s->used_ch_count) s->used_ch_count= s->in.ch_count; if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){ av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n"); s-> in_ch_layout= 0; } if(!s-> in_ch_layout) s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count); if(!s->out_ch_layout) s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count); s->rematrix= s->out_ch_layout !=s->in_ch_layout || s->rematrix_volume!=1.0 || s->rematrix_custom; if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){ if(av_get_planar_sample_fmt(s->in_sample_fmt) <= AV_SAMPLE_FMT_S16P){ s->int_sample_fmt= AV_SAMPLE_FMT_S16P; }else if( av_get_planar_sample_fmt(s-> in_sample_fmt) == AV_SAMPLE_FMT_S32P && av_get_planar_sample_fmt(s->out_sample_fmt) == AV_SAMPLE_FMT_S32P && !s->rematrix && s->engine != SWR_ENGINE_SOXR){ s->int_sample_fmt= AV_SAMPLE_FMT_S32P; }else if(av_get_planar_sample_fmt(s->in_sample_fmt) <= AV_SAMPLE_FMT_FLTP){ s->int_sample_fmt= AV_SAMPLE_FMT_FLTP; }else{ av_log(s, AV_LOG_DEBUG, "Using double precision mode\n"); s->int_sample_fmt= AV_SAMPLE_FMT_DBLP; } } if( s->int_sample_fmt != AV_SAMPLE_FMT_S16P &&s->int_sample_fmt != AV_SAMPLE_FMT_S32P &&s->int_sample_fmt != AV_SAMPLE_FMT_FLTP &&s->int_sample_fmt != AV_SAMPLE_FMT_DBLP){ av_log(s, AV_LOG_ERROR, "Requested sample format %s is not supported internally, S16/S32/FLT/DBL is supported\n", av_get_sample_fmt_name(s->int_sample_fmt)); return AVERROR(EINVAL); } set_audiodata_fmt(&s-> in, s-> in_sample_fmt); set_audiodata_fmt(&s->out, s->out_sample_fmt); if (s->firstpts_in_samples != AV_NOPTS_VALUE) { if (!s->async && s->min_compensation >= FLT_MAX/2) s->async = 1; s->firstpts = s->outpts = s->firstpts_in_samples * s->out_sample_rate; } else s->firstpts = AV_NOPTS_VALUE; if (s->async) { if (s->min_compensation >= FLT_MAX/2) s->min_compensation = 0.001; if (s->async > 1.0001) { s->max_soft_compensation = s->async / (double) s->in_sample_rate; } } if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){ s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta, s->precision, s->cheby); if (!s->resample) { av_log(s, AV_LOG_ERROR, "Failed to initilaize resampler\n"); return AVERROR(ENOMEM); } }else s->resampler->free(&s->resample); if( s->int_sample_fmt != AV_SAMPLE_FMT_S16P && s->int_sample_fmt != AV_SAMPLE_FMT_S32P && s->int_sample_fmt != AV_SAMPLE_FMT_FLTP && s->int_sample_fmt != AV_SAMPLE_FMT_DBLP && s->resample){ av_log(s, AV_LOG_ERROR, "Resampling only supported with internal s16/s32/flt/dbl\n"); ret = AVERROR(EINVAL); goto fail; } #define RSC 1 //FIXME finetune if(!s-> in.ch_count) s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout); if(!s->used_ch_count) s->used_ch_count= s->in.ch_count; if(!s->out.ch_count) s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout); if(!s-> in.ch_count){ av_assert0(!s->in_ch_layout); av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n"); ret = AVERROR(EINVAL); goto fail; } av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout); av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout); if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) { av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count); ret = AVERROR(EINVAL); goto fail; } if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) { av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count); ret = AVERROR(EINVAL); goto fail; } if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s " "but there is not enough information to do it\n", l1, l2); ret = AVERROR(EINVAL); goto fail; } av_assert0(s->used_ch_count); av_assert0(s->out.ch_count); s->resample_first= RSC*s->out.ch_count/s->in.ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; s->in_buffer= s->in; s->silence = s->in; s->drop_temp= s->out; if(!s->resample && !s->rematrix && !s->channel_map && !s->dither.method){ s->full_convert = swri_audio_convert_alloc(s->out_sample_fmt, s-> in_sample_fmt, s-> in.ch_count, NULL, 0); return 0; } s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt, s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0); s->out_convert= swri_audio_convert_alloc(s->out_sample_fmt, s->int_sample_fmt, s->out.ch_count, NULL, 0); if (!s->in_convert || !s->out_convert) { ret = AVERROR(ENOMEM); goto fail; } s->postin= s->in; s->preout= s->out; s->midbuf= s->in; if(s->channel_map){ s->postin.ch_count= s->midbuf.ch_count= s->used_ch_count; if(s->resample) s->in_buffer.ch_count= s->used_ch_count; } if(!s->resample_first){ s->midbuf.ch_count= s->out.ch_count; if(s->resample) s->in_buffer.ch_count = s->out.ch_count; } set_audiodata_fmt(&s->postin, s->int_sample_fmt); set_audiodata_fmt(&s->midbuf, s->int_sample_fmt); set_audiodata_fmt(&s->preout, s->int_sample_fmt); if(s->resample){ set_audiodata_fmt(&s->in_buffer, s->int_sample_fmt); } if ((ret = swri_dither_init(s, s->out_sample_fmt, s->int_sample_fmt)) < 0) goto fail; if(s->rematrix || s->dither.method) { ret = swri_rematrix_init(s); if (ret < 0) goto fail; } return 0; fail: swr_close(s); return ret; }
static int opus_decode_subpacket(OpusStreamContext *s, const uint8_t *buf, int buf_size, int nb_samples) { int output_samples = 0; int flush_needed = 0; int i, j, ret; /* check if we need to flush the resampler */ 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; } } 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; } swr_close(s->swr); 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; }
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; }