Browse code

lavdev/lavfi: add audio support

Stefano Sabatini authored on 2011/08/18 22:39:24
Showing 4 changed files
... ...
@@ -56,6 +56,7 @@ easier to use. The changes are:
56 56
 - Prores decoder
57 57
 - BIN/XBIN/ADF/IDF text file decoder
58 58
 - aconvert audio filter added
59
+- audio support to lavfi input device added
59 60
 
60 61
 
61 62
 version 0.8:
... ...
@@ -266,6 +266,21 @@ Create three different video test filtered sources and play them:
266 266
 @example
267 267
 ffplay -f lavfi -graph "testsrc [out0]; testsrc,hflip [out1]; testsrc,negate [out2]" test3
268 268
 @end example
269
+
270
+@item
271
+Read an audio stream from a file using the amovie source and play it
272
+back with @file{ffplay}:
273
+@example
274
+ffplay -f lavfi "amovie=test.wav"
275
+@end example
276
+
277
+@item
278
+Read an audio stream and a video stream and play it back with
279
+@file{ffplay}:
280
+@example
281
+ffplay -f lavfi "movie=test.avi[out0];amovie=test.wav[out1]"
282
+@end example
283
+
269 284
 @end itemize
270 285
 
271 286
 @section libdc1394
... ...
@@ -24,7 +24,7 @@
24 24
 
25 25
 #define LIBAVDEVICE_VERSION_MAJOR 53
26 26
 #define LIBAVDEVICE_VERSION_MINOR  3
27
-#define LIBAVDEVICE_VERSION_MICRO  2
27
+#define LIBAVDEVICE_VERSION_MICRO  3
28 28
 
29 29
 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
30 30
                                                LIBAVDEVICE_VERSION_MINOR, \
... ...
@@ -80,19 +80,17 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
80 80
 {
81 81
     LavfiContext *lavfi = avctx->priv_data;
82 82
     AVFilterInOut *input_links = NULL, *output_links = NULL, *inout;
83
-    AVFilter *buffersink;
83
+    AVFilter *buffersink, *abuffersink;
84 84
     int *pix_fmts = create_all_formats(PIX_FMT_NB);
85
+    enum AVMediaType type;
85 86
     int ret = 0, i, n;
86 87
 
87 88
 #define FAIL(ERR) { ret = ERR; goto end; }
88 89
 
89 90
     avfilter_register_all();
90 91
 
91
-    if (!(buffersink = avfilter_get_by_name("buffersink"))) {
92
-        av_log(avctx, AV_LOG_ERROR,
93
-               "Missing required buffersink filter, aborting.\n");
94
-        FAIL(AVERROR_FILTER_NOT_FOUND);
95
-    }
92
+    buffersink = avfilter_get_by_name("buffersink");
93
+    abuffersink = avfilter_get_by_name("abuffersink");
96 94
 
97 95
     if (!lavfi->graph_str)
98 96
         lavfi->graph_str = av_strdup(avctx->filename);
... ...
@@ -143,9 +141,10 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
143 143
         }
144 144
 
145 145
         /* is a video output? */
146
-        if (inout->filter_ctx->output_pads[inout->pad_idx].type != AVMEDIA_TYPE_VIDEO) {
146
+        type = inout->filter_ctx->output_pads[inout->pad_idx].type;
147
+        if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
147 148
             av_log(avctx,  AV_LOG_ERROR,
148
-                   "Output '%s' is not a video output, not yet supported", inout->name);
149
+                   "Output '%s' is not a video or audio output, not yet supported\n", inout->name);
149 150
             FAIL(AVERROR(EINVAL));
150 151
         }
151 152
 
... ...
@@ -173,7 +172,19 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
173 173
 
174 174
     for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
175 175
         AVFilterContext *sink;
176
+
177
+        type = inout->filter_ctx->output_pads[inout->pad_idx].type;
178
+
179
+        if (type == AVMEDIA_TYPE_VIDEO && ! buffersink ||
180
+            type == AVMEDIA_TYPE_AUDIO && ! abuffersink) {
181
+                av_log(avctx, AV_LOG_ERROR, "Missing required buffersink filter, aborting.\n");
182
+                FAIL(AVERROR_FILTER_NOT_FOUND);
183
+        }
184
+
185
+        if (type == AVMEDIA_TYPE_VIDEO) {
176 186
         AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
187
+        buffersink_params->pixel_fmts = pix_fmts;
188
+
177 189
 #if FF_API_OLD_VSINK_API
178 190
         ret = avfilter_graph_create_filter(&sink, buffersink,
179 191
                                            inout->name, NULL,
... ...
@@ -185,8 +196,25 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
185 185
                                            buffersink_params, lavfi->graph);
186 186
 #endif
187 187
         av_freep(&buffersink_params);
188
+
188 189
         if (ret < 0)
189 190
             goto end;
191
+        } else if (type == AVMEDIA_TYPE_AUDIO) {
192
+            enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 };
193
+            const int packing_fmts[] = { AVFILTER_PACKED, -1 };
194
+            const int64_t *chlayouts = avfilter_all_channel_layouts;
195
+            AVABufferSinkParams *abuffersink_params = av_abuffersink_params_alloc();
196
+            abuffersink_params->sample_fmts = sample_fmts;
197
+            abuffersink_params->packing_fmts = packing_fmts;
198
+            abuffersink_params->channel_layouts = chlayouts;
199
+
200
+            ret = avfilter_graph_create_filter(&sink, abuffersink,
201
+                                               inout->name, NULL,
202
+                                               abuffersink_params, lavfi->graph);
203
+            av_free(abuffersink_params);
204
+            if (ret < 0)
205
+                goto end;
206
+        }
190 207
 
191 208
         lavfi->sinks[i] = sink;
192 209
         if ((ret = avfilter_link(inout->filter_ctx, inout->pad_idx, sink, 0)) < 0)
... ...
@@ -211,6 +239,13 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
211 211
             st->codec->height     = link->h;
212 212
             st       ->sample_aspect_ratio =
213 213
             st->codec->sample_aspect_ratio = link->sample_aspect_ratio;
214
+        } else if (link->type == AVMEDIA_TYPE_AUDIO) {
215
+            st->codec->codec_id    = CODEC_ID_PCM_S16LE;
216
+            st->codec->channels    = av_get_channel_layout_nb_channels(link->channel_layout);
217
+            st->codec->sample_fmt  = link->format;
218
+            st->codec->sample_rate = link->sample_rate;
219
+            st->codec->time_base   = link->time_base;
220
+            st->codec->channel_layout = link->channel_layout;
214 221
         }
215 222
     }
216 223
 
... ...
@@ -226,8 +261,8 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
226 226
 {
227 227
     LavfiContext *lavfi = avctx->priv_data;
228 228
     double min_pts = DBL_MAX;
229
-    int min_pts_sink_idx = 0;
230
-    AVFilterBufferRef *picref;
229
+    int stream_idx, min_pts_sink_idx = 0;
230
+    AVFilterBufferRef *ref;
231 231
     AVPicture pict;
232 232
     int ret, i, size;
233 233
 
... ...
@@ -237,10 +272,10 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
237 237
         AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
238 238
         double d;
239 239
         int ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
240
-                                               &picref, AV_BUFFERSINK_FLAG_PEEK);
240
+                                               &ref, AV_BUFFERSINK_FLAG_PEEK);
241 241
         if (ret < 0)
242 242
             return ret;
243
-        d = av_rescale_q(picref->pts, tb, AV_TIME_BASE_Q);
243
+        d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
244 244
         av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
245 245
 
246 246
         if (d < min_pts) {
... ...
@@ -250,22 +285,31 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
250 250
     }
251 251
     av_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx);
252 252
 
253
-    av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &picref, 0);
253
+    av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &ref, 0);
254
+    stream_idx = lavfi->sink_stream_map[min_pts_sink_idx];
254 255
 
255
-    size = avpicture_get_size(picref->format, picref->video->w, picref->video->h);
256
+    if (ref->video) {
257
+    size = avpicture_get_size(ref->format, ref->video->w, ref->video->h);
256 258
     if ((ret = av_new_packet(pkt, size)) < 0)
257 259
         return ret;
258 260
 
259
-    memcpy(pict.data,     picref->data,     4*sizeof(picref->data[0]));
260
-    memcpy(pict.linesize, picref->linesize, 4*sizeof(picref->linesize[0]));
261
+    memcpy(pict.data,     ref->data,     4*sizeof(ref->data[0]));
262
+    memcpy(pict.linesize, ref->linesize, 4*sizeof(ref->linesize[0]));
263
+
264
+    avpicture_layout(&pict, ref->format, ref->video->w,
265
+                     ref->video->h, pkt->data, size);
266
+    } else if (ref->audio) {
267
+        size = ref->linesize[0];
268
+        if ((ret = av_new_packet(pkt, size)) < 0)
269
+            return ret;
270
+        memcpy(pkt->data, ref->data[0], size);
271
+    }
261 272
 
262
-    avpicture_layout(&pict, picref->format, picref->video->w,
263
-                     picref->video->h, pkt->data, size);
264
-    pkt->stream_index = lavfi->sink_stream_map[min_pts_sink_idx];
265
-    pkt->pts = picref->pts;
266
-    pkt->pos = picref->pos;
273
+    pkt->stream_index = stream_idx;
274
+    pkt->pts = ref->pts;
275
+    pkt->pos = ref->pos;
267 276
     pkt->size = size;
268
-    avfilter_unref_buffer(picref);
277
+    avfilter_unref_buffer(ref);
269 278
 
270 279
     return size;
271 280
 }