{
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);
}
/* 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));
}
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,
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)
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;
}
}
{
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;
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) {
}
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;
}