[FFmpeg-devel] [PATCH] lavdev/lavfi: add audio filtering support

Stefano Sabatini stefano.sabatini-lala at poste.it
Sun Sep 11 13:40:14 CEST 2011


---
 libavdevice/lavfi.c |   89 ++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 67 insertions(+), 22 deletions(-)

diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index 1c5a3aa..9f777b3 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -33,6 +33,7 @@
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavfilter/avfilter.h"
+#include "libavfilter/internal.h" /* FIXME */
 #include "libavfilter/avfiltergraph.h"
 #include "libavfilter/buffersink.h"
 #include "avdevice.h"
@@ -80,19 +81,17 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
 {
     LavfiContext *lavfi = avctx->priv_data;
     AVFilterInOut *input_links = NULL, *output_links = NULL, *inout;
-    AVFilter *buffersink;
+    AVFilter *buffersink, *abuffersink;
     int *pix_fmts = create_all_formats(PIX_FMT_NB);
+    enum AVMediaType type;
     int ret = 0, i, n;
 
 #define FAIL(ERR) { ret = ERR; goto end; }
 
     avfilter_register_all();
 
-    if (!(buffersink = avfilter_get_by_name("buffersink"))) {
-        av_log(avctx, AV_LOG_ERROR,
-               "Missing required buffersink filter, aborting.\n");
-        FAIL(AVERROR_FILTER_NOT_FOUND);
-    }
+    buffersink = avfilter_get_by_name("buffersink");
+    abuffersink = avfilter_get_by_name("abuffersink");
 
     if (!lavfi->graph_str)
         lavfi->graph_str = av_strdup(avctx->filename);
@@ -143,9 +142,10 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
         }
 
         /* is a video output? */
-        if (inout->filter_ctx->output_pads[inout->pad_idx].type != AVMEDIA_TYPE_VIDEO) {
+        type = inout->filter_ctx->output_pads[inout->pad_idx].type;
+        if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
             av_log(avctx,  AV_LOG_ERROR,
-                   "Output '%s' is not a video output, not yet supported", inout->name);
+                   "Output '%s' is not a video or audio output, not yet supported\n", inout->name);
             FAIL(AVERROR(EINVAL));
         }
 
@@ -173,7 +173,19 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
 
     for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
         AVFilterContext *sink;
+
+        type = inout->filter_ctx->output_pads[inout->pad_idx].type;
+
+        if (type == AVMEDIA_TYPE_VIDEO && ! buffersink ||
+            type == AVMEDIA_TYPE_AUDIO && ! abuffersink) {
+                av_log(avctx, AV_LOG_ERROR, "Missing required buffersink filter, aborting.\n");
+                FAIL(AVERROR_FILTER_NOT_FOUND);
+        }
+
+        if (type == AVMEDIA_TYPE_VIDEO) {
         AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
+        buffersink_params->pixel_fmts = pix_fmts;
+
 #if FF_API_OLD_VSINK_API
         ret = avfilter_graph_create_filter(&sink, buffersink,
                                            inout->name, NULL,
@@ -185,8 +197,25 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
                                            buffersink_params, lavfi->graph);
 #endif
         av_freep(&buffersink_params);
+
         if (ret < 0)
             goto end;
+        } else if (type == AVMEDIA_TYPE_AUDIO) {
+            enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 };
+            const int packing_fmts[] = { AVFILTER_PACKED, -1 };
+            const int64_t *chlayouts = avfilter_all_channel_layouts_int64;
+            AVABufferSinkParams *abuffersink_params = av_abuffersink_params_alloc();
+            abuffersink_params->sample_fmts = sample_fmts;
+            abuffersink_params->packing_fmts = packing_fmts;
+            abuffersink_params->channel_layouts = chlayouts;
+
+            ret = avfilter_graph_create_filter(&sink, abuffersink,
+                                               inout->name, NULL,
+                                               abuffersink_params, lavfi->graph);
+            av_free(abuffersink_params);
+            if (ret < 0)
+                goto end;
+        }
 
         lavfi->sinks[i] = sink;
         if ((ret = avfilter_link(inout->filter_ctx, inout->pad_idx, sink, 0)) < 0)
@@ -211,6 +240,13 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
             st->codec->height     = link->h;
             st       ->sample_aspect_ratio =
             st->codec->sample_aspect_ratio = link->sample_aspect_ratio;
+        } else if (link->type == AVMEDIA_TYPE_AUDIO) {
+            st->codec->codec_id    = CODEC_ID_PCM_S16LE;
+            st->codec->channels    = av_get_channel_layout_nb_channels(link->channel_layout);
+            st->codec->sample_fmt  = link->format;
+            st->codec->sample_rate = link->time_base.den;
+            st->codec->time_base   = link->time_base;
+            st->codec->channel_layout = link->channel_layout;
         }
     }
 
@@ -226,8 +262,8 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
 {
     LavfiContext *lavfi = avctx->priv_data;
     double min_pts = DBL_MAX;
-    int min_pts_sink_idx = 0;
-    AVFilterBufferRef *picref;
+    int stream_idx, min_pts_sink_idx = 0;
+    AVFilterBufferRef *ref;
     AVPicture pict;
     int ret, i, size;
 
@@ -237,10 +273,10 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
         AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
         double d;
         int ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
-                                               &picref, AV_BUFFERSINK_FLAG_PEEK);
+                                               &ref, AV_BUFFERSINK_FLAG_PEEK);
         if (ret < 0)
             return ret;
-        d = av_rescale_q(picref->pts, tb, AV_TIME_BASE_Q);
+        d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
         av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
 
         if (d < min_pts) {
@@ -250,22 +286,31 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     }
     av_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx);
 
-    av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &picref, 0);
+    av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &ref, 0);
+    stream_idx = lavfi->sink_stream_map[min_pts_sink_idx];
 
-    size = avpicture_get_size(picref->format, picref->video->w, picref->video->h);
+    if (ref->video) {
+    size = avpicture_get_size(ref->format, ref->video->w, ref->video->h);
     if ((ret = av_new_packet(pkt, size)) < 0)
         return ret;
 
-    memcpy(pict.data,     picref->data,     4*sizeof(picref->data[0]));
-    memcpy(pict.linesize, picref->linesize, 4*sizeof(picref->linesize[0]));
+    memcpy(pict.data,     ref->data,     4*sizeof(ref->data[0]));
+    memcpy(pict.linesize, ref->linesize, 4*sizeof(ref->linesize[0]));
+
+    avpicture_layout(&pict, ref->format, ref->video->w,
+                     ref->video->h, pkt->data, size);
+    } else if (ref->audio) {
+        size = ref->linesize[0];
+        if ((ret = av_new_packet(pkt, size)) < 0)
+            return ret;
+        memcpy(pkt->data, ref->data[0], size);
+    }
 
-    avpicture_layout(&pict, picref->format, picref->video->w,
-                     picref->video->h, pkt->data, size);
-    pkt->stream_index = lavfi->sink_stream_map[min_pts_sink_idx];
-    pkt->pts = picref->pts;
-    pkt->pos = picref->pos;
+    pkt->stream_index = stream_idx;
+    pkt->pts = ref->pts;
+    pkt->pos = ref->pos;
     pkt->size = size;
-    avfilter_unref_buffer(picref);
+    avfilter_unref_buffer(ref);
 
     return size;
 }
-- 
1.7.2.5



More information about the ffmpeg-devel mailing list