00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdint.h>
00023
00024 #include "config.h"
00025 #include "libavutil/libm.h"
00026 #include "libavutil/log.h"
00027 #include "libavutil/mem.h"
00028 #include "libavutil/samplefmt.h"
00029 #include "audio_convert.h"
00030 #include "audio_data.h"
00031
00032 enum ConvFuncType {
00033 CONV_FUNC_TYPE_FLAT,
00034 CONV_FUNC_TYPE_INTERLEAVE,
00035 CONV_FUNC_TYPE_DEINTERLEAVE,
00036 };
00037
00038 typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
00039
00040 typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
00041 int len, int channels);
00042
00043 typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
00044 int channels);
00045
00046 struct AudioConvert {
00047 AVAudioResampleContext *avr;
00048 enum AVSampleFormat in_fmt;
00049 enum AVSampleFormat out_fmt;
00050 int channels;
00051 int planes;
00052 int ptr_align;
00053 int samples_align;
00054 int has_optimized_func;
00055 const char *func_descr;
00056 const char *func_descr_generic;
00057 enum ConvFuncType func_type;
00058 conv_func_flat *conv_flat;
00059 conv_func_flat *conv_flat_generic;
00060 conv_func_interleave *conv_interleave;
00061 conv_func_interleave *conv_interleave_generic;
00062 conv_func_deinterleave *conv_deinterleave;
00063 conv_func_deinterleave *conv_deinterleave_generic;
00064 };
00065
00066 void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt,
00067 enum AVSampleFormat in_fmt, int channels,
00068 int ptr_align, int samples_align,
00069 const char *descr, void *conv)
00070 {
00071 int found = 0;
00072
00073 switch (ac->func_type) {
00074 case CONV_FUNC_TYPE_FLAT:
00075 if (av_get_packed_sample_fmt(ac->in_fmt) == in_fmt &&
00076 av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
00077 ac->conv_flat = conv;
00078 ac->func_descr = descr;
00079 ac->ptr_align = ptr_align;
00080 ac->samples_align = samples_align;
00081 if (ptr_align == 1 && samples_align == 1) {
00082 ac->conv_flat_generic = conv;
00083 ac->func_descr_generic = descr;
00084 } else {
00085 ac->has_optimized_func = 1;
00086 }
00087 found = 1;
00088 }
00089 break;
00090 case CONV_FUNC_TYPE_INTERLEAVE:
00091 if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
00092 (!channels || ac->channels == channels)) {
00093 ac->conv_interleave = conv;
00094 ac->func_descr = descr;
00095 ac->ptr_align = ptr_align;
00096 ac->samples_align = samples_align;
00097 if (ptr_align == 1 && samples_align == 1) {
00098 ac->conv_interleave_generic = conv;
00099 ac->func_descr_generic = descr;
00100 } else {
00101 ac->has_optimized_func = 1;
00102 }
00103 found = 1;
00104 }
00105 break;
00106 case CONV_FUNC_TYPE_DEINTERLEAVE:
00107 if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
00108 (!channels || ac->channels == channels)) {
00109 ac->conv_deinterleave = conv;
00110 ac->func_descr = descr;
00111 ac->ptr_align = ptr_align;
00112 ac->samples_align = samples_align;
00113 if (ptr_align == 1 && samples_align == 1) {
00114 ac->conv_deinterleave_generic = conv;
00115 ac->func_descr_generic = descr;
00116 } else {
00117 ac->has_optimized_func = 1;
00118 }
00119 found = 1;
00120 }
00121 break;
00122 }
00123 if (found) {
00124 av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
00125 "to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
00126 av_get_sample_fmt_name(ac->out_fmt), descr);
00127 }
00128 }
00129
00130 #define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
00131
00132 #define CONV_LOOP(otype, expr) \
00133 do { \
00134 *(otype *)po = expr; \
00135 pi += is; \
00136 po += os; \
00137 } while (po < end); \
00138
00139 #define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr) \
00140 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in, \
00141 int len) \
00142 { \
00143 int is = sizeof(itype); \
00144 int os = sizeof(otype); \
00145 const uint8_t *pi = in; \
00146 uint8_t *po = out; \
00147 uint8_t *end = out + os * len; \
00148 CONV_LOOP(otype, expr) \
00149 }
00150
00151 #define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr) \
00152 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in, \
00153 int len, int channels) \
00154 { \
00155 int ch; \
00156 int out_bps = sizeof(otype); \
00157 int is = sizeof(itype); \
00158 int os = channels * out_bps; \
00159 for (ch = 0; ch < channels; ch++) { \
00160 const uint8_t *pi = in[ch]; \
00161 uint8_t *po = out + ch * out_bps; \
00162 uint8_t *end = po + os * len; \
00163 CONV_LOOP(otype, expr) \
00164 } \
00165 }
00166
00167 #define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr) \
00168 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in, \
00169 int len, int channels) \
00170 { \
00171 int ch; \
00172 int in_bps = sizeof(itype); \
00173 int is = channels * in_bps; \
00174 int os = sizeof(otype); \
00175 for (ch = 0; ch < channels; ch++) { \
00176 const uint8_t *pi = in + ch * in_bps; \
00177 uint8_t *po = out[ch]; \
00178 uint8_t *end = po + os * len; \
00179 CONV_LOOP(otype, expr) \
00180 } \
00181 }
00182
00183 #define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
00184 CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \
00185 CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \
00186 CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr)
00187
00188 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_U8, uint8_t, *(const uint8_t *)pi)
00189 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 8)
00190 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 24)
00191 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0f / (1 << 7)))
00192 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) * (1.0 / (1 << 7)))
00193 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t, (*(const int16_t *)pi >> 8) + 0x80)
00194 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi)
00195 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16)
00196 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0f / (1 << 15)))
00197 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0 / (1 << 15)))
00198 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
00199 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16)
00200 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi)
00201 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0f / (1U << 31)))
00202 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0 / (1U << 31)))
00203 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8( lrintf(*(const float *)pi * (1 << 7)) + 0x80))
00204 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16( lrintf(*(const float *)pi * (1 << 15))))
00205 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *)pi * (1U << 31))))
00206 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
00207 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
00208 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8( lrint(*(const double *)pi * (1 << 7)) + 0x80))
00209 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16( lrint(*(const double *)pi * (1 << 15))))
00210 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *)pi * (1U << 31))))
00211 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
00212 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
00213
00214 #define SET_CONV_FUNC_GROUP(ofmt, ifmt) \
00215 ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \
00216 ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
00217 ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P));
00218
00219 static void set_generic_function(AudioConvert *ac)
00220 {
00221 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8)
00222 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
00223 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
00224 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
00225 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
00226 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16)
00227 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
00228 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
00229 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
00230 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
00231 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32)
00232 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
00233 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
00234 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
00235 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
00236 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT)
00237 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
00238 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
00239 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
00240 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
00241 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL)
00242 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
00243 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
00244 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
00245 SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
00246 }
00247
00248 AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
00249 enum AVSampleFormat out_fmt,
00250 enum AVSampleFormat in_fmt,
00251 int channels)
00252 {
00253 AudioConvert *ac;
00254 int in_planar, out_planar;
00255
00256 ac = av_mallocz(sizeof(*ac));
00257 if (!ac)
00258 return NULL;
00259
00260 ac->avr = avr;
00261 ac->out_fmt = out_fmt;
00262 ac->in_fmt = in_fmt;
00263 ac->channels = channels;
00264
00265 in_planar = av_sample_fmt_is_planar(in_fmt);
00266 out_planar = av_sample_fmt_is_planar(out_fmt);
00267
00268 if (in_planar == out_planar) {
00269 ac->func_type = CONV_FUNC_TYPE_FLAT;
00270 ac->planes = in_planar ? ac->channels : 1;
00271 } else if (in_planar)
00272 ac->func_type = CONV_FUNC_TYPE_INTERLEAVE;
00273 else
00274 ac->func_type = CONV_FUNC_TYPE_DEINTERLEAVE;
00275
00276 set_generic_function(ac);
00277
00278 if (ARCH_X86)
00279 ff_audio_convert_init_x86(ac);
00280
00281 return ac;
00282 }
00283
00284 int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len)
00285 {
00286 int use_generic = 1;
00287
00288
00289
00290 if (ac->has_optimized_func) {
00291 int ptr_align = FFMIN(in->ptr_align, out->ptr_align);
00292 int samples_align = FFMIN(in->samples_align, out->samples_align);
00293 int aligned_len = FFALIGN(len, ac->samples_align);
00294 if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
00295 len = aligned_len;
00296 use_generic = 0;
00297 }
00298 }
00299 av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", len,
00300 av_get_sample_fmt_name(ac->in_fmt),
00301 av_get_sample_fmt_name(ac->out_fmt),
00302 use_generic ? ac->func_descr_generic : ac->func_descr);
00303
00304 switch (ac->func_type) {
00305 case CONV_FUNC_TYPE_FLAT: {
00306 int p;
00307 if (!in->is_planar)
00308 len *= in->channels;
00309 if (use_generic) {
00310 for (p = 0; p < ac->planes; p++)
00311 ac->conv_flat_generic(out->data[p], in->data[p], len);
00312 } else {
00313 for (p = 0; p < ac->planes; p++)
00314 ac->conv_flat(out->data[p], in->data[p], len);
00315 }
00316 break;
00317 }
00318 case CONV_FUNC_TYPE_INTERLEAVE:
00319 if (use_generic)
00320 ac->conv_interleave_generic(out->data[0], in->data, len, ac->channels);
00321 else
00322 ac->conv_interleave(out->data[0], in->data, len, ac->channels);
00323 break;
00324 case CONV_FUNC_TYPE_DEINTERLEAVE:
00325 if (use_generic)
00326 ac->conv_deinterleave_generic(out->data, in->data[0], len, ac->channels);
00327 else
00328 ac->conv_deinterleave(out->data, in->data[0], len, ac->channels);
00329 break;
00330 }
00331
00332 out->nb_samples = in->nb_samples;
00333 return 0;
00334 }