1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2011 Stefano Sabatini 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci/** 22cabdff1aSopenharmony_ci * @file 23cabdff1aSopenharmony_ci * libavfilter virtual input device 24cabdff1aSopenharmony_ci */ 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci/* #define DEBUG */ 27cabdff1aSopenharmony_ci 28cabdff1aSopenharmony_ci#include <float.h> /* DBL_MIN, DBL_MAX */ 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavutil/bprint.h" 31cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 32cabdff1aSopenharmony_ci#include "libavutil/file.h" 33cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 34cabdff1aSopenharmony_ci#include "libavutil/internal.h" 35cabdff1aSopenharmony_ci#include "libavutil/log.h" 36cabdff1aSopenharmony_ci#include "libavutil/mem.h" 37cabdff1aSopenharmony_ci#include "libavutil/opt.h" 38cabdff1aSopenharmony_ci#include "libavutil/parseutils.h" 39cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 40cabdff1aSopenharmony_ci#include "libavfilter/avfilter.h" 41cabdff1aSopenharmony_ci#include "libavfilter/buffersink.h" 42cabdff1aSopenharmony_ci#include "libavformat/avio_internal.h" 43cabdff1aSopenharmony_ci#include "libavformat/internal.h" 44cabdff1aSopenharmony_ci#include "avdevice.h" 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_citypedef struct { 47cabdff1aSopenharmony_ci AVClass *class; ///< class for private options 48cabdff1aSopenharmony_ci char *graph_str; 49cabdff1aSopenharmony_ci char *graph_filename; 50cabdff1aSopenharmony_ci char *dump_graph; 51cabdff1aSopenharmony_ci AVFilterGraph *graph; 52cabdff1aSopenharmony_ci AVFilterContext **sinks; 53cabdff1aSopenharmony_ci int *sink_stream_map; 54cabdff1aSopenharmony_ci int *sink_eof; 55cabdff1aSopenharmony_ci int *stream_sink_map; 56cabdff1aSopenharmony_ci int *sink_stream_subcc_map; 57cabdff1aSopenharmony_ci AVFrame *decoded_frame; 58cabdff1aSopenharmony_ci int nb_sinks; 59cabdff1aSopenharmony_ci AVPacket subcc_packet; 60cabdff1aSopenharmony_ci} LavfiContext; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_cistatic int *create_all_formats(int n) 63cabdff1aSopenharmony_ci{ 64cabdff1aSopenharmony_ci int i, j, *fmts, count = 0; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci for (i = 0; i < n; i++) { 67cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); 68cabdff1aSopenharmony_ci if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) 69cabdff1aSopenharmony_ci count++; 70cabdff1aSopenharmony_ci } 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci if (!(fmts = av_malloc_array(count + 1, sizeof(*fmts)))) 73cabdff1aSopenharmony_ci return NULL; 74cabdff1aSopenharmony_ci for (j = 0, i = 0; i < n; i++) { 75cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); 76cabdff1aSopenharmony_ci if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) 77cabdff1aSopenharmony_ci fmts[j++] = i; 78cabdff1aSopenharmony_ci } 79cabdff1aSopenharmony_ci fmts[j] = AV_PIX_FMT_NONE; 80cabdff1aSopenharmony_ci return fmts; 81cabdff1aSopenharmony_ci} 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ciav_cold static int lavfi_read_close(AVFormatContext *avctx) 84cabdff1aSopenharmony_ci{ 85cabdff1aSopenharmony_ci LavfiContext *lavfi = avctx->priv_data; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci av_freep(&lavfi->sink_stream_map); 88cabdff1aSopenharmony_ci av_freep(&lavfi->sink_eof); 89cabdff1aSopenharmony_ci av_freep(&lavfi->stream_sink_map); 90cabdff1aSopenharmony_ci av_freep(&lavfi->sink_stream_subcc_map); 91cabdff1aSopenharmony_ci av_freep(&lavfi->sinks); 92cabdff1aSopenharmony_ci avfilter_graph_free(&lavfi->graph); 93cabdff1aSopenharmony_ci av_frame_free(&lavfi->decoded_frame); 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci return 0; 96cabdff1aSopenharmony_ci} 97cabdff1aSopenharmony_ci 98cabdff1aSopenharmony_cistatic int create_subcc_streams(AVFormatContext *avctx) 99cabdff1aSopenharmony_ci{ 100cabdff1aSopenharmony_ci LavfiContext *lavfi = avctx->priv_data; 101cabdff1aSopenharmony_ci AVStream *st; 102cabdff1aSopenharmony_ci int stream_idx, sink_idx; 103cabdff1aSopenharmony_ci AVRational *time_base; 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci for (stream_idx = 0; stream_idx < lavfi->nb_sinks; stream_idx++) { 106cabdff1aSopenharmony_ci sink_idx = lavfi->stream_sink_map[stream_idx]; 107cabdff1aSopenharmony_ci if (lavfi->sink_stream_subcc_map[sink_idx]) { 108cabdff1aSopenharmony_ci lavfi->sink_stream_subcc_map[sink_idx] = avctx->nb_streams; 109cabdff1aSopenharmony_ci if (!(st = avformat_new_stream(avctx, NULL))) 110cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 111cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_EIA_608; 112cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; 113cabdff1aSopenharmony_ci time_base = &avctx->streams[stream_idx]->time_base; 114cabdff1aSopenharmony_ci st->time_base.num = time_base->num; 115cabdff1aSopenharmony_ci st->time_base.den = time_base->den; 116cabdff1aSopenharmony_ci } else { 117cabdff1aSopenharmony_ci lavfi->sink_stream_subcc_map[sink_idx] = -1; 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci } 120cabdff1aSopenharmony_ci return 0; 121cabdff1aSopenharmony_ci} 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ciav_cold static int lavfi_read_header(AVFormatContext *avctx) 124cabdff1aSopenharmony_ci{ 125cabdff1aSopenharmony_ci LavfiContext *lavfi = avctx->priv_data; 126cabdff1aSopenharmony_ci AVFilterInOut *input_links = NULL, *output_links = NULL, *inout; 127cabdff1aSopenharmony_ci const AVFilter *buffersink, *abuffersink; 128cabdff1aSopenharmony_ci int *pix_fmts = create_all_formats(AV_PIX_FMT_NB); 129cabdff1aSopenharmony_ci enum AVMediaType type; 130cabdff1aSopenharmony_ci int ret = 0, i, n; 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci#define FAIL(ERR) { ret = ERR; goto end; } 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci if (!pix_fmts) 135cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci buffersink = avfilter_get_by_name("buffersink"); 138cabdff1aSopenharmony_ci abuffersink = avfilter_get_by_name("abuffersink"); 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci if (lavfi->graph_filename && lavfi->graph_str) { 141cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 142cabdff1aSopenharmony_ci "Only one of the graph or graph_file options must be specified\n"); 143cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci if (lavfi->graph_filename) { 147cabdff1aSopenharmony_ci AVBPrint graph_file_pb; 148cabdff1aSopenharmony_ci AVIOContext *avio = NULL; 149cabdff1aSopenharmony_ci AVDictionary *options = NULL; 150cabdff1aSopenharmony_ci if (avctx->protocol_whitelist && (ret = av_dict_set(&options, "protocol_whitelist", avctx->protocol_whitelist, 0)) < 0) 151cabdff1aSopenharmony_ci goto end; 152cabdff1aSopenharmony_ci ret = avio_open2(&avio, lavfi->graph_filename, AVIO_FLAG_READ, &avctx->interrupt_callback, &options); 153cabdff1aSopenharmony_ci av_dict_free(&options); 154cabdff1aSopenharmony_ci if (ret < 0) 155cabdff1aSopenharmony_ci goto end; 156cabdff1aSopenharmony_ci av_bprint_init(&graph_file_pb, 0, AV_BPRINT_SIZE_UNLIMITED); 157cabdff1aSopenharmony_ci ret = avio_read_to_bprint(avio, &graph_file_pb, INT_MAX); 158cabdff1aSopenharmony_ci avio_closep(&avio); 159cabdff1aSopenharmony_ci if (ret) { 160cabdff1aSopenharmony_ci av_bprint_finalize(&graph_file_pb, NULL); 161cabdff1aSopenharmony_ci goto end; 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci if ((ret = av_bprint_finalize(&graph_file_pb, &lavfi->graph_str))) 164cabdff1aSopenharmony_ci goto end; 165cabdff1aSopenharmony_ci } 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci if (!lavfi->graph_str) 168cabdff1aSopenharmony_ci lavfi->graph_str = av_strdup(avctx->url); 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci /* parse the graph, create a stream for each open output */ 171cabdff1aSopenharmony_ci if (!(lavfi->graph = avfilter_graph_alloc())) 172cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci if ((ret = avfilter_graph_parse_ptr(lavfi->graph, lavfi->graph_str, 175cabdff1aSopenharmony_ci &input_links, &output_links, avctx)) < 0) 176cabdff1aSopenharmony_ci goto end; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci if (input_links) { 179cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 180cabdff1aSopenharmony_ci "Open inputs in the filtergraph are not acceptable\n"); 181cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 182cabdff1aSopenharmony_ci } 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci /* count the outputs */ 185cabdff1aSopenharmony_ci for (n = 0, inout = output_links; inout; n++, inout = inout->next); 186cabdff1aSopenharmony_ci lavfi->nb_sinks = n; 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci if (!(lavfi->sink_stream_map = av_malloc(sizeof(int) * n))) 189cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 190cabdff1aSopenharmony_ci if (!(lavfi->sink_eof = av_mallocz(sizeof(int) * n))) 191cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 192cabdff1aSopenharmony_ci if (!(lavfi->stream_sink_map = av_malloc(sizeof(int) * n))) 193cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 194cabdff1aSopenharmony_ci if (!(lavfi->sink_stream_subcc_map = av_malloc(sizeof(int) * n))) 195cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci for (i = 0; i < n; i++) 198cabdff1aSopenharmony_ci lavfi->stream_sink_map[i] = -1; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci /* parse the output link names - they need to be of the form out0, out1, ... 201cabdff1aSopenharmony_ci * create a mapping between them and the streams */ 202cabdff1aSopenharmony_ci for (i = 0, inout = output_links; inout; i++, inout = inout->next) { 203cabdff1aSopenharmony_ci int stream_idx = 0, suffix = 0, use_subcc = 0; 204cabdff1aSopenharmony_ci sscanf(inout->name, "out%n%d%n", &suffix, &stream_idx, &suffix); 205cabdff1aSopenharmony_ci if (!suffix) { 206cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 207cabdff1aSopenharmony_ci "Invalid outpad name '%s'\n", inout->name); 208cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 209cabdff1aSopenharmony_ci } 210cabdff1aSopenharmony_ci if (inout->name[suffix]) { 211cabdff1aSopenharmony_ci if (!strcmp(inout->name + suffix, "+subcc")) { 212cabdff1aSopenharmony_ci use_subcc = 1; 213cabdff1aSopenharmony_ci } else { 214cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 215cabdff1aSopenharmony_ci "Invalid outpad suffix '%s'\n", inout->name); 216cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 217cabdff1aSopenharmony_ci } 218cabdff1aSopenharmony_ci } 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci if ((unsigned)stream_idx >= n) { 221cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 222cabdff1aSopenharmony_ci "Invalid index was specified in output '%s', " 223cabdff1aSopenharmony_ci "must be a non-negative value < %d\n", 224cabdff1aSopenharmony_ci inout->name, n); 225cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ci if (lavfi->stream_sink_map[stream_idx] != -1) { 229cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 230cabdff1aSopenharmony_ci "An output with stream index %d was already specified\n", 231cabdff1aSopenharmony_ci stream_idx); 232cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci lavfi->sink_stream_map[i] = stream_idx; 235cabdff1aSopenharmony_ci lavfi->stream_sink_map[stream_idx] = i; 236cabdff1aSopenharmony_ci lavfi->sink_stream_subcc_map[i] = !!use_subcc; 237cabdff1aSopenharmony_ci } 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_ci /* for each open output create a corresponding stream */ 240cabdff1aSopenharmony_ci for (i = 0, inout = output_links; inout; i++, inout = inout->next) { 241cabdff1aSopenharmony_ci AVStream *st; 242cabdff1aSopenharmony_ci if (!(st = avformat_new_stream(avctx, NULL))) 243cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 244cabdff1aSopenharmony_ci st->id = i; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ci /* create a sink for each output and connect them to the graph */ 248cabdff1aSopenharmony_ci lavfi->sinks = av_malloc_array(lavfi->nb_sinks, sizeof(AVFilterContext *)); 249cabdff1aSopenharmony_ci if (!lavfi->sinks) 250cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci for (i = 0, inout = output_links; inout; i++, inout = inout->next) { 253cabdff1aSopenharmony_ci AVFilterContext *sink; 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ci type = avfilter_pad_get_type(inout->filter_ctx->output_pads, inout->pad_idx); 256cabdff1aSopenharmony_ci 257cabdff1aSopenharmony_ci if (type == AVMEDIA_TYPE_VIDEO && ! buffersink || 258cabdff1aSopenharmony_ci type == AVMEDIA_TYPE_AUDIO && ! abuffersink) { 259cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Missing required buffersink filter, aborting.\n"); 260cabdff1aSopenharmony_ci FAIL(AVERROR_FILTER_NOT_FOUND); 261cabdff1aSopenharmony_ci } 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci if (type == AVMEDIA_TYPE_VIDEO) { 264cabdff1aSopenharmony_ci ret = avfilter_graph_create_filter(&sink, buffersink, 265cabdff1aSopenharmony_ci inout->name, NULL, 266cabdff1aSopenharmony_ci NULL, lavfi->graph); 267cabdff1aSopenharmony_ci if (ret >= 0) 268cabdff1aSopenharmony_ci ret = av_opt_set_int_list(sink, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); 269cabdff1aSopenharmony_ci if (ret < 0) 270cabdff1aSopenharmony_ci goto end; 271cabdff1aSopenharmony_ci } else if (type == AVMEDIA_TYPE_AUDIO) { 272cabdff1aSopenharmony_ci static const enum AVSampleFormat sample_fmts[] = { 273cabdff1aSopenharmony_ci AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, 274cabdff1aSopenharmony_ci AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL, 275cabdff1aSopenharmony_ci }; 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci ret = avfilter_graph_create_filter(&sink, abuffersink, 278cabdff1aSopenharmony_ci inout->name, NULL, 279cabdff1aSopenharmony_ci NULL, lavfi->graph); 280cabdff1aSopenharmony_ci if (ret >= 0) 281cabdff1aSopenharmony_ci ret = av_opt_set_bin(sink, "sample_fmts", (const uint8_t*)sample_fmts, 282cabdff1aSopenharmony_ci sizeof(sample_fmts), AV_OPT_SEARCH_CHILDREN); 283cabdff1aSopenharmony_ci if (ret < 0) 284cabdff1aSopenharmony_ci goto end; 285cabdff1aSopenharmony_ci ret = av_opt_set_int(sink, "all_channel_counts", 1, 286cabdff1aSopenharmony_ci AV_OPT_SEARCH_CHILDREN); 287cabdff1aSopenharmony_ci if (ret < 0) 288cabdff1aSopenharmony_ci goto end; 289cabdff1aSopenharmony_ci } else { 290cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 291cabdff1aSopenharmony_ci "Output '%s' is not a video or audio output, not yet supported\n", inout->name); 292cabdff1aSopenharmony_ci FAIL(AVERROR(EINVAL)); 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci lavfi->sinks[i] = sink; 296cabdff1aSopenharmony_ci if ((ret = avfilter_link(inout->filter_ctx, inout->pad_idx, sink, 0)) < 0) 297cabdff1aSopenharmony_ci goto end; 298cabdff1aSopenharmony_ci } 299cabdff1aSopenharmony_ci 300cabdff1aSopenharmony_ci /* configure the graph */ 301cabdff1aSopenharmony_ci if ((ret = avfilter_graph_config(lavfi->graph, avctx)) < 0) 302cabdff1aSopenharmony_ci goto end; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci if (lavfi->dump_graph) { 305cabdff1aSopenharmony_ci char *dump = avfilter_graph_dump(lavfi->graph, lavfi->dump_graph); 306cabdff1aSopenharmony_ci if (dump != NULL) { 307cabdff1aSopenharmony_ci fputs(dump, stderr); 308cabdff1aSopenharmony_ci fflush(stderr); 309cabdff1aSopenharmony_ci av_free(dump); 310cabdff1aSopenharmony_ci } else { 311cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 312cabdff1aSopenharmony_ci } 313cabdff1aSopenharmony_ci } 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci /* fill each stream with the information in the corresponding sink */ 316cabdff1aSopenharmony_ci for (i = 0; i < lavfi->nb_sinks; i++) { 317cabdff1aSopenharmony_ci AVFilterContext *sink = lavfi->sinks[lavfi->stream_sink_map[i]]; 318cabdff1aSopenharmony_ci AVRational time_base = av_buffersink_get_time_base(sink); 319cabdff1aSopenharmony_ci AVStream *st = avctx->streams[i]; 320cabdff1aSopenharmony_ci AVCodecParameters *const par = st->codecpar; 321cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, time_base.num, time_base.den); 322cabdff1aSopenharmony_ci par->codec_type = av_buffersink_get_type(sink); 323cabdff1aSopenharmony_ci if (par->codec_type == AVMEDIA_TYPE_VIDEO) { 324cabdff1aSopenharmony_ci int64_t probesize; 325cabdff1aSopenharmony_ci par->codec_id = AV_CODEC_ID_RAWVIDEO; 326cabdff1aSopenharmony_ci par->format = av_buffersink_get_format(sink); 327cabdff1aSopenharmony_ci par->width = av_buffersink_get_w(sink); 328cabdff1aSopenharmony_ci par->height = av_buffersink_get_h(sink); 329cabdff1aSopenharmony_ci probesize = par->width * par->height * 30 * 330cabdff1aSopenharmony_ci av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(par->format)); 331cabdff1aSopenharmony_ci avctx->probesize = FFMAX(avctx->probesize, probesize); 332cabdff1aSopenharmony_ci st ->sample_aspect_ratio = 333cabdff1aSopenharmony_ci par->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); 334cabdff1aSopenharmony_ci } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { 335cabdff1aSopenharmony_ci par->sample_rate = av_buffersink_get_sample_rate(sink); 336cabdff1aSopenharmony_ci ret = av_buffersink_get_ch_layout(sink, &par->ch_layout); 337cabdff1aSopenharmony_ci if (ret < 0) 338cabdff1aSopenharmony_ci goto end; 339cabdff1aSopenharmony_ci par->format = av_buffersink_get_format(sink); 340cabdff1aSopenharmony_ci par->codec_id = av_get_pcm_codec(par->format, -1); 341cabdff1aSopenharmony_ci if (par->codec_id == AV_CODEC_ID_NONE) 342cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 343cabdff1aSopenharmony_ci "Could not find PCM codec for sample format %s.\n", 344cabdff1aSopenharmony_ci av_get_sample_fmt_name(par->format)); 345cabdff1aSopenharmony_ci } 346cabdff1aSopenharmony_ci } 347cabdff1aSopenharmony_ci 348cabdff1aSopenharmony_ci if ((ret = create_subcc_streams(avctx)) < 0) 349cabdff1aSopenharmony_ci goto end; 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ci if (!(lavfi->decoded_frame = av_frame_alloc())) 352cabdff1aSopenharmony_ci FAIL(AVERROR(ENOMEM)); 353cabdff1aSopenharmony_ci 354cabdff1aSopenharmony_ciend: 355cabdff1aSopenharmony_ci av_free(pix_fmts); 356cabdff1aSopenharmony_ci avfilter_inout_free(&input_links); 357cabdff1aSopenharmony_ci avfilter_inout_free(&output_links); 358cabdff1aSopenharmony_ci return ret; 359cabdff1aSopenharmony_ci} 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_cistatic int create_subcc_packet(AVFormatContext *avctx, AVFrame *frame, 362cabdff1aSopenharmony_ci int sink_idx) 363cabdff1aSopenharmony_ci{ 364cabdff1aSopenharmony_ci LavfiContext *lavfi = avctx->priv_data; 365cabdff1aSopenharmony_ci AVFrameSideData *sd; 366cabdff1aSopenharmony_ci int stream_idx, ret; 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci if ((stream_idx = lavfi->sink_stream_subcc_map[sink_idx]) < 0) 369cabdff1aSopenharmony_ci return 0; 370cabdff1aSopenharmony_ci if (!(sd = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC))) 371cabdff1aSopenharmony_ci return 0; 372cabdff1aSopenharmony_ci if ((ret = av_new_packet(&lavfi->subcc_packet, sd->size)) < 0) 373cabdff1aSopenharmony_ci return ret; 374cabdff1aSopenharmony_ci memcpy(lavfi->subcc_packet.data, sd->data, sd->size); 375cabdff1aSopenharmony_ci lavfi->subcc_packet.stream_index = stream_idx; 376cabdff1aSopenharmony_ci lavfi->subcc_packet.pts = frame->pts; 377cabdff1aSopenharmony_ci lavfi->subcc_packet.pos = frame->pkt_pos; 378cabdff1aSopenharmony_ci return 0; 379cabdff1aSopenharmony_ci} 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_cistatic int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) 382cabdff1aSopenharmony_ci{ 383cabdff1aSopenharmony_ci LavfiContext *lavfi = avctx->priv_data; 384cabdff1aSopenharmony_ci double min_pts = DBL_MAX; 385cabdff1aSopenharmony_ci int stream_idx, min_pts_sink_idx = 0; 386cabdff1aSopenharmony_ci AVFrame *frame = lavfi->decoded_frame; 387cabdff1aSopenharmony_ci AVDictionary *frame_metadata; 388cabdff1aSopenharmony_ci int ret, i; 389cabdff1aSopenharmony_ci int size = 0; 390cabdff1aSopenharmony_ci AVStream *st; 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_ci if (lavfi->subcc_packet.size) { 393cabdff1aSopenharmony_ci av_packet_move_ref(pkt, &lavfi->subcc_packet); 394cabdff1aSopenharmony_ci return pkt->size; 395cabdff1aSopenharmony_ci } 396cabdff1aSopenharmony_ci 397cabdff1aSopenharmony_ci /* iterate through all the graph sinks. Select the sink with the 398cabdff1aSopenharmony_ci * minimum PTS */ 399cabdff1aSopenharmony_ci for (i = 0; i < lavfi->nb_sinks; i++) { 400cabdff1aSopenharmony_ci AVRational tb = av_buffersink_get_time_base(lavfi->sinks[i]); 401cabdff1aSopenharmony_ci double d; 402cabdff1aSopenharmony_ci int ret; 403cabdff1aSopenharmony_ci 404cabdff1aSopenharmony_ci if (lavfi->sink_eof[i]) 405cabdff1aSopenharmony_ci continue; 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci ret = av_buffersink_get_frame_flags(lavfi->sinks[i], frame, 408cabdff1aSopenharmony_ci AV_BUFFERSINK_FLAG_PEEK); 409cabdff1aSopenharmony_ci if (ret == AVERROR_EOF) { 410cabdff1aSopenharmony_ci ff_dlog(avctx, "EOF sink_idx:%d\n", i); 411cabdff1aSopenharmony_ci lavfi->sink_eof[i] = 1; 412cabdff1aSopenharmony_ci continue; 413cabdff1aSopenharmony_ci } else if (ret < 0) 414cabdff1aSopenharmony_ci return ret; 415cabdff1aSopenharmony_ci d = av_rescale_q_rnd(frame->pts, tb, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); 416cabdff1aSopenharmony_ci ff_dlog(avctx, "sink_idx:%d time:%f\n", i, d); 417cabdff1aSopenharmony_ci av_frame_unref(frame); 418cabdff1aSopenharmony_ci 419cabdff1aSopenharmony_ci if (d < min_pts) { 420cabdff1aSopenharmony_ci min_pts = d; 421cabdff1aSopenharmony_ci min_pts_sink_idx = i; 422cabdff1aSopenharmony_ci } 423cabdff1aSopenharmony_ci } 424cabdff1aSopenharmony_ci if (min_pts == DBL_MAX) 425cabdff1aSopenharmony_ci return AVERROR_EOF; 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_ci ff_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx); 428cabdff1aSopenharmony_ci 429cabdff1aSopenharmony_ci av_buffersink_get_frame_flags(lavfi->sinks[min_pts_sink_idx], frame, 0); 430cabdff1aSopenharmony_ci stream_idx = lavfi->sink_stream_map[min_pts_sink_idx]; 431cabdff1aSopenharmony_ci st = avctx->streams[stream_idx]; 432cabdff1aSopenharmony_ci 433cabdff1aSopenharmony_ci if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { 434cabdff1aSopenharmony_ci size = av_image_get_buffer_size(frame->format, frame->width, frame->height, 1); 435cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, size)) < 0) 436cabdff1aSopenharmony_ci goto fail; 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_ci av_image_copy_to_buffer(pkt->data, size, (const uint8_t **)frame->data, frame->linesize, 439cabdff1aSopenharmony_ci frame->format, frame->width, frame->height, 1); 440cabdff1aSopenharmony_ci } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { 441cabdff1aSopenharmony_ci size = frame->nb_samples * av_get_bytes_per_sample(frame->format) * 442cabdff1aSopenharmony_ci frame->ch_layout.nb_channels; 443cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, size)) < 0) 444cabdff1aSopenharmony_ci goto fail; 445cabdff1aSopenharmony_ci memcpy(pkt->data, frame->data[0], size); 446cabdff1aSopenharmony_ci } 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci frame_metadata = frame->metadata; 449cabdff1aSopenharmony_ci if (frame_metadata) { 450cabdff1aSopenharmony_ci size_t size; 451cabdff1aSopenharmony_ci uint8_t *metadata = av_packet_pack_dictionary(frame_metadata, &size); 452cabdff1aSopenharmony_ci 453cabdff1aSopenharmony_ci if (!metadata) { 454cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 455cabdff1aSopenharmony_ci goto fail; 456cabdff1aSopenharmony_ci } 457cabdff1aSopenharmony_ci if ((ret = av_packet_add_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, 458cabdff1aSopenharmony_ci metadata, size)) < 0) { 459cabdff1aSopenharmony_ci av_freep(&metadata); 460cabdff1aSopenharmony_ci goto fail; 461cabdff1aSopenharmony_ci } 462cabdff1aSopenharmony_ci } 463cabdff1aSopenharmony_ci 464cabdff1aSopenharmony_ci if ((ret = create_subcc_packet(avctx, frame, min_pts_sink_idx)) < 0) { 465cabdff1aSopenharmony_ci goto fail; 466cabdff1aSopenharmony_ci } 467cabdff1aSopenharmony_ci 468cabdff1aSopenharmony_ci pkt->stream_index = stream_idx; 469cabdff1aSopenharmony_ci pkt->pts = frame->pts; 470cabdff1aSopenharmony_ci pkt->pos = frame->pkt_pos; 471cabdff1aSopenharmony_ci av_frame_unref(frame); 472cabdff1aSopenharmony_ci return size; 473cabdff1aSopenharmony_cifail: 474cabdff1aSopenharmony_ci av_frame_unref(frame); 475cabdff1aSopenharmony_ci return ret; 476cabdff1aSopenharmony_ci 477cabdff1aSopenharmony_ci} 478cabdff1aSopenharmony_ci 479cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(LavfiContext, x) 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_ci#define DEC AV_OPT_FLAG_DECODING_PARAM 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_cistatic const AVOption options[] = { 484cabdff1aSopenharmony_ci { "graph", "set libavfilter graph", OFFSET(graph_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, 485cabdff1aSopenharmony_ci { "graph_file","set libavfilter graph filename", OFFSET(graph_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC}, 486cabdff1aSopenharmony_ci { "dumpgraph", "dump graph to stderr", OFFSET(dump_graph), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, 487cabdff1aSopenharmony_ci { NULL }, 488cabdff1aSopenharmony_ci}; 489cabdff1aSopenharmony_ci 490cabdff1aSopenharmony_cistatic const AVClass lavfi_class = { 491cabdff1aSopenharmony_ci .class_name = "lavfi indev", 492cabdff1aSopenharmony_ci .item_name = av_default_item_name, 493cabdff1aSopenharmony_ci .option = options, 494cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 495cabdff1aSopenharmony_ci .category = AV_CLASS_CATEGORY_DEVICE_INPUT, 496cabdff1aSopenharmony_ci}; 497cabdff1aSopenharmony_ci 498cabdff1aSopenharmony_ciconst AVInputFormat ff_lavfi_demuxer = { 499cabdff1aSopenharmony_ci .name = "lavfi", 500cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Libavfilter virtual input device"), 501cabdff1aSopenharmony_ci .priv_data_size = sizeof(LavfiContext), 502cabdff1aSopenharmony_ci .read_header = lavfi_read_header, 503cabdff1aSopenharmony_ci .read_packet = lavfi_read_packet, 504cabdff1aSopenharmony_ci .read_close = lavfi_read_close, 505cabdff1aSopenharmony_ci .flags = AVFMT_NOFILE, 506cabdff1aSopenharmony_ci .priv_class = &lavfi_class, 507cabdff1aSopenharmony_ci .flags_internal = FF_FMT_INIT_CLEANUP, 508cabdff1aSopenharmony_ci}; 509