]> git.sesse.net Git - ffmpeg/blob - libavdevice/lavfi.c
Merge commit '4c995fafd861f537360b3717901cdbed6a6844e7'
[ffmpeg] / libavdevice / lavfi.c
1 /*
2  * Copyright (c) 2011 Stefano Sabatini
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 /**
22  * @file
23  * libavfilter virtual input device
24  */
25
26 /* #define DEBUG */
27
28 #include "float.h"              /* DBL_MIN, DBL_MAX */
29
30 #include "libavutil/log.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/opt.h"
33 #include "libavutil/parseutils.h"
34 #include "libavutil/pixdesc.h"
35 #include "libavutil/audioconvert.h"
36 #include "libavfilter/avfilter.h"
37 #include "libavfilter/avfiltergraph.h"
38 #include "libavfilter/buffersink.h"
39 #include "libavformat/internal.h"
40 #include "avdevice.h"
41
42 typedef struct {
43     AVClass *class;          ///< class for private options
44     char          *graph_str;
45     char          *dump_graph;
46     AVFilterGraph *graph;
47     AVFilterContext **sinks;
48     int *sink_stream_map;
49     int *sink_eof;
50     int *stream_sink_map;
51 } LavfiContext;
52
53 static int *create_all_formats(int n)
54 {
55     int i, j, *fmts, count = 0;
56
57     for (i = 0; i < n; i++) {
58         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
59         if (!(desc->flags & PIX_FMT_HWACCEL))
60             count++;
61     }
62
63     if (!(fmts = av_malloc((count+1) * sizeof(int))))
64         return NULL;
65     for (j = 0, i = 0; i < n; i++) {
66         const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
67         if (!(desc->flags & PIX_FMT_HWACCEL))
68             fmts[j++] = i;
69     }
70     fmts[j] = -1;
71     return fmts;
72 }
73
74 av_cold static int lavfi_read_close(AVFormatContext *avctx)
75 {
76     LavfiContext *lavfi = avctx->priv_data;
77
78     av_freep(&lavfi->sink_stream_map);
79     av_freep(&lavfi->sink_eof);
80     av_freep(&lavfi->stream_sink_map);
81     av_freep(&lavfi->sinks);
82     avfilter_graph_free(&lavfi->graph);
83
84     return 0;
85 }
86
87 av_cold static int lavfi_read_header(AVFormatContext *avctx)
88 {
89     LavfiContext *lavfi = avctx->priv_data;
90     AVFilterInOut *input_links = NULL, *output_links = NULL, *inout;
91     AVFilter *buffersink, *abuffersink;
92     int *pix_fmts = create_all_formats(AV_PIX_FMT_NB);
93     enum AVMediaType type;
94     int ret = 0, i, n;
95
96 #define FAIL(ERR) { ret = ERR; goto end; }
97
98     if (!pix_fmts)
99         FAIL(AVERROR(ENOMEM));
100
101     avfilter_register_all();
102
103     buffersink = avfilter_get_by_name("ffbuffersink");
104     abuffersink = avfilter_get_by_name("ffabuffersink");
105
106     if (!lavfi->graph_str)
107         lavfi->graph_str = av_strdup(avctx->filename);
108
109     /* parse the graph, create a stream for each open output */
110     if (!(lavfi->graph = avfilter_graph_alloc()))
111         FAIL(AVERROR(ENOMEM));
112
113     if ((ret = avfilter_graph_parse(lavfi->graph, lavfi->graph_str,
114                                     &input_links, &output_links, avctx)) < 0)
115         FAIL(ret);
116
117     if (input_links) {
118         av_log(avctx, AV_LOG_ERROR,
119                "Open inputs in the filtergraph are not acceptable\n");
120         FAIL(AVERROR(EINVAL));
121     }
122
123     /* count the outputs */
124     for (n = 0, inout = output_links; inout; n++, inout = inout->next);
125
126     if (!(lavfi->sink_stream_map = av_malloc(sizeof(int) * n)))
127         FAIL(AVERROR(ENOMEM));
128     if (!(lavfi->sink_eof = av_mallocz(sizeof(int) * n)))
129         FAIL(AVERROR(ENOMEM));
130     if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n)))
131         FAIL(AVERROR(ENOMEM));
132
133     for (i = 0; i < n; i++)
134         lavfi->stream_sink_map[i] = -1;
135
136     /* parse the output link names - they need to be of the form out0, out1, ...
137      * create a mapping between them and the streams */
138     for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
139         int stream_idx;
140         if (!strcmp(inout->name, "out"))
141             stream_idx = 0;
142         else if (sscanf(inout->name, "out%d\n", &stream_idx) != 1) {
143             av_log(avctx,  AV_LOG_ERROR,
144                    "Invalid outpad name '%s'\n", inout->name);
145             FAIL(AVERROR(EINVAL));
146         }
147
148         if ((unsigned)stream_idx >= n) {
149             av_log(avctx, AV_LOG_ERROR,
150                    "Invalid index was specified in output '%s', "
151                    "must be a non-negative value < %d\n",
152                    inout->name, n);
153             FAIL(AVERROR(EINVAL));
154         }
155
156         /* is an audio or video output? */
157         type = inout->filter_ctx->output_pads[inout->pad_idx].type;
158         if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
159             av_log(avctx,  AV_LOG_ERROR,
160                    "Output '%s' is not a video or audio output, not yet supported\n", inout->name);
161             FAIL(AVERROR(EINVAL));
162         }
163
164         if (lavfi->stream_sink_map[stream_idx] != -1) {
165             av_log(avctx,  AV_LOG_ERROR,
166                    "An output with stream index %d was already specified\n",
167                    stream_idx);
168             FAIL(AVERROR(EINVAL));
169         }
170         lavfi->sink_stream_map[i] = stream_idx;
171         lavfi->stream_sink_map[stream_idx] = i;
172     }
173
174     /* for each open output create a corresponding stream */
175     for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
176         AVStream *st;
177         if (!(st = avformat_new_stream(avctx, NULL)))
178             FAIL(AVERROR(ENOMEM));
179         st->id = i;
180     }
181
182     /* create a sink for each output and connect them to the graph */
183     lavfi->sinks = av_malloc(sizeof(AVFilterContext *) * avctx->nb_streams);
184     if (!lavfi->sinks)
185         FAIL(AVERROR(ENOMEM));
186
187     for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
188         AVFilterContext *sink;
189
190         type = inout->filter_ctx->output_pads[inout->pad_idx].type;
191
192         if (type == AVMEDIA_TYPE_VIDEO && ! buffersink ||
193             type == AVMEDIA_TYPE_AUDIO && ! abuffersink) {
194                 av_log(avctx, AV_LOG_ERROR, "Missing required buffersink filter, aborting.\n");
195                 FAIL(AVERROR_FILTER_NOT_FOUND);
196         }
197
198         if (type == AVMEDIA_TYPE_VIDEO) {
199             AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
200
201             buffersink_params->pixel_fmts = pix_fmts;
202             ret = avfilter_graph_create_filter(&sink, buffersink,
203                                                inout->name, NULL,
204                                                buffersink_params, lavfi->graph);
205             av_freep(&buffersink_params);
206
207             if (ret < 0)
208                 goto end;
209         } else if (type == AVMEDIA_TYPE_AUDIO) {
210             enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_U8,
211                                                   AV_SAMPLE_FMT_S16,
212                                                   AV_SAMPLE_FMT_S32,
213                                                   AV_SAMPLE_FMT_FLT,
214                                                   AV_SAMPLE_FMT_DBL, -1 };
215             AVABufferSinkParams *abuffersink_params = av_abuffersink_params_alloc();
216             abuffersink_params->sample_fmts = sample_fmts;
217
218             ret = avfilter_graph_create_filter(&sink, abuffersink,
219                                                inout->name, NULL,
220                                                abuffersink_params, lavfi->graph);
221             av_free(abuffersink_params);
222             if (ret < 0)
223                 goto end;
224         }
225
226         lavfi->sinks[i] = sink;
227         if ((ret = avfilter_link(inout->filter_ctx, inout->pad_idx, sink, 0)) < 0)
228             FAIL(ret);
229     }
230
231     /* configure the graph */
232     if ((ret = avfilter_graph_config(lavfi->graph, avctx)) < 0)
233         FAIL(ret);
234
235     if (lavfi->dump_graph) {
236         char *dump = avfilter_graph_dump(lavfi->graph, lavfi->dump_graph);
237         fputs(dump, stderr);
238         fflush(stderr);
239         av_free(dump);
240     }
241
242     /* fill each stream with the information in the corresponding sink */
243     for (i = 0; i < avctx->nb_streams; i++) {
244         AVFilterLink *link = lavfi->sinks[lavfi->stream_sink_map[i]]->inputs[0];
245         AVStream *st = avctx->streams[i];
246         st->codec->codec_type = link->type;
247         avpriv_set_pts_info(st, 64, link->time_base.num, link->time_base.den);
248         if (link->type == AVMEDIA_TYPE_VIDEO) {
249             st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
250             st->codec->pix_fmt    = link->format;
251             st->codec->time_base  = link->time_base;
252             st->codec->width      = link->w;
253             st->codec->height     = link->h;
254             st       ->sample_aspect_ratio =
255             st->codec->sample_aspect_ratio = link->sample_aspect_ratio;
256         } else if (link->type == AVMEDIA_TYPE_AUDIO) {
257             st->codec->codec_id    = av_get_pcm_codec(link->format, -1);
258             st->codec->channels    = av_get_channel_layout_nb_channels(link->channel_layout);
259             st->codec->sample_fmt  = link->format;
260             st->codec->sample_rate = link->sample_rate;
261             st->codec->time_base   = link->time_base;
262             st->codec->channel_layout = link->channel_layout;
263             if (st->codec->codec_id == AV_CODEC_ID_NONE)
264                 av_log(avctx, AV_LOG_ERROR,
265                        "Could not find PCM codec for sample format %s.\n",
266                        av_get_sample_fmt_name(link->format));
267         }
268     }
269
270 end:
271     av_free(pix_fmts);
272     avfilter_inout_free(&input_links);
273     avfilter_inout_free(&output_links);
274     if (ret < 0)
275         lavfi_read_close(avctx);
276     return ret;
277 }
278
279 static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
280 {
281     LavfiContext *lavfi = avctx->priv_data;
282     double min_pts = DBL_MAX;
283     int stream_idx, min_pts_sink_idx = 0;
284     AVFilterBufferRef *ref;
285     AVPicture pict;
286     int ret, i;
287     int size = 0;
288
289     /* iterate through all the graph sinks. Select the sink with the
290      * minimum PTS */
291     for (i = 0; i < avctx->nb_streams; i++) {
292         AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
293         double d;
294         int ret;
295
296         if (lavfi->sink_eof[i])
297             continue;
298
299         ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
300                                        &ref, AV_BUFFERSINK_FLAG_PEEK);
301         if (ret == AVERROR_EOF) {
302             av_dlog(avctx, "EOF sink_idx:%d\n", i);
303             lavfi->sink_eof[i] = 1;
304             continue;
305         } else if (ret < 0)
306             return ret;
307         d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
308         av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
309
310         if (d < min_pts) {
311             min_pts = d;
312             min_pts_sink_idx = i;
313         }
314     }
315     if (min_pts == DBL_MAX)
316         return AVERROR_EOF;
317
318     av_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx);
319
320     av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &ref, 0);
321     stream_idx = lavfi->sink_stream_map[min_pts_sink_idx];
322
323     if (ref->video) {
324         size = avpicture_get_size(ref->format, ref->video->w, ref->video->h);
325         if ((ret = av_new_packet(pkt, size)) < 0)
326             return ret;
327
328         memcpy(pict.data,     ref->data,     4*sizeof(ref->data[0]));
329         memcpy(pict.linesize, ref->linesize, 4*sizeof(ref->linesize[0]));
330
331         avpicture_layout(&pict, ref->format, ref->video->w,
332                          ref->video->h, pkt->data, size);
333     } else if (ref->audio) {
334         size = ref->audio->nb_samples *
335             av_get_bytes_per_sample(ref->format) *
336             av_get_channel_layout_nb_channels(ref->audio->channel_layout);
337         if ((ret = av_new_packet(pkt, size)) < 0)
338             return ret;
339         memcpy(pkt->data, ref->data[0], size);
340     }
341
342     pkt->stream_index = stream_idx;
343     pkt->pts = ref->pts;
344     pkt->pos = ref->pos;
345     pkt->size = size;
346     avfilter_unref_buffer(ref);
347     return size;
348 }
349
350 #define OFFSET(x) offsetof(LavfiContext, x)
351
352 #define DEC AV_OPT_FLAG_DECODING_PARAM
353
354 static const AVOption options[] = {
355     { "graph",     "set libavfilter graph", OFFSET(graph_str),  AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
356     { "dumpgraph", "dump graph to stderr",  OFFSET(dump_graph), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
357     { NULL },
358 };
359
360 static const AVClass lavfi_class = {
361     .class_name = "lavfi indev",
362     .item_name  = av_default_item_name,
363     .option     = options,
364     .version    = LIBAVUTIL_VERSION_INT,
365 };
366
367 AVInputFormat ff_lavfi_demuxer = {
368     .name           = "lavfi",
369     .long_name      = NULL_IF_CONFIG_SMALL("Libavfilter virtual input device"),
370     .priv_data_size = sizeof(LavfiContext),
371     .read_header    = lavfi_read_header,
372     .read_packet    = lavfi_read_packet,
373     .read_close     = lavfi_read_close,
374     .flags          = AVFMT_NOFILE,
375     .priv_class     = &lavfi_class,
376 };