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