Mercurial > mplayer.hg
annotate libaf/af_format.c @ 34309:119af6360b00
Discard frames where the size does not match the AVCodecContext width/height.
This avoids possible crashes on video size changes. The problem
is that we reinitialize the vo on get_buffer but due to codec
delay libavcodec might still return frames with the old size
afterwards, which the vo might no longer be able to handle.
Ideally libavcodec should not show this behaviour, since it
requires that any application using DR1 can handle frames of
different sizes simultaneously - which seems a bit extreme.
author | reimar |
---|---|
date | Mon, 05 Dec 2011 18:08:29 +0000 |
parents | a93891202051 |
children | c2b5fda66143 |
rev | line source |
---|---|
28229
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
1 /* |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
2 * This audio filter changes the format of a data block. Valid |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
3 * formats are: AFMT_U8, AFMT_S8, AFMT_S16_LE, AFMT_S16_BE |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
4 * AFMT_U16_LE, AFMT_U16_BE, AFMT_S32_LE and AFMT_S32_BE. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
5 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
6 * This file is part of MPlayer. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
7 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
8 * MPlayer is free software; you can redistribute it and/or modify |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
11 * (at your option) any later version. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
12 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
13 * MPlayer is distributed in the hope that it will be useful, |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
16 * GNU General Public License for more details. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
17 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
18 * You should have received a copy of the GNU General Public License along |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
26345
diff
changeset
|
21 */ |
7568 | 22 |
23 #include <stdio.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 #include <inttypes.h> | |
27 #include <limits.h> | |
28337
34b7297904ac
Drop HAVE_LRINTF check, lrintf is used without checking in other places.
diego
parents:
28333
diff
changeset
|
28 #include <math.h> |
7568 | 29 |
28333
0ec2ac66f064
Fix build: Add required header and adjust preprocessor check.
diego
parents:
28238
diff
changeset
|
30 #include "config.h" |
21353
a965ca17debc
reordering of #include to avoid clash with math.h and quicktime/*.h, patch by Crhis Roccati<roccati@pobox.com>
nplourde
parents:
16982
diff
changeset
|
31 #include "af.h" |
34174
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
33736
diff
changeset
|
32 #include "mp_msg.h" |
21507
fa99b3d31d13
Hack around libavutil/bswap.h compilation problems due to always_inline undefined.
reimar
parents:
21372
diff
changeset
|
33 #include "mpbswap.h" |
21353
a965ca17debc
reordering of #include to avoid clash with math.h and quicktime/*.h, patch by Crhis Roccati<roccati@pobox.com>
nplourde
parents:
16982
diff
changeset
|
34 #include "libvo/fastmemcpy.h" |
a965ca17debc
reordering of #include to avoid clash with math.h and quicktime/*.h, patch by Crhis Roccati<roccati@pobox.com>
nplourde
parents:
16982
diff
changeset
|
35 |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
36 #include "libavutil/avutil.h" |
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
37 |
8167 | 38 /* Functions used by play to convert the input audio to the correct |
39 format */ | |
7568 | 40 |
24561 | 41 /* The below includes retrieves functions for converting to and from |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
42 ulaw and alaw */ |
28238
1bf9023840f9
Rename libaf/af_format_alaw.c --> libaf/af_format_alaw.h and
diego
parents:
28236
diff
changeset
|
43 #include "af_format_ulaw.h" |
1bf9023840f9
Rename libaf/af_format_alaw.c --> libaf/af_format_alaw.h and
diego
parents:
28236
diff
changeset
|
44 #include "af_format_alaw.h" |
7568 | 45 |
24561 | 46 // Switch endianness |
8167 | 47 static void endian(void* in, void* out, int len, int bps); |
24561 | 48 // From signed to unsigned and the other way |
16664 | 49 static void si2us(void* data, int len, int bps); |
8167 | 50 // Change the number of bits per sample |
51 static void change_bps(void* in, void* out, int len, int inbps, int outbps); | |
52 // From float to int signed | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
53 static void float2int(float* in, void* out, int len, int bps); |
8167 | 54 // From signed int to float |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
55 static void int2float(void* in, float* out, int len, int bps); |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
56 |
14272 | 57 static af_data_t* play(struct af_instance_s* af, af_data_t* data); |
58 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data); | |
59 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data); | |
60 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data); | |
61 | |
8607 | 62 // Helper functions to check sanity for input arguments |
63 | |
64 // Sanity check for bytes per sample | |
13989
dcb6b4a33aaa
declare check_format and check_bps static, they are used nowhere else.
reimar
parents:
12486
diff
changeset
|
65 static int check_bps(int bps) |
8607 | 66 { |
12478 | 67 if(bps != 4 && bps != 3 && bps != 2 && bps != 1){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
68 mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] The number of bytes per sample" |
12478 | 69 " must be 1, 2, 3 or 4. Current value is %i \n",bps); |
8607 | 70 return AF_ERROR; |
71 } | |
72 return AF_OK; | |
73 } | |
74 | |
75 // Check for unsupported formats | |
13989
dcb6b4a33aaa
declare check_format and check_bps static, they are used nowhere else.
reimar
parents:
12486
diff
changeset
|
76 static int check_format(int format) |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
77 { |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
78 char buf[256]; |
8607 | 79 switch(format & AF_FORMAT_SPECIAL_MASK){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
80 case(AF_FORMAT_IMA_ADPCM): |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
81 case(AF_FORMAT_MPEG2): |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
82 case(AF_FORMAT_AC3): |
29049 | 83 mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] Sample format %s not yet supported \n", |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
84 af_fmt2str(format,buf,256)); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
85 return AF_ERROR; |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
86 } |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
87 return AF_OK; |
8607 | 88 } |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
89 |
7568 | 90 // Initialization and runtime control |
91 static int control(struct af_instance_s* af, int cmd, void* arg) | |
92 { | |
93 switch(cmd){ | |
8167 | 94 case AF_CONTROL_REINIT:{ |
95 char buf1[256]; | |
96 char buf2[256]; | |
14272 | 97 af_data_t *data = arg; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
98 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
99 // Make sure this filter isn't redundant |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
100 if(af->data->format == data->format && |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
101 af->data->bps == data->bps) |
7568 | 102 return AF_DETACH; |
8607 | 103 |
30241
02b9c1a452e1
Add support for distinguishing between little- and big-endian SPDIF AC3
reimar
parents:
29401
diff
changeset
|
104 // Allow trivial AC3-endianness conversion |
02b9c1a452e1
Add support for distinguishing between little- and big-endian SPDIF AC3
reimar
parents:
29401
diff
changeset
|
105 if (!AF_FORMAT_IS_AC3(af->data->format) || !AF_FORMAT_IS_AC3(data->format)) |
24521 | 106 // Check for errors in configuration |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
107 if((AF_OK != check_bps(data->bps)) || |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
108 (AF_OK != check_format(data->format)) || |
8607 | 109 (AF_OK != check_bps(af->data->bps)) || |
110 (AF_OK != check_format(af->data->format))) | |
8167 | 111 return AF_ERROR; |
112 | |
29049 | 113 mp_msg(MSGT_AFILTER, MSGL_V, "[format] Changing sample format from %s to %s\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
114 af_fmt2str(data->format,buf1,256), |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
115 af_fmt2str(af->data->format,buf2,256)); |
7568 | 116 |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
117 af->data->rate = data->rate; |
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
118 af->data->nch = data->nch; |
24888 | 119 af->mul = (double)af->data->bps / data->bps; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
120 |
14272 | 121 af->play = play; // set default |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
122 |
24561 | 123 // look whether only endianness differences are there |
14272 | 124 if ((af->data->format & ~AF_FORMAT_END_MASK) == |
125 (data->format & ~AF_FORMAT_END_MASK)) | |
126 { | |
29049 | 127 mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated endianness conversion only\n"); |
14272 | 128 af->play = play_swapendian; |
129 } | |
130 if ((data->format == AF_FORMAT_FLOAT_NE) && | |
131 (af->data->format == AF_FORMAT_S16_NE)) | |
132 { | |
29049 | 133 mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
134 af_fmt2str(data->format,buf1,256), |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
135 af_fmt2str(af->data->format,buf2,256)); |
14272 | 136 af->play = play_float_s16; |
137 } | |
138 if ((data->format == AF_FORMAT_S16_NE) && | |
139 (af->data->format == AF_FORMAT_FLOAT_NE)) | |
140 { | |
29049 | 141 mp_msg(MSGT_AFILTER, MSGL_V, "[format] Accelerated %s to %s conversion\n", |
14717
51a7560a92b7
confusing mixture of typecasts and casted variable, removed typecasts
reimar
parents:
14433
diff
changeset
|
142 af_fmt2str(data->format,buf1,256), |
14399
1a882e2a419b
af_fmt2str fixes (remove trailing space, call with size of buffer, not size-1)
reimar
parents:
14335
diff
changeset
|
143 af_fmt2str(af->data->format,buf2,256)); |
14272 | 144 af->play = play_s16_float; |
145 } | |
7568 | 146 return AF_OK; |
8167 | 147 } |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
148 case AF_CONTROL_COMMAND_LINE:{ |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
149 int format = af_str2fmt_short(arg); |
15311 | 150 if (format == -1) { |
29049 | 151 mp_msg(MSGT_AFILTER, MSGL_ERR, "[format] %s is not a valid format\n", (char *)arg); |
15311 | 152 return AF_ERROR; |
153 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
154 if(AF_OK != af->control(af,AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET,&format)) |
8607 | 155 return AF_ERROR; |
156 return AF_OK; | |
8167 | 157 } |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
158 case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET:{ |
24561 | 159 // Check for errors in configuration |
30241
02b9c1a452e1
Add support for distinguishing between little- and big-endian SPDIF AC3
reimar
parents:
29401
diff
changeset
|
160 if(!AF_FORMAT_IS_AC3(*(int*)arg) && AF_OK != check_format(*(int*)arg)) |
8607 | 161 return AF_ERROR; |
162 | |
163 af->data->format = *(int*)arg; | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
164 af->data->bps = af_fmt2bits(af->data->format)/8; |
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
165 |
7568 | 166 return AF_OK; |
167 } | |
14335
8380694ba14f
af_bits2fmt and af_str2fmt_short, also removed the extra FORMAT_BPS control in format.c
alex
parents:
14272
diff
changeset
|
168 } |
7568 | 169 return AF_UNKNOWN; |
170 } | |
171 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
172 // Deallocate memory |
7568 | 173 static void uninit(struct af_instance_s* af) |
174 { | |
22179 | 175 if (af->data) |
176 free(af->data->audio); | |
177 free(af->data); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
178 af->setup = 0; |
7568 | 179 } |
180 | |
14272 | 181 static af_data_t* play_swapendian(struct af_instance_s* af, af_data_t* data) |
182 { | |
183 af_data_t* l = af->data; // Local data | |
184 af_data_t* c = data; // Current working data | |
24561 | 185 int len = c->len/c->bps; // Length in samples of current audio block |
14272 | 186 |
187 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
188 return NULL; | |
189 | |
190 endian(c->audio,l->audio,len,c->bps); | |
191 | |
192 c->audio = l->audio; | |
193 c->format = l->format; | |
194 | |
195 return c; | |
196 } | |
197 | |
198 static af_data_t* play_float_s16(struct af_instance_s* af, af_data_t* data) | |
199 { | |
200 af_data_t* l = af->data; // Local data | |
201 af_data_t* c = data; // Current working data | |
24561 | 202 int len = c->len/4; // Length in samples of current audio block |
14272 | 203 |
204 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
205 return NULL; | |
206 | |
207 float2int(c->audio, l->audio, len, 2); | |
208 | |
209 c->audio = l->audio; | |
210 c->len = len*2; | |
211 c->bps = 2; | |
212 c->format = l->format; | |
213 | |
214 return c; | |
215 } | |
216 | |
217 static af_data_t* play_s16_float(struct af_instance_s* af, af_data_t* data) | |
218 { | |
219 af_data_t* l = af->data; // Local data | |
220 af_data_t* c = data; // Current working data | |
24561 | 221 int len = c->len/2; // Length in samples of current audio block |
14272 | 222 |
223 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
224 return NULL; | |
225 | |
226 int2float(c->audio, l->audio, len, 2); | |
227 | |
228 c->audio = l->audio; | |
229 c->len = len*4; | |
230 c->bps = 4; | |
231 c->format = l->format; | |
232 | |
233 return c; | |
234 } | |
235 | |
7568 | 236 // Filter data through filter |
237 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
238 { | |
8167 | 239 af_data_t* l = af->data; // Local data |
240 af_data_t* c = data; // Current working data | |
24561 | 241 int len = c->len/c->bps; // Length in samples of current audio block |
7568 | 242 |
243 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
244 return NULL; | |
245 | |
8167 | 246 // Change to cpu native endian format |
247 if((c->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) | |
248 endian(c->audio,c->audio,len,c->bps); | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
249 |
8167 | 250 // Conversion table |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
251 if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_MU_LAW) { |
8167 | 252 from_ulaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
253 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
254 to_ulaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
255 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 256 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
257 } else if((c->format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_A_LAW) { |
8167 | 258 from_alaw(c->audio, l->audio, len, l->bps, l->format&AF_FORMAT_POINT_MASK); |
259 if(AF_FORMAT_A_LAW == (l->format&AF_FORMAT_SPECIAL_MASK)) | |
260 to_alaw(l->audio, l->audio, len, 1, AF_FORMAT_SI); | |
261 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) | |
16664 | 262 si2us(l->audio,len,l->bps); |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
263 } else if((c->format & AF_FORMAT_POINT_MASK) == AF_FORMAT_F) { |
8167 | 264 switch(l->format&AF_FORMAT_SPECIAL_MASK){ |
265 case(AF_FORMAT_MU_LAW): | |
266 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
267 break; | |
268 case(AF_FORMAT_A_LAW): | |
269 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
7568 | 270 break; |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
271 default: |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
272 float2int(c->audio, l->audio, len, l->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
273 if((l->format&AF_FORMAT_SIGN_MASK) == AF_FORMAT_US) |
16664 | 274 si2us(l->audio,len,l->bps); |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
275 break; |
8167 | 276 } |
14261
710b223604fa
100l use right mask type when checking for input format
rtognimp
parents:
14256
diff
changeset
|
277 } else { |
8167 | 278 // Input must be int |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
279 |
8167 | 280 // Change signed/unsigned |
281 if((c->format&AF_FORMAT_SIGN_MASK) != (l->format&AF_FORMAT_SIGN_MASK)){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
282 si2us(c->audio,len,c->bps); |
8167 | 283 } |
284 // Convert to special formats | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
285 switch(l->format&(AF_FORMAT_SPECIAL_MASK|AF_FORMAT_POINT_MASK)){ |
8167 | 286 case(AF_FORMAT_MU_LAW): |
287 to_ulaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
288 break; | |
289 case(AF_FORMAT_A_LAW): | |
290 to_alaw(c->audio, l->audio, len, c->bps, c->format&AF_FORMAT_POINT_MASK); | |
291 break; | |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
292 case(AF_FORMAT_F): |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
293 int2float(c->audio, l->audio, len, c->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
294 break; |
8167 | 295 default: |
8180
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
296 // Change the number of bits |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
297 if(c->bps != l->bps) |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
298 change_bps(c->audio,l->audio,len,c->bps,l->bps); |
4ba9aed295f2
Fixing segfault bug and addnig support for lrintf() in format conversion
anders
parents:
8167
diff
changeset
|
299 else |
23457
a124f3abc1ec
Replace implicit use of fast_memcpy via macro by explicit use to allow
reimar
parents:
22748
diff
changeset
|
300 fast_memcpy(l->audio,c->audio,len*c->bps); |
7568 | 301 break; |
302 } | |
303 } | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
304 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
305 // Switch from cpu native endian to the correct endianness |
8167 | 306 if((l->format&AF_FORMAT_END_MASK)!=AF_FORMAT_NE) |
307 endian(l->audio,l->audio,len,l->bps); | |
7568 | 308 |
309 // Set output data | |
310 c->audio = l->audio; | |
8167 | 311 c->len = len*l->bps; |
7568 | 312 c->bps = l->bps; |
313 c->format = l->format; | |
314 return c; | |
315 } | |
316 | |
317 // Allocate memory and set function pointers | |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22179
diff
changeset
|
318 static int af_open(af_instance_t* af){ |
7568 | 319 af->control=control; |
320 af->uninit=uninit; | |
321 af->play=play; | |
24888 | 322 af->mul=1; |
7568 | 323 af->data=calloc(1,sizeof(af_data_t)); |
324 if(af->data == NULL) | |
325 return AF_ERROR; | |
326 return AF_OK; | |
327 } | |
328 | |
329 // Description of this filter | |
330 af_info_t af_info_format = { | |
331 "Sample format conversion", | |
332 "format", | |
333 "Anders", | |
334 "", | |
7615 | 335 AF_FLAGS_REENTRANT, |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22179
diff
changeset
|
336 af_open |
7568 | 337 }; |
8167 | 338 |
12478 | 339 static inline uint32_t load24bit(void* data, int pos) { |
29401
f01023c524c3
Replace WORDS_BIGENDIAN by HAVE_BIGENDIAN in all internal code.
diego
parents:
29263
diff
changeset
|
340 #if HAVE_BIGENDIAN |
12478 | 341 return (((uint32_t)((uint8_t*)data)[3*pos])<<24) | |
342 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
343 (((uint32_t)((uint8_t*)data)[3*pos+2])<<8); | |
344 #else | |
345 return (((uint32_t)((uint8_t*)data)[3*pos])<<8) | | |
346 (((uint32_t)((uint8_t*)data)[3*pos+1])<<16) | | |
347 (((uint32_t)((uint8_t*)data)[3*pos+2])<<24); | |
348 #endif | |
349 } | |
350 | |
351 static inline void store24bit(void* data, int pos, uint32_t expanded_value) { | |
29401
f01023c524c3
Replace WORDS_BIGENDIAN by HAVE_BIGENDIAN in all internal code.
diego
parents:
29263
diff
changeset
|
352 #if HAVE_BIGENDIAN |
12478 | 353 ((uint8_t*)data)[3*pos]=expanded_value>>24; |
354 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
355 ((uint8_t*)data)[3*pos+2]=expanded_value>>8; | |
356 #else | |
357 ((uint8_t*)data)[3*pos]=expanded_value>>8; | |
358 ((uint8_t*)data)[3*pos+1]=expanded_value>>16; | |
359 ((uint8_t*)data)[3*pos+2]=expanded_value>>24; | |
360 #endif | |
361 } | |
362 | |
8167 | 363 // Function implementations used by play |
364 static void endian(void* in, void* out, int len, int bps) | |
365 { | |
366 register int i; | |
367 switch(bps){ | |
368 case(2):{ | |
369 for(i=0;i<len;i++){ | |
12486 | 370 ((uint16_t*)out)[i]=bswap_16(((uint16_t*)in)[i]); |
8167 | 371 } |
372 break; | |
373 } | |
12478 | 374 case(3):{ |
375 register uint8_t s; | |
376 for(i=0;i<len;i++){ | |
377 s=((uint8_t*)in)[3*i]; | |
378 ((uint8_t*)out)[3*i]=((uint8_t*)in)[3*i+2]; | |
12481
dbbc25ea6403
fix endian conversion for (curently unused) case where in buffer != out buffer
reimar
parents:
12478
diff
changeset
|
379 if (in != out) |
dbbc25ea6403
fix endian conversion for (curently unused) case where in buffer != out buffer
reimar
parents:
12478
diff
changeset
|
380 ((uint8_t*)out)[3*i+1]=((uint8_t*)in)[3*i+1]; |
12478 | 381 ((uint8_t*)out)[3*i+2]=s; |
382 } | |
383 break; | |
384 } | |
8167 | 385 case(4):{ |
386 for(i=0;i<len;i++){ | |
12486 | 387 ((uint32_t*)out)[i]=bswap_32(((uint32_t*)in)[i]); |
8167 | 388 } |
389 break; | |
390 } | |
391 } | |
392 } | |
393 | |
16664 | 394 static void si2us(void* data, int len, int bps) |
8167 | 395 { |
16664 | 396 register long i = -(len * bps); |
397 register uint8_t *p = &((uint8_t *)data)[len * bps]; | |
398 #if AF_FORMAT_NE == AF_FORMAT_LE | |
399 p += bps - 1; | |
400 #endif | |
401 if (len <= 0) return; | |
402 do { | |
403 p[i] ^= 0x80; | |
404 } while (i += bps); | |
8167 | 405 } |
406 | |
407 static void change_bps(void* in, void* out, int len, int inbps, int outbps) | |
408 { | |
409 register int i; | |
410 switch(inbps){ | |
411 case(1): | |
412 switch(outbps){ | |
413 case(2): | |
414 for(i=0;i<len;i++) | |
415 ((uint16_t*)out)[i]=((uint16_t)((uint8_t*)in)[i])<<8; | |
416 break; | |
12478 | 417 case(3): |
418 for(i=0;i<len;i++) | |
419 store24bit(out, i, ((uint32_t)((uint8_t*)in)[i])<<24); | |
420 break; | |
8167 | 421 case(4): |
422 for(i=0;i<len;i++) | |
423 ((uint32_t*)out)[i]=((uint32_t)((uint8_t*)in)[i])<<24; | |
424 break; | |
425 } | |
426 break; | |
427 case(2): | |
428 switch(outbps){ | |
429 case(1): | |
430 for(i=0;i<len;i++) | |
431 ((uint8_t*)out)[i]=(uint8_t)((((uint16_t*)in)[i])>>8); | |
432 break; | |
12478 | 433 case(3): |
434 for(i=0;i<len;i++) | |
435 store24bit(out, i, ((uint32_t)((uint16_t*)in)[i])<<16); | |
436 break; | |
8167 | 437 case(4): |
438 for(i=0;i<len;i++) | |
439 ((uint32_t*)out)[i]=((uint32_t)((uint16_t*)in)[i])<<16; | |
440 break; | |
441 } | |
442 break; | |
12478 | 443 case(3): |
444 switch(outbps){ | |
445 case(1): | |
446 for(i=0;i<len;i++) | |
447 ((uint8_t*)out)[i]=(uint8_t)(load24bit(in, i)>>24); | |
448 break; | |
449 case(2): | |
450 for(i=0;i<len;i++) | |
451 ((uint16_t*)out)[i]=(uint16_t)(load24bit(in, i)>>16); | |
452 break; | |
453 case(4): | |
454 for(i=0;i<len;i++) | |
455 ((uint32_t*)out)[i]=(uint32_t)load24bit(in, i); | |
456 break; | |
457 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
458 break; |
8167 | 459 case(4): |
460 switch(outbps){ | |
461 case(1): | |
462 for(i=0;i<len;i++) | |
463 ((uint8_t*)out)[i]=(uint8_t)((((uint32_t*)in)[i])>>24); | |
464 break; | |
465 case(2): | |
466 for(i=0;i<len;i++) | |
467 ((uint16_t*)out)[i]=(uint16_t)((((uint32_t*)in)[i])>>16); | |
468 break; | |
12478 | 469 case(3): |
470 for(i=0;i<len;i++) | |
471 store24bit(out, i, ((uint32_t*)in)[i]); | |
472 break; | |
8167 | 473 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
474 break; |
8167 | 475 } |
476 } | |
477 | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
478 static void float2int(float* in, void* out, int len, int bps) |
8167 | 479 { |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
480 float f; |
8167 | 481 register int i; |
482 switch(bps){ | |
483 case(1): | |
484 for(i=0;i<len;i++) | |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
485 ((int8_t *)out)[i] = av_clip_int8(lrintf(128.0 * in[i])); |
8167 | 486 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
487 case(2): |
8167 | 488 for(i=0;i<len;i++) |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
489 ((int16_t*)out)[i] = av_clip_int16(lrintf(32768.0 * in[i])); |
8167 | 490 break; |
12478 | 491 case(3): |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
492 for(i=0;i<len;i++){ |
33736
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
493 f = in[i] * 8388608; |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
494 store24bit(out, i, av_clip(lrintf(f), -1*(1<<23), (1<<23)-1) << 8); |
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
495 } |
12478 | 496 break; |
8167 | 497 case(4): |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
498 for(i=0;i<len;i++){ |
33736
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
499 f = in[i]; |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
500 if (f <= -1.0) |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
501 ((int32_t*)out)[i] = INT_MIN; |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
502 else |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
503 if (f >= 1.0)//no need to use corrected constant, rounding won't cause overflow |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
504 ((int32_t*)out)[i] = INT_MAX; |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
505 else |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
506 ((int32_t*)out)[i] = lrintf(f*2147483648.0); |
a5a54c7a15ce
Fix the precision loss in float -> 32bit conversion case, introduced
iive
parents:
33723
diff
changeset
|
507 |
33723
6c8743e5fa30
Audio format conversion from float to int is not checked for overflow.
iive
parents:
30241
diff
changeset
|
508 } |
8167 | 509 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
510 } |
8167 | 511 } |
512 | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
513 static void int2float(void* in, float* out, int len, int bps) |
8167 | 514 { |
515 register int i; | |
516 switch(bps){ | |
517 case(1): | |
518 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
519 out[i]=(1.0/128.0)*((int8_t*)in)[i]; |
8167 | 520 break; |
521 case(2): | |
522 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
523 out[i]=(1.0/32768.0)*((int16_t*)in)[i]; |
8167 | 524 break; |
12478 | 525 case(3): |
526 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
527 out[i]=(1.0/2147483648.0)*((int32_t)load24bit(in, i)); |
12478 | 528 break; |
8167 | 529 case(4): |
530 for(i=0;i<len;i++) | |
14791
df515839c8a9
100l for me, lrintf is better. now fixed so it should be prototyped, and should work even if there is no prototype
rfelker
parents:
14758
diff
changeset
|
531 out[i]=(1.0/2147483648.0)*((int32_t*)in)[i]; |
8167 | 532 break; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
533 } |
8167 | 534 } |