00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00025 #include "libavutil/avassert.h"
00026 #include "libavutil/avstring.h"
00027 #include "libavutil/mathematics.h"
00028 #include "libavutil/opt.h"
00029
00030 #include "libavresample/avresample.h"
00031
00032 #include "audio.h"
00033 #include "avfilter.h"
00034 #include "formats.h"
00035 #include "internal.h"
00036
00037 typedef struct ResampleContext {
00038 AVAudioResampleContext *avr;
00039
00040 int64_t next_pts;
00041 } ResampleContext;
00042
00043 static av_cold void uninit(AVFilterContext *ctx)
00044 {
00045 ResampleContext *s = ctx->priv;
00046
00047 if (s->avr) {
00048 avresample_close(s->avr);
00049 avresample_free(&s->avr);
00050 }
00051 }
00052
00053 static int query_formats(AVFilterContext *ctx)
00054 {
00055 AVFilterLink *inlink = ctx->inputs[0];
00056 AVFilterLink *outlink = ctx->outputs[0];
00057
00058 AVFilterFormats *in_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
00059 AVFilterFormats *out_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
00060 AVFilterFormats *in_samplerates = ff_all_samplerates();
00061 AVFilterFormats *out_samplerates = ff_all_samplerates();
00062 AVFilterChannelLayouts *in_layouts = ff_all_channel_layouts();
00063 AVFilterChannelLayouts *out_layouts = ff_all_channel_layouts();
00064
00065 avfilter_formats_ref(in_formats, &inlink->out_formats);
00066 avfilter_formats_ref(out_formats, &outlink->in_formats);
00067
00068 avfilter_formats_ref(in_samplerates, &inlink->out_samplerates);
00069 avfilter_formats_ref(out_samplerates, &outlink->in_samplerates);
00070
00071 ff_channel_layouts_ref(in_layouts, &inlink->out_channel_layouts);
00072 ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts);
00073
00074 return 0;
00075 }
00076
00077 static int config_output(AVFilterLink *outlink)
00078 {
00079 AVFilterContext *ctx = outlink->src;
00080 AVFilterLink *inlink = ctx->inputs[0];
00081 ResampleContext *s = ctx->priv;
00082 char buf1[64], buf2[64];
00083 int ret;
00084
00085 if (s->avr) {
00086 avresample_close(s->avr);
00087 avresample_free(&s->avr);
00088 }
00089
00090 if (inlink->channel_layout == outlink->channel_layout &&
00091 inlink->sample_rate == outlink->sample_rate &&
00092 inlink->format == outlink->format)
00093 return 0;
00094
00095 if (!(s->avr = avresample_alloc_context()))
00096 return AVERROR(ENOMEM);
00097
00098 av_opt_set_int(s->avr, "in_channel_layout", inlink ->channel_layout, 0);
00099 av_opt_set_int(s->avr, "out_channel_layout", outlink->channel_layout, 0);
00100 av_opt_set_int(s->avr, "in_sample_fmt", inlink ->format, 0);
00101 av_opt_set_int(s->avr, "out_sample_fmt", outlink->format, 0);
00102 av_opt_set_int(s->avr, "in_sample_rate", inlink ->sample_rate, 0);
00103 av_opt_set_int(s->avr, "out_sample_rate", outlink->sample_rate, 0);
00104
00105
00106
00107 if (av_get_bytes_per_sample(inlink->format) <= 2 &&
00108 av_get_bytes_per_sample(outlink->format) <= 2)
00109 av_opt_set_int(s->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
00110
00111 if ((ret = avresample_open(s->avr)) < 0)
00112 return ret;
00113
00114 outlink->time_base = (AVRational){ 1, outlink->sample_rate };
00115 s->next_pts = AV_NOPTS_VALUE;
00116
00117 av_get_channel_layout_string(buf1, sizeof(buf1),
00118 -1, inlink ->channel_layout);
00119 av_get_channel_layout_string(buf2, sizeof(buf2),
00120 -1, outlink->channel_layout);
00121 av_log(ctx, AV_LOG_VERBOSE,
00122 "fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n",
00123 av_get_sample_fmt_name(inlink ->format), inlink ->sample_rate, buf1,
00124 av_get_sample_fmt_name(outlink->format), outlink->sample_rate, buf2);
00125
00126 return 0;
00127 }
00128
00129 static int request_frame(AVFilterLink *outlink)
00130 {
00131 AVFilterContext *ctx = outlink->src;
00132 ResampleContext *s = ctx->priv;
00133 int ret = avfilter_request_frame(ctx->inputs[0]);
00134
00135
00136 if (ret == AVERROR_EOF && s->avr) {
00137 AVFilterBufferRef *buf;
00138 int nb_samples = av_rescale_rnd(avresample_get_delay(s->avr),
00139 outlink->sample_rate,
00140 ctx->inputs[0]->sample_rate,
00141 AV_ROUND_UP);
00142
00143 if (!nb_samples)
00144 return ret;
00145
00146 buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
00147 if (!buf)
00148 return AVERROR(ENOMEM);
00149
00150 ret = avresample_convert(s->avr, (void**)buf->extended_data,
00151 buf->linesize[0], nb_samples,
00152 NULL, 0, 0);
00153 if (ret <= 0) {
00154 avfilter_unref_buffer(buf);
00155 return (ret == 0) ? AVERROR_EOF : ret;
00156 }
00157
00158 buf->pts = s->next_pts;
00159 ff_filter_samples(outlink, buf);
00160 return 0;
00161 }
00162 return ret;
00163 }
00164
00165 static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
00166 {
00167 AVFilterContext *ctx = inlink->dst;
00168 ResampleContext *s = ctx->priv;
00169 AVFilterLink *outlink = ctx->outputs[0];
00170
00171 if (s->avr) {
00172 AVFilterBufferRef *buf_out;
00173 int delay, nb_samples, ret;
00174
00175
00176 delay = avresample_get_delay(s->avr);
00177 nb_samples = av_rescale_rnd(buf->audio->nb_samples + delay,
00178 outlink->sample_rate, inlink->sample_rate,
00179 AV_ROUND_UP);
00180
00181 buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
00182 ret = avresample_convert(s->avr, (void**)buf_out->extended_data,
00183 buf_out->linesize[0], nb_samples,
00184 (void**)buf->extended_data, buf->linesize[0],
00185 buf->audio->nb_samples);
00186
00187 av_assert0(!avresample_available(s->avr));
00188
00189 if (s->next_pts == AV_NOPTS_VALUE) {
00190 if (buf->pts == AV_NOPTS_VALUE) {
00191 av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, "
00192 "assuming 0.\n");
00193 s->next_pts = 0;
00194 } else
00195 s->next_pts = av_rescale_q(buf->pts, inlink->time_base,
00196 outlink->time_base);
00197 }
00198
00199 if (ret > 0) {
00200 buf_out->audio->nb_samples = ret;
00201 if (buf->pts != AV_NOPTS_VALUE) {
00202 buf_out->pts = av_rescale_q(buf->pts, inlink->time_base,
00203 outlink->time_base) -
00204 av_rescale(delay, outlink->sample_rate,
00205 inlink->sample_rate);
00206 } else
00207 buf_out->pts = s->next_pts;
00208
00209 s->next_pts = buf_out->pts + buf_out->audio->nb_samples;
00210
00211 ff_filter_samples(outlink, buf_out);
00212 }
00213 avfilter_unref_buffer(buf);
00214 } else
00215 ff_filter_samples(outlink, buf);
00216 }
00217
00218 AVFilter avfilter_af_resample = {
00219 .name = "resample",
00220 .description = NULL_IF_CONFIG_SMALL("Audio resampling and conversion."),
00221 .priv_size = sizeof(ResampleContext),
00222
00223 .uninit = uninit,
00224 .query_formats = query_formats,
00225
00226 .inputs = (const AVFilterPad[]) {{ .name = "default",
00227 .type = AVMEDIA_TYPE_AUDIO,
00228 .filter_samples = filter_samples,
00229 .min_perms = AV_PERM_READ },
00230 { .name = NULL}},
00231 .outputs = (const AVFilterPad[]) {{ .name = "default",
00232 .type = AVMEDIA_TYPE_AUDIO,
00233 .config_props = config_output,
00234 .request_frame = request_frame },
00235 { .name = NULL}},
00236 };