... | ... |
@@ -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 |
} |