|
|
|
@ -161,6 +161,7 @@ static void clear_context(SwrContext *s){ |
|
|
|
|
free_temp(&s->dither.temp); |
|
|
|
|
av_channel_layout_uninit(&s->in_ch_layout); |
|
|
|
|
av_channel_layout_uninit(&s->out_ch_layout); |
|
|
|
|
av_channel_layout_uninit(&s->used_ch_layout); |
|
|
|
|
swri_audio_convert_free(&s-> in_convert); |
|
|
|
|
swri_audio_convert_free(&s->out_convert); |
|
|
|
|
swri_audio_convert_free(&s->full_convert); |
|
|
|
@ -176,6 +177,7 @@ av_cold void swr_free(SwrContext **ss){ |
|
|
|
|
clear_context(s); |
|
|
|
|
av_channel_layout_uninit(&s->user_in_chlayout); |
|
|
|
|
av_channel_layout_uninit(&s->user_out_chlayout); |
|
|
|
|
av_channel_layout_uninit(&s->user_used_chlayout); |
|
|
|
|
|
|
|
|
|
if (s->resampler) |
|
|
|
|
s->resampler->free(&s->resample); |
|
|
|
@ -211,12 +213,20 @@ av_cold int swr_init(struct SwrContext *s){ |
|
|
|
|
av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate); |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
s->used_ch_count = s->user_used_ch_count; |
|
|
|
|
#if FF_API_OLD_CHANNEL_LAYOUT |
|
|
|
|
s->out.ch_count = s-> user_out_ch_count; |
|
|
|
|
s-> in.ch_count = s-> user_in_ch_count; |
|
|
|
|
|
|
|
|
|
// if the old/new fields are set inconsistently, prefer the old ones
|
|
|
|
|
if (s->user_used_ch_count && s->user_used_ch_count != s->user_used_chlayout.nb_channels) { |
|
|
|
|
av_channel_layout_uninit(&s->used_ch_layout); |
|
|
|
|
s->used_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; |
|
|
|
|
s->used_ch_layout.nb_channels = s->user_used_ch_count; |
|
|
|
|
} else if (av_channel_layout_check(&s->user_used_chlayout)) { |
|
|
|
|
ret = av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) || |
|
|
|
|
(s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE || |
|
|
|
|
s->user_in_chlayout.u.mask != s->user_in_ch_layout))) { |
|
|
|
@ -243,9 +253,9 @@ av_cold int swr_init(struct SwrContext *s){ |
|
|
|
|
} else if (av_channel_layout_check(&s->user_out_chlayout)) |
|
|
|
|
av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); |
|
|
|
|
|
|
|
|
|
if (!s->out.ch_count && !s->user_out_ch_layout) |
|
|
|
|
if (!s->out.ch_count) |
|
|
|
|
s->out.ch_count = s->out_ch_layout.nb_channels; |
|
|
|
|
if (!s-> in.ch_count && !s-> user_in_ch_layout) |
|
|
|
|
if (!s-> in.ch_count) |
|
|
|
|
s-> in.ch_count = s->in_ch_layout.nb_channels; |
|
|
|
|
|
|
|
|
|
if (!(ret = av_channel_layout_check(&s->in_ch_layout)) || s->in_ch_layout.nb_channels > SWR_CH_MAX) { |
|
|
|
@ -281,6 +291,7 @@ av_cold int swr_init(struct SwrContext *s){ |
|
|
|
|
|
|
|
|
|
ret = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout); |
|
|
|
|
ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); |
|
|
|
|
ret |= av_channel_layout_copy(&s->used_ch_layout, &s->user_used_chlayout); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
#endif |
|
|
|
@ -299,16 +310,19 @@ av_cold int swr_init(struct SwrContext *s){ |
|
|
|
|
return AVERROR(EINVAL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(!s->used_ch_count) |
|
|
|
|
s->used_ch_count= s->in.ch_count; |
|
|
|
|
if (!av_channel_layout_check(&s->used_ch_layout)) |
|
|
|
|
av_channel_layout_default(&s->used_ch_layout, s->in.ch_count); |
|
|
|
|
|
|
|
|
|
if (s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { |
|
|
|
|
av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n"); |
|
|
|
|
if (s->used_ch_layout.nb_channels != s->in_ch_layout.nb_channels) |
|
|
|
|
av_channel_layout_uninit(&s->in_ch_layout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) |
|
|
|
|
av_channel_layout_default(&s->in_ch_layout, s->used_ch_count); |
|
|
|
|
if (s->used_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) |
|
|
|
|
av_channel_layout_default(&s->used_ch_layout, s->used_ch_layout.nb_channels); |
|
|
|
|
if (s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { |
|
|
|
|
ret = av_channel_layout_copy(&s->in_ch_layout, &s->used_ch_layout); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
if (s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) |
|
|
|
|
av_channel_layout_default(&s->out_ch_layout, s->out.ch_count); |
|
|
|
|
|
|
|
|
@ -389,8 +403,8 @@ av_cold int swr_init(struct SwrContext *s){ |
|
|
|
|
#define RSC 1 //FIXME finetune
|
|
|
|
|
if(!s-> in.ch_count) |
|
|
|
|
s-> in.ch_count = s->in_ch_layout.nb_channels; |
|
|
|
|
if(!s->used_ch_count) |
|
|
|
|
s->used_ch_count= s->in.ch_count; |
|
|
|
|
if (!av_channel_layout_check(&s->used_ch_layout)) |
|
|
|
|
av_channel_layout_default(&s->used_ch_layout, s->in.ch_count); |
|
|
|
|
if(!s->out.ch_count) |
|
|
|
|
s->out.ch_count = s->out_ch_layout.nb_channels; |
|
|
|
|
|
|
|
|
@ -410,23 +424,23 @@ av_cold int swr_init(struct SwrContext *s){ |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); |
|
|
|
|
if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count); |
|
|
|
|
if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_layout.nb_channels != s->in_ch_layout.nb_channels) { |
|
|
|
|
av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_layout.nb_channels); |
|
|
|
|
ret = AVERROR(EINVAL); |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (( s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC |
|
|
|
|
|| s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { |
|
|
|
|
|| s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_layout.nb_channels != 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->used_ch_layout.nb_channels); |
|
|
|
|
av_assert0(s->out.ch_count); |
|
|
|
|
s->resample_first= RSC*s->out.ch_count/s->used_ch_count - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; |
|
|
|
|
s->resample_first= RSC*s->out.ch_count/s->used_ch_layout.nb_channels - RSC < s->out_sample_rate/(float)s-> in_sample_rate - 1.0; |
|
|
|
|
|
|
|
|
|
s->in_buffer= s->in; |
|
|
|
|
s->silence = s->in; |
|
|
|
@ -442,7 +456,7 @@ av_assert0(s->out.ch_count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt, |
|
|
|
|
s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0); |
|
|
|
|
s-> in_sample_fmt, s->used_ch_layout.nb_channels, 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); |
|
|
|
|
|
|
|
|
@ -457,9 +471,9 @@ av_assert0(s->out.ch_count); |
|
|
|
|
|
|
|
|
|
if(s->channel_map){ |
|
|
|
|
s->postin.ch_count= |
|
|
|
|
s->midbuf.ch_count= s->used_ch_count; |
|
|
|
|
s->midbuf.ch_count= s->used_ch_layout.nb_channels; |
|
|
|
|
if(s->resample) |
|
|
|
|
s->in_buffer.ch_count= s->used_ch_count; |
|
|
|
|
s->in_buffer.ch_count= s->used_ch_layout.nb_channels; |
|
|
|
|
} |
|
|
|
|
if(!s->resample_first){ |
|
|
|
|
s->midbuf.ch_count= s->out.ch_count; |
|
|
|
@ -697,7 +711,7 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co |
|
|
|
|
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); |
|
|
|
|
av_assert0(s->midbuf.ch_count == s->used_ch_layout.nb_channels); |
|
|
|
|
if((ret=swri_realloc_audio(&s->midbuf, out_count))<0) |
|
|
|
|
return ret; |
|
|
|
|
}else{ |
|
|
|
|