2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2013 Stefano Pigozzi <stefano.pigozzi@gmail.com>
4 * Copyright (c) 2013 Uoti Urpala <uau@mplayer2.org>
6 * This file is part of mplayer2.
8 * mplayer2 is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * mplayer2 is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with mplayer2. If not, see <http://www.gnu.org/licenses/>.
28 #include <libavutil/common.h>
29 #include <libavutil/opt.h>
30 #include <libavutil/samplefmt.h>
31 #include <libavutil/mathematics.h>
32 #include <libavresample/avresample.h>
38 #include "subopt-helper.h"
41 struct af_resample_opts
{
52 struct AVAudioResampleContext
*avrctx
;
53 struct af_resample_opts ctx
; // opts in the context
54 struct af_resample_opts opts
; // opts requested by the user
57 static double af_resample_default_cutoff(int filter_size
)
59 return FFMAX(1.0 - 6.5 / (filter_size
+ 8), 0.80);
62 static bool needs_lavrctx_reconfigure(struct af_resample
*s
,
66 return s
->ctx
.out_rate
!= out
->rate
||
67 s
->ctx
.in_rate
!= in
->rate
||
68 s
->ctx
.filter_size
!= s
->opts
.filter_size
||
69 s
->ctx
.phase_shift
!= s
->opts
.phase_shift
||
70 s
->ctx
.linear
!= s
->opts
.linear
||
71 s
->ctx
.cutoff
!= s
->opts
.cutoff
;
75 #define ctx_opt_set_int(a,b) av_opt_set_int(s->avrctx, (a), (b), 0)
76 #define ctx_opt_set_dbl(a,b) av_opt_set_double(s->avrctx, (a), (b), 0)
78 static int control(struct af_instance_s
*af
, int cmd
, void *arg
)
80 struct af_resample
*s
= af
->setup
;
81 struct af_data
*in
= arg
;
82 struct af_data
*out
= af
->data
;
85 case AF_CONTROL_REINIT
: {
86 if ((out
->rate
== in
->rate
) || (out
->rate
== 0))
89 out
->nch
= FFMIN(in
->nch
, AF_NCH
);
90 out
->format
= AF_FORMAT_S16_NE
;
92 af
->mul
= (double) out
->rate
/ in
->rate
;
93 af
->delay
= out
->nch
* s
->opts
.filter_size
/ FFMIN(af
->mul
, 1);
95 if (needs_lavrctx_reconfigure(s
, in
, out
)) {
97 avresample_close(s
->avrctx
);
99 s
->ctx
.out_rate
= out
->rate
;
100 s
->ctx
.in_rate
= in
->rate
;
101 s
->ctx
.filter_size
= s
->opts
.filter_size
;
102 s
->ctx
.phase_shift
= s
->opts
.phase_shift
;
103 s
->ctx
.linear
= s
->opts
.linear
;
104 s
->ctx
.cutoff
= s
->opts
.cutoff
;
106 int ch_layout
= av_get_default_channel_layout(out
->nch
);
108 ctx_opt_set_int("in_channel_layout", ch_layout
);
109 ctx_opt_set_int("out_channel_layout", ch_layout
);
111 ctx_opt_set_int("in_sample_rate", s
->ctx
.in_rate
);
112 ctx_opt_set_int("out_sample_rate", s
->ctx
.out_rate
);
114 ctx_opt_set_int("in_sample_fmt", AV_SAMPLE_FMT_S16
);
115 ctx_opt_set_int("out_sample_fmt", AV_SAMPLE_FMT_S16
);
117 ctx_opt_set_int("filter_size", s
->ctx
.filter_size
);
118 ctx_opt_set_int("phase_shift", s
->ctx
.phase_shift
);
119 ctx_opt_set_int("linear_interp", s
->ctx
.linear
);
121 ctx_opt_set_dbl("cutoff", s
->ctx
.cutoff
);
123 if (avresample_open(s
->avrctx
) < 0) {
124 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "[lavrresample] Cannot open "
125 "Libavresample Context. \n");
130 int out_rate
, test_output_res
;
131 // hack to make af_test_output ignore the samplerate change
132 out_rate
= out
->rate
;
133 out
->rate
= in
->rate
;
134 test_output_res
= af_test_output(af
, in
);
135 out
->rate
= out_rate
;
136 return test_output_res
;
138 case AF_CONTROL_COMMAND_LINE
: {
139 s
->opts
.cutoff
= 0.0;
141 const opt_t subopts
[] = {
142 {"srate", OPT_ARG_INT
, &out
->rate
, NULL
},
143 {"filter_size", OPT_ARG_INT
, &s
->opts
.filter_size
, NULL
},
144 {"phase_shift", OPT_ARG_INT
, &s
->opts
.phase_shift
, NULL
},
145 {"linear", OPT_ARG_BOOL
, &s
->opts
.linear
, NULL
},
146 {"cutoff", OPT_ARG_FLOAT
, &s
->opts
.cutoff
, NULL
},
149 if (subopt_parse(arg
, subopts
) != 0) {
150 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "[lavrresample] Invalid option "
155 if (s
->opts
.cutoff
<= 0.0)
156 s
->opts
.cutoff
= af_resample_default_cutoff(s
->opts
.filter_size
);
159 case AF_CONTROL_RESAMPLE_RATE
| AF_CONTROL_SET
:
160 out
->rate
= *(int *)arg
;
166 #undef ctx_opt_set_int
167 #undef ctx_opt_set_dbl
169 static void uninit(struct af_instance_s
*af
)
172 struct af_resample
*s
= af
->setup
;
174 avresample_close(s
->avrctx
);
175 talloc_free(af
->setup
);
179 static struct af_data
*play(struct af_instance_s
*af
, struct af_data
*data
)
181 struct af_resample
*s
= af
->setup
;
182 struct af_data
*in
= data
;
183 struct af_data
*out
= af
->data
;
186 int in_size
= data
->len
;
187 int in_samples
= in_size
/ (data
->bps
* data
->nch
);
188 int out_samples
= avresample_available(s
->avrctx
) +
189 av_rescale_rnd(avresample_get_delay(s
->avrctx
) + in_samples
,
190 s
->ctx
.out_rate
, s
->ctx
.in_rate
, AV_ROUND_UP
);
191 int out_size
= out
->bps
* out_samples
* out
->nch
;
193 if (talloc_get_size(out
->audio
) < out_size
)
194 out
->audio
= talloc_realloc_size(out
, out
->audio
, out_size
);
196 af
->delay
= out
->bps
* av_rescale_rnd(avresample_get_delay(s
->avrctx
),
197 s
->ctx
.out_rate
, s
->ctx
.in_rate
,
200 out_samples
= avresample_convert(s
->avrctx
,
201 (uint8_t **) &out
->audio
, out_size
, out_samples
,
202 (uint8_t **) &in
->audio
, in_size
, in_samples
);
204 out_size
= out
->bps
* out_samples
* out
->nch
;
205 in
->audio
= out
->audio
;
207 in
->rate
= s
->ctx
.out_rate
;
211 static int af_open(struct af_instance_s
*af
)
213 struct af_resample
*s
= talloc_zero(NULL
, struct af_resample
);
215 af
->control
= control
;
219 af
->data
= talloc_zero(s
, struct af_data
);
221 af
->data
->rate
= 44100;
223 int default_filter_size
= 16;
224 s
->opts
= (struct af_resample_opts
) {
226 .filter_size
= default_filter_size
,
227 .cutoff
= af_resample_default_cutoff(default_filter_size
),
231 s
->avrctx
= avresample_alloc_context();
237 mp_msg(MSGT_AFILTER
, MSGL_ERR
, "[lavrresample] Cannot initialize "
238 "libavresample context. \n");
244 struct af_info af_info_lavrresample
= {
245 "Sample frequency conversion using libavresample",
247 "Stefano Pigozzi (based on Michael Niedermayer's lavcresample)",
252 #warning don't use subopt / positional arguments
253 #warning use lavr default option values
254 #warning support float and other data types