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 }