lavdev/lavfi: add audio support
This commit is contained in:
		
				
					committed by
					
						
						Stefano Sabatini
					
				
			
			
				
	
			
			
			
						parent
						
							3ee0bedcc0
						
					
				
				
					commit
					4893c204c8
				
			@@ -56,6 +56,7 @@ easier to use. The changes are:
 | 
				
			|||||||
- Prores decoder
 | 
					- Prores decoder
 | 
				
			||||||
- BIN/XBIN/ADF/IDF text file decoder
 | 
					- BIN/XBIN/ADF/IDF text file decoder
 | 
				
			||||||
- aconvert audio filter added
 | 
					- aconvert audio filter added
 | 
				
			||||||
 | 
					- audio support to lavfi input device added
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
version 0.8:
 | 
					version 0.8:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -266,6 +266,21 @@ Create three different video test filtered sources and play them:
 | 
				
			|||||||
@example
 | 
					@example
 | 
				
			||||||
ffplay -f lavfi -graph "testsrc [out0]; testsrc,hflip [out1]; testsrc,negate [out2]" test3
 | 
					ffplay -f lavfi -graph "testsrc [out0]; testsrc,hflip [out1]; testsrc,negate [out2]" test3
 | 
				
			||||||
@end example
 | 
					@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
 | 
					@end itemize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@section libdc1394
 | 
					@section libdc1394
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define LIBAVDEVICE_VERSION_MAJOR 53
 | 
					#define LIBAVDEVICE_VERSION_MAJOR 53
 | 
				
			||||||
#define LIBAVDEVICE_VERSION_MINOR  3
 | 
					#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, \
 | 
					#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
 | 
				
			||||||
                                               LIBAVDEVICE_VERSION_MINOR, \
 | 
					                                               LIBAVDEVICE_VERSION_MINOR, \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,19 +80,17 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    LavfiContext *lavfi = avctx->priv_data;
 | 
					    LavfiContext *lavfi = avctx->priv_data;
 | 
				
			||||||
    AVFilterInOut *input_links = NULL, *output_links = NULL, *inout;
 | 
					    AVFilterInOut *input_links = NULL, *output_links = NULL, *inout;
 | 
				
			||||||
    AVFilter *buffersink;
 | 
					    AVFilter *buffersink, *abuffersink;
 | 
				
			||||||
    int *pix_fmts = create_all_formats(PIX_FMT_NB);
 | 
					    int *pix_fmts = create_all_formats(PIX_FMT_NB);
 | 
				
			||||||
 | 
					    enum AVMediaType type;
 | 
				
			||||||
    int ret = 0, i, n;
 | 
					    int ret = 0, i, n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FAIL(ERR) { ret = ERR; goto end; }
 | 
					#define FAIL(ERR) { ret = ERR; goto end; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    avfilter_register_all();
 | 
					    avfilter_register_all();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!(buffersink = avfilter_get_by_name("buffersink"))) {
 | 
					    buffersink = avfilter_get_by_name("buffersink");
 | 
				
			||||||
        av_log(avctx, AV_LOG_ERROR,
 | 
					    abuffersink = avfilter_get_by_name("abuffersink");
 | 
				
			||||||
               "Missing required buffersink filter, aborting.\n");
 | 
					 | 
				
			||||||
        FAIL(AVERROR_FILTER_NOT_FOUND);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!lavfi->graph_str)
 | 
					    if (!lavfi->graph_str)
 | 
				
			||||||
        lavfi->graph_str = av_strdup(avctx->filename);
 | 
					        lavfi->graph_str = av_strdup(avctx->filename);
 | 
				
			||||||
@@ -143,9 +141,10 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* is a video output? */
 | 
					        /* 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,
 | 
					            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));
 | 
					            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) {
 | 
					    for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
 | 
				
			||||||
        AVFilterContext *sink;
 | 
					        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();
 | 
					        AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
 | 
				
			||||||
 | 
					        buffersink_params->pixel_fmts = pix_fmts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if FF_API_OLD_VSINK_API
 | 
					#if FF_API_OLD_VSINK_API
 | 
				
			||||||
        ret = avfilter_graph_create_filter(&sink, buffersink,
 | 
					        ret = avfilter_graph_create_filter(&sink, buffersink,
 | 
				
			||||||
                                           inout->name, NULL,
 | 
					                                           inout->name, NULL,
 | 
				
			||||||
@@ -185,8 +196,25 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx,
 | 
				
			|||||||
                                           buffersink_params, lavfi->graph);
 | 
					                                           buffersink_params, lavfi->graph);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        av_freep(&buffersink_params);
 | 
					        av_freep(&buffersink_params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (ret < 0)
 | 
					        if (ret < 0)
 | 
				
			||||||
            goto end;
 | 
					            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;
 | 
					        lavfi->sinks[i] = sink;
 | 
				
			||||||
        if ((ret = avfilter_link(inout->filter_ctx, inout->pad_idx, sink, 0)) < 0)
 | 
					        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->codec->height     = link->h;
 | 
				
			||||||
            st       ->sample_aspect_ratio =
 | 
					            st       ->sample_aspect_ratio =
 | 
				
			||||||
            st->codec->sample_aspect_ratio = link->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;
 | 
					    LavfiContext *lavfi = avctx->priv_data;
 | 
				
			||||||
    double min_pts = DBL_MAX;
 | 
					    double min_pts = DBL_MAX;
 | 
				
			||||||
    int min_pts_sink_idx = 0;
 | 
					    int stream_idx, min_pts_sink_idx = 0;
 | 
				
			||||||
    AVFilterBufferRef *picref;
 | 
					    AVFilterBufferRef *ref;
 | 
				
			||||||
    AVPicture pict;
 | 
					    AVPicture pict;
 | 
				
			||||||
    int ret, i, size;
 | 
					    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;
 | 
					        AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
 | 
				
			||||||
        double d;
 | 
					        double d;
 | 
				
			||||||
        int ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
 | 
					        int ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
 | 
				
			||||||
                                               &picref, AV_BUFFERSINK_FLAG_PEEK);
 | 
					                                               &ref, AV_BUFFERSINK_FLAG_PEEK);
 | 
				
			||||||
        if (ret < 0)
 | 
					        if (ret < 0)
 | 
				
			||||||
            return ret;
 | 
					            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);
 | 
					        av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (d < min_pts) {
 | 
					        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_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)
 | 
					    if ((ret = av_new_packet(pkt, size)) < 0)
 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memcpy(pict.data,     picref->data,     4*sizeof(picref->data[0]));
 | 
					    memcpy(pict.data,     ref->data,     4*sizeof(ref->data[0]));
 | 
				
			||||||
    memcpy(pict.linesize, picref->linesize, 4*sizeof(picref->linesize[0]));
 | 
					    memcpy(pict.linesize, ref->linesize, 4*sizeof(ref->linesize[0]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    avpicture_layout(&pict, picref->format, picref->video->w,
 | 
					    avpicture_layout(&pict, ref->format, ref->video->w,
 | 
				
			||||||
                     picref->video->h, pkt->data, size);
 | 
					                     ref->video->h, pkt->data, size);
 | 
				
			||||||
    pkt->stream_index = lavfi->sink_stream_map[min_pts_sink_idx];
 | 
					    } else if (ref->audio) {
 | 
				
			||||||
    pkt->pts = picref->pts;
 | 
					        size = ref->linesize[0];
 | 
				
			||||||
    pkt->pos = picref->pos;
 | 
					        if ((ret = av_new_packet(pkt, size)) < 0)
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        memcpy(pkt->data, ref->data[0], size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pkt->stream_index = stream_idx;
 | 
				
			||||||
 | 
					    pkt->pts = ref->pts;
 | 
				
			||||||
 | 
					    pkt->pos = ref->pos;
 | 
				
			||||||
    pkt->size = size;
 | 
					    pkt->size = size;
 | 
				
			||||||
    avfilter_unref_buffer(picref);
 | 
					    avfilter_unref_buffer(ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return size;
 | 
					    return size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user