73 const char *descr,
void *
conv)
85 if (ptr_align == 1 && samples_align == 1) {
96 (!channels || ac->
channels == channels)) {
101 if (ptr_align == 1 && samples_align == 1) {
112 (!channels || ac->
channels == channels)) {
117 if (ptr_align == 1 && samples_align == 1) {
134 #define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt 136 #define CONV_LOOP(otype, expr) \ 138 *(otype *)po = expr; \ 141 } while (po < end); \ 143 #define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr) \ 144 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in, \ 147 int is = sizeof(itype); \ 148 int os = sizeof(otype); \ 149 const uint8_t *pi = in; \ 151 uint8_t *end = out + os * len; \ 152 CONV_LOOP(otype, expr) \ 155 #define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr) \ 156 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in, \ 157 int len, int channels) \ 160 int out_bps = sizeof(otype); \ 161 int is = sizeof(itype); \ 162 int os = channels * out_bps; \ 163 for (ch = 0; ch < channels; ch++) { \ 164 const uint8_t *pi = in[ch]; \ 165 uint8_t *po = out + ch * out_bps; \ 166 uint8_t *end = po + os * len; \ 167 CONV_LOOP(otype, expr) \ 171 #define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr) \ 172 static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in, \ 173 int len, int channels) \ 176 int in_bps = sizeof(itype); \ 177 int is = channels * in_bps; \ 178 int os = sizeof(otype); \ 179 for (ch = 0; ch < channels; ch++) { \ 180 const uint8_t *pi = in + ch * in_bps; \ 181 uint8_t *po = out[ch]; \ 182 uint8_t *end = po + os * len; \ 183 CONV_LOOP(otype, expr) \ 187 #define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \ 188 CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \ 189 CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \ 190 CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr) 198 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi)
199 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16)
200 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT,
float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0f / (1 << 15)))
201 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL,
double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi * (1.0 / (1 << 15)))
202 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t, (*(const int32_t *)pi >> 24) + 0x80)
203 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16)
204 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi)
205 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT,
float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0f / (1
U << 31)))
206 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL,
double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi * (1.0 / (1
U << 31)))
207 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT,
float, av_clip_uint8(
lrintf(*(const
float *)pi * (1 << 7)) + 0x80))
208 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT,
float, av_clip_int16(
lrintf(*(const
float *)pi * (1 << 15))))
209 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT,
float, av_clipl_int32(
llrintf(*(const
float *)pi * (1
U << 31))))
210 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT,
float, AV_SAMPLE_FMT_FLT,
float, *(const
float *)pi)
211 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL,
double, AV_SAMPLE_FMT_FLT,
float, *(const
float *)pi)
212 CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL,
double, av_clip_uint8(
lrint(*(const
double *)pi * (1 << 7)) + 0x80))
213 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL,
double, av_clip_int16(
lrint(*(const
double *)pi * (1 << 15))))
214 CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL,
double, av_clipl_int32(
llrint(*(const
double *)pi * (1
U << 31))))
215 CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT,
float, AV_SAMPLE_FMT_DBL,
double, *(const
double *)pi)
216 CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL,
double, AV_SAMPLE_FMT_DBL,
double, *(const
double *)pi)
218 #define SET_CONV_FUNC_GROUP(ofmt, ifmt) \ 219 ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \ 220 ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \ 221 ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P)); 267 int in_planar, out_planar;
294 if (in_planar == out_planar) {
297 }
else if (in_planar)
302 set_generic_function(ac);
335 if (!(ptr_align % ac->
ptr_align) && samples_align >= aligned_len) {
358 for (p = 0; p < ac->
planes; p++)
374 for (p = 0; p < ac->
planes; p++) {
388 for (p = 0; p < ac->
planes; p++)
391 for (p = 0; p < ac->
planes; p++)
AVAudioResampleContext * avr
void ff_dither_free(DitherContext **cp)
Free a DitherContext.
static int conv(int samples, float **pcm, char *buf, int channels)
int input_map[AVRESAMPLE_MAX_CHANNELS]
dest index of each input channel
Audio buffer used for intermediate storage between conversion phases.
conv_func_deinterleave * conv_deinterleave
Memory handling functions.
int do_zero
zeroing needed
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in)
Convert audio data from one sample format to another.
void() conv_func_flat(uint8_t *out, const uint8_t *in, int len)
void ff_audio_convert_init_x86(AudioConvert *ac)
int channel_zero[AVRESAMPLE_MAX_CHANNELS]
dest index to zero
int nb_samples
current number of samples
conv_func_interleave * conv_interleave
void() conv_func_interleave(uint8_t *out, uint8_t *const *in, int len, int channels)
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
int ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels)
AudioConvert * ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map)
Allocate and initialize AudioConvert context for sample format conversion.
AV_RESAMPLE_DITHER_NONE
Do not use dithering.
enum AVResampleDitherMethod dither_method
dither method
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Fill an audio buffer with silence.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> out
int stride
sample byte offset within a plane
int channels
channel count
void() conv_func_deinterleave(uint8_t **out, const uint8_t *in, int len, int channels)
av_cold void ff_audio_convert_init_arm(AudioConvert *ac)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
void ff_audio_convert_free(AudioConvert **ac)
Free AudioConvert.
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
DitherContext * ff_dither_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map)
Allocate and initialize a DitherContext.
int is_planar
sample format is planar
int channel_copy[AVRESAMPLE_MAX_CHANNELS]
dest index to copy from
#define SET_CONV_FUNC_GROUP(ofmt, ifmt)
conv_func_flat * conv_flat
int ff_convert_dither(DitherContext *c, AudioData *dst, AudioData *src)
Convert audio sample format with dithering.
static int convert(uint8_t x)
#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr)
conv_func_interleave * conv_interleave_generic
ChannelMapInfo ch_map_info
AVSampleFormat
Audio sample formats.
typedef void(RENAME(mix_any_func_type))
uint8_t * data[AVRESAMPLE_MAX_CHANNELS]
data plane pointers
#define AVRESAMPLE_MAX_CHANNELS
Replacements for frequently missing libm functions.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
const VDPAUPixFmtMap * map
conv_func_flat * conv_flat_generic
int channel_map[AVRESAMPLE_MAX_CHANNELS]
source index of each output channel, -1 if not remapped
int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt)
Return number of bytes per sample.
int samples_align
allocated samples alignment
const char * func_descr_generic
common internal and external API header
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
Get the packed alternative form of the given sample format.
enum ConvFuncType func_type
enum AVSampleFormat out_fmt
conv_func_deinterleave * conv_deinterleave_generic
void ff_audio_convert_set_func(AudioConvert *ac, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int ptr_align, int samples_align, const char *descr, void *conv)
Set conversion function if the parameters match.
enum AVSampleFormat in_fmt
av_cold void ff_audio_convert_init_aarch64(AudioConvert *ac)
int ptr_align
minimum data pointer alignment