annotate ffmpeg/libavdevice/lavfi.c @ 13:844d341cf643 tip

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