00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026
00027
00028 #include "float.h"
00029
00030 #include "libavutil/log.h"
00031 #include "libavutil/mem.h"
00032 #include "libavutil/opt.h"
00033 #include "libavutil/parseutils.h"
00034 #include "libavutil/pixdesc.h"
00035 #include "libavfilter/avfilter.h"
00036 #include "libavfilter/avfiltergraph.h"
00037 #include "libavfilter/buffersink.h"
00038 #include "libavformat/internal.h"
00039 #include "avdevice.h"
00040
00041 typedef struct {
00042 AVClass *class;
00043 char *graph_str;
00044 AVFilterGraph *graph;
00045 AVFilterContext **sinks;
00046 int *sink_stream_map;
00047 int *stream_sink_map;
00048 } LavfiContext;
00049
00050 static int *create_all_formats(int n)
00051 {
00052 int i, j, *fmts, count = 0;
00053
00054 for (i = 0; i < n; i++)
00055 if (!(av_pix_fmt_descriptors[i].flags & PIX_FMT_HWACCEL))
00056 count++;
00057
00058 if (!(fmts = av_malloc((count+1) * sizeof(int))))
00059 return NULL;
00060 for (j = 0, i = 0; i < n; i++) {
00061 if (!(av_pix_fmt_descriptors[i].flags & PIX_FMT_HWACCEL))
00062 fmts[j++] = i;
00063 }
00064 fmts[j] = -1;
00065 return fmts;
00066 }
00067
00068 av_cold static int lavfi_read_close(AVFormatContext *avctx)
00069 {
00070 LavfiContext *lavfi = avctx->priv_data;
00071
00072 av_freep(&lavfi->sink_stream_map);
00073 av_freep(&lavfi->stream_sink_map);
00074 avfilter_graph_free(&lavfi->graph);
00075
00076 return 0;
00077 }
00078
00079 av_cold static int lavfi_read_header(AVFormatContext *avctx,
00080 AVFormatParameters *ap)
00081 {
00082 LavfiContext *lavfi = avctx->priv_data;
00083 AVFilterInOut *input_links = NULL, *output_links = NULL, *inout;
00084 AVFilter *buffersink, *abuffersink;
00085 int *pix_fmts = create_all_formats(PIX_FMT_NB);
00086 enum AVMediaType type;
00087 int ret = 0, i, n;
00088
00089 #define FAIL(ERR) { ret = ERR; goto end; }
00090
00091 if (!pix_fmts)
00092 FAIL(AVERROR(ENOMEM));
00093
00094 avfilter_register_all();
00095
00096 buffersink = avfilter_get_by_name("buffersink");
00097 abuffersink = avfilter_get_by_name("abuffersink");
00098
00099 if (!lavfi->graph_str)
00100 lavfi->graph_str = av_strdup(avctx->filename);
00101
00102
00103 if (!(lavfi->graph = avfilter_graph_alloc()))
00104 FAIL(AVERROR(ENOMEM));
00105
00106 if ((ret = avfilter_graph_parse(lavfi->graph, lavfi->graph_str,
00107 &input_links, &output_links, avctx)) < 0)
00108 FAIL(ret);
00109
00110 if (input_links) {
00111 av_log(avctx, AV_LOG_ERROR,
00112 "Open inputs in the filtergraph are not acceptable\n");
00113 FAIL(AVERROR(EINVAL));
00114 }
00115
00116
00117 for (n = 0, inout = output_links; inout; n++, inout = inout->next);
00118
00119 if (!(lavfi->sink_stream_map = av_malloc(sizeof(int) * n)))
00120 FAIL(AVERROR(ENOMEM));
00121 if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n)))
00122 FAIL(AVERROR(ENOMEM));
00123
00124 for (i = 0; i < n; i++)
00125 lavfi->stream_sink_map[i] = -1;
00126
00127
00128
00129 for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
00130 int stream_idx;
00131 if (!strcmp(inout->name, "out"))
00132 stream_idx = 0;
00133 else if (sscanf(inout->name, "out%d\n", &stream_idx) != 1) {
00134 av_log(avctx, AV_LOG_ERROR,
00135 "Invalid outpad name '%s'\n", inout->name);
00136 FAIL(AVERROR(EINVAL));
00137 }
00138
00139 if ((unsigned)stream_idx >= n) {
00140 av_log(avctx, AV_LOG_ERROR,
00141 "Invalid index was specified in output '%s', "
00142 "must be a non-negative value < %d\n",
00143 inout->name, n);
00144 FAIL(AVERROR(EINVAL));
00145 }
00146
00147
00148 type = inout->filter_ctx->output_pads[inout->pad_idx].type;
00149 if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
00150 av_log(avctx, AV_LOG_ERROR,
00151 "Output '%s' is not a video or audio output, not yet supported\n", inout->name);
00152 FAIL(AVERROR(EINVAL));
00153 }
00154
00155 if (lavfi->stream_sink_map[stream_idx] != -1) {
00156 av_log(avctx, AV_LOG_ERROR,
00157 "An with stream index %d was already specified\n",
00158 stream_idx);
00159 FAIL(AVERROR(EINVAL));
00160 }
00161 lavfi->sink_stream_map[i] = stream_idx;
00162 lavfi->stream_sink_map[stream_idx] = i;
00163 }
00164
00165
00166 for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
00167 AVStream *st;
00168 if (!(st = avformat_new_stream(avctx, NULL)))
00169 FAIL(AVERROR(ENOMEM));
00170 st->id = i;
00171 }
00172
00173
00174 lavfi->sinks = av_malloc(sizeof(AVFilterContext *) * avctx->nb_streams);
00175 if (!lavfi->sinks)
00176 FAIL(AVERROR(ENOMEM));
00177
00178 for (i = 0, inout = output_links; inout; i++, inout = inout->next) {
00179 AVFilterContext *sink;
00180
00181 type = inout->filter_ctx->output_pads[inout->pad_idx].type;
00182
00183 if (type == AVMEDIA_TYPE_VIDEO && ! buffersink ||
00184 type == AVMEDIA_TYPE_AUDIO && ! abuffersink) {
00185 av_log(avctx, AV_LOG_ERROR, "Missing required buffersink filter, aborting.\n");
00186 FAIL(AVERROR_FILTER_NOT_FOUND);
00187 }
00188
00189 if (type == AVMEDIA_TYPE_VIDEO) {
00190 AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
00191 buffersink_params->pixel_fmts = pix_fmts;
00192
00193 #if FF_API_OLD_VSINK_API
00194 ret = avfilter_graph_create_filter(&sink, buffersink,
00195 inout->name, NULL,
00196 pix_fmts, lavfi->graph);
00197 #else
00198 buffersink_params->pixel_fmts = pix_fmts;
00199 ret = avfilter_graph_create_filter(&sink, buffersink,
00200 inout->name, NULL,
00201 buffersink_params, lavfi->graph);
00202 #endif
00203 av_freep(&buffersink_params);
00204
00205 if (ret < 0)
00206 goto end;
00207 } else if (type == AVMEDIA_TYPE_AUDIO) {
00208 enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 };
00209 const int packing_fmts[] = { AVFILTER_PACKED, -1 };
00210 const int64_t *chlayouts = avfilter_all_channel_layouts;
00211 AVABufferSinkParams *abuffersink_params = av_abuffersink_params_alloc();
00212 abuffersink_params->sample_fmts = sample_fmts;
00213 abuffersink_params->packing_fmts = packing_fmts;
00214 abuffersink_params->channel_layouts = chlayouts;
00215
00216 ret = avfilter_graph_create_filter(&sink, abuffersink,
00217 inout->name, NULL,
00218 abuffersink_params, lavfi->graph);
00219 av_free(abuffersink_params);
00220 if (ret < 0)
00221 goto end;
00222 }
00223
00224 lavfi->sinks[i] = sink;
00225 if ((ret = avfilter_link(inout->filter_ctx, inout->pad_idx, sink, 0)) < 0)
00226 FAIL(ret);
00227 }
00228
00229
00230 if ((ret = avfilter_graph_config(lavfi->graph, avctx)) < 0)
00231 FAIL(ret);
00232
00233
00234 for (i = 0; i < avctx->nb_streams; i++) {
00235 AVFilterLink *link = lavfi->sinks[lavfi->stream_sink_map[i]]->inputs[0];
00236 AVStream *st = avctx->streams[i];
00237 st->codec->codec_type = link->type;
00238 avpriv_set_pts_info(st, 64, link->time_base.num, link->time_base.den);
00239 if (link->type == AVMEDIA_TYPE_VIDEO) {
00240 st->codec->codec_id = CODEC_ID_RAWVIDEO;
00241 st->codec->pix_fmt = link->format;
00242 st->codec->time_base = link->time_base;
00243 st->codec->width = link->w;
00244 st->codec->height = link->h;
00245 st ->sample_aspect_ratio =
00246 st->codec->sample_aspect_ratio = link->sample_aspect_ratio;
00247 } else if (link->type == AVMEDIA_TYPE_AUDIO) {
00248 st->codec->codec_id = CODEC_ID_PCM_S16LE;
00249 st->codec->channels = av_get_channel_layout_nb_channels(link->channel_layout);
00250 st->codec->sample_fmt = link->format;
00251 st->codec->sample_rate = link->sample_rate;
00252 st->codec->time_base = link->time_base;
00253 st->codec->channel_layout = link->channel_layout;
00254 }
00255 }
00256
00257 end:
00258 avfilter_inout_free(&input_links);
00259 avfilter_inout_free(&output_links);
00260 if (ret < 0)
00261 lavfi_read_close(avctx);
00262 return ret;
00263 }
00264
00265 static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
00266 {
00267 LavfiContext *lavfi = avctx->priv_data;
00268 double min_pts = DBL_MAX;
00269 int stream_idx, min_pts_sink_idx = 0;
00270 AVFilterBufferRef *ref;
00271 AVPicture pict;
00272 int ret, i, size;
00273
00274
00275
00276 for (i = 0; i < avctx->nb_streams; i++) {
00277 AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
00278 double d;
00279 int ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
00280 &ref, AV_BUFFERSINK_FLAG_PEEK);
00281 if (ret < 0)
00282 return ret;
00283 d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
00284 av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);
00285
00286 if (d < min_pts) {
00287 min_pts = d;
00288 min_pts_sink_idx = i;
00289 }
00290 }
00291 av_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx);
00292
00293 av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &ref, 0);
00294 stream_idx = lavfi->sink_stream_map[min_pts_sink_idx];
00295
00296 if (ref->video) {
00297 size = avpicture_get_size(ref->format, ref->video->w, ref->video->h);
00298 if ((ret = av_new_packet(pkt, size)) < 0)
00299 return ret;
00300
00301 memcpy(pict.data, ref->data, 4*sizeof(ref->data[0]));
00302 memcpy(pict.linesize, ref->linesize, 4*sizeof(ref->linesize[0]));
00303
00304 avpicture_layout(&pict, ref->format, ref->video->w,
00305 ref->video->h, pkt->data, size);
00306 } else if (ref->audio) {
00307 size = ref->audio->nb_samples *
00308 av_get_bytes_per_sample(ref->format) *
00309 av_get_channel_layout_nb_channels(ref->audio->channel_layout);
00310 if ((ret = av_new_packet(pkt, size)) < 0)
00311 return ret;
00312 memcpy(pkt->data, ref->data[0], size);
00313 }
00314
00315 pkt->stream_index = stream_idx;
00316 pkt->pts = ref->pts;
00317 pkt->pos = ref->pos;
00318 pkt->size = size;
00319 avfilter_unref_buffer(ref);
00320
00321 return size;
00322 }
00323
00324 #define OFFSET(x) offsetof(LavfiContext, x)
00325
00326 #define DEC AV_OPT_FLAG_DECODING_PARAM
00327
00328 static const AVOption options[] = {
00329 { "graph", "Libavfilter graph", OFFSET(graph_str), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC },
00330 { NULL },
00331 };
00332
00333 static const AVClass lavfi_class = {
00334 .class_name = "lavfi indev",
00335 .item_name = av_default_item_name,
00336 .option = options,
00337 .version = LIBAVUTIL_VERSION_INT,
00338 };
00339
00340 AVInputFormat ff_lavfi_demuxer = {
00341 .name = "lavfi",
00342 .long_name = NULL_IF_CONFIG_SMALL("Libavfilter virtual input device"),
00343 .priv_data_size = sizeof(LavfiContext),
00344 .read_header = lavfi_read_header,
00345 .read_packet = lavfi_read_packet,
00346 .read_close = lavfi_read_close,
00347 .flags = AVFMT_NOFILE,
00348 .priv_class = &lavfi_class,
00349 };