[FFmpeg-devel] [PATCH 9/9] ffplay: add -af option

Stefano Sabatini stefasab at gmail.com
Fri Jun 22 12:11:23 CEST 2012


---
 doc/ffplay.texi |    6 +++
 ffplay.c        |  133 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 130 insertions(+), 9 deletions(-)

diff --git a/doc/ffplay.texi b/doc/ffplay.texi
index e2bded7..8ea3b25 100644
--- a/doc/ffplay.texi
+++ b/doc/ffplay.texi
@@ -83,6 +83,12 @@ the input video.
 Use the option "-filters" to show all the available filters (including
 also sources and sinks).
 
+ at item -af @var{filter_graph}
+ at var{filter_graph} is a description of the filter graph to apply to
+the input audio.
+Use the option "-filters" to show all the available filters (including
+sources and sinks).
+
 @item -i @var{input_file}
 Read @var{input_file}.
 @end table
diff --git a/ffplay.c b/ffplay.c
index cb234f3..c8663f6 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -110,6 +110,7 @@ typedef struct VideoPicture {
 
 #if CONFIG_AVFILTER
     AVFilterBufferRef *picref;
+    AVFilterBufferRef *samplesref;
 #endif
 } VideoPicture;
 
@@ -233,6 +234,10 @@ typedef struct VideoState {
     AVFilterGraph *graph;
     int use_dr1;
     FrameBuffer *buffer_pool;
+
+    AVFilterContext *in_audio_filter;           ///<the first filter in the audio chain
+    AVFilterContext *out_audio_filter;          ///<the last filter in the audio chain
+    AVFilterGraph *agraph;
 #endif
 
     int refresh;
@@ -289,6 +294,7 @@ static const char *video_codec_name;
 static int rdftspeed = 20;
 #if CONFIG_AVFILTER
 static char *vfilters = NULL;
+static char *afilters = NULL;
 #endif
 
 /* current context */
@@ -1634,6 +1640,65 @@ static int configure_video_filters(VideoState *is, const char *vfilters)
     return ret;
 }
 
+static int configure_audio_filters(VideoState *is)
+{
+    static const enum PixelFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, PIX_FMT_NONE };
+    int64_t layouts[] = { 0, PIX_FMT_NONE };
+    AVFilterContext *filt_asrc = NULL, *filt_asink = NULL;
+    AVCodecContext *avctx = is->audio_st->codec;
+    char abuffer_args[256];
+    AVABufferSinkParams *abuffersink_params = av_abuffersink_params_alloc();
+    int ret;
+
+    is->agraph = avfilter_graph_alloc();
+
+    if (!avctx->channel_layout)
+        avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
+    layouts[0] = avctx->channel_layout;
+
+    snprintf(abuffer_args, sizeof(abuffer_args), "sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,
+             avctx->sample_rate,
+             av_get_sample_fmt_name(avctx->sample_fmt),
+             avctx->channel_layout);
+    ret = avfilter_graph_create_filter(&filt_asrc,
+                                       avfilter_get_by_name("abuffer"), "ffplay_abuffer",
+                                       abuffer_args, NULL, is->agraph);
+    if (ret < 0) goto fail;
+
+    abuffersink_params->sample_fmts     = sample_fmts;
+    abuffersink_params->channel_layouts = layouts;
+
+    ret = avfilter_graph_create_filter(&filt_asink,
+                                       avfilter_get_by_name("abuffersink"), "ffplay_abuffersink",
+                                       NULL, abuffersink_params, is->agraph);
+    if (ret < 0) goto fail;
+
+    if (afilters) {
+        AVFilterInOut *inputs  = av_malloc(sizeof(AVFilterInOut));
+        AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
+
+        *inputs  = (AVFilterInOut){ av_strdup("out"), filt_asink, 0, NULL };
+        *outputs = (AVFilterInOut){ av_strdup("in" ), filt_asrc, 0, NULL };
+
+        if ((ret = avfilter_graph_parse(is->agraph, afilters, &inputs, &outputs, NULL)) < 0)
+            goto fail;
+        av_freep(&afilters);
+    } else {
+        if ((ret = avfilter_link(filt_asrc, 0, filt_asink, 0)) < 0)
+            goto fail;
+    }
+
+    if ((ret = avfilter_graph_config(is->agraph, NULL)) < 0)
+        goto fail;
+    is->in_audio_filter = filt_asrc;
+    is->out_audio_filter = filt_asink;
+    return 0;
+
+fail:
+    avfilter_graph_free(&is->agraph);
+    return ret;
+}
+
 #endif  /* CONFIG_AVFILTER */
 
 static int video_thread(void *arg)
@@ -2058,6 +2123,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
 {
     VideoState *is = opaque;
     int audio_size, len1;
+    AVFilterBufferRef av_unused *samplesref;
     int bytes_per_sec;
     int frame_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, 1, is->audio_tgt.fmt, 1);
     double pts;
@@ -2072,6 +2138,25 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
                is->audio_buf      = is->silence_buf;
                is->audio_buf_size = sizeof(is->silence_buf) / frame_size * frame_size;
            } else {
+#if CONFIG_AVFILTER
+                const AVCodecContext *avctx = is->audio_st->codec;
+
+                /* inject the buffer into the filter graph
+                 * note that AVFilterBufferRef stores pts with timebase 1/samplerate */
+                av_buffersrc_add_frame(is->in_audio_filter, is->frame, 0);
+
+                if (av_buffersink_get_buffer_ref(is->out_audio_filter,
+                                                 &samplesref, 0) < 0)
+                    return;
+
+                pts = samplesref->pts / (double)avctx->sample_rate;
+
+                is->audio_buf = samplesref->data[0];
+                audio_size = samplesref->audio->nb_samples *
+                    av_get_channel_layout_nb_channels(samplesref->audio->channel_layout) *
+                    av_get_bytes_per_sample(samplesref->format);
+#endif
+
                if (is->show_mode != SHOW_MODE_VIDEO)
                    update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
                is->audio_buf_size = audio_size;
@@ -2155,6 +2240,10 @@ static int stream_component_open(VideoState *is, int stream_index)
     AVCodec *codec;
     AVDictionary *opts;
     AVDictionaryEntry *t = NULL;
+    int av_unused ret;
+    int sample_rate, nb_channels;
+    int64_t channel_layout;
+    int audio_hw_buf_size;
 
     if (stream_index < 0 || stream_index >= ic->nb_streams)
         return -1;
@@ -2199,15 +2288,6 @@ static int stream_component_open(VideoState *is, int stream_index)
         return AVERROR_OPTION_NOT_FOUND;
     }
 
-    /* prepare audio output */
-    if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
-        int audio_hw_buf_size = audio_open(is, avctx->channel_layout, avctx->channels, avctx->sample_rate, &is->audio_src);
-        if (audio_hw_buf_size < 0)
-            return -1;
-        is->audio_hw_buf_size = audio_hw_buf_size;
-        is->audio_tgt = is->audio_src;
-    }
-
     ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
@@ -2225,6 +2305,37 @@ static int stream_component_open(VideoState *is, int stream_index)
 
         memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
         memset(&is->audio_pkt_temp, 0, sizeof(is->audio_pkt_temp));
+
+
+       if (avctx->sample_rate <= 0 || avctx->channels <= 0){
+           fprintf(stderr, "Invalid sample rate or channel count\n");
+           return AVERROR(EINVAL);
+        }
+
+#if CONFIG_AVFILTER
+        if ((ret = configure_audio_filters(is)) < 0)
+            return ret;
+#endif
+
+        if (CONFIG_AVFILTER &&
+            is->out_audio_filter && is->out_audio_filter->inputs[0]) {
+            AVFilterLink *link = is->out_audio_filter->inputs[0];
+            sample_rate = link->sample_rate;
+            nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+            channel_layout = link->channel_layout;
+        } else {
+            sample_rate = avctx->sample_rate;
+            nb_channels = avctx->channels;
+            channel_layout = avctx->channel_layout;
+        }
+
+        /* prepare audio output */
+        audio_hw_buf_size = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_src);
+        if (audio_hw_buf_size < 0)
+            return -1;
+        is->audio_hw_buf_size = audio_hw_buf_size;
+        is->audio_tgt = is->audio_src;
+
         packet_queue_start(&is->audioq);
         SDL_PauseAudio(0);
         break;
@@ -2277,6 +2388,9 @@ static void stream_component_close(VideoState *is, int stream_index)
             is->rdft = NULL;
             is->rdft_bits = 0;
         }
+#if CONFIG_AVFILTER
+        avfilter_graph_free(&is->agraph);
+#endif
         break;
     case AVMEDIA_TYPE_VIDEO:
         packet_queue_abort(&is->videoq);
@@ -3002,6 +3116,7 @@ static const OptionDef options[] = {
     { "window_title", OPT_STRING | HAS_ARG, { (void*)&window_title }, "set window title", "window title" },
 #if CONFIG_AVFILTER
     { "vf", OPT_STRING | HAS_ARG, { (void*)&vfilters }, "video filters", "filter list" },
+    { "af", OPT_STRING | HAS_ARG, {(void*)&afilters}, "audio filters", "filter list" },
 #endif
     { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { (void*)&rdftspeed }, "rdft speed", "msecs" },
     { "showmode", HAS_ARG, {(void*)opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list