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 case SWR_ENGINE_SOXR: s->resampler = &swri_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_bytes_per_sample(s-> in_sample_fmt) <= 2 && av_get_bytes_per_sample(s->out_sample_fmt) <= 2){ s->int_sample_fmt= AV_SAMPLE_FMT_S16P; }else if( av_get_bytes_per_sample(s-> in_sample_fmt) <= 2 && !s->rematrix && s->out_sample_rate==s->in_sample_rate && !(s->flags & SWR_FLAG_RESAMPLE)){ 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_bytes_per_sample(s->in_sample_fmt) <= 4){ s->int_sample_fmt= AV_SAMPLE_FMT_FLTP; }else{ s->int_sample_fmt= AV_SAMPLE_FMT_DBLP; } } av_log(s, AV_LOG_DEBUG, "Using %s internally between filters\n", av_get_sample_fmt_name(s->int_sample_fmt)); 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 initialize 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; }
int avresample_open(AVAudioResampleContext *avr) { int ret; /* set channel mixing parameters */ avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout); if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) { av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n", avr->in_channel_layout); return AVERROR(EINVAL); } avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout); if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) { av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n", avr->out_channel_layout); return AVERROR(EINVAL); } avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels); avr->downmix_needed = avr->in_channels > avr->out_channels; avr->upmix_needed = avr->out_channels > avr->in_channels || (!avr->downmix_needed && (avr->am->matrix || avr->in_channel_layout != avr->out_channel_layout)); avr->mixing_needed = avr->downmix_needed || avr->upmix_needed; /* set resampling parameters */ avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate || avr->force_resampling; /* select internal sample format if not specified by the user */ if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE && (avr->mixing_needed || avr->resample_needed)) { enum AVSampleFormat in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt), av_get_bytes_per_sample(out_fmt)); if (max_bps <= 2) { avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P; } else if (avr->mixing_needed) { avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; } else { if (max_bps <= 4) { if (in_fmt == AV_SAMPLE_FMT_S32P || out_fmt == AV_SAMPLE_FMT_S32P) { if (in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_FLTP) { /* if one is s32 and the other is flt, use dbl */ avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; } else { /* if one is s32 and the other is s32, s16, or u8, use s32 */ avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P; } } else { /* if one is flt and the other is flt, s16 or u8, use flt */ avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; } } else { /* if either is dbl, use dbl */ avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; } } av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n", av_get_sample_fmt_name(avr->internal_sample_fmt)); } /* set sample format conversion parameters */ if (avr->in_channels == 1) avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); if (avr->out_channels == 1) avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); avr->in_convert_needed = (avr->resample_needed || avr->mixing_needed) && avr->in_sample_fmt != avr->internal_sample_fmt; if (avr->resample_needed || avr->mixing_needed) avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt; else avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt; /* allocate buffers */ if (avr->mixing_needed || avr->in_convert_needed) { avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels), 0, avr->internal_sample_fmt, "in_buffer"); if (!avr->in_buffer) { ret = AVERROR(EINVAL); goto error; } } if (avr->resample_needed) { avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels, 0, avr->internal_sample_fmt, "resample_out_buffer"); if (!avr->resample_out_buffer) { ret = AVERROR(EINVAL); goto error; } } if (avr->out_convert_needed) { avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0, avr->out_sample_fmt, "out_buffer"); if (!avr->out_buffer) { ret = AVERROR(EINVAL); goto error; } } avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels, 1024); if (!avr->out_fifo) { ret = AVERROR(ENOMEM); goto error; } /* setup contexts */ if (avr->in_convert_needed) { avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt, avr->in_sample_fmt, avr->in_channels); if (!avr->ac_in) { ret = AVERROR(ENOMEM); goto error; } } if (avr->out_convert_needed) { enum AVSampleFormat src_fmt; if (avr->in_convert_needed) src_fmt = avr->internal_sample_fmt; else src_fmt = avr->in_sample_fmt; avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt, avr->out_channels); if (!avr->ac_out) { ret = AVERROR(ENOMEM); goto error; } } if (avr->resample_needed) { avr->resample = ff_audio_resample_init(avr); if (!avr->resample) { ret = AVERROR(ENOMEM); goto error; } } if (avr->mixing_needed) { ret = ff_audio_mix_init(avr); if (ret < 0) goto error; } return 0; error: avresample_close(avr); return ret; }
av_cold int swr_init(struct SwrContext *s) { s->in_buffer_index= 0; s->in_buffer_count= 0; s->resample_in_constraint= 0; free_temp(&s->postin); free_temp(&s->midbuf); free_temp(&s->preout); free_temp(&s->in_buffer); free_temp(&s->dither); memset(s->in.ch, 0, sizeof(s->in.ch)); memset(s->out.ch, 0, sizeof(s->out.ch)); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); swri_rematrix_free(s); s->flushed = 0; 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); } 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_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->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)) { s->resample = swri_resample_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); } else swri_resample_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"); return -1; } 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; #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"); return -1; } 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 but there is not enough information to do it\n"); return -1; } 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; 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); 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); } s->dither = s->preout; if(s->rematrix || s->dither_method) return swri_rematrix_init(s); return 0; }
int avresample_open(AVAudioResampleContext *avr) { int ret; if (avresample_is_open(avr)) { av_log(avr, AV_LOG_ERROR, "The resampling context is already open.\n"); return AVERROR(EINVAL); } /* set channel mixing parameters */ avr->in_channels = av_get_channel_layout_nb_channels(avr->in_channel_layout); if (avr->in_channels <= 0 || avr->in_channels > AVRESAMPLE_MAX_CHANNELS) { av_log(avr, AV_LOG_ERROR, "Invalid input channel layout: %"PRIu64"\n", avr->in_channel_layout); return AVERROR(EINVAL); } avr->out_channels = av_get_channel_layout_nb_channels(avr->out_channel_layout); if (avr->out_channels <= 0 || avr->out_channels > AVRESAMPLE_MAX_CHANNELS) { av_log(avr, AV_LOG_ERROR, "Invalid output channel layout: %"PRIu64"\n", avr->out_channel_layout); return AVERROR(EINVAL); } avr->resample_channels = FFMIN(avr->in_channels, avr->out_channels); avr->downmix_needed = avr->in_channels > avr->out_channels; avr->upmix_needed = avr->out_channels > avr->in_channels || (!avr->downmix_needed && (avr->mix_matrix || avr->in_channel_layout != avr->out_channel_layout)); avr->mixing_needed = avr->downmix_needed || avr->upmix_needed; /* set resampling parameters */ avr->resample_needed = avr->in_sample_rate != avr->out_sample_rate || avr->force_resampling; /* select internal sample format if not specified by the user */ if (avr->internal_sample_fmt == AV_SAMPLE_FMT_NONE && (avr->mixing_needed || avr->resample_needed)) { enum AVSampleFormat in_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); enum AVSampleFormat out_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); int max_bps = FFMAX(av_get_bytes_per_sample(in_fmt), av_get_bytes_per_sample(out_fmt)); if (max_bps <= 2) { avr->internal_sample_fmt = AV_SAMPLE_FMT_S16P; } else if (avr->mixing_needed) { avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; } else { if (max_bps <= 4) { if (in_fmt == AV_SAMPLE_FMT_S32P || out_fmt == AV_SAMPLE_FMT_S32P) { if (in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_FLTP) { /* if one is s32 and the other is flt, use dbl */ avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; } else { /* if one is s32 and the other is s32, s16, or u8, use s32 */ avr->internal_sample_fmt = AV_SAMPLE_FMT_S32P; } } else { /* if one is flt and the other is flt, s16 or u8, use flt */ avr->internal_sample_fmt = AV_SAMPLE_FMT_FLTP; } } else { /* if either is dbl, use dbl */ avr->internal_sample_fmt = AV_SAMPLE_FMT_DBLP; } } av_log(avr, AV_LOG_DEBUG, "Using %s as internal sample format\n", av_get_sample_fmt_name(avr->internal_sample_fmt)); } /* treat all mono as planar for easier comparison */ if (avr->in_channels == 1) avr->in_sample_fmt = av_get_planar_sample_fmt(avr->in_sample_fmt); if (avr->out_channels == 1) avr->out_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); /* we may need to add an extra conversion in order to remap channels if the output format is not planar */ if (avr->use_channel_map && !avr->mixing_needed && !avr->resample_needed && !av_sample_fmt_is_planar(avr->out_sample_fmt)) { avr->internal_sample_fmt = av_get_planar_sample_fmt(avr->out_sample_fmt); } /* set sample format conversion parameters */ if (avr->resample_needed || avr->mixing_needed) avr->in_convert_needed = avr->in_sample_fmt != avr->internal_sample_fmt; else avr->in_convert_needed = avr->use_channel_map && !av_sample_fmt_is_planar(avr->out_sample_fmt); if (avr->resample_needed || avr->mixing_needed || avr->in_convert_needed) avr->out_convert_needed = avr->internal_sample_fmt != avr->out_sample_fmt; else avr->out_convert_needed = avr->in_sample_fmt != avr->out_sample_fmt; avr->in_copy_needed = !avr->in_convert_needed && (avr->mixing_needed || (avr->use_channel_map && avr->resample_needed)); if (avr->use_channel_map) { if (avr->in_copy_needed) { avr->remap_point = REMAP_IN_COPY; av_dlog(avr, "remap channels during in_copy\n"); } else if (avr->in_convert_needed) { avr->remap_point = REMAP_IN_CONVERT; av_dlog(avr, "remap channels during in_convert\n"); } else if (avr->out_convert_needed) { avr->remap_point = REMAP_OUT_CONVERT; av_dlog(avr, "remap channels during out_convert\n"); } else { avr->remap_point = REMAP_OUT_COPY; av_dlog(avr, "remap channels during out_copy\n"); } #ifdef DEBUG { int ch; av_dlog(avr, "output map: "); if (avr->ch_map_info.do_remap) for (ch = 0; ch < avr->in_channels; ch++) av_dlog(avr, " % 2d", avr->ch_map_info.channel_map[ch]); else av_dlog(avr, "n/a"); av_dlog(avr, "\n"); av_dlog(avr, "copy map: "); if (avr->ch_map_info.do_copy) for (ch = 0; ch < avr->in_channels; ch++) av_dlog(avr, " % 2d", avr->ch_map_info.channel_copy[ch]); else av_dlog(avr, "n/a"); av_dlog(avr, "\n"); av_dlog(avr, "zero map: "); if (avr->ch_map_info.do_zero) for (ch = 0; ch < avr->in_channels; ch++) av_dlog(avr, " % 2d", avr->ch_map_info.channel_zero[ch]); else av_dlog(avr, "n/a"); av_dlog(avr, "\n"); av_dlog(avr, "input map: "); for (ch = 0; ch < avr->in_channels; ch++) av_dlog(avr, " % 2d", avr->ch_map_info.input_map[ch]); av_dlog(avr, "\n"); } #endif } else avr->remap_point = REMAP_NONE; /* allocate buffers */ if (avr->in_copy_needed || avr->in_convert_needed) { avr->in_buffer = ff_audio_data_alloc(FFMAX(avr->in_channels, avr->out_channels), 0, avr->internal_sample_fmt, "in_buffer"); if (!avr->in_buffer) { ret = AVERROR(EINVAL); goto error; } } if (avr->resample_needed) { avr->resample_out_buffer = ff_audio_data_alloc(avr->out_channels, 1024, avr->internal_sample_fmt, "resample_out_buffer"); if (!avr->resample_out_buffer) { ret = AVERROR(EINVAL); goto error; } } if (avr->out_convert_needed) { avr->out_buffer = ff_audio_data_alloc(avr->out_channels, 0, avr->out_sample_fmt, "out_buffer"); if (!avr->out_buffer) { ret = AVERROR(EINVAL); goto error; } } avr->out_fifo = av_audio_fifo_alloc(avr->out_sample_fmt, avr->out_channels, 1024); if (!avr->out_fifo) { ret = AVERROR(ENOMEM); goto error; } /* setup contexts */ if (avr->in_convert_needed) { avr->ac_in = ff_audio_convert_alloc(avr, avr->internal_sample_fmt, avr->in_sample_fmt, avr->in_channels, avr->in_sample_rate, avr->remap_point == REMAP_IN_CONVERT); if (!avr->ac_in) { ret = AVERROR(ENOMEM); goto error; } } if (avr->out_convert_needed) { enum AVSampleFormat src_fmt; if (avr->in_convert_needed) src_fmt = avr->internal_sample_fmt; else src_fmt = avr->in_sample_fmt; avr->ac_out = ff_audio_convert_alloc(avr, avr->out_sample_fmt, src_fmt, avr->out_channels, avr->out_sample_rate, avr->remap_point == REMAP_OUT_CONVERT); if (!avr->ac_out) { ret = AVERROR(ENOMEM); goto error; } } if (avr->resample_needed) { avr->resample = ff_audio_resample_init(avr); if (!avr->resample) { ret = AVERROR(ENOMEM); goto error; } } if (avr->mixing_needed) { avr->am = ff_audio_mix_alloc(avr); if (!avr->am) { ret = AVERROR(ENOMEM); goto error; } } return 0; error: avresample_close(avr); return ret; }
static int configure_lavrr(struct af_instance *af, struct mp_audio *in, struct mp_audio *out) { struct af_resample *s = af->priv; close_lavrr(af); s->avrctx = avresample_alloc_context(); s->avrctx_out = avresample_alloc_context(); if (!s->avrctx || !s->avrctx_out) goto error; enum AVSampleFormat in_samplefmt = af_to_avformat(in->format); enum AVSampleFormat out_samplefmt = check_output_conversion(out->format); enum AVSampleFormat out_samplefmtp = av_get_planar_sample_fmt(out_samplefmt); if (in_samplefmt == AV_SAMPLE_FMT_NONE || out_samplefmt == AV_SAMPLE_FMT_NONE || out_samplefmtp == AV_SAMPLE_FMT_NONE) goto error; s->ctx.out_rate = out->rate; s->ctx.in_rate_af = in->rate; s->ctx.in_rate = rate_from_speed(in->rate, s->playback_speed); s->ctx.out_format = out->format; s->ctx.in_format = in->format; s->ctx.out_channels= out->channels; s->ctx.in_channels = in->channels; s->ctx.filter_size = s->opts.filter_size; s->ctx.phase_shift = s->opts.phase_shift; s->ctx.linear = s->opts.linear; s->ctx.cutoff = s->opts.cutoff; av_opt_set_int(s->avrctx, "filter_size", s->ctx.filter_size, 0); av_opt_set_int(s->avrctx, "phase_shift", s->ctx.phase_shift, 0); av_opt_set_int(s->avrctx, "linear_interp", s->ctx.linear, 0); av_opt_set_double(s->avrctx, "cutoff", s->ctx.cutoff, 0); #if HAVE_LIBSWRESAMPLE av_opt_set_double(s->avrctx, "rematrix_maxval", 1.0, 0); #endif if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0) goto error; struct mp_chmap map_in = in->channels; struct mp_chmap map_out = out->channels; // Try not to do any remixing if at least one is "unknown". if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out)) { mp_chmap_set_unknown(&map_in, map_in.num); mp_chmap_set_unknown(&map_out, map_out.num); } // unchecked: don't take any channel reordering into account uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in); uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out); struct mp_chmap in_lavc; mp_chmap_from_lavc(&in_lavc, in_ch_layout); if (in_lavc.num != map_in.num) { // For handling NA channels, we would have to add a planarization step. MP_FATAL(af, "Unsupported channel remapping.\n"); goto error; } mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc); transpose_order(s->reorder_in, map_in.num); struct mp_chmap out_lavc; mp_chmap_from_lavc(&out_lavc, out_ch_layout); if (mp_chmap_equals(&out_lavc, &map_out)) { // No intermediate step required - output new format directly. out_samplefmtp = out_samplefmt; } else { // Verify that we really just reorder and/or insert NA channels. struct mp_chmap withna = out_lavc; mp_chmap_fill_na(&withna, map_out.num); if (withna.num != map_out.num) goto error; } mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out); s->avrctx_fmt = *out; mp_audio_set_channels(&s->avrctx_fmt, &out_lavc); mp_audio_set_format(&s->avrctx_fmt, af_from_avformat(out_samplefmtp)); s->pre_out_fmt = *out; mp_audio_set_format(&s->pre_out_fmt, af_from_avformat(out_samplefmt)); // If there are NA channels, the final output will have more channels than // the avrctx output. Also, avrctx will output planar (out_samplefmtp was // not overwritten). Allocate the output frame with more channels, so the // NA channels can be trivially added. s->pool_fmt = s->avrctx_fmt; if (map_out.num > out_lavc.num) mp_audio_set_channels(&s->pool_fmt, &map_out); // Real conversion; output is input to avrctx_out. av_opt_set_int(s->avrctx, "in_channel_layout", in_ch_layout, 0); av_opt_set_int(s->avrctx, "out_channel_layout", out_ch_layout, 0); av_opt_set_int(s->avrctx, "in_sample_rate", s->ctx.in_rate, 0); av_opt_set_int(s->avrctx, "out_sample_rate", s->ctx.out_rate, 0); av_opt_set_int(s->avrctx, "in_sample_fmt", in_samplefmt, 0); av_opt_set_int(s->avrctx, "out_sample_fmt", out_samplefmtp, 0); // Just needs the correct number of channels. int fake_out_ch_layout = av_get_default_channel_layout(map_out.num); if (!fake_out_ch_layout) goto error; // Deplanarize if needed. av_opt_set_int(s->avrctx_out, "in_channel_layout", fake_out_ch_layout, 0); av_opt_set_int(s->avrctx_out, "out_channel_layout", fake_out_ch_layout, 0); av_opt_set_int(s->avrctx_out, "in_sample_fmt", out_samplefmtp, 0); av_opt_set_int(s->avrctx_out, "out_sample_fmt", out_samplefmt, 0); av_opt_set_int(s->avrctx_out, "in_sample_rate", s->ctx.out_rate, 0); av_opt_set_int(s->avrctx_out, "out_sample_rate", s->ctx.out_rate, 0); // API has weird requirements, quoting avresample.h: // * This function can only be called when the allocated context is not open. // * Also, the input channel layout must have already been set. avresample_set_channel_mapping(s->avrctx, s->reorder_in); if (avresample_open(s->avrctx) < 0 || avresample_open(s->avrctx_out) < 0) { MP_ERR(af, "Cannot open Libavresample Context. \n"); goto error; } return AF_OK; error: close_lavrr(af); return AF_ERROR; }
static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; ResampleContext *s = ctx->priv; char buf1[64], buf2[64]; int ret; int64_t resampling_forced; if (s->avr) { avresample_close(s->avr); avresample_free(&s->avr); } if (inlink->channel_layout == outlink->channel_layout && inlink->sample_rate == outlink->sample_rate && (inlink->format == outlink->format || (av_get_channel_layout_nb_channels(inlink->channel_layout) == 1 && av_get_channel_layout_nb_channels(outlink->channel_layout) == 1 && av_get_planar_sample_fmt(inlink->format) == av_get_planar_sample_fmt(outlink->format)))) return 0; if (!(s->avr = avresample_alloc_context())) return AVERROR(ENOMEM); if (s->options) { int ret; AVDictionaryEntry *e = NULL; while ((e = av_dict_get(s->options, "", e, AV_DICT_IGNORE_SUFFIX))) av_log(ctx, AV_LOG_VERBOSE, "lavr option: %s=%s\n", e->key, e->value); ret = av_opt_set_dict(s->avr, &s->options); if (ret < 0) return ret; } av_opt_set_int(s->avr, "in_channel_layout", inlink ->channel_layout, 0); av_opt_set_int(s->avr, "out_channel_layout", outlink->channel_layout, 0); av_opt_set_int(s->avr, "in_sample_fmt", inlink ->format, 0); av_opt_set_int(s->avr, "out_sample_fmt", outlink->format, 0); av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0); av_opt_set_int(s->avr, "out_sample_rate", outlink->sample_rate, 0); if ((ret = avresample_open(s->avr)) < 0) return ret; av_opt_get_int(s->avr, "force_resampling", 0, &resampling_forced); s->resampling = resampling_forced || (inlink->sample_rate != outlink->sample_rate); if (s->resampling) { outlink->time_base = (AVRational){ 1, outlink->sample_rate }; s->next_pts = AV_NOPTS_VALUE; s->next_in_pts = AV_NOPTS_VALUE; } else outlink->time_base = inlink->time_base; av_get_channel_layout_string(buf1, sizeof(buf1), -1, inlink ->channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, outlink->channel_layout); av_log(ctx, AV_LOG_VERBOSE, "fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n", av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, buf1, av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf2); return 0; }