Browse code

ffplay: add -af option

Based on a patch by Stefano Sabatini <stefasab@gmail.com>:
http://ffmpeg.org/pipermail/ffmpeg-devel/2013-February/138452.html

Signed-off-by: Marton Balint <cus@passwd.hu>

Marton Balint authored on 2013/02/26 06:00:30
Showing 3 changed files
... ...
@@ -8,6 +8,7 @@ version <next>:
8 8
   or vice versa
9 9
 - support for Monkey's Audio versions from 3.93
10 10
 - perms and aperms filters
11
+- audio filtering support in ffplay
11 12
 
12 13
 
13 14
 version 1.2:
... ...
@@ -84,6 +84,12 @@ output. In the filter graph, the input is associated to the label
84 84
 ffmpeg-filters manual for more information about the filtergraph
85 85
 syntax.
86 86
 
87
+@item -af @var{filter_graph}
88
+@var{filter_graph} is a description of the filter graph to apply to
89
+the input audio.
90
+Use the option "-filters" to show all the available filters (including
91
+sources and sinks).
92
+
87 93
 @item -i @var{input_file}
88 94
 Read @var{input_file}.
89 95
 @end table
... ...
@@ -191,7 +191,11 @@ typedef struct VideoState {
191 191
     AVPacket audio_pkt_temp;
192 192
     AVPacket audio_pkt;
193 193
     int audio_pkt_temp_serial;
194
+    int audio_last_serial;
194 195
     struct AudioParams audio_src;
196
+#if CONFIG_AVFILTER
197
+    struct AudioParams audio_filter_src;
198
+#endif
195 199
     struct AudioParams audio_tgt;
196 200
     struct SwrContext *swr_ctx;
197 201
     double audio_current_pts;
... ...
@@ -253,6 +257,9 @@ typedef struct VideoState {
253 253
 #if CONFIG_AVFILTER
254 254
     AVFilterContext *in_video_filter;   // the first filter in the video chain
255 255
     AVFilterContext *out_video_filter;  // the last filter in the video chain
256
+    AVFilterContext *in_audio_filter;   // the first filter in the audio chain
257
+    AVFilterContext *out_audio_filter;  // the last filter in the audio chain
258
+    AVFilterGraph *agraph;              // audio filter graph
256 259
 #endif
257 260
 
258 261
     int last_video_stream, last_audio_stream, last_subtitle_stream;
... ...
@@ -309,6 +316,7 @@ static int64_t cursor_last_shown;
309 309
 static int cursor_hidden = 0;
310 310
 #if CONFIG_AVFILTER
311 311
 static char *vfilters = NULL;
312
+static char *afilters = NULL;
312 313
 #endif
313 314
 
314 315
 /* current context */
... ...
@@ -322,6 +330,26 @@ static AVPacket flush_pkt;
322 322
 
323 323
 static SDL_Surface *screen;
324 324
 
325
+static inline
326
+int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1,
327
+                   enum AVSampleFormat fmt2, int64_t channel_count2)
328
+{
329
+    /* If channel count == 1, planar and non-planar formats are the same */
330
+    if (channel_count1 == 1 && channel_count2 == 1)
331
+        return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2);
332
+    else
333
+        return channel_count1 != channel_count2 || fmt1 != fmt2;
334
+}
335
+
336
+static inline
337
+int64_t get_valid_channel_layout(int64_t channel_layout, int channels)
338
+{
339
+    if (channel_layout && av_get_channel_layout_nb_channels(channel_layout) == channels)
340
+        return channel_layout;
341
+    else
342
+        return 0;
343
+}
344
+
325 345
 static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
326 346
 
327 347
 static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
... ...
@@ -1781,6 +1809,71 @@ fail:
1781 1781
     return ret;
1782 1782
 }
1783 1783
 
1784
+static int configure_audio_filters(VideoState *is, const char *afilters, int force_output_format)
1785
+{
1786
+    static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, PIX_FMT_NONE };
1787
+    int sample_rates[2] = { 0, -1 };
1788
+    int64_t channel_layouts[2] = { 0, -1 };
1789
+    int channels[2] = { 0, -1 };
1790
+    AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
1791
+    char asrc_args[256];
1792
+    AVABufferSinkParams *asink_params = NULL;
1793
+    int ret;
1794
+
1795
+    avfilter_graph_free(&is->agraph);
1796
+    if (!(is->agraph = avfilter_graph_alloc()))
1797
+        return AVERROR(ENOMEM);
1798
+
1799
+    ret = snprintf(asrc_args, sizeof(asrc_args),
1800
+                   "sample_rate=%d:sample_fmt=%s:channels=%d",
1801
+                   is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt),
1802
+                   is->audio_filter_src.channels);
1803
+    if (is->audio_filter_src.channel_layout)
1804
+        snprintf(asrc_args + ret, sizeof(asrc_args) - ret,
1805
+                 ":channel_layout=0x%"PRIx64,  is->audio_filter_src.channel_layout);
1806
+
1807
+    ret = avfilter_graph_create_filter(&filt_asrc,
1808
+                                       avfilter_get_by_name("abuffer"), "ffplay_abuffer",
1809
+                                       asrc_args, NULL, is->agraph);
1810
+    if (ret < 0)
1811
+        goto end;
1812
+
1813
+    if (!(asink_params = av_abuffersink_params_alloc())) {
1814
+        ret = AVERROR(ENOMEM);
1815
+        goto end;
1816
+    }
1817
+    asink_params->sample_fmts = sample_fmts;
1818
+
1819
+    asink_params->all_channel_counts = 1;
1820
+    if (force_output_format) {
1821
+        channel_layouts[0] = is->audio_tgt.channel_layout;
1822
+        asink_params->channel_layouts = channel_layouts;
1823
+        asink_params->all_channel_counts = 0;
1824
+        channels[0] = is->audio_tgt.channels;
1825
+        asink_params->channel_counts = channels;
1826
+        asink_params->all_channel_counts = 0;
1827
+        sample_rates[0] = is->audio_tgt.freq;
1828
+        asink_params->sample_rates = sample_rates;
1829
+    }
1830
+
1831
+    ret = avfilter_graph_create_filter(&filt_asink,
1832
+                                       avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
1833
+                                       NULL, asink_params, is->agraph);
1834
+    if (ret < 0)
1835
+        goto end;
1836
+
1837
+    if ((ret = configure_filtergraph(is->agraph, afilters, filt_asrc, filt_asink)) < 0)
1838
+        goto end;
1839
+
1840
+    is->in_audio_filter  = filt_asrc;
1841
+    is->out_audio_filter = filt_asink;
1842
+
1843
+end:
1844
+    av_freep(&asink_params);
1845
+    if (ret < 0)
1846
+        avfilter_graph_free(&is->agraph);
1847
+    return ret;
1848
+}
1784 1849
 #endif  /* CONFIG_AVFILTER */
1785 1850
 
1786 1851
 static int video_thread(void *arg)
... ...
@@ -2056,6 +2149,7 @@ static int audio_decode_frame(VideoState *is)
2056 2056
     int new_packet = 0;
2057 2057
     int flush_complete = 0;
2058 2058
     int wanted_nb_samples;
2059
+    AVRational tb;
2059 2060
 
2060 2061
     for (;;) {
2061 2062
         /* NOTE: the audio packet can contain several frames */
... ...
@@ -2098,6 +2192,49 @@ static int audio_decode_frame(VideoState *is)
2098 2098
                 is->frame->pts = av_rescale_q(pkt_temp->pts, is->audio_st->time_base, dec->time_base);
2099 2099
             if (pkt_temp->pts != AV_NOPTS_VALUE)
2100 2100
                 pkt_temp->pts += (double) is->frame->nb_samples / is->frame->sample_rate / av_q2d(is->audio_st->time_base);
2101
+            tb = dec->time_base;
2102
+
2103
+#if CONFIG_AVFILTER
2104
+            {
2105
+                int ret;
2106
+                int reconfigure;
2107
+
2108
+                dec_channel_layout = get_valid_channel_layout(is->frame->channel_layout, av_frame_get_channels(is->frame));
2109
+
2110
+                reconfigure =
2111
+                    cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
2112
+                                   is->frame->format, av_frame_get_channels(is->frame))    ||
2113
+                    is->audio_filter_src.channel_layout != dec_channel_layout ||
2114
+                    is->audio_filter_src.freq           != is->frame->sample_rate ||
2115
+                    is->audio_pkt_temp_serial           != is->audio_last_serial;
2116
+
2117
+                if (reconfigure) {
2118
+                    char buf1[1024], buf2[1024];
2119
+                    av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
2120
+                    av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
2121
+                    av_log(NULL, AV_LOG_DEBUG,
2122
+                           "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
2123
+                           is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, is->audio_last_serial,
2124
+                           is->frame->sample_rate, av_frame_get_channels(is->frame), av_get_sample_fmt_name(is->frame->format), buf2, is->audio_pkt_temp_serial);
2125
+
2126
+                    is->audio_filter_src.fmt            = is->frame->format;
2127
+                    is->audio_filter_src.channels       = av_frame_get_channels(is->frame);
2128
+                    is->audio_filter_src.channel_layout = dec_channel_layout;
2129
+                    is->audio_filter_src.freq           = is->frame->sample_rate;
2130
+                    is->audio_last_serial               = is->audio_pkt_temp_serial;
2131
+
2132
+                    if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
2133
+                        return ret;
2134
+                }
2135
+
2136
+                if ((ret = av_buffersrc_add_frame(is->in_audio_filter, is->frame)) < 0)
2137
+                    return ret;
2138
+                av_frame_unref(is->frame);
2139
+                if ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, is->frame, 0)) < 0)
2140
+                    return ret;
2141
+                tb = is->out_audio_filter->inputs[0]->time_base;
2142
+            }
2143
+#endif
2101 2144
 
2102 2145
             data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(is->frame),
2103 2146
                                                    is->frame->nb_samples,
... ...
@@ -2164,7 +2301,7 @@ static int audio_decode_frame(VideoState *is)
2164 2164
             audio_clock0 = is->audio_clock;
2165 2165
             /* update the audio clock with the pts */
2166 2166
             if (is->frame->pts != AV_NOPTS_VALUE) {
2167
-                is->audio_clock = is->frame->pts * av_q2d(dec->time_base) + (double) is->frame->nb_samples / is->frame->sample_rate;
2167
+                is->audio_clock = is->frame->pts * av_q2d(tb) + (double) is->frame->nb_samples / is->frame->sample_rate;
2168 2168
                 is->audio_clock_serial = is->audio_pkt_temp_serial;
2169 2169
             }
2170 2170
 #ifdef DEBUG
... ...
@@ -2308,6 +2445,8 @@ static int stream_component_open(VideoState *is, int stream_index)
2308 2308
     const char *forced_codec_name = NULL;
2309 2309
     AVDictionary *opts;
2310 2310
     AVDictionaryEntry *t = NULL;
2311
+    int sample_rate, nb_channels;
2312
+    int64_t channel_layout;
2311 2313
     int ret;
2312 2314
 
2313 2315
     if (stream_index < 0 || stream_index >= ic->nb_streams)
... ...
@@ -2363,8 +2502,29 @@ static int stream_component_open(VideoState *is, int stream_index)
2363 2363
     ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
2364 2364
     switch (avctx->codec_type) {
2365 2365
     case AVMEDIA_TYPE_AUDIO:
2366
+#if CONFIG_AVFILTER
2367
+        {
2368
+            AVFilterLink *link;
2369
+
2370
+            is->audio_filter_src.freq           = avctx->sample_rate;
2371
+            is->audio_filter_src.channels       = avctx->channels;
2372
+            is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels);
2373
+            is->audio_filter_src.fmt            = avctx->sample_fmt;
2374
+            if ((ret = configure_audio_filters(is, afilters, 0)) < 0)
2375
+                return ret;
2376
+            link = is->out_audio_filter->inputs[0];
2377
+            sample_rate    = link->sample_rate;
2378
+            nb_channels    = link->channels;
2379
+            channel_layout = link->channel_layout;
2380
+        }
2381
+#else
2382
+        sample_rate    = avctx->sample_rate;
2383
+        nb_channels    = avctx->channels;
2384
+        channel_layout = avctx->channel_layout;
2385
+#endif
2386
+
2366 2387
         /* prepare audio output */
2367
-        if ((ret = audio_open(is, avctx->channel_layout, avctx->channels, avctx->sample_rate, &is->audio_tgt)) < 0)
2388
+        if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0)
2368 2389
             return ret;
2369 2390
         is->audio_hw_buf_size = ret;
2370 2391
         is->audio_src = is->audio_tgt;
... ...
@@ -2436,6 +2596,9 @@ static void stream_component_close(VideoState *is, int stream_index)
2436 2436
             is->rdft = NULL;
2437 2437
             is->rdft_bits = 0;
2438 2438
         }
2439
+#if CONFIG_AVFILTER
2440
+        avfilter_graph_free(&is->agraph);
2441
+#endif
2439 2442
         break;
2440 2443
     case AVMEDIA_TYPE_VIDEO:
2441 2444
         packet_queue_abort(&is->videoq);
... ...
@@ -2825,6 +2988,7 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
2825 2825
     is->video_current_pts_drift = is->audio_current_pts_drift;
2826 2826
     is->audio_clock_serial = -1;
2827 2827
     is->video_clock_serial = -1;
2828
+    is->audio_last_serial = -1;
2828 2829
     is->av_sync_type = av_sync_type;
2829 2830
     is->read_tid     = SDL_CreateThread(read_thread, is);
2830 2831
     if (!is->read_tid) {
... ...
@@ -3233,6 +3397,7 @@ static const OptionDef options[] = {
3233 3233
     { "window_title", OPT_STRING | HAS_ARG, { &window_title }, "set window title", "window title" },
3234 3234
 #if CONFIG_AVFILTER
3235 3235
     { "vf", OPT_STRING | HAS_ARG, { &vfilters }, "set video filters", "filter_graph" },
3236
+    { "af", OPT_STRING | HAS_ARG, { &afilters }, "set audio filters", "filter_graph" },
3236 3237
 #endif
3237 3238
     { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" },
3238 3239
     { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },