[FFmpeg-devel] [PATCH] examples: add resampling_audio.c file

Michael Niedermayer michaelni at gmx.at
Sun Dec 2 00:34:03 CET 2012


On Sat, Dec 01, 2012 at 08:21:47PM +0100, Stefano Sabatini wrote:
> On date Saturday 2012-12-01 05:09:04 +0100, Michael Niedermayer encoded:
> > On Fri, Nov 30, 2012 at 11:42:43PM +0100, Stefano Sabatini wrote:
> > > On date Friday 2012-11-30 19:58:51 +0100, Stefano Sabatini encoded:
> > > > ---
> > > >  doc/examples/Makefile           |    3 +-
> > > >  doc/examples/resampling_audio.c |  208 +++++++++++++++++++++++++++++++++++++++
> > > >  2 files changed, 210 insertions(+), 1 deletion(-)
> > > >  create mode 100644 doc/examples/resampling_audio.c
> > > 
> > > Upped.
> > > 
> > > Note, this doesn't work if I change destination layout MONO ->
> > > SURROUND, I got:
> > > $ resampling_audio out.raw
> > > ...
> > > Resampling succeeded. Play the output file with the command:
> > > ffplay -f s16le -channel_layout 7 -ac 3 -ar 44100 out.raw
> > > $ ffplay -f s16le -channel_layout 7 -ac 3 -ar 44100 out.raw
> > > ffplay version N-46906-ga5e382a Copyright (c) 2003-2012 the FFmpeg developers
> > > [...]
> > > [s16le @ 0x7f11080042d0] Estimating duration from bitrate, this may be inaccurate
> > > Input #0, s16le, from 'out.raw':
> > >   Duration: 00:00:10.01, start: 0.000000, bitrate: 2116 kb/s
> > >     Stream #0:0: Audio: pcm_s16le, 44100 Hz, 3.0, s16, 2116 kb/s
> > > SDL_OpenAudio (3 channels): 1 (mono) and 2 (stereo) channels supported
> > > [pcm_s16le @ 0x7f1108000ad0] Invalid PCM packet, data has size 2 but at least a size of 6 was expected
> > > 
> > > and I got distorted sound. Any hint?
> > 
> > try -channels 3
> 
> Yes, this fixes it, still ffplay shows the wrong number of channels (6
> in place of 3).
> 
> Patch updated, will push it in a couple of days, please comment.
> -- 
> FFmpeg = Faithless and Fostering Martial Puristic Exciting Genius

>  Makefile           |    1 
>  resampling_audio.c |  213 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 214 insertions(+)
> 30e82c84ef67fae46e26d59d35f604e66999b9ba  0002-examples-add-resampling_audio.c-file.patch
> From c249e5a01288f9037a1b5e63855769c9e30e7360 Mon Sep 17 00:00:00 2001
> From: Stefano Sabatini <stefasab at gmail.com>
> Date: Fri, 30 Nov 2012 13:51:40 +0100
> Subject: [PATCH] examples: add resampling_audio.c file
> 
> ---
>  doc/examples/Makefile           |    1 +
>  doc/examples/resampling_audio.c |  213 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 214 insertions(+)
>  create mode 100644 doc/examples/resampling_audio.c
> 
> diff --git a/doc/examples/Makefile b/doc/examples/Makefile
> index 36c949a..c849daa 100644
> --- a/doc/examples/Makefile
> +++ b/doc/examples/Makefile
> @@ -17,6 +17,7 @@ EXAMPLES=       decoding_encoding                  \
>                  filtering_audio                    \
>                  metadata                           \
>                  muxing                             \
> +                resampling_audio                   \
>                  scaling_video                      \
>  
>  OBJS=$(addsuffix .o,$(EXAMPLES))
> diff --git a/doc/examples/resampling_audio.c b/doc/examples/resampling_audio.c
> new file mode 100644
> index 0000000..028ff20
> --- /dev/null
> +++ b/doc/examples/resampling_audio.c
> @@ -0,0 +1,213 @@
> +/*
> + * Copyright (c) 2012 Stefano Sabatini
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +/**
> + * @file
> + * libswresample API use example.
> + */
> +
> +#include <libavutil/opt.h>
> +#include <libavutil/channel_layout.h>
> +#include <libavutil/samplefmt.h>
> +#include <libswresample/swresample.h>
> +
> +static int get_format_from_sample_fmt(const char **fmt,
> +                                      enum AVSampleFormat sample_fmt)
> +{
> +    int i;
> +    struct sample_fmt_entry {
> +        enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le;
> +    } sample_fmt_entries[] = {
> +        { AV_SAMPLE_FMT_U8,  "u8",    "u8"    },
> +        { AV_SAMPLE_FMT_S16, "s16be", "s16le" },
> +        { AV_SAMPLE_FMT_S32, "s32be", "s32le" },
> +        { AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
> +        { AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
> +    };
> +    *fmt = NULL;
> +
> +    for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
> +        struct sample_fmt_entry *entry = &sample_fmt_entries[i];
> +        if (sample_fmt == entry->sample_fmt) {
> +            *fmt = AV_NE(entry->fmt_be, entry->fmt_le);
> +            return 0;
> +        }
> +    }

something like
{ AV_SAMPLE_FMT_U8,  AV_NE("u8",    "u8"   )    },
{ AV_SAMPLE_FMT_S16, AV_NE("s16be", "s16le")    },
...
should be slightly simpler


> +
> +    fprintf(stderr,
> +            "Sample format %s not supported as output format\n",
> +            av_get_sample_fmt_name(sample_fmt));
> +    return AVERROR(EINVAL);
> +}
> +
> +/**
> + * Fill dst buffer with nb_samples, generated starting from t.
> + */
> +void fill_samples(double *dst, int nb_samples, int nb_channels, int sample_rate, double *t)
> +{
> +    int i, j;
> +    double tincr = (double)1 / sample_rate, *dstp = dst;
> +    const double c = 2 * M_PI * (double)440.0;
> +
> +    /* generate sin tone with 440Hz frequency and duplicated channels */
> +    for (i = 0; i < nb_samples; i++) {
> +        *dstp = sin(c * *t);
> +        for (j = 1; j < nb_channels; j++)
> +            dstp[j] = dstp[0];
> +        dstp += nb_channels;
> +        *t += tincr;
> +    }
> +}
> +
> +int alloc_samples_array_and_data(uint8_t ***data, int *linesize, int nb_channels,
> +                                    int nb_samples, enum AVSampleFormat sample_fmt, int align)
> +{
> +    int nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1;
> +
> +    *data = av_malloc(sizeof(*data) * nb_planes);
> +    if (!*data)
> +        return AVERROR(ENOMEM);
> +    return av_samples_alloc(*data, linesize, nb_channels,
> +                            nb_samples, sample_fmt, align);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND;
> +    int src_rate = 48000, dst_rate = 44100;
> +    uint8_t **src_data, **dst_data;
> +    int src_nb_channels = 0, dst_nb_channels = 0;
> +    int src_linesize, dst_linesize;
> +    int src_nb_samples = 1024, dst_nb_samples;
> +    enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL, dst_sample_fmt = AV_SAMPLE_FMT_S16;
> +    const char *dst_filename = NULL;
> +    FILE *dst_file;
> +    int dst_bufsize;
> +    const char *fmt;
> +    struct SwrContext *swr_ctx;
> +    double t;
> +    int ret;
> +
> +    if (argc != 2) {
> +        fprintf(stderr, "Usage: %s output_file output_opts\n"
> +                "API example program to show how to resample an audio stream with libswresample.\n"
> +                "This program generates a series of audio frames, resamples them to a specified "
> +                "output format and rate and saves them to an output file named output_file.\n",
> +            argv[0]);
> +        exit(1);
> +    }
> +    dst_filename = argv[1];
> +
> +    dst_file = fopen(dst_filename, "wb");
> +    if (!dst_file) {
> +        fprintf(stderr, "Could not open destination file %s\n", dst_filename);
> +        exit(1);
> +    }
> +
> +    /* create resampler context */
> +    swr_ctx = swr_alloc();
> +    if (!swr_ctx) {
> +        fprintf(stderr, "Could not allocate resampler context\n");
> +        ret = AVERROR(ENOMEM);
> +        goto end;
> +    }
> +
> +    /* set options */
> +    av_opt_set_int(swr_ctx, "in_channel_layout",    src_ch_layout, 0);
> +    av_opt_set_int(swr_ctx, "in_sample_rate",       src_rate, 0);
> +    av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
> +
> +    av_opt_set_int(swr_ctx, "out_channel_layout",    dst_ch_layout, 0);
> +    av_opt_set_int(swr_ctx, "out_sample_rate",       dst_rate, 0);
> +    av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);
> +
> +    /* initialize the resampling context */
> +    if ((ret = swr_init(swr_ctx)) < 0) {
> +        fprintf(stderr, "Failed to initialize the resampling context\n");
> +        goto end;
> +    }
> +
> +    /* allocate source and destination samples buffers */
> +
> +    src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
> +    ret = alloc_samples_array_and_data(&src_data, &src_linesize, src_nb_channels,
> +                                       src_nb_samples, src_sample_fmt, 0);
> +    if (ret < 0) {
> +        fprintf(stderr, "Could not allocate source samples\n");
> +        goto end;
> +    }
> +

> +    /* compute the number of converted samples: buffering is avoided
> +     * ensuring that the output buffer will contain at least all the
> +     * converted input samples */
> +    dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, dst_rate) + src_nb_samples,
> +                                    dst_rate, src_rate, AV_ROUND_UP);

isnt this mixing up src and dst rates ?


[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The worst form of inequality is to try to make unequal things equal.
-- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121202/22a4acb3/attachment.asc>


More information about the ffmpeg-devel mailing list