diff options
author | Stefano Sabatini <stefano.sabatini-lala@poste.it> | 2011-08-18 15:39:24 +0200 |
---|---|---|
committer | Stefano Sabatini <stefasab@gmail.com> | 2011-09-16 21:22:05 +0200 |
commit | 4893c204c8e94d9e97acb8b48f63ba8d5dd50135 (patch) | |
tree | 8a5fe55e0eac3ce564f6a4a39c5539dc7a3c1e77 | |
parent | 3ee0bedcc00650b0827833e3fa90e76d10cf6e01 (diff) | |
download | ffmpeg-4893c204c8e94d9e97acb8b48f63ba8d5dd50135.tar.gz |
lavdev/lavfi: add audio support
-rw-r--r-- | Changelog | 1 | ||||
-rw-r--r-- | doc/indevs.texi | 15 | ||||
-rw-r--r-- | libavdevice/avdevice.h | 2 | ||||
-rw-r--r-- | libavdevice/lavfi.c | 88 |
4 files changed, 83 insertions, 23 deletions
@@ -56,6 +56,7 @@ easier to use. The changes are: - Prores decoder - BIN/XBIN/ADF/IDF text file decoder - aconvert audio filter added +- audio support to lavfi input device added version 0.8: diff --git a/doc/indevs.texi b/doc/indevs.texi index a3711857bf..79f786f8e0 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -266,6 +266,21 @@ Create three different video test filtered sources and play them: @example ffplay -f lavfi -graph "testsrc [out0]; testsrc,hflip [out1]; testsrc,negate [out2]" test3 @end example + +@item +Read an audio stream from a file using the amovie source and play it +back with @file{ffplay}: +@example +ffplay -f lavfi "amovie=test.wav" +@end example + +@item +Read an audio stream and a video stream and play it back with +@file{ffplay}: +@example +ffplay -f lavfi "movie=test.avi[out0];amovie=test.wav[out1]" +@end example + @end itemize @section libdc1394 diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index ac7916e0e4..8b75d5cda8 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -24,7 +24,7 @@ #define LIBAVDEVICE_VERSION_MAJOR 53 #define LIBAVDEVICE_VERSION_MINOR 3 -#define LIBAVDEVICE_VERSION_MICRO 2 +#define LIBAVDEVICE_VERSION_MICRO 3 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 1c5a3aaee4..42079e4d0a 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -80,19 +80,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 +141,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 +172,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 +196,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; + 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 +239,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->sample_rate; + st->codec->time_base = link->time_base; + st->codec->channel_layout = link->channel_layout; } } @@ -226,8 +261,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 +272,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 +285,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; } |