Commit c8af852b authored by Justin Ruggles's avatar Justin Ruggles

Add libavresample

This is a new library for audio sample format, channel layout, and sample rate
conversion.
parent c5671aeb
......@@ -16,6 +16,7 @@ version <next>:
- RealAudio Lossless decoder
- ZeroCodec decoder
- drop support for avconv without libavfilter
- add libavresample audio conversion library
version 0.8:
......
......@@ -20,7 +20,7 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR))))
$(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_PATH)/%=%)); $(INSTALL))
endif
ALLFFLIBS = avcodec avdevice avfilter avformat avutil swscale
ALLFFLIBS = avcodec avdevice avfilter avformat avresample avutil swscale
IFLAGS := -I. -I$(SRC_PATH)
CPPFLAGS := $(IFLAGS) $(CPPFLAGS)
......@@ -71,6 +71,7 @@ ALLMANPAGES = $(BASENAMES:%=%.1)
FFLIBS-$(CONFIG_AVDEVICE) += avdevice
FFLIBS-$(CONFIG_AVFILTER) += avfilter
FFLIBS-$(CONFIG_AVFORMAT) += avformat
FFLIBS-$(CONFIG_AVRESAMPLE) += avresample
FFLIBS-$(CONFIG_AVCODEC) += avcodec
FFLIBS-$(CONFIG_SWSCALE) += swscale
......
......@@ -110,6 +110,7 @@ Component options:
--disable-avformat disable libavformat build
--disable-swscale disable libswscale build
--disable-avfilter disable video filter support [no]
--disable-avresample disable libavresample build [no]
--disable-pthreads disable pthreads [auto]
--disable-w32threads disable Win32 threads [auto]
--enable-x11grab enable X11 grabbing [no]
......@@ -927,6 +928,7 @@ CONFIG_LIST="
avdevice
avfilter
avformat
avresample
avisynth
bzlib
dct
......@@ -1536,7 +1538,7 @@ avdevice_deps="avcodec avformat"
avformat_deps="avcodec"
# programs
avconv_deps="avcodec avfilter avformat swscale"
avconv_deps="avcodec avfilter avformat avresample swscale"
avplay_deps="avcodec avformat swscale sdl"
avplay_select="rdft"
avprobe_deps="avcodec avformat"
......@@ -1684,6 +1686,7 @@ enable avcodec
enable avdevice
enable avfilter
enable avformat
enable avresample
enable avutil
enable swscale
......@@ -3385,6 +3388,7 @@ get_version LIBAVCODEC libavcodec/version.h
get_version LIBAVDEVICE libavdevice/avdevice.h
get_version LIBAVFILTER libavfilter/version.h
get_version LIBAVFORMAT libavformat/version.h
get_version LIBAVRESAMPLE libavresample/version.h
get_version LIBAVUTIL libavutil/avutil.h
get_version LIBSWSCALE libswscale/swscale.h
......@@ -3504,4 +3508,5 @@ pkgconfig_generate libavcodec "Libav codec library" "$LIBAVCODEC_VERSION" "$extr
pkgconfig_generate libavformat "Libav container format library" "$LIBAVFORMAT_VERSION" "$extralibs" "libavcodec = $LIBAVCODEC_VERSION"
pkgconfig_generate libavdevice "Libav device handling library" "$LIBAVDEVICE_VERSION" "$extralibs" "libavformat = $LIBAVFORMAT_VERSION"
pkgconfig_generate libavfilter "Libav video filtering library" "$LIBAVFILTER_VERSION" "$extralibs"
pkgconfig_generate libavresample "Libav audio resampling library" "$LIBAVRESAMPLE_VERSION" "$extralibs"
pkgconfig_generate libswscale "Libav image rescaling library" "$LIBSWSCALE_VERSION" "$LIBM" "libavutil = $LIBAVUTIL_VERSION"
......@@ -2,16 +2,20 @@ Never assume the API of libav* to be stable unless at least 1 month has passed
since the last major version increase.
The last version increases were:
libavcodec: 2012-01-27
libavdevice: 2011-04-18
libavfilter: 2011-04-18
libavformat: 2012-01-27
libswscale: 2011-06-20
libavutil: 2011-04-18
libavcodec: 2012-01-27
libavdevice: 2011-04-18
libavfilter: 2011-04-18
libavformat: 2012-01-27
libavresample: 2012-xx-xx
libswscale: 2011-06-20
libavutil: 2011-04-18
API changes, most recent first:
2012-xx-xx - xxxxxxx - lavr 0.0.0
Add libavresample audio conversion library
2012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h
Add audio FIFO functions:
av_audio_fifo_free()
......
NAME = avresample
FFLIBS = avutil
HEADERS = avresample.h \
version.h
OBJS = audio_convert.o \
audio_data.o \
audio_mix.o \
audio_mix_matrix.o \
options.o \
resample.o \
utils.o
TESTPROGS = avresample
/*
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "config.h"
#include "libavutil/libm.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
#include "libavutil/samplefmt.h"
#include "audio_convert.h"
#include "audio_data.h"
enum ConvFuncType {
CONV_FUNC_TYPE_FLAT,
CONV_FUNC_TYPE_INTERLEAVE,
CONV_FUNC_TYPE_DEINTERLEAVE,
};
typedef void (conv_func_flat)(uint8_t *out, const uint8_t *in, int len);
typedef void (conv_func_interleave)(uint8_t *out, uint8_t *const *in,
int len, int channels);
typedef void (conv_func_deinterleave)(uint8_t **out, const uint8_t *in, int len,
int channels);
struct AudioConvert {
AVAudioResampleContext *avr;
enum AVSampleFormat in_fmt;
enum AVSampleFormat out_fmt;
int channels;
int planes;
int ptr_align;
int samples_align;
int has_optimized_func;
const char *func_descr;
const char *func_descr_generic;
enum ConvFuncType func_type;
conv_func_flat *conv_flat;
conv_func_flat *conv_flat_generic;
conv_func_interleave *conv_interleave;
conv_func_interleave *conv_interleave_generic;
conv_func_deinterleave *conv_deinterleave;
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)
{
int found = 0;
switch (ac->func_type) {
case CONV_FUNC_TYPE_FLAT:
if (av_get_packed_sample_fmt(ac->in_fmt) == in_fmt &&
av_get_packed_sample_fmt(ac->out_fmt) == out_fmt) {
ac->conv_flat = conv;
ac->func_descr = descr;
ac->ptr_align = ptr_align;
ac->samples_align = samples_align;
if (ptr_align == 1 && samples_align == 1) {
ac->conv_flat_generic = conv;
ac->func_descr_generic = descr;
} else {
ac->has_optimized_func = 1;
}
found = 1;
}
break;
case CONV_FUNC_TYPE_INTERLEAVE:
if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
(!channels || ac->channels == channels)) {
ac->conv_interleave = conv;
ac->func_descr = descr;
ac->ptr_align = ptr_align;
ac->samples_align = samples_align;
if (ptr_align == 1 && samples_align == 1) {
ac->conv_interleave_generic = conv;
ac->func_descr_generic = descr;
} else {
ac->has_optimized_func = 1;
}
found = 1;
}
break;
case CONV_FUNC_TYPE_DEINTERLEAVE:
if (ac->in_fmt == in_fmt && ac->out_fmt == out_fmt &&
(!channels || ac->channels == channels)) {
ac->conv_deinterleave = conv;
ac->func_descr = descr;
ac->ptr_align = ptr_align;
ac->samples_align = samples_align;
if (ptr_align == 1 && samples_align == 1) {
ac->conv_deinterleave_generic = conv;
ac->func_descr_generic = descr;
} else {
ac->has_optimized_func = 1;
}
found = 1;
}
break;
}
if (found) {
av_log(ac->avr, AV_LOG_DEBUG, "audio_convert: found function: %-4s "
"to %-4s (%s)\n", av_get_sample_fmt_name(ac->in_fmt),
av_get_sample_fmt_name(ac->out_fmt), descr);
}
}
#define CONV_FUNC_NAME(dst_fmt, src_fmt) conv_ ## src_fmt ## _to_ ## dst_fmt
#define CONV_LOOP(otype, expr) \
do { \
*(otype *)po = expr; \
pi += is; \
po += os; \
} while (po < end); \
#define CONV_FUNC_FLAT(ofmt, otype, ifmt, itype, expr) \
static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t *in, \
int len) \
{ \
int is = sizeof(itype); \
int os = sizeof(otype); \
const uint8_t *pi = in; \
uint8_t *po = out; \
uint8_t *end = out + os * len; \
CONV_LOOP(otype, expr) \
}
#define CONV_FUNC_INTERLEAVE(ofmt, otype, ifmt, itype, expr) \
static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t *out, const uint8_t **in, \
int len, int channels) \
{ \
int ch; \
int out_bps = sizeof(otype); \
int is = sizeof(itype); \
int os = channels * out_bps; \
for (ch = 0; ch < channels; ch++) { \
const uint8_t *pi = in[ch]; \
uint8_t *po = out + ch * out_bps; \
uint8_t *end = po + os * len; \
CONV_LOOP(otype, expr) \
} \
}
#define CONV_FUNC_DEINTERLEAVE(ofmt, otype, ifmt, itype, expr) \
static void CONV_FUNC_NAME(ofmt, ifmt)(uint8_t **out, const uint8_t *in, \
int len, int channels) \
{ \
int ch; \
int in_bps = sizeof(itype); \
int is = channels * in_bps; \
int os = sizeof(otype); \
for (ch = 0; ch < channels; ch++) { \
const uint8_t *pi = in + ch * in_bps; \
uint8_t *po = out[ch]; \
uint8_t *end = po + os * len; \
CONV_LOOP(otype, expr) \
} \
}
#define CONV_FUNC_GROUP(ofmt, otype, ifmt, itype, expr) \
CONV_FUNC_FLAT( ofmt, otype, ifmt, itype, expr) \
CONV_FUNC_INTERLEAVE( ofmt, otype, ifmt ## P, itype, expr) \
CONV_FUNC_DEINTERLEAVE(ofmt ## P, otype, ifmt, itype, expr)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_U8, uint8_t, *(const uint8_t *)pi)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 8)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8, uint8_t, (*(const uint8_t *)pi - 0x80) << 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_S16, int16_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *)pi << 16)
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_S16, int16_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi >> 16)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *)pi)
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_FLT, float, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_FLT, float, *(const float *)pi)
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))))
CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_DBL, double, *(const double *)pi)
#define SET_CONV_FUNC_GROUP(ofmt, ifmt) \
ff_audio_convert_set_func(ac, ofmt, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt)); \
ff_audio_convert_set_func(ac, ofmt ## P, ifmt, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt ## P, ifmt)); \
ff_audio_convert_set_func(ac, ofmt, ifmt ## P, 0, 1, 1, "C", CONV_FUNC_NAME(ofmt, ifmt ## P));
static void set_generic_function(AudioConvert *ac)
{
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL)
SET_CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL)
}
AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
enum AVSampleFormat out_fmt,
enum AVSampleFormat in_fmt,
int channels)
{
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;
in_planar = av_sample_fmt_is_planar(in_fmt);
out_planar = av_sample_fmt_is_planar(out_fmt);
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_X86)
ff_audio_convert_init_x86(ac);
return ac;
}
int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len)
{
int use_generic = 1;
/* determine whether to use the optimized function based on pointer and
samples alignment in both the input and output */
if (ac->has_optimized_func) {
int ptr_align = FFMIN(in->ptr_align, out->ptr_align);
int samples_align = FFMIN(in->samples_align, out->samples_align);
int aligned_len = FFALIGN(len, ac->samples_align);
if (!(ptr_align % ac->ptr_align) && samples_align >= aligned_len) {
len = aligned_len;
use_generic = 0;
}
}
av_dlog(ac->avr, "%d samples - audio_convert: %s to %s (%s)\n", 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);
switch (ac->func_type) {
case CONV_FUNC_TYPE_FLAT: {
int p;
if (!in->is_planar)
len *= in->channels;
if (use_generic) {
for (p = 0; p < ac->planes; p++)
ac->conv_flat_generic(out->data[p], in->data[p], len);
} else {
for (p = 0; p < ac->planes; p++)
ac->conv_flat(out->data[p], in->data[p], len);
}
break;
}
case CONV_FUNC_TYPE_INTERLEAVE:
if (use_generic)
ac->conv_interleave_generic(out->data[0], in->data, len, ac->channels);
else
ac->conv_interleave(out->data[0], in->data, len, ac->channels);
break;
case CONV_FUNC_TYPE_DEINTERLEAVE:
if (use_generic)
ac->conv_deinterleave_generic(out->data, in->data[0], len, ac->channels);
else
ac->conv_deinterleave(out->data, in->data[0], len, ac->channels);
break;
}
out->nb_samples = in->nb_samples;
return 0;
}
/*
* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVRESAMPLE_AUDIO_CONVERT_H
#define AVRESAMPLE_AUDIO_CONVERT_H
#include "libavutil/samplefmt.h"
#include "avresample.h"
#include "audio_data.h"
typedef struct AudioConvert AudioConvert;
/**
* Set conversion function if the parameters match.
*
* This compares the parameters of the conversion function to the parameters
* in the AudioConvert context. If the parameters do not match, no changes are
* made to the active functions. If the parameters do match and the alignment
* is not constrained, the function is set as the generic conversion function.
* If the parameters match and the alignment is constrained, the function is
* set as the optimized conversion function.
*
* @param ac AudioConvert context
* @param out_fmt output sample format
* @param in_fmt input sample format
* @param channels number of channels, or 0 for any number of channels
* @param ptr_align buffer pointer alignment, in bytes
* @param sample_align buffer size alignment, in samples
* @param descr function type description (e.g. "C" or "SSE")
* @param conv conversion function pointer
*/
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);
/**
* Allocate and initialize AudioConvert context for sample format conversion.
*
* @param avr AVAudioResampleContext
* @param out_fmt output sample format
* @param in_fmt input sample format
* @param channels number of channels
* @return newly-allocated AudioConvert context
*/
AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr,
enum AVSampleFormat out_fmt,
enum AVSampleFormat in_fmt,
int channels);
/**
* Convert audio data from one sample format to another.
*
* For each call, the alignment of the input and output AudioData buffers are
* examined to determine whether to use the generic or optimized conversion
* function (when available).
*
* @param ac AudioConvert context
* @param out output audio data
* @param in input audio data
* @param len number of samples to convert
* @return 0 on success, negative AVERROR code on failure
*/
int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in, int len);
/* arch-specific initialization functions */
void ff_audio_convert_init_x86(AudioConvert *ac);
#endif /* AVRESAMPLE_AUDIO_CONVERT_H */
/*
* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
*
* This file is part of Libav.
*
* Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "libavutil/mem.h"
#include "audio_data.h"
static const AVClass audio_data_class = {
.class_name = "AudioData",
.item_name = av_default_item_name,
.version = LIBAVUTIL_VERSION_INT,
};
/*
* Calculate alignment for data pointers.
*/
static void calc_ptr_alignment(AudioData *a)
{
int p;
int min_align = 128;
for (p = 0; p < a->planes; p++) {
int cur_align = 128;
while ((intptr_t)a->data[p] % cur_align)
cur_align >>= 1;
if (cur_align < min_align)
min_align = cur_align;
}
a->ptr_align = min_align;
}
int ff_audio_data_set_channels(AudioData *a, int channels)
{
if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
channels > a->allocated_channels)
return AVERROR(EINVAL);
a->channels = channels;
a->planes = a->is_planar ? channels : 1;
calc_ptr_alignment(a);
return 0;
}
int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
int nb_samples, enum AVSampleFormat sample_fmt,
int read_only, const char *name)
{
int p;