~ppsspp/ppsspp/ppsspp-1.1.1

« back to all changes in this revision

Viewing changes to ffmpeg/doc/examples/filter_audio.c

  • Committer: Sérgio Benjamim
  • Date: 2015-10-17 01:37:55 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20151017013755-avrlz2pt37kwt43x
PPSSPP 1.1.1 source.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * copyright (c) 2013 Andrew Kelley
 
3
 *
 
4
 * This file is part of FFmpeg.
 
5
 *
 
6
 * FFmpeg is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2.1 of the License, or (at your option) any later version.
 
10
 *
 
11
 * FFmpeg is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with FFmpeg; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
19
 */
 
20
 
 
21
/**
 
22
 * @file
 
23
 * libavfilter API usage example.
 
24
 *
 
25
 * @example filter_audio.c
 
26
 * This example will generate a sine wave audio,
 
27
 * pass it through a simple filter chain, and then compute the MD5 checksum of
 
28
 * the output data.
 
29
 *
 
30
 * The filter chain it uses is:
 
31
 * (input) -> abuffer -> volume -> aformat -> abuffersink -> (output)
 
32
 *
 
33
 * abuffer: This provides the endpoint where you can feed the decoded samples.
 
34
 * volume: In this example we hardcode it to 0.90.
 
35
 * aformat: This converts the samples to the samplefreq, channel layout,
 
36
 *          and sample format required by the audio device.
 
37
 * abuffersink: This provides the endpoint where you can read the samples after
 
38
 *              they have passed through the filter chain.
 
39
 */
 
40
 
 
41
#include <inttypes.h>
 
42
#include <math.h>
 
43
#include <stdio.h>
 
44
#include <stdlib.h>
 
45
 
 
46
#include "libavutil/channel_layout.h"
 
47
#include "libavutil/md5.h"
 
48
#include "libavutil/mem.h"
 
49
#include "libavutil/opt.h"
 
50
#include "libavutil/samplefmt.h"
 
51
 
 
52
#include "libavfilter/avfilter.h"
 
53
#include "libavfilter/buffersink.h"
 
54
#include "libavfilter/buffersrc.h"
 
55
 
 
56
#define INPUT_SAMPLERATE     48000
 
57
#define INPUT_FORMAT         AV_SAMPLE_FMT_FLTP
 
58
#define INPUT_CHANNEL_LAYOUT AV_CH_LAYOUT_5POINT0
 
59
 
 
60
#define VOLUME_VAL 0.90
 
61
 
 
62
static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src,
 
63
                             AVFilterContext **sink)
 
64
{
 
65
    AVFilterGraph *filter_graph;
 
66
    AVFilterContext *abuffer_ctx;
 
67
    AVFilter        *abuffer;
 
68
    AVFilterContext *volume_ctx;
 
69
    AVFilter        *volume;
 
70
    AVFilterContext *aformat_ctx;
 
71
    AVFilter        *aformat;
 
72
    AVFilterContext *abuffersink_ctx;
 
73
    AVFilter        *abuffersink;
 
74
 
 
75
    AVDictionary *options_dict = NULL;
 
76
    uint8_t options_str[1024];
 
77
    uint8_t ch_layout[64];
 
78
 
 
79
    int err;
 
80
 
 
81
    /* Create a new filtergraph, which will contain all the filters. */
 
82
    filter_graph = avfilter_graph_alloc();
 
83
    if (!filter_graph) {
 
84
        fprintf(stderr, "Unable to create filter graph.\n");
 
85
        return AVERROR(ENOMEM);
 
86
    }
 
87
 
 
88
    /* Create the abuffer filter;
 
89
     * it will be used for feeding the data into the graph. */
 
90
    abuffer = avfilter_get_by_name("abuffer");
 
91
    if (!abuffer) {
 
92
        fprintf(stderr, "Could not find the abuffer filter.\n");
 
93
        return AVERROR_FILTER_NOT_FOUND;
 
94
    }
 
95
 
 
96
    abuffer_ctx = avfilter_graph_alloc_filter(filter_graph, abuffer, "src");
 
97
    if (!abuffer_ctx) {
 
98
        fprintf(stderr, "Could not allocate the abuffer instance.\n");
 
99
        return AVERROR(ENOMEM);
 
100
    }
 
101
 
 
102
    /* Set the filter options through the AVOptions API. */
 
103
    av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, INPUT_CHANNEL_LAYOUT);
 
104
    av_opt_set    (abuffer_ctx, "channel_layout", ch_layout,                            AV_OPT_SEARCH_CHILDREN);
 
105
    av_opt_set    (abuffer_ctx, "sample_fmt",     av_get_sample_fmt_name(INPUT_FORMAT), AV_OPT_SEARCH_CHILDREN);
 
106
    av_opt_set_q  (abuffer_ctx, "time_base",      (AVRational){ 1, INPUT_SAMPLERATE },  AV_OPT_SEARCH_CHILDREN);
 
107
    av_opt_set_int(abuffer_ctx, "sample_rate",    INPUT_SAMPLERATE,                     AV_OPT_SEARCH_CHILDREN);
 
108
 
 
109
    /* Now initialize the filter; we pass NULL options, since we have already
 
110
     * set all the options above. */
 
111
    err = avfilter_init_str(abuffer_ctx, NULL);
 
112
    if (err < 0) {
 
113
        fprintf(stderr, "Could not initialize the abuffer filter.\n");
 
114
        return err;
 
115
    }
 
116
 
 
117
    /* Create volume filter. */
 
118
    volume = avfilter_get_by_name("volume");
 
119
    if (!volume) {
 
120
        fprintf(stderr, "Could not find the volume filter.\n");
 
121
        return AVERROR_FILTER_NOT_FOUND;
 
122
    }
 
123
 
 
124
    volume_ctx = avfilter_graph_alloc_filter(filter_graph, volume, "volume");
 
125
    if (!volume_ctx) {
 
126
        fprintf(stderr, "Could not allocate the volume instance.\n");
 
127
        return AVERROR(ENOMEM);
 
128
    }
 
129
 
 
130
    /* A different way of passing the options is as key/value pairs in a
 
131
     * dictionary. */
 
132
    av_dict_set(&options_dict, "volume", AV_STRINGIFY(VOLUME_VAL), 0);
 
133
    err = avfilter_init_dict(volume_ctx, &options_dict);
 
134
    av_dict_free(&options_dict);
 
135
    if (err < 0) {
 
136
        fprintf(stderr, "Could not initialize the volume filter.\n");
 
137
        return err;
 
138
    }
 
139
 
 
140
    /* Create the aformat filter;
 
141
     * it ensures that the output is of the format we want. */
 
142
    aformat = avfilter_get_by_name("aformat");
 
143
    if (!aformat) {
 
144
        fprintf(stderr, "Could not find the aformat filter.\n");
 
145
        return AVERROR_FILTER_NOT_FOUND;
 
146
    }
 
147
 
 
148
    aformat_ctx = avfilter_graph_alloc_filter(filter_graph, aformat, "aformat");
 
149
    if (!aformat_ctx) {
 
150
        fprintf(stderr, "Could not allocate the aformat instance.\n");
 
151
        return AVERROR(ENOMEM);
 
152
    }
 
153
 
 
154
    /* A third way of passing the options is in a string of the form
 
155
     * key1=value1:key2=value2.... */
 
156
    snprintf(options_str, sizeof(options_str),
 
157
             "sample_fmts=%s:sample_rates=%d:channel_layouts=0x%"PRIx64,
 
158
             av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 44100,
 
159
             (uint64_t)AV_CH_LAYOUT_STEREO);
 
160
    err = avfilter_init_str(aformat_ctx, options_str);
 
161
    if (err < 0) {
 
162
        av_log(NULL, AV_LOG_ERROR, "Could not initialize the aformat filter.\n");
 
163
        return err;
 
164
    }
 
165
 
 
166
    /* Finally create the abuffersink filter;
 
167
     * it will be used to get the filtered data out of the graph. */
 
168
    abuffersink = avfilter_get_by_name("abuffersink");
 
169
    if (!abuffersink) {
 
170
        fprintf(stderr, "Could not find the abuffersink filter.\n");
 
171
        return AVERROR_FILTER_NOT_FOUND;
 
172
    }
 
173
 
 
174
    abuffersink_ctx = avfilter_graph_alloc_filter(filter_graph, abuffersink, "sink");
 
175
    if (!abuffersink_ctx) {
 
176
        fprintf(stderr, "Could not allocate the abuffersink instance.\n");
 
177
        return AVERROR(ENOMEM);
 
178
    }
 
179
 
 
180
    /* This filter takes no options. */
 
181
    err = avfilter_init_str(abuffersink_ctx, NULL);
 
182
    if (err < 0) {
 
183
        fprintf(stderr, "Could not initialize the abuffersink instance.\n");
 
184
        return err;
 
185
    }
 
186
 
 
187
    /* Connect the filters;
 
188
     * in this simple case the filters just form a linear chain. */
 
189
    err = avfilter_link(abuffer_ctx, 0, volume_ctx, 0);
 
190
    if (err >= 0)
 
191
        err = avfilter_link(volume_ctx, 0, aformat_ctx, 0);
 
192
    if (err >= 0)
 
193
        err = avfilter_link(aformat_ctx, 0, abuffersink_ctx, 0);
 
194
    if (err < 0) {
 
195
        fprintf(stderr, "Error connecting filters\n");
 
196
        return err;
 
197
    }
 
198
 
 
199
    /* Configure the graph. */
 
200
    err = avfilter_graph_config(filter_graph, NULL);
 
201
    if (err < 0) {
 
202
        av_log(NULL, AV_LOG_ERROR, "Error configuring the filter graph\n");
 
203
        return err;
 
204
    }
 
205
 
 
206
    *graph = filter_graph;
 
207
    *src   = abuffer_ctx;
 
208
    *sink  = abuffersink_ctx;
 
209
 
 
210
    return 0;
 
211
}
 
212
 
 
213
/* Do something useful with the filtered data: this simple
 
214
 * example just prints the MD5 checksum of each plane to stdout. */
 
215
static int process_output(struct AVMD5 *md5, AVFrame *frame)
 
216
{
 
217
    int planar     = av_sample_fmt_is_planar(frame->format);
 
218
    int channels   = av_get_channel_layout_nb_channels(frame->channel_layout);
 
219
    int planes     = planar ? channels : 1;
 
220
    int bps        = av_get_bytes_per_sample(frame->format);
 
221
    int plane_size = bps * frame->nb_samples * (planar ? 1 : channels);
 
222
    int i, j;
 
223
 
 
224
    for (i = 0; i < planes; i++) {
 
225
        uint8_t checksum[16];
 
226
 
 
227
        av_md5_init(md5);
 
228
        av_md5_sum(checksum, frame->extended_data[i], plane_size);
 
229
 
 
230
        fprintf(stdout, "plane %d: 0x", i);
 
231
        for (j = 0; j < sizeof(checksum); j++)
 
232
            fprintf(stdout, "%02X", checksum[j]);
 
233
        fprintf(stdout, "\n");
 
234
    }
 
235
    fprintf(stdout, "\n");
 
236
 
 
237
    return 0;
 
238
}
 
239
 
 
240
/* Construct a frame of audio data to be filtered;
 
241
 * this simple example just synthesizes a sine wave. */
 
242
static int get_input(AVFrame *frame, int frame_num)
 
243
{
 
244
    int err, i, j;
 
245
 
 
246
#define FRAME_SIZE 1024
 
247
 
 
248
    /* Set up the frame properties and allocate the buffer for the data. */
 
249
    frame->sample_rate    = INPUT_SAMPLERATE;
 
250
    frame->format         = INPUT_FORMAT;
 
251
    frame->channel_layout = INPUT_CHANNEL_LAYOUT;
 
252
    frame->nb_samples     = FRAME_SIZE;
 
253
    frame->pts            = frame_num * FRAME_SIZE;
 
254
 
 
255
    err = av_frame_get_buffer(frame, 0);
 
256
    if (err < 0)
 
257
        return err;
 
258
 
 
259
    /* Fill the data for each channel. */
 
260
    for (i = 0; i < 5; i++) {
 
261
        float *data = (float*)frame->extended_data[i];
 
262
 
 
263
        for (j = 0; j < frame->nb_samples; j++)
 
264
            data[j] = sin(2 * M_PI * (frame_num + j) * (i + 1) / FRAME_SIZE);
 
265
    }
 
266
 
 
267
    return 0;
 
268
}
 
269
 
 
270
int main(int argc, char *argv[])
 
271
{
 
272
    struct AVMD5 *md5;
 
273
    AVFilterGraph *graph;
 
274
    AVFilterContext *src, *sink;
 
275
    AVFrame *frame;
 
276
    uint8_t errstr[1024];
 
277
    float duration;
 
278
    int err, nb_frames, i;
 
279
 
 
280
    if (argc < 2) {
 
281
        fprintf(stderr, "Usage: %s <duration>\n", argv[0]);
 
282
        return 1;
 
283
    }
 
284
 
 
285
    duration  = atof(argv[1]);
 
286
    nb_frames = duration * INPUT_SAMPLERATE / FRAME_SIZE;
 
287
    if (nb_frames <= 0) {
 
288
        fprintf(stderr, "Invalid duration: %s\n", argv[1]);
 
289
        return 1;
 
290
    }
 
291
 
 
292
    avfilter_register_all();
 
293
 
 
294
    /* Allocate the frame we will be using to store the data. */
 
295
    frame  = av_frame_alloc();
 
296
    if (!frame) {
 
297
        fprintf(stderr, "Error allocating the frame\n");
 
298
        return 1;
 
299
    }
 
300
 
 
301
    md5 = av_md5_alloc();
 
302
    if (!md5) {
 
303
        fprintf(stderr, "Error allocating the MD5 context\n");
 
304
        return 1;
 
305
    }
 
306
 
 
307
    /* Set up the filtergraph. */
 
308
    err = init_filter_graph(&graph, &src, &sink);
 
309
    if (err < 0) {
 
310
        fprintf(stderr, "Unable to init filter graph:");
 
311
        goto fail;
 
312
    }
 
313
 
 
314
    /* the main filtering loop */
 
315
    for (i = 0; i < nb_frames; i++) {
 
316
        /* get an input frame to be filtered */
 
317
        err = get_input(frame, i);
 
318
        if (err < 0) {
 
319
            fprintf(stderr, "Error generating input frame:");
 
320
            goto fail;
 
321
        }
 
322
 
 
323
        /* Send the frame to the input of the filtergraph. */
 
324
        err = av_buffersrc_add_frame(src, frame);
 
325
        if (err < 0) {
 
326
            av_frame_unref(frame);
 
327
            fprintf(stderr, "Error submitting the frame to the filtergraph:");
 
328
            goto fail;
 
329
        }
 
330
 
 
331
        /* Get all the filtered output that is available. */
 
332
        while ((err = av_buffersink_get_frame(sink, frame)) >= 0) {
 
333
            /* now do something with our filtered frame */
 
334
            err = process_output(md5, frame);
 
335
            if (err < 0) {
 
336
                fprintf(stderr, "Error processing the filtered frame:");
 
337
                goto fail;
 
338
            }
 
339
            av_frame_unref(frame);
 
340
        }
 
341
 
 
342
        if (err == AVERROR(EAGAIN)) {
 
343
            /* Need to feed more frames in. */
 
344
            continue;
 
345
        } else if (err == AVERROR_EOF) {
 
346
            /* Nothing more to do, finish. */
 
347
            break;
 
348
        } else if (err < 0) {
 
349
            /* An error occurred. */
 
350
            fprintf(stderr, "Error filtering the data:");
 
351
            goto fail;
 
352
        }
 
353
    }
 
354
 
 
355
    avfilter_graph_free(&graph);
 
356
    av_frame_free(&frame);
 
357
    av_freep(&md5);
 
358
 
 
359
    return 0;
 
360
 
 
361
fail:
 
362
    av_strerror(err, errstr, sizeof(errstr));
 
363
    fprintf(stderr, "%s\n", errstr);
 
364
    return 1;
 
365
}