Mercurial > mplayer.hg
annotate libaf/af_lavcresample.c @ 32127:24299859359f
swscale-test: move conversion from ref to source back to doTest()
The source format parameters are kept in static variables and conversion from
ref to source is only made when any parameter changes.
author | ramiro |
---|---|
date | Sun, 12 Sep 2010 18:14:42 +0000 |
parents | 3af732078f52 |
children | 2b9bc3c2933d |
rev | line source |
---|---|
25529
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
1 /* |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
2 * Copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at> |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
3 * |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
4 * This file is part of MPlayer. |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
5 * |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
6 * MPlayer is free software; you can redistribute it and/or modify |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
7 * it under the terms of the GNU General Public License as published by |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
8 * the Free Software Foundation; either version 2 of the License, or |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
9 * (at your option) any later version. |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
10 * |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
11 * MPlayer is distributed in the hope that it will be useful, |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
14 * GNU General Public License for more details. |
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
15 * |
26740
b3a38b361fef
Use standard license headers with standard formatting.
diego
parents:
26069
diff
changeset
|
16 * You should have received a copy of the GNU General Public License along |
b3a38b361fef
Use standard license headers with standard formatting.
diego
parents:
26069
diff
changeset
|
17 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
b3a38b361fef
Use standard license headers with standard formatting.
diego
parents:
26069
diff
changeset
|
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
25529
867ee1c2114b
Relicense GPL v2 files as GPL v2+ and add proper license headers.
diego
parents:
24900
diff
changeset
|
19 */ |
13713 | 20 |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 #include <inttypes.h> | |
25 | |
16982 | 26 #include "config.h" |
13713 | 27 #include "af.h" |
26069
1318e956c092
FFmpeg now uses different (unified) #include paths.
diego
parents:
25529
diff
changeset
|
28 #include "libavcodec/avcodec.h" |
1318e956c092
FFmpeg now uses different (unified) #include paths.
diego
parents:
25529
diff
changeset
|
29 #include "libavutil/rational.h" |
13713 | 30 |
31 // Data for specific instances of this filter | |
32 typedef struct af_resample_s{ | |
33 struct AVResampleContext *avrctx; | |
22178
c4d9550c9faf
Use AF_NCH for max number of channels instead of private CHANS define.
uau
parents:
17522
diff
changeset
|
34 int16_t *in[AF_NCH]; |
13713 | 35 int in_alloc; |
36 int index; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
37 |
13713 | 38 int filter_length; |
39 int linear; | |
40 int phase_shift; | |
13730 | 41 double cutoff; |
31632
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
42 |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
43 int ctx_out_rate; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
44 int ctx_in_rate; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
45 int ctx_filter_size; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
46 int ctx_phase_shift; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
47 int ctx_linear; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
48 double ctx_cutoff; |
13713 | 49 }af_resample_t; |
50 | |
51 | |
52 // Initialization and runtime control | |
53 static int control(struct af_instance_s* af, int cmd, void* arg) | |
54 { | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
55 af_resample_t* s = (af_resample_t*)af->setup; |
13713 | 56 af_data_t *data= (af_data_t*)arg; |
14213
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
57 int out_rate, test_output_res; // helpers for checking input format |
13713 | 58 |
59 switch(cmd){ | |
60 case AF_CONTROL_REINIT: | |
61 if((af->data->rate == data->rate) || (af->data->rate == 0)) | |
62 return AF_DETACH; | |
63 | |
64 af->data->nch = data->nch; | |
22178
c4d9550c9faf
Use AF_NCH for max number of channels instead of private CHANS define.
uau
parents:
17522
diff
changeset
|
65 if (af->data->nch > AF_NCH) af->data->nch = AF_NCH; |
14245 | 66 af->data->format = AF_FORMAT_S16_NE; |
13713 | 67 af->data->bps = 2; |
24888 | 68 af->mul = (double)af->data->rate / data->rate; |
24900 | 69 af->delay = af->data->nch * s->filter_length / min(af->mul, 1); // *bps*.5 |
13713 | 70 |
31632
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
71 if (s->ctx_out_rate != af->data->rate || s->ctx_in_rate != data->rate || s->ctx_filter_size != s->filter_length || |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
72 s->ctx_phase_shift != s->phase_shift || s->ctx_linear != s->linear || s->ctx_cutoff != s->cutoff) { |
31633 | 73 if(s->avrctx) av_resample_close(s->avrctx); |
74 s->avrctx= av_resample_init(af->data->rate, /*in_rate*/data->rate, s->filter_length, s->phase_shift, s->linear, s->cutoff); | |
31632
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
75 s->ctx_out_rate = af->data->rate; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
76 s->ctx_in_rate = data->rate; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
77 s->ctx_filter_size = s->filter_length; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
78 s->ctx_phase_shift = s->phase_shift; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
79 s->ctx_linear = s->linear; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
80 s->ctx_cutoff = s->cutoff; |
fc6f2b4e8a26
Avoid calling av_resample_init again when the values are the same as before.
reimar
parents:
29263
diff
changeset
|
81 } |
13713 | 82 |
14213
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
83 // hack to make af_test_output ignore the samplerate change |
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
84 out_rate = af->data->rate; |
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
85 af->data->rate = data->rate; |
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
86 test_output_res = af_test_output(af, (af_data_t*)arg); |
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
87 af->data->rate = out_rate; |
3c56b18bbb0c
Make filters request a supported input format instead of failing.
reimar
parents:
14186
diff
changeset
|
88 return test_output_res; |
13713 | 89 case AF_CONTROL_COMMAND_LINE:{ |
22755 | 90 s->cutoff= 0.0; |
13730 | 91 sscanf((char*)arg,"%d:%d:%d:%d:%lf", &af->data->rate, &s->filter_length, &s->linear, &s->phase_shift, &s->cutoff); |
22755 | 92 if(s->cutoff <= 0.0) s->cutoff= max(1.0 - 6.5/(s->filter_length+8), 0.80); |
13713 | 93 return AF_OK; |
94 } | |
95 case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: | |
96 af->data->rate = *(int*)arg; | |
97 return AF_OK; | |
98 } | |
99 return AF_UNKNOWN; | |
100 } | |
101 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
102 // Deallocate memory |
13713 | 103 static void uninit(struct af_instance_s* af) |
104 { | |
105 if(af->data) | |
22179 | 106 free(af->data->audio); |
107 free(af->data); | |
13713 | 108 if(af->setup){ |
22182 | 109 int i; |
13713 | 110 af_resample_t *s = af->setup; |
111 if(s->avrctx) av_resample_close(s->avrctx); | |
22181
e99ebf35812b
Cosmetics: remove tabs added in last commit from otherwise tab-free file.
reimar
parents:
22179
diff
changeset
|
112 for (i=0; i < AF_NCH; i++) |
e99ebf35812b
Cosmetics: remove tabs added in last commit from otherwise tab-free file.
reimar
parents:
22179
diff
changeset
|
113 free(s->in[i]); |
13713 | 114 free(s); |
115 } | |
116 } | |
117 | |
118 // Filter data through filter | |
119 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
120 { |
13713 | 121 af_resample_t *s = af->setup; |
122 int i, j, consumed, ret; | |
123 int16_t *in = (int16_t*)data->audio; | |
124 int16_t *out; | |
125 int chans = data->nch; | |
126 int in_len = data->len/(2*chans); | |
24888 | 127 int out_len = in_len * af->mul + 10; |
22178
c4d9550c9faf
Use AF_NCH for max number of channels instead of private CHANS define.
uau
parents:
17522
diff
changeset
|
128 int16_t tmp[AF_NCH][out_len]; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
129 |
13713 | 130 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) |
131 return NULL; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
132 |
13713 | 133 out= (int16_t*)af->data->audio; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
134 |
13730 | 135 out_len= min(out_len, af->data->len/(2*chans)); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
136 |
13713 | 137 if(s->in_alloc < in_len + s->index){ |
138 s->in_alloc= in_len + s->index; | |
139 for(i=0; i<chans; i++){ | |
22179 | 140 s->in[i]= realloc(s->in[i], s->in_alloc*sizeof(int16_t)); |
13713 | 141 } |
142 } | |
143 | |
14283 | 144 if(chans==1){ |
145 memcpy(&s->in[0][s->index], in, in_len * sizeof(int16_t)); | |
146 }else if(chans==2){ | |
147 for(j=0; j<in_len; j++){ | |
148 s->in[0][j + s->index]= *(in++); | |
149 s->in[1][j + s->index]= *(in++); | |
150 } | |
151 }else{ | |
152 for(j=0; j<in_len; j++){ | |
153 for(i=0; i<chans; i++){ | |
154 s->in[i][j + s->index]= *(in++); | |
155 } | |
13713 | 156 } |
157 } | |
158 in_len += s->index; | |
159 | |
160 for(i=0; i<chans; i++){ | |
161 ret= av_resample(s->avrctx, tmp[i], s->in[i], &consumed, in_len, out_len, i+1 == chans); | |
162 } | |
163 out_len= ret; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
26740
diff
changeset
|
164 |
13713 | 165 s->index= in_len - consumed; |
166 for(i=0; i<chans; i++){ | |
167 memmove(s->in[i], s->in[i] + consumed, s->index*sizeof(int16_t)); | |
168 } | |
169 | |
14283 | 170 if(chans==1){ |
171 memcpy(out, tmp[0], out_len*sizeof(int16_t)); | |
172 }else if(chans==2){ | |
173 for(j=0; j<out_len; j++){ | |
174 *(out++)= tmp[0][j]; | |
175 *(out++)= tmp[1][j]; | |
176 } | |
177 }else{ | |
178 for(j=0; j<out_len; j++){ | |
179 for(i=0; i<chans; i++){ | |
180 *(out++)= tmp[i][j]; | |
181 } | |
13713 | 182 } |
183 } | |
184 | |
185 data->audio = af->data->audio; | |
186 data->len = out_len*chans*2; | |
187 data->rate = af->data->rate; | |
188 return data; | |
189 } | |
190 | |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22182
diff
changeset
|
191 static int af_open(af_instance_t* af){ |
14186
5053490906c3
Initialize cutoff, too. Fixes crash when AF_CONTROL_COMMAND_LINE is not set.
reimar
parents:
13859
diff
changeset
|
192 af_resample_t *s = calloc(1,sizeof(af_resample_t)); |
13713 | 193 af->control=control; |
194 af->uninit=uninit; | |
195 af->play=play; | |
24888 | 196 af->mul=1; |
13713 | 197 af->data=calloc(1,sizeof(af_data_t)); |
14186
5053490906c3
Initialize cutoff, too. Fixes crash when AF_CONTROL_COMMAND_LINE is not set.
reimar
parents:
13859
diff
changeset
|
198 s->filter_length= 16; |
22755 | 199 s->cutoff= max(1.0 - 6.5/(s->filter_length+8), 0.80); |
14186
5053490906c3
Initialize cutoff, too. Fixes crash when AF_CONTROL_COMMAND_LINE is not set.
reimar
parents:
13859
diff
changeset
|
200 s->phase_shift= 10; |
5053490906c3
Initialize cutoff, too. Fixes crash when AF_CONTROL_COMMAND_LINE is not set.
reimar
parents:
13859
diff
changeset
|
201 // s->setup = RSMP_INT | FREQ_SLOPPY; |
5053490906c3
Initialize cutoff, too. Fixes crash when AF_CONTROL_COMMAND_LINE is not set.
reimar
parents:
13859
diff
changeset
|
202 af->setup=s; |
13713 | 203 return AF_OK; |
204 } | |
205 | |
206 af_info_t af_info_lavcresample = { | |
207 "Sample frequency conversion using libavcodec", | |
208 "lavcresample", | |
209 "Michael Niedermayer", | |
210 "", | |
211 AF_FLAGS_REENTRANT, | |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22182
diff
changeset
|
212 af_open |
13713 | 213 }; |