From f0dbbe966ff321997e57c5e47308b1e18d962781 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Aug 2007 00:23:48 +0000 Subject: [PATCH] add makefiles to speex/ and ffmpeg/ to easy compilation from emacs git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1715 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/ffmpeg/Makefile | 13 ++++++++ src/pulsecore/resampler.c | 78 +++++++++++++++++++++++++++++++++++++++++-- src/pulsecore/resampler.h | 4 ++- src/pulsecore/sink-input.c | 10 +++--- src/pulsecore/source-output.c | 11 +++--- src/pulsecore/speex/Makefile | 13 ++++++++ 6 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 src/pulsecore/ffmpeg/Makefile create mode 100644 src/pulsecore/speex/Makefile diff --git a/src/pulsecore/ffmpeg/Makefile b/src/pulsecore/ffmpeg/Makefile new file mode 100644 index 0000000..316beb7 --- /dev/null +++ b/src/pulsecore/ffmpeg/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C ../.. + +clean: + $(MAKE) -C ../.. clean + +.PHONY: all clean diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c index 57de0d1..47a5eac 100644 --- a/src/pulsecore/resampler.c +++ b/src/pulsecore/resampler.c @@ -39,6 +39,8 @@ #include "speexwrap.h" +#include "ffmpeg/avcodec.h" + #include "resampler.h" struct pa_resampler { @@ -75,11 +77,17 @@ struct pa_resampler { struct { /* data specific to speex */ SpeexResamplerState* state; } speex; + + struct { /* data specific to ffmpeg */ + struct AVResampleContext *state; + unsigned initial_i_rate, initial_o_rate; + } ffmpeg; }; static int libsamplerate_init(pa_resampler*r); static int trivial_init(pa_resampler*r); static int speex_init(pa_resampler*r); +static int ffmpeg_init(pa_resampler*r); static void calc_map_table(pa_resampler *r); @@ -112,6 +120,7 @@ static int (* const init_table[])(pa_resampler*r) = { [PA_RESAMPLER_SPEEX_FIXED_BASE+8] = speex_init, [PA_RESAMPLER_SPEEX_FIXED_BASE+9] = speex_init, [PA_RESAMPLER_SPEEX_FIXED_BASE+10] = speex_init, + [PA_RESAMPLER_FFMPEG] = ffmpeg_init, [PA_RESAMPLER_AUTO] = NULL, }; @@ -131,7 +140,8 @@ pa_resampler* pa_resampler_new( const pa_channel_map *am, const pa_sample_spec *b, const pa_channel_map *bm, - pa_resample_method_t resample_method) { + pa_resample_method_t resample_method, + int variable_rate) { pa_resampler *r = NULL; @@ -144,6 +154,12 @@ pa_resampler* pa_resampler_new( pa_assert(resample_method < PA_RESAMPLER_MAX); /* Fix method */ + + if (resample_method == PA_RESAMPLER_FFMPEG && variable_rate) { + pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'." ); + resample_method = PA_RESAMPLER_AUTO; + } + if (resample_method == PA_RESAMPLER_AUTO) { if (a->format == PA_SAMPLE_FLOAT32LE || a->format == PA_SAMPLE_FLOAT32BE || b->format == PA_SAMPLE_FLOAT32LE || b->format == PA_SAMPLE_FLOAT32BE) @@ -151,7 +167,7 @@ pa_resampler* pa_resampler_new( else resample_method = PA_RESAMPLER_SPEEX_FIXED_BASE + 0; } - + r = pa_xnew(pa_resampler, 1); r->mempool = pool; r->resample_method = resample_method; @@ -188,7 +204,8 @@ pa_resampler* pa_resampler_new( pa_log_info("Using resampler '%s'", pa_resample_method_to_string(resample_method)); - if (resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) + if ((resample_method >= PA_RESAMPLER_SPEEX_FIXED_BASE && resample_method <= PA_RESAMPLER_SPEEX_FIXED_MAX) || + (resample_method == PA_RESAMPLER_FFMPEG)) r->work_format = PA_SAMPLE_S16NE; else if (resample_method == PA_RESAMPLER_TRIVIAL) { @@ -268,6 +285,7 @@ void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) { return; r->i_ss.rate = rate; + r->impl_update_rates(r); } @@ -279,6 +297,7 @@ void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) { return; r->o_ss.rate = rate; + r->impl_update_rates(r); } @@ -323,6 +342,7 @@ static const char * const resample_methods[] = { "speex-fixed-8", "speex-fixed-9", "speex-fixed-10", + "ffmpeg", "auto" }; @@ -825,4 +845,56 @@ static int trivial_init(pa_resampler*r) { return 0; } +/*** ffmpeg based implementation ***/ + +static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) { + short *src, *dst; + int consumed; + int c; + + pa_assert(r); + pa_assert(input); + pa_assert(output); + pa_assert(out_n_frames); + + src = (short*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index); + dst = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index); + + for (c = 0; c < r->o_ss.channels; c++) + *out_n_frames = av_resample(r->ffmpeg.state, + dst + r->w_sz*c, + src + r->w_sz*c, + &consumed, + in_n_frames, *out_n_frames, + c >= r->o_ss.channels-1); + + pa_assert(*out_n_frames > 0); + pa_assert(consumed == in_n_frames); + + pa_memblock_release(input->memblock); + pa_memblock_release(output->memblock); +} + +static void ffmpeg_free(pa_resampler *r) { + pa_assert(r); + + if (r->ffmpeg.state) + av_resample_close(r->ffmpeg.state); +} + +static int ffmpeg_init(pa_resampler *r) { + pa_assert(r); + + /* We could probably implement different quality levels by + * adjusting the filter parameters here. However, ffmpeg + * internally only uses these hardcoded values, so let's use them + * here for now as well until ffmpeg makes this configurable. */ + + if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8))) + return -1; + + r->impl_free = ffmpeg_free; + r->impl_resample = ffmpeg_resample; + return 0; +} diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h index 35f53db..2a943e3 100644 --- a/src/pulsecore/resampler.h +++ b/src/pulsecore/resampler.h @@ -45,6 +45,7 @@ typedef enum pa_resample_method { PA_RESAMPLER_SPEEX_FLOAT_MAX = PA_RESAMPLER_SPEEX_FLOAT_BASE + 10, PA_RESAMPLER_SPEEX_FIXED_BASE, PA_RESAMPLER_SPEEX_FIXED_MAX = PA_RESAMPLER_SPEEX_FIXED_BASE + 10, + PA_RESAMPLER_FFMPEG, PA_RESAMPLER_AUTO, /* automatic select based on sample format */ PA_RESAMPLER_MAX } pa_resample_method_t; @@ -55,7 +56,8 @@ pa_resampler* pa_resampler_new( const pa_channel_map *am, const pa_sample_spec *b, const pa_channel_map *bm, - pa_resample_method_t resample_method); + pa_resample_method_t resample_method, + int variable_rate); void pa_resampler_free(pa_resampler *r); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 8bec5d5..0cdcbc0 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -153,7 +153,8 @@ pa_sink_input* pa_sink_input_new( core->mempool, &data->sample_spec, &data->channel_map, &data->sink->sample_spec, &data->sink->channel_map, - data->resample_method))) { + data->resample_method, + !!(flags & PA_SINK_INPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -639,8 +640,8 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { new_resampler = i->thread_info.resampler; else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || - !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || - !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { + !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || + !pa_channel_map_equal(&i->channel_map, &dest->channel_map)) { /* Okey, we need a new resampler for the new sink */ @@ -648,7 +649,8 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { dest->core->mempool, &i->sample_spec, &i->channel_map, &dest->sample_spec, &dest->channel_map, - i->resample_method))) { + i->resample_method, + !!(i->flags & PA_SINK_INPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return -1; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index ce81fcc..2532246 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -121,7 +121,8 @@ pa_source_output* pa_source_output_new( core->mempool, &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, - data->resample_method))) { + data->resample_method, + !!(flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return NULL; } @@ -351,8 +352,9 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { /* Try to reuse the old resampler if possible */ new_resampler = o->thread_info.resampler; - else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || - !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { + else if ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) || + !pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || + !pa_channel_map_equal(&o->channel_map, &dest->channel_map)) { /* Okey, we need a new resampler for the new source */ @@ -360,7 +362,8 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { dest->core->mempool, &dest->sample_spec, &dest->channel_map, &o->sample_spec, &o->channel_map, - o->resample_method))) { + o->resample_method, + !!(o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE)))) { pa_log_warn("Unsupported resampling operation."); return -1; } diff --git a/src/pulsecore/speex/Makefile b/src/pulsecore/speex/Makefile new file mode 100644 index 0000000..316beb7 --- /dev/null +++ b/src/pulsecore/speex/Makefile @@ -0,0 +1,13 @@ +# This is a dirty trick just to ease compilation with emacs +# +# This file is not intended to be distributed or anything +# +# So: don't touch it, even better ignore it! + +all: + $(MAKE) -C ../.. + +clean: + $(MAKE) -C ../.. clean + +.PHONY: all clean -- 2.7.4